Package edu.cmu.cs.fusion.relationship

Source Code of edu.cmu.cs.fusion.relationship.RelationshipDelta

package edu.cmu.cs.fusion.relationship;

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import edu.cmu.cs.fusion.Relationship;
import edu.cmu.cs.fusion.ThreeValue;

/**
* Represents the delta lattice. These are the changes to make to the final lattice.
* A bottom value signifies no change.
*
* Notice that this is a mutable class!
* @author ciera
*
*/
public class RelationshipDelta implements Iterable<Entry<Relationship, SevenPointLattice>>
  private Map<Relationship, SevenPointLattice> rels; 
  static private RelationshipDelta FULL_BOT = new RelationshipDelta(true);
 
  static public RelationshipDelta getTrueBottom() {return FULL_BOT;}
 
  /**
   * Creates a new delta where everything maps to bottom.
   */
  private RelationshipDelta(boolean isBot) {
  }

  /**
   * Creates a new delta where everything maps to star.
   */
  public RelationshipDelta() {
    rels = new LinkedHashMap<Relationship, SevenPointLattice>();
  }

  /**
   *
   * @return Number of relationship changes. Does not count alias updates!
   */
  public int numberOfChanges() {
    if (this == FULL_BOT)
      return 0;
    return rels.size();
  }
 
  public SevenPointLattice getValue(Relationship rel) {
    if (this == FULL_BOT)
      return SevenPointLattice.BOT;
    SevenPointLattice val = rels.get(rel);
    if (val == null)
      return SevenPointLattice.STAR;
    else
      return val;
  }

  public void setRelationship(Relationship rel, SevenPointLattice fp) {
    assert (this != FULL_BOT);
    rels.put(rel, fp);
  }

  public RelationshipDelta polarize() {
    if (this == FULL_BOT)
      return this;
    RelationshipDelta polar = new RelationshipDelta();
   
    for (Entry<Relationship, SevenPointLattice> entry : rels.entrySet())
      polar.setRelationship(entry.getKey(), entry.getValue().polarize());
    return polar;
  }

  /**
   * Joins a list of relationship deltas.
   *
   * This algorithm needs to be as fast as possible. The calls to join(RelationshipDelta) are fairly
   * expensive as they have to go through all of the relationships in both deltas to be joined. We can't
   * do any better than linear there. Therefore, this method needs to avoid as many of those calls as possible.
   * It attempts to do so by skipping items in the list that are either fully bot or fully star (the default state).
   * Bots are skipped entirely. All-stars are remembered, and then the result is polarized if any existed.
   * @param deltas
   * @return A new joined relationship delta
   */
  static public RelationshipDelta join(List<RelationshipDelta> deltas) {
    Iterator<RelationshipDelta> itr = deltas.iterator();
    RelationshipDelta joined = new RelationshipDelta();;
    boolean hasAllStars = false, found = false;
   
    assert(!deltas.isEmpty());
   
    RelationshipDelta first = null;
   
    //find the first one that isn't either a bot or an all-stars
    while (itr.hasNext() && !found) {
       first = itr.next()
       found = first != FULL_BOT && !first.rels.isEmpty();
       hasAllStars = hasAllStars || (first != FULL_BOT && first.rels.isEmpty());
    }

    if (!found && hasAllStars)
      return joined;
    else if (!found && !hasAllStars)
        return FULL_BOT; 
    else
      joined.rels = new LinkedHashMap<Relationship, SevenPointLattice>(first.rels);
   
    while (itr.hasNext()) {
      RelationshipDelta next = itr.next();
      if (next == FULL_BOT) //bot case, ignore everything
        continue;
      if (next.rels.isEmpty()) //top case, polarize at the end.
        hasAllStars = true;
      else
        joined.join(next);
    }
   
    if (hasAllStars) {
      for (Entry<Relationship, SevenPointLattice> entry : joined.rels.entrySet())
        entry.setValue(entry.getValue().polarize());
    }

    return joined;
  }
 
  static public RelationshipDelta joinAlt(List<RelationshipDelta> deltas) {
    Iterator<RelationshipDelta> itr = deltas.iterator();
    RelationshipDelta joined = new RelationshipDelta();;
    boolean hasChanges = false, foundStar = false;
   
    assert(!deltas.isEmpty());
   
    RelationshipDelta first = null;   
    while (itr.hasNext() && !hasChanges) {
      first = itr.next();
      if (first != FULL_BOT) {
        hasChanges = !first.rels.isEmpty();
        foundStar = true;
      }
    }
   
    if (hasChanges) {
      joined.rels = new LinkedHashMap<Relationship, SevenPointLattice>(first.rels);
    }
    else
      return foundStar ? joined : FULL_BOT;
   
    while (itr.hasNext()) {
      RelationshipDelta next = itr.next();
      if (next != FULL_BOT && !next.rels.isEmpty()) {
        joined.joinAlt(next);
        hasChanges = true;
      }
    }
    return hasChanges ? joined : FULL_BOT;
  }


 
  /**
   * This and other cannot be a full bot
   * @param other
   */
  private void join(RelationshipDelta other) {
    Iterator<Entry<Relationship, SevenPointLattice>> itr = rels.entrySet().iterator();   
    while (itr.hasNext()) {
      Entry<Relationship, SevenPointLattice> entry = itr.next();
      entry.setValue(entry.getValue().join(other.getValue(entry.getKey())));
    }
   
    itr = other.rels.entrySet().iterator();   
    while (itr.hasNext()) {
      Entry<Relationship, SevenPointLattice> entry = itr.next();
      //if we don't have this relationship, then it must be star. Save the cost
      //of trying to find it again. Hashing is expensive!
      if (!rels.containsKey(entry.getKey()))
        setRelationship(entry.getKey(), entry.getValue().join(SevenPointLattice.STAR));
    }
  }

   
  private void joinAlt(RelationshipDelta other) {
    Iterator<Entry<Relationship, SevenPointLattice>> itr = rels.entrySet().iterator();   
    while (itr.hasNext()) {
      Entry<Relationship, SevenPointLattice> entry = itr.next();
      entry.setValue(entry.getValue().joinAlt(other.getValue(entry.getKey())));
    }
   
    itr = other.rels.entrySet().iterator();   
    while (itr.hasNext()) {
      Entry<Relationship, SevenPointLattice> entry = itr.next();
      //if we don't have this relationship, then it must be star. Save the cost
      //of trying to find it again. Hashing is expensive!
      if (!rels.containsKey(entry.getKey()))
        setRelationship(entry.getKey(), entry.getValue().joinAlt(SevenPointLattice.STAR));
    }
  }

  /*
   * Can't call this on the bottom delta
   */
  public void override(RelationshipDelta makeEffects) {
    Set<Relationship> combinedRels = new HashSet<Relationship>(rels.keySet());
    combinedRels.addAll(makeEffects.rels.keySet());
   
    for (Relationship rel : combinedRels) {
      SevenPointLattice myVal = getValue(rel);
      SevenPointLattice otherVal = makeEffects.getValue(rel);
      setRelationship(rel, myVal.override(otherVal));
    }
  }

  /*
   * Can't call this on the bottom delta
   */
  public boolean isStrictlyMorePrecise(RelationshipContext context) {
    boolean strictlyMore = false;
    if (rels.isEmpty())
      return false;
    for (Entry<Relationship, SevenPointLattice> entry : rels.entrySet()) {
      ThreeValue contextVal = context.getRelationship(entry.getKey());
      //all most be more precise or equal to
      if (!entry.getValue().isAtLeastAsPrecise(contextVal))
        return false;
      //and one must be more precise
      if (contextVal == ThreeValue.UNKNOWN && (entry.getValue() == SevenPointLattice.TRU || entry.getValue() == SevenPointLattice.FAL))
        strictlyMore = true;
    }
   
    return strictlyMore;
  }
 
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result
        + ((rels == null) ? 0 : rels.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    final RelationshipDelta other = (RelationshipDelta) obj;
    if (rels == null) {
      if (other.rels != null)
        return false;
    } else if (!rels.equals(other.rels))
      return false;
    return true;
  }

 
  public String toString() {
    if (this == FULL_BOT)
      return "<BOTTOM>";
   
    String str = "<";
   
    for (Entry<Relationship, SevenPointLattice> entry : rels.entrySet()) {
      str += entry.getKey() + "->" + entry.getValue() + ", ";
    }

    str += ">";
   
    return str;
  }

  public Iterator<Entry<Relationship, SevenPointLattice>> iterator() {
    assert (this != FULL_BOT);
    return rels.entrySet().iterator();
  }
}
TOP

Related Classes of edu.cmu.cs.fusion.relationship.RelationshipDelta

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.