Package javaff.planning

Source Code of javaff.planning.RelaxedMetricPlanningGraph

/************************************************************************
* Strathclyde Planning Group,
* Department of Computer and Information Sciences,
* University of Strathclyde, Glasgow, UK
* http://planning.cis.strath.ac.uk/
*
* Copyright 2007, Keith Halsey
* Copyright 2008, Andrew Coles and Amanda Smith
*
* (Questions/bug reports now to be sent to Andrew Coles)
*
* This file is part of JavaFF.
*
* JavaFF is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* JavaFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with JavaFF.  If not, see <http://www.gnu.org/licenses/>.
*
************************************************************************/

package javaff.planning;

import javaff.data.GroundProblem;
import javaff.data.GroundCondition;
import javaff.data.metric.MetricSymbolStore;
import javaff.data.metric.NamedFunction;
import javaff.data.metric.BinaryComparator;
import javaff.data.metric.ResourceOperator;
import javaff.data.metric.Function;
import javaff.data.metric.BinaryFunction;
import javaff.data.metric.NumberFunction;

import java.math.BigDecimal;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Hashtable;
import java.util.Iterator;

public class RelaxedMetricPlanningGraph extends RelaxedPlanningGraph
{
  protected Set metricGoal = new HashSet();

  protected List minResources = null;       //List of Maps [(PGFunction => BigDecimal)]
  protected List maxResources = null;

  protected Map PGFuncMap = new Hashtable();         // (NamedFunction => PGNamedFunction)
  protected Map ActionComparators = new Hashtable(); // (PGAction => (PGBinaryComparator))
  protected Map ActionOperators = new Hashtable();   // (PGAction => (PGFunctionOperator))

  //Used during graph construction
  private Set resOps = null;       // PGResourceOperators that are in the graph

  public RelaxedMetricPlanningGraph(GroundProblem gp)
  {
    super(gp);
    setupPGFuncMap(gp.functionValues.keySet());
    makeComparators(actions);
    makeOperators(actions);
    resOps = new HashSet();
  }

  //*************************************
    // Initial Setup
    //*************************************

  private void setupPGFuncMap(Set funcs)
  {
    Iterator fit = funcs.iterator();
    while (fit.hasNext())
    {
      NamedFunction nf = (NamedFunction) fit.next();
      PGFuncMap.put(nf, new PGNamedFunction(nf));
    }
  }

  private void makeComparators(Set actions)
  {
    Iterator ait = actions.iterator();
    while (ait.hasNext())
    {
      PGAction pga = (PGAction) ait.next();
      Set ss = new HashSet();
      ActionComparators.put(pga,ss);
      Set cs = pga.getComparators();
      Iterator cit = cs.iterator();
      while (cit.hasNext())
      {
        BinaryComparator bc = (BinaryComparator) cit.next();
        ss.add(makeComparator(bc));
      }
    }
  }

  private PGBinaryComparator makeComparator(BinaryComparator bc)
  {
    PGFunction f = makeFunction(bc.first);
    PGFunction s = makeFunction(bc.second);
    return new PGBinaryComparator(f,s,bc.type);
  }

  private void makeOperators(Set actions)
  {
    Iterator ait = actions.iterator();
    while (ait.hasNext())
    {
      PGAction pga = (PGAction) ait.next();
      Set s = new HashSet();
      ActionOperators.put(pga,s);
      Set os = pga.getOperators();
      Iterator oit = os.iterator();
      while (oit.hasNext())
      {
        ResourceOperator ro = (ResourceOperator) oit.next();
        s.add(makeOperator(ro));
      }
    }
  }

  private PGResourceOperator makeOperator(ResourceOperator ro)
  {
    PGNamedFunction r = (PGNamedFunction) PGFuncMap.get(ro.resource);
    PGFunction c = makeFunction(ro.change);
    return new PGResourceOperator(r,c,ro.type);
  }


  protected PGFunction makeFunction(Function f)
  {
    if (f instanceof NamedFunction) return (PGNamedFunction) PGFuncMap.get(f);
    else if (f instanceof NumberFunction) return new PGNumberFunction(f.getValue(null));
    else if (f instanceof BinaryFunction)
    {
      BinaryFunction bf = (BinaryFunction) f;
      PGFunction f1 = makeFunction(bf.first);
      PGFunction s2 = makeFunction(bf.second);
      return new PGBinaryFunction(f1,s2,bf.type);
    }
    else return null;
  }

