/**
*
*/
package edu.isi.karma.modeling.research.graphmatching.util;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
import edu.isi.karma.modeling.research.graphmatching.algorithms.HungarianAlgorithm;
/**
* @author riesen
*
*/
public class MatrixGenerator {
/**
* the cource and target graph whereon the cost matrix is built
*/
private Graph source, target;
/**
* the cost function actually employed
*/
private CostFunction cf;
/**
* the matching algorithm for recursive
* edge matchings (hungarian is used in any case!)
*/
private HungarianAlgorithm ha;
/**
* whether or not the cost matrix is logged on the console
*/
private int outputCostMatrix;
/**
* the decimal format for the distances found
*/
private DecimalFormat decFormat;
/**
* constructs a MatrixGenerator
* @param costFunction
* @param outputCostMatrix
*/
public MatrixGenerator(CostFunction costFunction, int outputCostMatrix) {
this.cf = costFunction;
this.ha = new HungarianAlgorithm();
this.outputCostMatrix = outputCostMatrix;
this.decFormat = (DecimalFormat) NumberFormat
.getInstance(Locale.ENGLISH);
this.decFormat.applyPattern("0.00000");
}
/**
* @return the cost matrix for two graphs @param sourceGraph and @param targetGraph
* | |
* | c_i,j | del
* |_________|______
* | |
* | ins | 0
* | |
*
*/
public double[][] getMatrix(Graph sourceGraph, Graph targetGraph) {
this.source = sourceGraph;
this.target = targetGraph;
int sSize = sourceGraph.size();
int tSize = targetGraph.size();
int dim = sSize + tSize;
double[][] matrix = new double[dim][dim];
double[][] edgeMatrix;
Node u;
Node v;
for (int i = 0; i < sSize; i++) {
u = (Node) this.source.get(i);
for (int j = 0; j < tSize; j++) {
v = (Node) this.target.get(j);
double costs = cf.getCost(u, v);
// adjacency information is added to the node costs
edgeMatrix = this.getEdgeMatrix(u, v);
costs += this.ha.hgAlgorithmOnlyCost(edgeMatrix);
matrix[i][j] = costs;
}
}
for (int i = sSize; i < dim; i++) {
for (int j = 0; j < tSize; j++) {
if ((i - sSize) == j) {
v = (Node) this.target.get(j);
double costs = cf.getNodeCosts();
double f = v.getEdges().size();
costs += (f * cf.getEdgeCosts());
matrix[i][j] = costs;
} else {
matrix[i][j] = Double.POSITIVE_INFINITY;
}
}
}
for (int i = 0; i < sSize; i++) {
u = (Node) this.source.get(i);
for (int j = tSize; j < dim; j++) {
if ((j - tSize) == i) {
double costs = cf.getNodeCosts();;
double f = u.getEdges().size();
costs += (f * cf.getEdgeCosts());
matrix[i][j] = costs;
} else {
matrix[i][j] = Double.POSITIVE_INFINITY;
}
}
}
for (int i = sSize; i < dim; i++) {
for (int j = tSize; j < dim; j++) {
matrix[i][j] =0.0;
}
}
if (this.outputCostMatrix==1){
System.out.println("\nThe Cost Matrix:");
for (int k = 0; k < matrix.length; k++){
for (int l = 0; l < matrix[0].length; l++){
if (matrix[k][l] < Double.POSITIVE_INFINITY){
System.out.print(decFormat.format(matrix[k][l])+"\t");
} else {
System.out.print("infty\t");
}
}
System.out.println();
}
}
return matrix;
}
/**
* @return the cost matrix for the edge operations
* between the nodes @param u
* @param v
*/
private double[][] getEdgeMatrix(Node u, Node v) {
int uSize = u.getEdges().size();
int vSize = v.getEdges().size();
int dim = uSize + vSize;
double[][] edgeMatrix = new double[dim][dim];
Edge e_u;
Edge e_v;
for (int i = 0; i < uSize; i++) {
e_u = (Edge) u.getEdges().get(i);
for (int j = 0; j < vSize; j++) {
e_v = (Edge) v.getEdges().get(j);
double costs = cf.getCost(e_u, e_v);
edgeMatrix[i][j] = costs;
}
}
for (int i = uSize; i < dim; i++) {
for (int j = 0; j < vSize; j++) {
// diagonal
if ((i - uSize) == j) {
e_v = (Edge) v.getEdges().get(j);
double costs = cf.getEdgeCosts();
edgeMatrix[i][j] = costs;
} else {
edgeMatrix[i][j] = Double.POSITIVE_INFINITY;
}
}
}
for (int i = 0; i < uSize; i++) {
e_u = (Edge) u.getEdges().get(i);
for (int j = vSize; j < dim; j++) {
// diagonal
if ((j - vSize) == i) {
double costs = cf.getEdgeCosts();
edgeMatrix[i][j] = costs;
} else {
edgeMatrix[i][j] = Double.POSITIVE_INFINITY;
}
}
}
for (int i = uSize; i < dim; i++) {
for (int j = vSize; j < dim; j++) {
edgeMatrix[i][j] = 0.0;
}
}
return edgeMatrix;
}
}