Package ai.domain.boxes

Source Code of ai.domain.boxes.IntegerBoxesHelper

package ai.domain.boxes;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import ai.common.CollectionUtils;
import ai.common.CollectionUtils.Predicate;
import ai.common.Pair;
import ai.domain.Variable;
import ai.domain.generic.NonRelationalDomain;
import ai.domain.interval.Interval;
import ai.domain.interval.IntervalValue;

public class IntegerBoxesHelper {
  static abstract class GenericOperation {
    protected abstract ArrayList<SequencePair> zeroCase(ArrayList<SequencePair> left, ArrayList<SequencePair> right);

    private static double getNextValue(int idx, ArrayList<SequencePair> data) {
      if (idx>=data.size())
        return Double.POSITIVE_INFINITY;
      return data.get(idx).key;
    }
   
    private ArrayList<SequencePair> recursiveCompute(ArrayList<SequencePair> left,
        ArrayList<SequencePair> right, int varIdx) {
      //here 0 dimensional version??
      if (left == null || right == null || varIdx == 0)
        return zeroCase(left, right);

      ArrayList<SequencePair> currentLeftValue = null;
      ArrayList<SequencePair> currentRightValue = null;
      ArrayList<SequencePair> lastAddedValue = null; // normalization here
      int leftIdx = -1;
      int rightIdx = -1;
      ArrayList<SequencePair> result = new ArrayList<SequencePair>();
      while(true) {
        if (leftIdx == left.size()-1 && rightIdx == right.size()-1)
          break;
        double nextLeftKey = getNextValue(leftIdx+1, left);
        double nextRightKey = getNextValue(rightIdx+1, right);
        if (nextLeftKey <= nextRightKey) {
          leftIdx += 1;
          currentLeftValue = left.get(leftIdx).value;
        }
        if (nextRightKey <= nextLeftKey) {
          rightIdx += 1;
          currentRightValue = right.get(rightIdx).value;       
        }
        //compute value
        double key = Math.min(nextLeftKey, nextRightKey);
        ArrayList<SequencePair> val = recursiveCompute(currentLeftValue, currentRightValue, varIdx-1);
        //normalization
        if (!IntegerBoxesHelper.equals(lastAddedValue, val)) {
          result.add(new SequencePair(key, val));
          lastAddedValue = val;
        }
      }
      return (result.size() == 0) ? null : result;
    }
   
    public ArrayList<SequencePair> apply(ArrayList<SequencePair> left, ArrayList<SequencePair> right, int varCount) {
      return recursiveCompute(left, right, varCount);
    }
  }
 
 
  private static class JoinOperation extends GenericOperation {
    @Override
    protected ArrayList<SequencePair> zeroCase(ArrayList<SequencePair> left,
        ArrayList<SequencePair> right) {
      return (left == null) ? right : left;
    }
  }
 

  private static class MeetOperation extends GenericOperation {

    @Override
    protected ArrayList<SequencePair> zeroCase(ArrayList<SequencePair> left,
        ArrayList<SequencePair> right) {
      return (left == null) ? left : right;
    }
   
  }

  private static class LeqOperation extends GenericOperation {

    @Override
    protected ArrayList<SequencePair> zeroCase(ArrayList<SequencePair> left,
        ArrayList<SequencePair> right) {
      return (left != null && right == null) ? left : null;
    }
   
  }

  static GenericOperation joinOp = new JoinOperation();
  static GenericOperation meetOp = new MeetOperation();
  static GenericOperation leqOp = new LeqOperation();
 
  static IntegerBoxes applyOpOnCommonVariables(IntegerBoxes left,
      IntegerBoxes right, GenericOperation op) {
    Pair<ArrayList<Variable>, Pair<ArrayList<Integer>, ArrayList<Integer>>> x = findVariablesToRemove(left, right);
    ArrayList<SequencePair> leftData = IntegerBoxesHelper.removeVariables(x.right.left, left.data, left.variables.size());
    ArrayList<SequencePair> rightData = IntegerBoxesHelper.removeVariables(x.right.right, right.data, right.variables.size());
    ArrayList<SequencePair> opData = op.apply(leftData, rightData, x.left.size());
    return (opData == null) ? IntegerBoxes.BOTTOM : new IntegerBoxes(x.left, opData);
  }
 
