/*******************************************************************************
* Copyright 2012 University of Southern California
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This code was developed by the Information Integration Group as part
* of the Karma project at the Information Sciences Institute of the
* University of Southern California. For more information, publications,
* and related projects, please see: http://www.isi.edu/integration
******************************************************************************/
package edu.isi.karma.modeling.research.approach1;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import org.jgrapht.graph.DirectedWeightedMultigraph;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import edu.isi.karma.rep.alignment.Link;
import edu.isi.karma.rep.alignment.Node;
public class RankedModel implements Comparable<RankedModel>{
private class Coherence implements Comparable<Coherence>{
private int linkCount;
private int patternFrequency;
public Coherence(int linkCount,int patternFrequency) {
this.linkCount = linkCount;
this.patternFrequency = patternFrequency;
}
@Override
public int compareTo(Coherence c) {
if (c == null)
return 1;
else if (this.linkCount > c.linkCount)
return 1;
else if (this.linkCount < c.linkCount)
return -1;
else if (this.patternFrequency > c.patternFrequency)
return 1;
else if (this.patternFrequency < c.patternFrequency)
return -1;
else
return 0;
}
}
private DirectedWeightedMultigraph<Node, Link> model;
private double cost;
private List<Coherence> coherence;
private SteinerNodes steinerNodes;
// the number of patterns shared among all the links
// private int frequency;
// private List<Integer> cohesion;
public RankedModel(DirectedWeightedMultigraph<Node, Link> model, SteinerNodes steinerNodes) {
this.model = model;
this.steinerNodes = steinerNodes;
if (this.model != null && this.model.edgeSet().size() > 0) {
this.cost = this.computeCost();
// this.frequency = this.computeFrequency();
// this.cohesion = this.computeCohesion();
this.coherence = this.computeCoherence();
}
}
public RankedModel(DirectedWeightedMultigraph<Node, Link> model) {
this.model = model;
if (this.model != null && this.model.edgeSet().size() > 0) {
this.cost = this.computeCost();
// this.frequency = this.computeFrequency();
// this.cohesion = this.computeCohesion();
this.coherence = this.computeCoherence();
}
}
public double getCost() {
return cost;
}
public double getScore() {
return this.steinerNodes.getScore();
}
public SteinerNodes getSteinerNodes() {
return this.steinerNodes;
}
public String getEdgeCoherenceString() {
String s = "";
for (Coherence c : this.coherence)
s += "(" + c.linkCount + "," + c.patternFrequency + ")";
return s;
}
private static double roundTwoDecimals(double d) {
DecimalFormat twoDForm = new DecimalFormat("#.##");
return Double.valueOf(twoDForm.format(d));
}
public String getDescription() {
String s = "";
s += "coherence: ";
for (CoherenceItem ci : this.getSteinerNodes().getCoherenceList())
s += "(" + ci.getX() + "," + ci.getY() + ")";
s += " --- ";
s += "score: " + this.steinerNodes.getScore();
s += " --- ";
s += "cost: " + roundTwoDecimals(this.getCost());
return s;
}
// public int getFrequency() {
// return frequency;
// }
//
// public String getCohesionString() {
// String s = "";
// for (Integer i : this.cohesion)
// s += String.valueOf(i);
// return s;
// }
public DirectedWeightedMultigraph<Node, Link> getModel() {
return model;
}
private double computeCost() {
double cost = 0.0;
for (Link e : model.edgeSet()) {
cost += e.getWeight();
}
return cost;
}
// private int computeFrequency() {
//
// Set<String> commonPatterns = null;
//
// if (model == null || model.edgeSet().size() == 0)
// return 0;
//
// boolean firstVisit = true;
//
// for (Link e : model.edgeSet()) {
//
// if (firstVisit) {
// commonPatterns = e.getPatternIds();
// firstVisit = false;
// }
// else
// commonPatterns = Sets.intersection(e.getPatternIds(), commonPatterns);
//
// if (commonPatterns.size() == 0)
// return 0;
// }
//
// return commonPatterns.size();
// }
private List<Coherence> computeCoherence() {
if (model == null || model.edgeSet().size() == 0)
return null;
List<Coherence> coherence = new ArrayList<Coherence>();
List<String> patternIds = new ArrayList<String>();
HashMap<String, HashSet<String>> patternToLinks = new HashMap<String, HashSet<String>>();
HashMap<String, Integer> patternToFrequency = new HashMap<String, Integer>();
for (Link e : model.edgeSet())
for (String s : e.getPatternIds()) {
if (!patternIds.contains(s))
patternIds.add(s);
patternToFrequency.put(s, 1);
HashSet<String> links = patternToLinks.get(s);
if (links == null) {
links = new HashSet<String>();
patternToLinks.put(s, links);
}
links.add(e.getId());
}
int size1, size2, size3;
String p1, p2;
for (int i = 0; i < patternIds.size() - 1; i++) {
p1 = patternIds.get(i);
if (!patternToLinks.containsKey(p1)) continue;
size1 = patternToLinks.get(p1).size();
for (int j = i + 1; j < patternIds.size(); j++) {
p2 = patternIds.get(j);
if (!patternToLinks.containsKey(p1)) continue;
if (!patternToLinks.containsKey(p2)) continue;
size2 = patternToLinks.get(p2).size();
Set<String> shared = Sets.intersection(patternToLinks.get(p1), patternToLinks.get(p2));
if (shared == null) continue;
size3 = shared.size();
if (size3 < size2 && size3 < size1) continue;
else if (size3 == size1 && size3 < size2) {
patternToLinks.remove(p1);
patternToFrequency.remove(p1);
} else if (size3 == size2 && size3 < size1) {
patternToLinks.remove(p2);
patternToFrequency.remove(p2);
} else if (size3 == size1 && size3 == size2) {
Integer count = patternToFrequency.get(p1);
patternToFrequency.put(p1, count + 1);
patternToLinks.remove(p2);
patternToFrequency.remove(p2);
}
}
}
for (Entry<String, HashSet<String>> entry : patternToLinks.entrySet()) {
Coherence c = new Coherence(entry.getValue().size(), patternToFrequency.get(entry.getKey()).intValue());
coherence.add(c);
}
Collections.sort(coherence);
coherence = Lists.reverse(coherence);
return coherence;
}
// private List<Integer> computeCohesion() {
//
// if (model == null || model.edgeSet().size() == 0)
// return null;
//
// List<String> patternIds = new ArrayList<String>();
//
// for (Link e : model.edgeSet())
// for (String s : e.getPatternIds())
// patternIds.add(s);
//
// Function<String, String> stringEqualiy = new Function<String, String>() {
// @Override public String apply(final String s) {
// return s;
// }
// };
//
// Multimap<String, String> index =
// Multimaps.index(patternIds, stringEqualiy);
//
// List<Integer> frequencies = new ArrayList<Integer>();
// for (String s : index.keySet()) {
// frequencies.add(index.get(s).size());
// }
//
// Collections.sort(frequencies);
// frequencies = Lists.reverse(frequencies);
// return frequencies;
// }
// private int compareCohesions(List<Integer> c1, List<Integer> c2) {
// if (c1 == null || c2 == null)
// return 0;
//
// for (int i = 0; i < c1.size(); i++) {
// if (i < c2.size()) {
// if (c1.get(i) > c2.get(i)) return 1;
// else if (c1.get(i) < c2.get(i)) return -1;
// }
// }
// if (c1.size() < c2.size())
// return 1;
// else if (c2.size() < c1.size())
// return -1;
// else
// return 0;
// }
// private int compareCoherence(List<Coherence> c1, List<Coherence> c2) {
// if (c1 == null || c2 == null)
// return 0;
//
// for (int i = 0; i < c1.size(); i++) {
// if (i < c2.size()) {
// if (c1.get(i).compareTo(c2.get(i)) > 0) return 1;
// else if (c1.get(i).compareTo(c2.get(i)) < 0) return -1;
// }
// }
// if (c1.size() < c2.size())
// return 1;
// else if (c2.size() < c1.size())
// return -1;
// else
// return 0;
// }
@Override
public int compareTo(RankedModel m) {
double score1 = this.getSteinerNodes().getScore();
double score2 = m.getSteinerNodes().getScore();
if (score1 > score2)
return -1;
else if (score1 < score2)
return 1;
else if (this.cost < m.cost)
return -1;
else if (m.cost < this.cost)
return 1;
else {
return 0;
}
}
// @Override
// public int compareTo(RankedModel m) {
//
// int k = compareCoherence(this.coherence, m.coherence);
// if (k > 0)
// return -1;
// else if (k < 0)
// return 1;
// else if (this.cost < m.cost)
// return -1;
// else if (m.cost < this.cost)
// return 1;
// else {
// return 0;
// }
// }
// @Override
// public int compareTo(RankedModel m) {
//
// if (this.cost < m.cost)
// return -1;
// else if (m.cost < this.cost)
// return 1;
// else {
// int k = compareCoherence(this.coherence, m.coherence);
// if (k > 0)
// return -1;
// else if (k < 0)
// return 1;
// else if (this.cost < m.cost)
// return -1;
// else if (m.cost < this.cost)
// return 1;
// else {
// return 0;
// }
// }
// }
// @Override
// public int compareTo(RankedModel m) {
//
// if (this.frequency > m.getFrequency())
// return -1;
// else if (m.getFrequency() > this.frequency)
// return 1;
// else {
// int k = compareCohesions(this.cohesion, m.cohesion);
// if (k > 0)
// return -1;
// else if (k < 0)
// return 1;
// else if (this.cost < m.cost)
// return -1;
// else if (m.cost < this.cost)
// return 1;
// else {
// return 0;
// }
// }
// }
}