/* * Ivory: A Hadoop toolkit for web-scale information retrieval * * 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. */ package ivory.smrf.model; import ivory.core.ConfigurationException; import ivory.smrf.model.potential.PotentialFunction; import java.util.Comparator; import java.util.List; import com.google.common.base.Preconditions; /** * A clique in a MRF. * * @author Don Metzler * @author Lidan Wang */ public class Clique { public static enum Type { Document, Term, Ordered, Unordered } private final List<GraphNode> nodes; // Nodes associated with this clique. private final PotentialFunction potential; // Potential function associated with this clique. private final Parameter param; // Parameter associated with this clique. private final boolean isDocDependent; // Note: User must keep track of this! private float combinedWeight; // combined weight = parameter weight * clique importance private float importance; // Query-dependent clique importance. private Type type; // Clique type. private String concept; // Textual representation of the term nodes in this clique. public Clique(List<GraphNode> nodes, PotentialFunction f, Parameter weight) { this(nodes, f, weight, 1.0f, null, true); } public Clique(List<GraphNode> nodes, PotentialFunction f, Parameter param, float importance, Type type, boolean docDependent) { this.nodes = Preconditions.checkNotNull(nodes); this.param = Preconditions.checkNotNull(param); this.potential = Preconditions.checkNotNull(f); this.isDocDependent = docDependent; this.importance = importance; this.combinedWeight = param.getWeight() * importance; this.type = type; this.concept = generateConcept(); } private String generateConcept() { StringBuilder sb = new StringBuilder(); for (GraphNode n : nodes) { if (n.getType() == GraphNode.Type.TERM) { sb.append(((TermNode) n).getTerm()).append(" "); } } return sb.toString().trim(); } /** * Initializes this clique. */ public void initialize(GlobalEvidence globalEvidence) throws ConfigurationException { Preconditions.checkNotNull(globalEvidence); this.potential.initialize(nodes, globalEvidence); } /** * Returns the potential of this clique. */ public float getPotential() { return potential.computePotential(); } /** * Returns the potential function associated with this clique. */ public PotentialFunction getPotentialFunction() { return potential; } /** * Returns the parameter associated with this clique. */ public Parameter getParameter() { return param; } /** * Sets the parameter name. */ public void setParameterName(String name) { this.param.setName(name); } /** * Sets the parameter weight. */ public void setParameterWeight(float weight) { this.param.setWeight(weight); this.combinedWeight = weight * importance; } /** * Returns the weight associated with this clique */ public float getWeight() { return combinedWeight; } /** * Returns the clique-dependent importance. */ public float getImportance() { return importance; } /** * Sets the clique-dependent importance. */ public void setImportance(float w) { this.importance = w; this.combinedWeight = param.getWeight() * w; } /** * Returns a textual representation of the term nodes in this clique. */ public String getConcept() { return concept; } /** * Returns the clique type. */ public Type getType() { return type; } /** * Sets the clique type. */ public void setType(Type type) { this.type = type; } /** * Returns nodes in this clique. */ public List<GraphNode> getNodes() { return nodes; } /** * Returns whether or not this clique is document dependent. */ public boolean isDocDependent() { return isDocDependent; } /** * Returns the next candidate document. */ public int getNextCandidate() { return this.potential.getNextCandidate(); } /** * Returns the max score. */ public float getMaxScore() { if (combinedWeight == 0.0) { return 0.0f; } else if (combinedWeight < 0.0) { return combinedWeight * potential.getMinScore(); } else { return combinedWeight * potential.getMaxScore(); } } /** * Sets the next candidate for evaluation. */ public void setNextCandidate(int docid) { this.potential.setNextCandidate(docid); } @Override public String toString() { return toString(false); } public String toString(boolean verbose) { StringBuilder s = new StringBuilder(); s.append("<clique type=\"").append(type).append("\">"); if (verbose) { s.append("<docdependent>").append(isDocDependent).append("</docdependent>"); s.append("<weight>").append(combinedWeight).append("</weight>"); s.append(potential.toString()); s.append("<maxscore>").append(potential.getMaxScore()).append("</maxscore>"); } else { s.append("<terms>").append(getConcept()).append("</terms>"); } s.append("</clique>"); return s.toString(); } /** * Comparator based on the max score of a clique. */ public static class MaxScoreComparator implements Comparator<Clique> { public int compare(Clique a, Clique b) { double maxScoreA = a.getMaxScore(); double maxScoreB = b.getMaxScore(); if (maxScoreA == maxScoreB) { return 0; } else if (maxScoreA < maxScoreB) { return 1; } else { return -1; } } } }