  static ArrayList<SequencePair> removeHelper(int currentVar, int varToRemove, ArrayList<SequencePair> data, int variablesCount) {
    if (data == null || currentVar > varToRemove)
      return data;
    ArrayList<SequencePair> result;
    if (currentVar == varToRemove) {
      result = null;
      for(SequencePair item: data)
        result = joinOp.apply(result, item.value, variablesCount-1);
    } else {//currentVar < varToRemove - apply recursive and normalize result
      result = new ArrayList<SequencePair>();
      ArrayList<SequencePair> previous = null;
      for(SequencePair item: data) {
        ArrayList<SequencePair> newItemData = removeHelper(currentVar+1, varToRemove, item.value, variablesCount);
        if (!equals(previous, newItemData)) {
          result.add(new SequencePair(item.key, newItemData));
          previous = newItemData;
        }
      }
    }
    return result;
   
  }
 
  static ArrayList<SequencePair> removeVariables(ArrayList<Integer> variables, ArrayList<SequencePair> data, int variablesCount) {
    int removedCount = 0;
    for(int i: variables) {
      if (data == null)
        return data;
      data = removeHelper(0, i - removedCount, data, variablesCount-removedCount);
      removedCount ++;
    }
    return data;
  }
 
  static Pair<ArrayList<Variable>, Pair<ArrayList<Integer>, ArrayList<Integer>>> findVariablesToRemove(IntegerBoxes left, IntegerBoxes right) {
    final Set<Variable> commonVars = getCommonVariables(left, right);
    Predicate<Variable> filterPredicate = new CollectionUtils.Predicate<Variable>() {
      @Override
      public boolean meets(Variable var) {
        return commonVars.contains(var);
      }
    };
   
    ArrayList<Variable> leftVarsOrdered = CollectionUtils.filter(left.variables, filterPredicate);
    ArrayList<Variable> rightVarsOrdered = CollectionUtils.filter(right.variables, filterPredicate);
    if (!leftVarsOrdered.equals(rightVarsOrdered))
      throw new IntegerBoxes.IntegerBoxesException("Not the same variable order!!");
    //find indexes of variables to remove
    ArrayList<Integer> toRemoveLeft = new ArrayList<Integer>();
    for(int i=0; i< left.variables.size(); i++)
      if (!commonVars.contains(left.variables.get(i)))
        toRemoveLeft.add(i);
    ArrayList<Integer> toRemoveRight = new ArrayList<Integer>();
    for(int i=0; i< right.variables.size(); i++)
      if (!commonVars.contains(right.variables.get(i)))
        toRemoveRight.add(i);
    return Pair.create(leftVarsOrdered, Pair.create(toRemoveLeft, toRemoveRight));
  }
 
  /**
   * Returns set of variables present in both arguments
   * Assume arguments are not bottom.
   *
   * @param left
   * @param right
   * @return
   */
  static Set<Variable> getCommonVariables(IntegerBoxes left, IntegerBoxes right) {
    Set<Variable> commonVars = new HashSet<Variable>(left.variables);
    commonVars.retainAll(right.variables);
    return commonVars;
  }
 
 
  public static boolean equals(ArrayList<SequencePair> left, ArrayList<SequencePair> right) {
    if (left == null)
      return right == null;
    if (right == null)
      return false;
    if (left == right)
      return true;
    if (left.size() != right.size())
      return false;
    for(int i=0; i< left.size(); i++) {
      SequencePair leftItem = left.get(i);
      SequencePair rightItem = right.get(i);
      if (!leftItem.key.equals(rightItem.key))
        return false;
      if (!equals(leftItem.value, rightItem.value))
        return false;
    }
    return true;
  }
 
