package graphmatcher.matcher.komatcher;
import graphmatcher.graph.Edge;
import graphmatcher.graph.Graph;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.Vector;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
public class Candidate implements Comparable<Candidate> {
private static Logger logger = Logger.getLogger(Candidate.class);
private Graph pattern, template;
private LinkedHashMap<Integer, Vector<Integer>> matching;
/**
* SubMatching: Kante a matcht auf b => Teilkanten von a matchen auf
* Teilkanten von b
*/
private LinkedHashMap<Integer, Vector<Integer>> subMatching;
private HashSet<Edge> matchedEdges;
private boolean[][] match1on1;
private int votes;
private double fitnessCache = -1;
static {
logger.setLevel(Level.OFF);
}
private Candidate(Graph pattern, Graph template, boolean[][] match1on1) {
this.pattern = pattern;
this.template = template;
matching = new LinkedHashMap<Integer, Vector<Integer>>();
subMatching = new LinkedHashMap<Integer, Vector<Integer>>();
matchedEdges = new HashSet<Edge>();
this.match1on1 = match1on1;
votes = 0;
}
public Candidate(Graph pattern, Graph template, int patternEdgeID, int templateEdgeID,
boolean[][] match1on1) {
this(pattern, template, match1on1);
Vector<Integer> vector = new Vector<Integer>();
vector.add(templateEdgeID);
matching.put(patternEdgeID, vector);
subMatching = computeSubMatching(pattern, template, patternEdgeID, templateEdgeID, match1on1);
}
public String toString() {
// NumberFormat format = NumberFormat.getNumberInstance();
// format.setMaximumFractionDigits(2);
// format.setMinimumFractionDigits(2);
// TODO: getFitness ist SEHR teuer!
// String result = "Candidate (" + format.format(getFitness()) + "): ";
String result = "Candidate: ";
Set<Integer> keys = matching.keySet();
Iterator<Integer> iter = keys.iterator();
while (iter.hasNext()) {
int patternEdgeID = iter.next();
Edge patternEdge = pattern.virtualEdges()[patternEdgeID];
result += patternEdge + "->(";
Vector<Integer> templateEdgeIDs = matching.get(patternEdgeID);
for (int i = 0; i < templateEdgeIDs.size(); i++) {
Edge templateEdge = template.virtualEdges()[templateEdgeIDs.get(i)];
result += templateEdge;
if (i < templateEdgeIDs.size() - 1) {
result += "|";
}
}
result += ")";
if (iter.hasNext()) {
result += " -/- ";
}
}
// for (Integer key : keys) {
// Edge patternEdge = pattern.virtualEdges()[key];
// result+= patternEdge+"->(";
// for (Integer templateEdgeID: matching.get(key)) {
// Edge templateEdge = template.virtualEdges()[templateEdgeID];
// result+=templateEdge+" | ";
// }
// result += ") / ";
// }
// result = result.substring(0, result.length() - 2);
return result;
}
public LinkedHashMap<Integer, Vector<Integer>> getMatching() {
return matching;
}
@Deprecated
public double getFitness() {
if (matching.size() < 2) {
return 0;
}
if (fitnessCache > -1) {
return fitnessCache;
}
double fitness = 0;
int counter = 0;
Vector<Integer> patternEdgeIDs = new Vector<Integer>(matching.keySet());
double minRating = Double.MAX_VALUE;
for (int i = 0; i < patternEdgeIDs.size() - 1; i++) {
int patternEdgeID1 = patternEdgeIDs.get(i);
int templateEdgeID1 = matching.get(patternEdgeID1).firstElement();
for (int j = i + 1; j < patternEdgeIDs.size(); j++) {
int patternEdgeID2 = patternEdgeIDs.get(j);
int templateEdgeID2 = matching.get(patternEdgeID2).firstElement();
double rating = EdgeRater.rateMatchingPair(pattern, template, patternEdgeID1,
templateEdgeID1, patternEdgeID2, templateEdgeID2, match1on1);
if (rating < minRating) {
minRating = rating;
}
fitness += rating;
counter++;
}
}
return minRating;
}
/**
* @deprecated
* @return
*/
public int getVotes() {
return votes;
}
/**
* @deprecated
*/
public void addVote() {
votes++;
}
public static Candidate mergeCandidates(Graph pattern, Graph template, Candidate candidate1,
Candidate candidate2, double minimumRatingForGoodPair) {
logger.info("<<<CandidateMerge>>>");
logger.info("Candidate 1: " + candidate1);
logger.info("Candidate 2: " + candidate2);
Candidate result = new Candidate(pattern, template, candidate1.match1on1);
LinkedHashMap<Integer, Vector<Integer>> matching1 = candidate1.matching;
LinkedHashMap<Integer, Vector<Integer>> matching2 = candidate2.matching;
Vector<Integer> pEdges1 = new Vector<Integer>(matching1.keySet());
for (int i = 0; i < pEdges1.size(); i++) {
int pEdgeID1 = pEdges1.get(i);
Vector<Integer> tEdges1 = matching1.get(pEdgeID1);
for (int ii = 0; ii < tEdges1.size(); ii++) {
int tEdgeID1 = matching1.get(pEdgeID1).get(ii);
Vector<Integer> pEdges2 = new Vector<Integer>(matching2.keySet());
for (int j = 0; j < pEdges2.size(); j++) {
int pEdgeID2 = pEdges2.get(j);
if (candidate1.isInSubMatching(pEdgeID2)) {
break;
}
int tEdgeID2 = matching2.get(pEdgeID2).firstElement();
Edge pEdge1 = pattern.virtualEdges()[pEdgeID1];
// System.out.println("pedge1: " + pEdge1);
// for (Edge subEdge : pEdge1.subEdges) {
// System.out.println(subEdge);
// }
Edge tEdge1 = template.virtualEdges()[tEdgeID1];
Edge pEdge2 = pattern.virtualEdges()[pEdgeID2];
// System.out.println("pedge2: " + pEdge2);
// for (Edge subEdge : pEdge2.subEdges) {
// System.out.println(subEdge);
// }
Edge tEdge2 = template.virtualEdges()[tEdgeID2];
double rating = EdgeRater.rateMatchingPair(pattern, template, pEdgeID1, tEdgeID1,
pEdgeID2, tEdgeID2, candidate1.match1on1);
logger.debug(pEdge1 + "->" + tEdge1 + " <---> " + pEdge2 + "->" + tEdge2 + " Rating: "
+ rating);
if (rating < minimumRatingForGoodPair) {
logger.debug("Kein Ergebnis beim CandidateMerge");
return null;
}
if (rating >= minimumRatingForGoodPair) {
result.matching.put(pEdgeID1, matching1.get(pEdgeID1));
result.matching.put(pEdgeID2, matching2.get(pEdgeID2));
// result.matching.putAll(matching1);
// result.matching.putAll(matching2);
// return result;
}
}
}
}
result.matchedEdges.addAll(candidate1.matchedEdges);
result.matchedEdges.addAll(candidate2.matchedEdges);
result.subMatching.putAll(candidate1.subMatching);
result.subMatching.putAll(candidate2.subMatching);
logger.info("Ergebnis beim CandidateMerge:\n\t" + result);
return result;
}
public static Candidate simpleMergeCandidates(Graph pattern, Graph template, Candidate candidate1,
Candidate candidate2) {
Candidate result = new Candidate(pattern, template, candidate1.match1on1);
result.matching.putAll(candidate1.matching);
result.matching.putAll(candidate2.matching);
result.matchedEdges.addAll(candidate1.matchedEdges);
result.matchedEdges.addAll(candidate2.matchedEdges);
return result;
}
public static boolean similarCandidates(Graph pattern, Graph template, Candidate candidate1,
Candidate candidate2, boolean[][] match1On1) {
if (candidate1.matching.size() > 1 || candidate2.matching.size() > 1) {
throw new IllegalStateException(
"�hnliche Kandidaten d�rfen nur nach der Initialisierung gemerged werden");
}
Set<Integer> patternEdgeIDs = candidate1.matching.keySet();
Iterator<Integer> iter = patternEdgeIDs.iterator();
while (iter.hasNext()) {
int patternEdgeID = iter.next();
Vector<Integer> templateEdges1 = candidate1.matching.get(patternEdgeID);
Vector<Integer> templateEdges2 = candidate2.matching.get(patternEdgeID);
int edgeID1 = templateEdges1.firstElement();
int edgeID2 = templateEdges2.firstElement();
double rating = EdgeRater.rateMatchingPair(pattern, template, patternEdgeID, edgeID1,
patternEdgeID, edgeID2, match1On1);
if (rating < 0.9) {
return false;
}
}
return true;
}
public static Candidate mergeSimilarCandidates(Candidate candidate1, Candidate candidate2) {
Candidate result = new Candidate(candidate1.pattern, candidate1.template, candidate1.match1on1);
// FIXME: vereinfachen?
result.matching = candidate1.matching;
Set<Integer> patternEdgeIDs = result.matching.keySet();
Iterator<Integer> iter = patternEdgeIDs.iterator();
while (iter.hasNext()) {
int patternEdgeID = iter.next();
Vector<Integer> templateEdgeIDs1 = result.matching.get(patternEdgeID);
Vector<Integer> templateEdgeIDs2 = candidate2.matching.get(patternEdgeID);
templateEdgeIDs1.addAll(templateEdgeIDs2);
}
result.matchedEdges.addAll(candidate1.matchedEdges);
result.matchedEdges.addAll(candidate2.matchedEdges);
result.subMatching.putAll(candidate1.subMatching);
result.subMatching.putAll(candidate2.subMatching);
return result;
}
public static double rateCandidates(Graph pattern, Graph template, Candidate candidate1,
Candidate candidate2) {
double rating = 0;
int counter = 0;
LinkedHashMap<Integer, Vector<Integer>> matching1 = candidate1.matching;
LinkedHashMap<Integer, Vector<Integer>> matching2 = candidate2.matching;
Vector<Integer> pEdges1 = new Vector<Integer>(matching1.keySet());
for (int i = 0; i < pEdges1.size(); i++) {
int pEdge1 = pEdges1.get(i);
int tEdge1 = matching1.get(pEdge1).firstElement();
Vector<Integer> pEdges2 = new Vector<Integer>(matching2.keySet());
for (int j = 0; j < pEdges2.size(); j++) {
int pEdge2 = pEdges2.get(j);
int tEdge2 = matching2.get(pEdge2).firstElement();
counter++;
rating += EdgeRater.rateMatchingPair(pattern, template, pEdge1, tEdge1, pEdge2, tEdge2,
candidate1.match1on1);
}
}
return rating / counter;
}
private LinkedHashMap<Integer, Vector<Integer>> computeSubMatching(Graph pattern, Graph template,
int patternEdgeID, int templateEdgeID, boolean[][] match1on1) {
LinkedHashMap<Integer, Vector<Integer>> result = new LinkedHashMap<Integer, Vector<Integer>>();
Edge patternEdge = pattern.virtualEdges()[patternEdgeID];
matchedEdges.addAll(patternEdge.getOriginalEdges());
// FIXME: submatching ermitteln
// Vector<Edge> patternSubEdges = getAllSubEdges(patternEdge);
// patternSubEdges.remove(patternEdge);
// Edge templateEdge = template.virtualEdges()[templateEdgeID];
// Vector<Edge> templateSubEdges = getAllSubEdges(templateEdge);
// templateSubEdges.remove(templateEdge);
//
// for (Edge edge : patternSubEdges) {
// int edgeID = pattern.getEdgeID(edge.vertex1, edge.vertex2);
// result.put(new Integer(edgeID), new Vector<Integer>());
// }
return result;
}
public boolean isInSubMatching(int patternEdgeID) {
Edge edge = pattern.virtualEdges()[patternEdgeID];
for (Edge subEdge : edge.getOriginalEdges()) {
if (!matchedEdges.contains(subEdge)) {
return false;
}
}
return true;
}
@Override
public int compareTo(Candidate o) {
return this.hashCode() - o.hashCode();
}
}