  protected void setGoal(GroundCondition g)
  {
    super.setGoal(g);
    Iterator cit = g.getComparators().iterator();
    while (cit.hasNext())
    {
      BinaryComparator c = (BinaryComparator) cit.next();
      metricGoal.add(makeComparator(c));
    }
  }


  //*************************************
    // Graph Setup
    //*************************************
  protected void resetAll(State s)
  {
    super.resetAll(s);
    maxResources = new ArrayList();
    minResources = new ArrayList();
    setInitialValues((MetricState) s);
  }

  protected void setInitialValues(MetricState ms)
  {
    Iterator fit = ms.funcValues.keySet().iterator();
    Map max = new Hashtable();
    Map min = new Hashtable();
    while (fit.hasNext())
    {
      NamedFunction nf = (NamedFunction) fit.next();
      PGFunction pgf = (PGFunction) PGFuncMap.get(nf);
      BigDecimal bd = (BigDecimal) ms.funcValues.get(nf);
      max.put(pgf, bd);
      min.put(pgf, bd);
    }
    maxResources.add(max);
    minResources.add(min);
  }

  //*************************************
    // Graph Construction Methods
    //*************************************

  protected ArrayList createFactLayer(Set scheduledFacts, int layer)
  {
    ArrayList rActionList = super.createFactLayer(scheduledFacts, layer);
    updateResourceValues(layer);
    return rActionList;
  }

  private void updateResourceValues(int layer)
  {
    if (layer == 0) return;
    //duplicate the previous layers
    Hashtable maxminus = (Hashtable) maxResources.get(layer-1);
    Hashtable minminus = (Hashtable) minResources.get(layer-1);
    Map newmax = (Hashtable) maxminus.clone();
    Map newmin = (Hashtable) minminus.clone();
    maxResources.add(layer, newmax);
    minResources.add(layer, newmin);

    //loop throught the current resource operators and if they increase/decrease update the values on the new layer
    Iterator roit = resOps.iterator();
    while (roit.hasNext())
    {
      PGResourceOperator ro = (PGResourceOperator) roit.next();
      BigDecimal max = ro.resource.getMaxValue(layer-1, maxResources, minResources);
      BigDecimal min = ro.resource.getMinValue(layer-1, maxResources, minResources);
      BigDecimal nmax = ro.maximise(layer-1, maxResources, minResources);
      BigDecimal nmin = ro.minimise(layer-1, maxResources, minResources);
      if (nmax.compareTo(max) > 0)
      {
        newmax.put(ro.resource, nmax);
        numeric_level_off ++;
      }
      if (nmin.compareTo(min) < 0)
      {
        newmin.put(ro.resource, nmin);
        numeric_level_off ++;
      }
    }
  }

  protected HashSet filterSet(Set pActions, int layer)
  {
    Set fActions = super.filterSet(pActions, layer);
    HashSet rSet = new HashSet();
    Iterator ait = fActions.iterator();
    while (ait.hasNext())
    {
      PGAction a = (PGAction) ait.next();
      if (actionReady(a, layer)) rSet.add(a);
      else readyActions.add(a);
    }
    readyActions.removeAll(rSet);
    return rSet;
  }

  private boolean actionReady(PGAction a, int layer)
  {
    Set cs = (HashSet) ActionComparators.get(a);
    Iterator csit = cs.iterator();
    boolean allmet = true;
    while (csit.hasNext() && allmet)
    {
      PGBinaryComparator c = (PGBinaryComparator) csit.next();
      allmet = c.met(layer, maxResources, minResources);
    }
    return allmet;
  }

  protected HashSet calculateActionMutexesAndProps(Set filteredSet,int pLayer)
  {
    HashSet rSet = super.calculateActionMutexesAndProps(filteredSet, pLayer);
    Iterator ait = filteredSet.iterator();
    while (ait.hasNext())
    {
      PGAction a = (PGAction) ait.next();
      Set ops = (Set) ActionOperators.get(a);
      resOps.addAll(ops);
    }
    return rSet;
  }


  //*************************************
    // Graph Extraction
    //*************************************

  protected boolean goalMet()
  {
    boolean met = super.goalMet();
    Iterator mgit = metricGoal.iterator();
    while (met && mgit.hasNext())
    {
      PGBinaryComparator c = (PGBinaryComparator) mgit.next();
      met = c.met(num_layers, maxResources, minResources);
    }
    return met;
  }

  public List extractPlan() //Should be done better buts its not
  {
    return searchRelaxedPlan(goal, metricGoal, num_layers);
  }

  public List searchRelaxedPlan(Set goalSet, Set mgoalSet, int l)
  {
    if (l == 0) return new ArrayList();
    Set chosenActions = new HashSet();
    //loop through actions to achieve the goal set
    Iterator git = goalSet.iterator();
    while (git.hasNext())
    {
      PGProposition g = (PGProposition) git.next();
      PGAction a = null;
      Iterator ait = g.achievedBy.iterator();
      while (ait.hasNext())
      {
        PGAction na = (PGAction) ait.next();
        if (na.layer < l && na.layer >= 0)
        {
          if (na instanceof PGNoOp)
          {
            a = na;
            break;
          }
          else if (chosenActions.contains(na))
          {
            a = na;
            break;
          }
          else
          {
            if (a == null) a = na;
            else if (a.difficulty > na.difficulty) a = na;
          }
        }
      }

      if (a != null) chosenActions.add(a);
    }

    Set newMGoalSet = new HashSet();
    //loop through the metric goals and see if they are satisfied, if not find some actions
    Iterator mit = mgoalSet.iterator();
    while (mit.hasNext())
    {
      PGBinaryComparator c = (PGBinaryComparator) mit.next();
      Iterator ait = actions.iterator();
      while (!c.met(l-1, maxResources, minResources) && ait.hasNext())
      {
        PGAction a = null;
        while (ait.hasNext())
        {
          a = (PGAction) ait.next();
          if (a.layer < l && a.layer >= 0 && c.makeBetter(a)) break;
        }

        Iterator roit = ((Set) ActionOperators.get(a)).iterator();
        while (roit.hasNext())
        {
          PGResourceOperator o = (PGResourceOperator) roit.next();
          if (c.makeBetter(o))
          {
            c = c.affect(o);
          }
        }
        chosenActions.add(a);
      }
      newMGoalSet.add(c);
    }

    Set newGoalSet = new HashSet();
    //loop through chosen actions  adding in propositions and comparators
    Iterator cait = chosenActions.iterator();
    while (cait.hasNext())
    {
      PGAction ca = (PGAction) cait.next();
      newGoalSet.addAll(ca.conditions);
      newMGoalSet.addAll((Set)ActionComparators.get(ca));
    }

    List rplan = searchRelaxedPlan(newGoalSet, newMGoalSet, l-1);
    rplan.addAll(chosenActions);
    return rplan;
  }


  //*************************************
    // Internal Metric Classes
    //*************************************

  // Note these do not deal with max and mins where there a -ve changes with multiplication and division. For example if x*y could be max if max*max or min*min if both mins were negative

  protected interface PGFunction
  {
    public BigDecimal getMaxValue(int layer, List maxes, List mins);
    public BigDecimal getMinValue(int layer, List maxes, List mins);
    public boolean effectedBy(PGResourceOperator ro);
    public boolean increase(PGResourceOperator ro);
    public boolean decrease(PGResourceOperator ro);
  }

  protected class PGNamedFunction implements PGFunction
  {
    public NamedFunction namedFunction;

    protected PGNamedFunction()
    {
     
    }
   
    public PGNamedFunction(NamedFunction nf)
    {
      namedFunction = nf;
    }

    public BigDecimal getMaxValue(int layer, List maxes, List mins)
    {
      Map max = (Hashtable) maxes.get(layer);
      return (BigDecimal) max.get(this);
    }

    public BigDecimal getMinValue(int layer, List maxes, List mins)
    {
      Map min = (Hashtable) mins.get(layer);
      return (BigDecimal) min.get(this);
    }

    public int hashcode()
    {
      return namedFunction.hashCode();
    }

    public boolean effectedBy(PGResourceOperator ro)
    {
      return (this == ro.resource);
    }

    public boolean increase(PGResourceOperator ro)
    {
      return ro.increase(this);
    }
   
    public boolean decrease(PGResourceOperator ro)
    {
      return ro.decrease(this);
    }
  }

 
 
  protected class PGNumberFunction implements PGFunction
  {
    public BigDecimal value;
    public PGNumberFunction(BigDecimal v)
    {
      value = v;
    }
    public BigDecimal getMaxValue(int layer, List maxes, List mins)
    {
      return value;
    }
    public BigDecimal getMinValue(int layer, List maxes, List mins)
    {
      return value;
    }
    public boolean effectedBy(PGResourceOperator ro)
    {
      return false;
    }

    public boolean increase(PGResourceOperator ro)
    {
      return false;
    }

    public boolean decrease(PGResourceOperator ro)
    {
      return false;
    }
  }

 

