📄 minimizerclassic.java
字号:
} else {
repuFactor = 1.0;
}
}
/**
* Returns the Euclidean distance between the positions pos1 and pos2.
* @return Euclidean distance between the positions pos1 and pos2
*/
private final double getDist(final double[] pos1, final double[] pos2) {
double dist = 0.0;
for (int d = 0; d < nrDims; d++) {
double diff = pos1[d] - pos2[d];
dist += diff * diff;
}
return Math.sqrt(dist);
}
/**
* Returns the repulsion energy of a node.
* @param node repulsing node
* @return repulsion energy of the specified node
*/
private double getRepulsionEnergy(final Node node) {
if (node.weight == 0.0) return 0.0;
final double[] position = positions.get(node);
double energy = 0.0;
for (Node node2 : nodes) {
if (node2 == node || node2.weight == 0.0) continue;
final double dist = getDist(position, positions.get(node2));
if (repuExponent == 0.0) {
energy -= repuFactor * node.weight * node2.weight
* Math.log(dist);
} else {
energy -= repuFactor * node.weight * node2.weight
* Math.pow(dist, repuExponent) / repuExponent;
}
}
return energy;
}
/**
* Returns the attraction energy of a node.
* @param node attracting node
* @return attraction energy of the specified node
*/
private double getAttractionEnergy(final Node node) {
double energy = 0.0;
final double[] position = positions.get(node);
for (Edge edge : attrEdges.get(node)) {
final double dist = getDist(position, positions.get(edge.endNode));
if (attrExponent == 0.0) {
energy += edge.weight * Math.log(dist);
} else {
energy += edge.weight * Math.pow(dist, attrExponent) / attrExponent;
}
}
return energy;
}
/**
* Returns the gravitation energy of a node.
* @param node gravitating node
* @return gravitation energy of the specified node
*/
private double getGravitationEnergy(final Node node) {
final double dist = getDist(positions.get(node), baryCenter);
if (attrExponent == 0.0) {
return gravFactor * node.weight * Math.log(dist);
} else {
return gravFactor * node.weight * Math.pow(dist, attrExponent) / attrExponent;
}
}
/**
* Returns the total energy of a node.
* @param node node
* @return total energy of the specified node
*/
private double getEnergy(final Node node) {
return getRepulsionEnergy(node)
+ getAttractionEnergy(node) + getGravitationEnergy(node);
}
/**
* Computes the direction of the repulsion force on a node.
* @param node repulsing node
* @param dir direction of the repulsion force acting on the node
* is added to this variable (output parameter)
* @return approximate second derivation of the repulsion energy
*/
private double addRepulsionDir(final Node node, final double[] dir) {
if (node.weight == 0.0) return 0.0;
final double[] position = positions.get(node);
double dir2 = 0.0;
for (Node node2 : nodes) {
if (node2 == node || node2.weight == 0.0) continue;
final double[] position2 = positions.get(node2);
final double dist = getDist(position, position2);
if (dist == 0.0) continue;
double tmp = repuFactor * node.weight * node2.weight
* Math.pow(dist, repuExponent-2);
dir2 += tmp * Math.abs(repuExponent-1);
for (int d = 0; d < nrDims; d++) {
dir[d] -= (position2[d] - position[d]) * tmp;
}
}
return dir2;
}
/**
* Computes the direction of the attraction force on the a node.
* @param node attracting node
* @param dir direction of the attraction force acting on the node
* is added to this variable (output parameter)
* @return approximate second derivation of the attraction energy
*/
private double addAttractionDir(final Node node, final double[] dir) {
double dir2 = 0.0;
final double[] position = positions.get(node);
for (Edge edge : attrEdges.get(node)) {
final double[] position2 = positions.get(edge.endNode);
final double dist = getDist(position, position2);
if (dist == 0.0) continue;
double tmp = edge.weight * Math.pow(dist, attrExponent-2);
dir2 += tmp * Math.abs(attrExponent-1);
for (int d = 0; d < nrDims; d++) {
dir[d] += (position2[d] - position[d]) * tmp;
}
}
return dir2;
}
/**
* Computes the direction of the gravitation force on the a node.
* @param node gravitating node
* @param dir direction of the gravitation force acting on the node
* is added to this variable (output parameter)
* @return approximate second derivation of the gravitation energy
*/
private double addGravitationDir(final Node node, final double[] dir) {
final double[] position = positions.get(node);
final double dist = getDist(position, baryCenter);
double tmp = gravFactor * repuFactor * node.weight * Math.pow(dist, attrExponent-2);
for (int d = 0; d < nrDims; d++) {
dir[d] += (baryCenter[d] - position[d]) * tmp;
}
return tmp * Math.abs(attrExponent-1);
}
/**
* Computes the direction of the total force acting on a node.
* @param node node
* @param dir direction of the total force acting on the node
* (output parameter)
*/
private void getDirection(final Node node, final double[] dir) {
for (int d=0; d<nrDims; d++) dir[d] = 0.0;
double dir2 = addRepulsionDir(node, dir);
dir2 += addAttractionDir(node, dir);
dir2 += addGravitationDir(node, dir);
// compute average Euclidean distance to other nodes
double avgDist = 0.0;
for (Node node2 : nodes) {
avgDist += getDist(positions.get(node), positions.get(node2));
}
avgDist /= nodes.size()-1;
if (dir2 != 0.0) {
// normalize force vector with second derivation of energy
for (int d=0; d<nrDims; d++) dir[d] /= dir2;
// ensure that the length of dir is not greater
// than average Euclidean distance to other nodes
double length = getDist(dir, new double[nrDims]);
if (avgDist > 0.0 && length > avgDist) {
length /= avgDist;
for (int d=0; d<nrDims; d++) dir[d] /= length;
}
} else {
for (int d=0; d<nrDims; d++) dir[d] = 0.0;
}
}
/**
* Computes the position of the barycenter of all nodes
* and stores it in the attribute <code>baryCenter</code>.
*/
private void computeBaryCenter() {
for (int d=0; d<nrDims; d++) baryCenter[d] = 0.0;
double weightSum = 0.0;
for (Node node : nodes) {
weightSum += node.weight;
double[] position = positions.get(node);
for (int d=0; d<nrDims; d++) baryCenter[d] += node.weight * position[d];
}
if (weightSum > 0.0) {
for (int d=0; d<nrDims; d++) baryCenter[d] /= weightSum;
}
}
/**
* Computes and outputs some statistics.
*/
private void printStatistics() {
System.out.println("Number of nodes: " + nodes.size());
double attrSum = 0.0;
for (Node node : nodes) {
for (Edge edge : attrEdges.get(node)) {
attrSum += edge.weight;
}
}
System.out.println("Overall attraction: " + attrSum);
double meanAttrEnergy = 0.0;
for (Node node : nodes) meanAttrEnergy += getAttractionEnergy(node);
meanAttrEnergy = (attrExponent == 0.0)
? Math.exp(meanAttrEnergy / attrSum)
: Math.pow(meanAttrEnergy * attrExponent / attrSum, 1.0 / attrExponent);
System.out.println("Weighted mean of attraction energy: " + meanAttrEnergy);
double repuSum = 0.0, repuSquareSum = 0.0;
for (Node node : nodes) {
repuSum += node.weight;
repuSquareSum += node.weight * node.weight;
}
repuSum = repuSum*repuSum - repuSquareSum;
System.out.println("Overall repulsion: " + repuSum);
double meanRepuEnergy = 0.0;
for (Node node : nodes) meanRepuEnergy += getRepulsionEnergy(node);
meanRepuEnergy /= repuFactor;
meanRepuEnergy = (repuExponent == 0.0)
? Math.exp(-meanRepuEnergy / repuSum)
: Math.pow(-meanRepuEnergy * repuExponent / repuSum, 1.0 / repuExponent);
System.out.println("Weighted mean of repulsion energy: " + meanRepuEnergy);
System.out.println("Mean attraction / mean repulsion: " + meanAttrEnergy / meanRepuEnergy);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -