package graphmatcher.matcher.komatcher;
import graphmatcher.graph.Edge;
import graphmatcher.graph.Graph;
import graphmatcher.matcher.MatchingOptions;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.Vector;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
public class CandidateBundle {
private static Logger logger = Logger.getLogger(CandidateBundle.class);
private Graph pattern, template;
private Vector<Candidate> candidates;
private int initialEdgeID;
private boolean[][] match1On1;
private MatchingOptions matchingOptions;
static {
logger.setLevel(Level.OFF);
}
public CandidateBundle(Graph pattern, Graph template, int initialPatternEdgeID, boolean[][] match1On1,
MatchingOptions matchingOptions) {
this.pattern = pattern;
this.template = template;
this.candidates = new Vector<Candidate>();
this.initialEdgeID = initialPatternEdgeID;
this.match1On1 = match1On1;
this.matchingOptions = matchingOptions;
}
public void addCandidate(Candidate candidate) {
candidates.add(candidate);
}
public void removeBadCandidates() {
// System.out.println("removeBadCandidates: ");
// System.out.println("Anzahl = " + candidates.size());
Candidate[] array = candidates.toArray(new Candidate[candidates.size()]);
Arrays.sort(array, new Comparator<Candidate>() {
@Override
public int compare(Candidate o1, Candidate o2) {
if (o1.getMatching().size() > o2.getMatching().size()) {
return -1;
}
if (o1.getMatching().size() < o2.getMatching().size()) {
return 1;
}
return 0;
}
});
candidates = new Vector<Candidate>();
for (int i = 0; i < Math.min(array.length, 10); i++) {
candidates.add(array[i]);
}
// alt:
// int maxSize = 0;
// for (Candidate candidate : candidates) {
// if (candidate.getMatching().size() > maxSize) {
// maxSize = candidate.getMatching().size();
// }
// }
// System.out.println("MaxSize = " + maxSize);
// Iterator<Candidate> candidateIterator = candidates.iterator();
// while (candidateIterator.hasNext()) {
// Candidate next = candidateIterator.next();
// if (next.getMatching().size() < maxSize * 0.75) {
// candidateIterator.remove();
// }
// }
}
public int getSize() {
return candidates.size();
}
/**
* -1, falls Bundle durch Vereinigung entstanden ist
*
* @return
*/
public int getInitialEdgeID() {
return initialEdgeID;
}
public Candidate getBestCandidate() {
int maxVotes = Integer.MIN_VALUE;
Candidate bestCandidate = null;
for (Candidate candidate : candidates) {
if (candidate.getVotes() > maxVotes) {
bestCandidate = candidate;
maxVotes = candidate.getVotes();
}
}
return bestCandidate;
}
public void mergeSimilarCandidates() {
Vector<Candidate> currentCandidates = new Vector<Candidate>(candidates);
Vector<Candidate> newCandidates = new Vector<Candidate>();
while (currentCandidates.size() > 0) {
Candidate candidate = currentCandidates.firstElement();
for (int i = 1; i < currentCandidates.size(); i++) {
Candidate candidate2 = currentCandidates.get(i);
if (Candidate.similarCandidates(pattern, template, candidate, candidate2, match1On1)) {
candidate = Candidate.mergeSimilarCandidates(candidate, candidate2);
currentCandidates.remove(i);
i--;
}
}
newCandidates.add(candidate);
currentCandidates.remove(0);
}
candidates = new Vector<Candidate>(newCandidates);
}
public int[] getEdgeMatching() {
int[] result = new int[pattern.virtualEdges().length];
Arrays.fill(result, -1);
Candidate maxCandidate = candidates.get(0);
int maxSize = maxCandidate.getMatching().size();
for (Candidate candidate : candidates) {
if (candidate.getMatching().size() > maxSize) {
maxCandidate = candidate;
maxSize = maxCandidate.getMatching().size();
}
}
LinkedHashMap<Integer, Vector<Integer>> map = maxCandidate.getMatching();
Set<Integer> patternEdgeIDs = map.keySet();
for (Integer patternEdgeID : patternEdgeIDs) {
Vector<Integer> templateEdgeIDs = map.get(patternEdgeID);
int bestEdgeID = 0;
Edge bestEdge;
double maxRating = -1;
for (Integer templateEdgeID : templateEdgeIDs) {
double rating = EdgeRater.computeInitialEdgeRating(pattern, patternEdgeID.intValue(),
template, templateEdgeID.intValue(), match1On1, matchingOptions);
Edge templateEdge = template.virtualEdges()[templateEdgeID.intValue()];
// double length = DistanceHelper.getLength(templateEdge,
// template);
if (rating > maxRating) {
maxRating = rating;
bestEdge = templateEdge;
bestEdgeID = templateEdgeID.intValue();
}
}
result[patternEdgeID.intValue()] = bestEdgeID;
// result[patternEdgeID.intValue()] = templateEdgeIDs.get(0);
}
return result;
}
/**
* umgewandelt in KNOTENMATCHING!
*
* @param match1on1Array
* @return
*/
public int[] getMatching(boolean[][] match1on1Array) {
LinkedHashMap<Integer, TemplateVertexContainer> vertexMatchingMap = new LinkedHashMap<Integer, TemplateVertexContainer>();
logger.info(candidates.size() + " Kandidaten werden ausgewertet");
for (Candidate candidate : candidates) {
LinkedHashMap<Integer, Vector<Integer>> candidateMatching = candidate.getMatching();
Set<Integer> patternEdges = candidateMatching.keySet();
for (Integer patternEdgeID : patternEdges) {
Edge patternEdge = pattern.virtualEdges()[patternEdgeID];
// TODO: ist das korrekt ;-)
for (Integer templateEdgeID : candidateMatching.get(patternEdgeID)) {
Edge templateEdge = template.virtualEdges()[templateEdgeID];
if (match1on1Array[patternEdgeID][templateEdgeID]) {
put2(vertexMatchingMap, patternEdge.vertex1, templateEdge.vertex1);
put2(vertexMatchingMap, patternEdge.vertex2, templateEdge.vertex2);
} else {
put2(vertexMatchingMap, patternEdge.vertex1, templateEdge.vertex2);
put2(vertexMatchingMap, patternEdge.vertex2, templateEdge.vertex1);
}
}
// int templateEdgeID =
// candidateMatching.get(patternEdgeID).firstElement();
// Edge templateEdge = template.virtualEdges()[templateEdgeID];
//
// if (match1on1Array[patternEdgeID][templateEdgeID]) {
// put2(vertexMatchingMap, patternEdge.vertex1,
// templateEdge.vertex1);
// put2(vertexMatchingMap, patternEdge.vertex2,
// templateEdge.vertex2);
// } else {
// put2(vertexMatchingMap, patternEdge.vertex1,
// templateEdge.vertex2);
// put2(vertexMatchingMap, patternEdge.vertex2,
// templateEdge.vertex1);
// }
}
}
int[] matching = new int[pattern.getNumberOfVertices()];
for (int i = 0; i < matching.length; i++) {
matching[i] = -1;
}
Set<Integer> patternVertices = vertexMatchingMap.keySet();
for (Integer patternVertex : patternVertices) {
matching[patternVertex] = vertexMatchingMap.get(patternVertex).getMostMatchedVertex();
}
return matching;
}
private void put2(LinkedHashMap<Integer, TemplateVertexContainer> map, int patternVertexID,
int templateVertexID) {
if (!map.containsKey(patternVertexID)) {
map.put(patternVertexID, new TemplateVertexContainer());
}
map.get(patternVertexID).addVertex(templateVertexID);
}
public boolean isInSubMatching(int patternEdgeID) {
for (Candidate candidate : candidates) {
if (candidate.isInSubMatching(patternEdgeID)) {
return true;
}
}
return false;
}
public String toString() {
String result = "Bundle (" + getSize() + " Kandidaten):";
for (Candidate candidate : candidates) {
result += "\n\t" + candidate.toString();
}
return result;
}
/*
* statische Methoden
*/
public static CandidateBundle mergeCandidateBundles(Graph pattern, Graph template,
CandidateBundle bundle1, CandidateBundle bundle2, double minimumRatingForGoodPair) {
if (bundle1 == null || bundle2 == null) {
throw new IllegalArgumentException("BundleMerge: ein Bundle ist null");
}
logger.debug("<<<<<<<<<<<<<<<<<<<<<<< Bundle Merge >>>>>>>>>>>>>>>>>>>>>>>>>>>");
logger.debug("Bundle1: " + bundle1);
logger.debug("Bundle2: " + bundle2);
CandidateBundle result = new CandidateBundle(pattern, template, -1, bundle1.match1On1,
bundle1.matchingOptions);
Vector<Candidate> candidates1 = bundle1.candidates;
Vector<Candidate> candidates2 = bundle2.candidates;
Vector<Candidate> unusedCandidates = new Vector<Candidate>();
unusedCandidates.addAll(candidates1);
unusedCandidates.addAll(candidates2);
for (Candidate candidate1 : candidates1) {
for (Candidate candidate2 : candidates2) {
Candidate newCandidate = Candidate.mergeCandidates(pattern, template, candidate1, candidate2,
minimumRatingForGoodPair);
if (newCandidate != null) {
result.candidates.add(newCandidate);
unusedCandidates.remove(candidate1);
unusedCandidates.remove(candidate2);
}
}
}
// wichtig:
if (result.getSize() == 0) {
result.candidates.addAll(unusedCandidates);
}
if (result.getSize() > 20) {
logger.fatal("zuviele Kandidaten: " + result.getSize());
}
logger.debug("Ergebnis: " + result);
return result;
}
/**
* @deprecated nicht mehr benutzt
* @param pattern
* @param template
* @param bundle1
* @param bundle2
*/
public static void voteBestCandidates(Graph pattern, Graph template, CandidateBundle bundle1,
CandidateBundle bundle2) {
// System.out.println("<<< Vote >>>");
// System.out.println("Bundle 1: " + bundle1);
// System.out.println("Bundle 2: " + bundle2);
Vector<Candidate> candidates1 = new Vector<Candidate>(bundle1.candidates);
Vector<Candidate> candidates2 = new Vector<Candidate>(bundle2.candidates);
if (candidates1.size() == 1 && candidates2.size() == 1) {
// System.out.println("quickvote");
candidates1.firstElement().addVote();
candidates2.firstElement().addVote();
return;
}
for (Candidate candidate1 : candidates1) {
for (Candidate candidate2 : candidates2) {
double rating = Candidate.rateCandidates(pattern, template, candidate1, candidate2);
// System.out.println("Kandidat 1: " + candidate1);
// System.out.println("Kandidat 2: " + candidate2);
// System.out.println("Rating: " + rating);
if (rating > 0.7) {
// System.out.println(" -> addVote()");
candidate1.addVote();
candidate2.addVote();
}
}
}
}
/**
* @deprecated
* @param pattern
* @param template
* @param bundle1
* @param bundle2
* @return
*/
public static CandidateBundle mergeVotedCandidates(Graph pattern, Graph template,
CandidateBundle bundle1, CandidateBundle bundle2) {
Candidate candidate1 = bundle1.getBestCandidate();
Candidate candidate2 = bundle2.getBestCandidate();
Candidate newCandidate = Candidate.simpleMergeCandidates(pattern, template, candidate1, candidate2);
CandidateBundle result = new CandidateBundle(pattern, template, -1, bundle1.match1On1,
bundle1.matchingOptions);
result.candidates.add(newCandidate);
return result;
}
private class TemplateVertexContainer {
/*
* key = Template Vertex-ID value = wie oft wurde darauf gematcht
*/
private LinkedHashMap<Integer, Integer> vertexMap = new LinkedHashMap<Integer, Integer>();
public void addVertex(int vertexID) {
if (!vertexMap.containsKey(vertexID)) {
vertexMap.put(vertexID, 0);
}
int count = vertexMap.get(vertexID);
vertexMap.put(vertexID, count + 1);
}
public int getMostMatchedVertex() {
int max = Integer.MIN_VALUE;
int bestVertexID = -1;
Set<Integer> vertexIDs = vertexMap.keySet();
for (int vertexID : vertexIDs) {
if (vertexMap.get(vertexID) > max) {
bestVertexID = vertexID;
max = vertexMap.get(vertexID);
}
}
return bestVertexID;
}
}
}