  protected class PGBinaryFunction implements PGFunction
  {
    public PGFunction first, second;
    public int type;
    public PGBinaryFunction(PGFunction f, PGFunction s, int t)
    {
      first = f;
      second = s;
      type = t;
    }
    public BigDecimal getMaxValue(int layer, List maxes, List mins)
    {
      if (type == MetricSymbolStore.PLUS) return first.getMaxValue(layer, maxes, mins).add(second.getMaxValue(layer, maxes, mins));
      else if (type == MetricSymbolStore.MINUS) return first.getMaxValue(layer, maxes, mins).subtract(second.getMinValue(layer, maxes, mins));
      else if (type == MetricSymbolStore.MULTIPLY) return first.getMaxValue(layer, maxes, mins).multiply(second.getMaxValue(layer, maxes, mins));
      else if (type == MetricSymbolStore.DIVIDE) return first.getMaxValue(layer, maxes, mins).divide(second.getMinValue(layer, maxes, mins), MetricSymbolStore.SCALE, MetricSymbolStore.ROUND);
      else return null;
    }
    public BigDecimal getMinValue(int layer, List maxes, List mins)
    {
      return getMaxValue(layer, mins, maxes);
    }
    public boolean effectedBy(PGResourceOperator ro)
    {
      return (first.effectedBy(ro) || second.effectedBy(ro));
    }
    public boolean increase(PGResourceOperator ro)
    {
      if (type == MetricSymbolStore.PLUS) return (first.increase(ro) || second.increase(ro));
      else if (type == MetricSymbolStore.MINUS) return (first.increase(ro) || second.decrease(ro));
      else if (type == MetricSymbolStore.MULTIPLY) return (first.increase(ro) || second.increase(ro));
      else if (type == MetricSymbolStore.DIVIDE) return (first.increase(ro) || second.decrease(ro));
      else return false;
    }
    public boolean decrease(PGResourceOperator ro)
    {
      if (type == MetricSymbolStore.PLUS) return (first.decrease(ro) || second.decrease(ro));
      else if (type == MetricSymbolStore.MINUS) return (first.decrease(ro) || second.increase(ro));
      else if (type == MetricSymbolStore.MULTIPLY) return (first.decrease(ro) || second.decrease(ro));
      else if (type == MetricSymbolStore.DIVIDE) return (first.decrease(ro) || second.increase(ro));
      else return false;
    }
  }

  protected class PGResourceOperator
  {
    public PGNamedFunction resource;
    public PGFunction change;
    public int type;

    public PGResourceOperator(PGNamedFunction r, PGFunction c, int t)
    {
      resource = r;
      change = c;
      type = t;
    }

    public BigDecimal maximise(int layer, List maxes, List mins)
    {
      if (type == MetricSymbolStore.ASSIGN) return change.getMaxValue(layer, maxes, mins);
      else if (type == MetricSymbolStore.INCREASE) return resource.getMaxValue(layer, maxes, mins).add(change.getMaxValue(layer, maxes, mins));
      else if (type == MetricSymbolStore.DECREASE) return resource.getMaxValue(layer, maxes, mins).subtract(change.getMinValue(layer, maxes, mins));
      else if (type == MetricSymbolStore.SCALE_UP) return resource.getMaxValue(layer, maxes, mins).multiply(change.getMaxValue(layer, maxes, mins));
      else if (type == MetricSymbolStore.SCALE_DOWN) return resource.getMaxValue(layer, maxes, mins).divide(change.getMinValue(layer, maxes, mins), MetricSymbolStore.SCALE, MetricSymbolStore.ROUND);
      else return null;
    }

    public BigDecimal minimise(int layer, List maxes, List mins)
    {
      return maximise(layer, mins, maxes);
    }

    public PGFunction invertFunction(PGFunction f)
    {
      if (type == MetricSymbolStore.ASSIGN) return change;
      else if (type == MetricSymbolStore.INCREASE) return new PGBinaryFunction(f, change, MetricSymbolStore.MINUS);
      else if (type == MetricSymbolStore.DECREASE) return new PGBinaryFunction(f, change, MetricSymbolStore.PLUS);
      else if (type == MetricSymbolStore.SCALE_UP) return new PGBinaryFunction(f, change, MetricSymbolStore.DIVIDE);
      else if (type == MetricSymbolStore.SCALE_DOWN) return new PGBinaryFunction(f, change, MetricSymbolStore.MULTIPLY);
      else return null;
    }