  private static ArrayList<SequencePair> getSequenceFor(IntervalValue interval, ArrayList<SequencePair> inner) {
    ArrayList<SequencePair> result = new ArrayList<SequencePair>(interval.right < Double.POSITIVE_INFINITY ? 2 : 1);
    result.add(new SequencePair(interval.left, inner));
    if (interval.right < Double.POSITIVE_INFINITY && interval.right != interval.right+1)
      result.add(new SequencePair(interval.right+1, null));
    return result;
  }
 
  public static IntegerBoxes fromIntervalBox(NonRelationalDomain<Interval> in) {
    //FIXME: should we reverse variables??
    if (in.isBottom())
      return IntegerBoxes.BOTTOM;
    //NOTE: we sort variables according to their order they appear in
    ArrayList<Variable> variables = new ArrayList<Variable>(in.getVariables());
    Collections.sort(variables);
   
    ArrayList<SequencePair> result = new ArrayList<SequencePair>(0);
    for(Variable var: variables)
      result = getSequenceFor(in.getValueFor(var).getValue(), result);
    Collections.reverse(variables);
    return new IntegerBoxes(variables, result);
  }
 
  private static class Split {
    private static final NonRelationalDomain<Interval> INITIAL_INTV = NonRelationalDomain.getInitialValue();
    @SuppressWarnings("unchecked")
    private static final List<NonRelationalDomain<Interval>> FINAL_LIST = Arrays.asList(INITIAL_INTV);
    private final ArrayList<Variable> variables;

    private Split(ArrayList<Variable> variables){
      this.variables = variables;
    }
   
    private void process(List<NonRelationalDomain<Interval>> result,
        double start, double end, int varIdx, ArrayList<SequencePair> subData) {
      Variable currentVar = variables.get(varIdx);
      for(NonRelationalDomain<Interval> smaller: apply(subData, varIdx+1))
        result.add(smaller.addNewVariable(currentVar, new Interval(start, end), false));
    }
   
//    private final FINISH = new LinkedList<NonRelationalDomain<Interval>>
   
    private List<NonRelationalDomain<Interval>> apply(ArrayList<SequencePair> data, int varIdx) {
      if (varIdx >= variables.size())
        return FINAL_LIST;
      double start = Double.NEGATIVE_INFINITY;
      ArrayList<SequencePair> lastValue = null;
      List<NonRelationalDomain<Interval>> result = new LinkedList<NonRelationalDomain<Interval>>();
      for(SequencePair elem: data){
        double end = elem.key-1;
        if (lastValue != null)
          process(result, start, end, varIdx, lastValue);
        start = elem.key;
        lastValue = elem.value;
      }
      if (lastValue != null)
        process(result, start, Double.POSITIVE_INFINITY, varIdx, lastValue);
      return result;
    }
   
    public static List<NonRelationalDomain<Interval>> execute(IntegerBoxes boxes) {
      Split x = new Split(boxes.variables);
      return x.apply(boxes.data, 0);
    }
  }
 
  public static IntegerBoxes removeVariables(IntegerBoxes input, List<Variable> variables){
    if (input.isBottom())
      return input;
    final Set<Variable> varSet = new HashSet<Variable>(input.variables);
    varSet.retainAll(variables);
    if (varSet.size() == 0)
      return input;
    //find indexes to remove
    ArrayList<Integer> variablesToRemove = new ArrayList<Integer>();
    for(int i=0; i< input.variables.size(); i++)
      if (varSet.contains(input.variables.get(i)))
        variablesToRemove.add(i);
   
    ArrayList<SequencePair> newData = IntegerBoxesHelper.removeVariables(variablesToRemove, input.data, input.variables.size());
    ArrayList<Variable> vars = CollectionUtils.filter(input.variables, new Predicate<Variable>() {
      @Override
      public boolean meets(Variable var) {
        return !varSet.contains(var);
      }
    });
    return (newData == null) ? IntegerBoxes.BOTTOM : new IntegerBoxes(vars, newData);
  }
 
