Package urban.transformers

Source Code of urban.transformers.AddPinchesModelTransformer

package urban.transformers;

import static org.apache.commons.collections15.CollectionUtils.collect;
import static org.apache.commons.collections15.CollectionUtils.disjunction;
import static org.apache.commons.collections15.CollectionUtils.intersection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections15.Transformer;

import urban.model.Agent;
import urban.model.Model;
import urban.model.Rule;
import urban.model.Site;
import urban.model.Statement;

/**
* Identifies rules that may have 'pinches' and adds extra rules to represent them.
*
* <p>For example a rule like:<br/>
* <code> A(f~0,x!1,y!2),B(x!1),B(y!2) <-> A(f~1,x!1,y!2),B(x!1),B(y!2) </code><br/>
* will produce an extra rule of the form<br/>
* <code> A(f~0,x!1,y!2),B(x!1,y!2) <-> A(f~1,x!1,y!2),B(x!1,y!2)</code>
*/
public class AddPinchesModelTransformer implements ModelTransformer {

  @Override
  public Model transform(Model in) {
    Model out = new Model();
 
    for(Statement s : in.getLines()){
      out.addStatement(s);
      if (s instanceof Rule){
        out.addStatements(pinches((Rule)s,1));
      }
    }
    return out;
  }

  /**
   * This represents the possibility of bindings going to the same agent instead of different ones
   * @param searchAfter
   * @param name2
   * @param i
   * @param before2
   * @param after2
   * @param sc
   * @return the generated collection of rules that are 'pinches' of the given rule
   */
  protected static Collection<Rule> pinches(Rule rule, int searchAfter) {
    Set<Rule> list = new HashSet<Rule>();
   
    List<Agent> added = new ArrayList<Agent>(rule.getLhs()).subList(searchAfter,rule.getLhs().size());
   
    Collections.sort(added, new Comparator<Agent>() {
      public int compare(Agent o1, Agent o2) {
        return o1.getName().compareTo(o2.getName());
      }
    });
   
    List<List<Agent>> permutations = new ArrayList<List<Agent>>();
    List<Agent> empty = Collections.emptyList();
    addPinchPermutations(permutations, empty , added);
    int i=0;
    for (List<Agent> lc : permutations) {
      List<Agent> btmp = new ArrayList<Agent>(rule.getLhs()).subList(0, searchAfter);
      btmp.addAll(lc);
      List<Agent> atmp = new ArrayList<Agent>(rule.getRhs()).subList(0, searchAfter);
      atmp.addAll(lc);
      try {
        list.add( new Rule(rule.getName() == null ? null : rule.getName()+"."+i,btmp,atmp, rule.isBidirectional(), rule.getForwardRate(), rule.getBackwardRate()));
      } catch (Exception e) {
        e.printStackTrace();
      }
      i++;
    }
    return list;
  }
 
  /**
   * Look for constraints with the same agent, check that they could be merged together
   * if they can then join them and recursively check the rest of the constraints
   * @param permutations
   * @param checked
   * @param added
   */
  private static void addPinchPermutations(List<List<Agent>> permutations, List<Agent> checked, List<Agent> added) {
    Agent previous = null;
    List<Agent> checked2 = new ArrayList<Agent>();
   
    int i=0;
    for (Agent constraint : added) {
      if (previous == null){
        previous = constraint;
      } else {
        if (constraint.getName().equals(previous.getName())){
          if (canBeMerged(previous, constraint)){
            // (A.x, A.z) plus A.x (A.z .. from continuing loop
            List<Agent> todo = new ArrayList<Agent>();
            todo.add(merge(previous,constraint)); // could still be merged further
            todo.addAll(added.subList(i+1, added.size()));

            ArrayList<Agent> tmp = new ArrayList<Agent>();
            tmp.addAll(checked);
            tmp.addAll(checked2);
            addPinchPermutations(permutations, tmp, todo);
            tmp.addAll(todo);
            permutations.add(tmp);
           
            // A.z (A.x ... A.y
            todo = new ArrayList<Agent>();
            todo.add(previous);
            todo.addAll(added.subList(i+1, added.size()));
            tmp = new ArrayList<Agent>();
            tmp.addAll(checked);
            tmp.addAll(checked2);
            tmp.add(constraint);
            addPinchPermutations(permutations, tmp, todo);
          }
        }
        checked2.add(previous);
        previous = constraint;
      }
      i++;
    }
  }
  private static Agent merge(Agent previous, Agent constraint) {
    Set<Site> set = new HashSet<Site>();
    set.addAll(previous.getSites());
    set.addAll(constraint.getSites());
    return new Agent(previous.getName(), set);
  }
 
  private static boolean canBeMerged(Agent previous, Agent constraint) {
    Collection<Site> theSame = intersection(previous.getSites(), constraint.getSites());
   
    return Collections.disjoint(
    collect(disjunction(previous.getSites(), theSame), toName),
    collect(disjunction(constraint.getSites(), theSame), toName));
  }

  static Transformer<Site,String> toName = new Transformer<Site,String>(){

    @Override
    public String transform(Site arg0) {
      return arg0.getName();
    }
   
  };
}
TOP

Related Classes of urban.transformers.AddPinchesModelTransformer

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.