    public boolean increase(PGFunction f)
    {
      if (resource == f)
      {
        if (type == MetricSymbolStore.ASSIGN) return true; // could do something better here by looking at the values
        else if (type == MetricSymbolStore.INCREASE) return true;
        else if (type == MetricSymbolStore.DECREASE) return false;
        else if (type == MetricSymbolStore.SCALE_UP) return true;
        else if (type == MetricSymbolStore.SCALE_DOWN) return false;
        else return false;
      }
      else return false;
    }

    public boolean decrease(PGFunction f)
    {
      if (resource == f)
      {
        if (type == MetricSymbolStore.ASSIGN) return true; // could do something better here by looking at the values
        else if (type == MetricSymbolStore.INCREASE) return false;
        else if (type == MetricSymbolStore.DECREASE) return true;
        else if (type == MetricSymbolStore.SCALE_UP) return false;
        else if (type == MetricSymbolStore.SCALE_DOWN) return true;
        else return false;
      }
      else return false;
    }
  }

  protected class PGBinaryComparator
  {
    public PGFunction left, right;
    public int type;

    public PGBinaryComparator(PGFunction l, PGFunction r, int t)
    {
      left = l;
      right = r;
      type = t;
    }

    public boolean met(int layer, List maxes, List mins)
    {
      if (type == MetricSymbolStore.GREATER_THAN) return left.getMaxValue(layer, maxes, mins).compareTo(right.getMinValue(layer, maxes, mins)) > 0;
      else if (type == MetricSymbolStore.GREATER_THAN_EQUAL) return left.getMaxValue(layer, maxes, mins).compareTo(right.getMinValue(layer, maxes, mins)) >= 0;
      else if (type == MetricSymbolStore.LESS_THAN) return left.getMinValue(layer, maxes, mins).compareTo(right.getMaxValue(layer, maxes, mins)) < 0;
      else if (type == MetricSymbolStore.LESS_THAN_EQUAL) return left.getMinValue(layer, maxes, mins).compareTo(right.getMaxValue(layer, maxes, mins)) <= 0;
      else if (type == MetricSymbolStore.EQUAL) return (left.getMaxValue(layer, maxes, mins).compareTo(right.getMinValue(layer, maxes, mins)) >= 0 && left.getMinValue(layer, maxes, mins).compareTo(right.getMaxValue(layer, maxes, mins)) <= 0);
      else return true;
    }


    public boolean effectedBy(PGResourceOperator ro)
    {
      return (left.effectedBy(ro) || right.effectedBy(ro));
    }

    public PGBinaryComparator affect(PGResourceOperator ro)
    {
      if (effectedBy(ro))
      {
        PGFunction newLeft = left;
        PGFunction newRight = right;
        if (left.effectedBy(ro))
        {
          newLeft = ro.invertFunction(left);
        }
        if (right.effectedBy(ro))
        {
          newRight = ro.invertFunction(right);
        }
        PGBinaryComparator nbc = new PGBinaryComparator(newLeft, newRight, type);
        return nbc;
      }
      else return this;
    }

    public boolean makeBetter(PGResourceOperator ro)
    {
      if (type == MetricSymbolStore.GREATER_THAN || type == MetricSymbolStore.GREATER_THAN_EQUAL) return left.increase(ro) || right.decrease(ro);
      else if (type == MetricSymbolStore.LESS_THAN || type == MetricSymbolStore.LESS_THAN_EQUAL) return left.decrease(ro) || right.increase(ro);
      else if (type == MetricSymbolStore.EQUAL) return true;
      else return true;
    }

    public boolean makeBetter(PGAction a)
    {
      Iterator oit = ((Set) ActionOperators.get(a)).iterator();
      while (oit.hasNext())
      {
        PGResourceOperator o = (PGResourceOperator) oit.next();
        if (makeBetter(o)) return true;
      }
      return false;
    }
  }

  //*************************************
    // Debugging Classes
    //*************************************

  public void printLayer(int i)
  {
    super.printLayer(i);
    Map max = (Hashtable) maxResources.get(i);
    Map min = (Hashtable) minResources.get(i);
    System.out.println("Resources:");
    Iterator rit = max.keySet().iterator();
    while (rit.hasNext())
    {
      PGNamedFunction r = (PGNamedFunction) rit.next();
      System.out.print("\t"+r.namedFunction.toString());
      System.out.print(" max:"+max.get(r));
      System.out.println(" min:"+min.get(r));
    }
  }

}
TOP

Related Classes of javaff.planning.RelaxedMetricPlanningGraph

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.