  /**
   * NOTE: when boxes is not bottom but empty we return initial value for intervals
   * @param boxes
   * @return
   */
  public static List<NonRelationalDomain<Interval>> split(IntegerBoxes boxes) {
    if (boxes.isBottom())
      return null
//    if (boxes.variables.size() == 0 && boxes.data.size() == 0)
//      return new LinkedList<NonRelationalDomain<Interval>>();
    return Split.execute(boxes);
  }
 
  public static IntegerBoxes join(IntegerBoxes... arguments) {
    IntegerBoxes result = IntegerBoxes.BOTTOM;
    for(IntegerBoxes arg: arguments)
      result = result.join(arg);
    return result;
  }
 
  private static void processHelp(ArrayList<SequencePair> data, StringBuffer result, String indent) {
    if (data == null) {
      result.append("BOT");
      return;
    }
    if (data.isEmpty()){
      result.append("TOP");
      return;
    }
    for(SequencePair item: data) {
      result.append("\n");
      result.append(indent);
      result.append(item.key + ":");
      processHelp(item.value, result, indent+ "     ");
    }
  }
 
  public static String formatData(IntegerBoxes boxes) {
    StringBuffer result = new StringBuffer();
    processHelp(boxes.data, result, "");
    return result.toString();
  }
 
 
  private static void getSurroundingBoxHelper(ArrayList<SequencePair> data, int variable,
      ArrayList<Pair<Double, Double>> restricions) {
    if (data == null || data.size() == 0)
      return;
    Pair<Double, Double> restriction = restricions.get(variable);
    SequencePair first = data.get(0);
    SequencePair last = data.get(data.size()-1);
    if (first.key < restriction.left)
      restriction = restriction.setLeft(first.key);
    restriction = restriction.setRight((last.value == null) ? last.key : Double.POSITIVE_INFINITY);
    restricions.set(variable, restriction);
    for(SequencePair sp: data)
      getSurroundingBoxHelper(sp.value, variable+1, restricions);
  }
 
  public static NonRelationalDomain<Interval> getSurroundingBox(IntegerBoxes boxes) {
    if (boxes.isBottom())
      return NonRelationalDomain.getStaticBottom();
    ArrayList<Pair<Double, Double>> restrictions = new ArrayList<Pair<Double, Double>>(boxes.variables.size());
    for(Variable var: boxes.variables)
      restrictions.add(Pair.create(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
    getSurroundingBoxHelper(boxes.data, 0, restrictions);
    NonRelationalDomain<Interval> result = NonRelationalDomain.getInitialValue();
    for(int i=0; i< boxes.variables.size(); i++) {
      Pair<Double, Double> r = restrictions.get(i);
      result = result.addNewVariable(boxes.variables.get(i),
          new Interval(r.left, r.right-1), false);
    }
    return result;
  }
 
  private static void getLocalPointsHelper(ArrayList<SequencePair> data, ArrayList<Variable> variables,
      int variable, Map<Variable, Set<Double>> result) {
    if (data == null || data.size() == 0)
      return;
    Set<Double> x = result.get(variables.get(variable));
    for(SequencePair sp: data) {
      x.add(sp.key);
      getLocalPointsHelper(sp.value, variables, variable+1, result);
    }
  }
 
  public static Map<Variable, Set<Double>> getLocalPoints(IntegerBoxes boxes) {
    Map<Variable, Set<Double>> result = new HashMap<Variable, Set<Double>>();
    if (boxes.isBottom())
      return result;
    for(Variable var: boxes.variables)
      result.put(var, new HashSet<Double>());
    getLocalPointsHelper(boxes.data, boxes.variables, 0, result);
    return result;
  }

}
TOP

Related Classes of ai.domain.boxes.IntegerBoxesHelper

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.