All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.metacsp.meta.simplePlanner.SimpleDomain Maven / Gradle / Ivy

There is a newer version: 1.3.5
Show newest version
/*******************************************************************************
 * Copyright (c) 2010-2013 Federico Pecora 
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 ******************************************************************************/
package org.metacsp.meta.simplePlanner;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;

import org.metacsp.framework.Constraint;
import org.metacsp.framework.ConstraintNetwork;
import org.metacsp.framework.ConstraintSolver;
import org.metacsp.framework.ValueOrderingH;
import org.metacsp.framework.Variable;
import org.metacsp.framework.VariableOrderingH;
import org.metacsp.framework.VariablePrototype;
import org.metacsp.framework.meta.MetaConstraint;
import org.metacsp.framework.meta.MetaConstraintSolver;
import org.metacsp.framework.meta.MetaVariable;
import org.metacsp.meta.hybridPlanner.FluentBasedSimpleDomain;
import org.metacsp.meta.symbolsAndTime.Schedulable;
import org.metacsp.multi.activity.SymbolicVariableActivity;
import org.metacsp.multi.activity.ActivityNetworkSolver;
import org.metacsp.multi.allenInterval.AllenIntervalConstraint;
import org.metacsp.spatial.utility.SpatialRule;
import org.metacsp.time.Bounds;

public class SimpleDomain extends MetaConstraint {
	/**
	 * 
	 */
	private static final long serialVersionUID = 5143516447467774523L;
	protected Vector operators;
	protected String[] resourceNames;
	protected HashMap resourcesMap;
	protected HashMap> currentResourceUtilizers;
	private String everything = null;
	protected long filteringTime = Long.MIN_VALUE;
	private String name;

	protected Vector sensors = new Vector();
	protected Vector actuators = new Vector();
	protected Vector contextVars = new Vector();
	protected HashMap operatorsLevels = new HashMap(); 
	
	public HashMap unificationTrack = new HashMap();
    private Vector timelines = new Vector();

    public String[] getTimelines() {
        return this.timelines.toArray(new String[this.timelines.size()]);
    }

    public enum markings {UNJUSTIFIED, JUSTIFIED, DIRTY, STATIC, IGNORE, PLANNED, UNPLANNED, PERMANENT, OBSERVED_UNJ, OBSERVED_JUST, IMPOSSIBLE,
		COND_UNJUSTIFIED, COND_CURRENT_UNJUSTIFIED};

	public Schedulable[] getSchedulingMetaConstraints() {
		return currentResourceUtilizers.keySet().toArray(new Schedulable[currentResourceUtilizers.keySet().size()]);
	}
	
	public HashMap getUnificationTrack(){
		return unificationTrack;
	}
	
	public void setFileteringTime(long filteringTime) {
		this.filteringTime = filteringTime;
	}
	
	public SimpleDomain(int[] capacities, String[] resourceNames, String domainName) {
		super(null, null);
		this.name = domainName;
		this.resourceNames = resourceNames;
		currentResourceUtilizers = new HashMap>();
		resourcesMap = new HashMap();
		operators = new Vector();

		for (int i = 0; i < capacities.length; i++) {
			//Most critical conflict is the one with most activities 
			VariableOrderingH varOH = new VariableOrderingH() {
				@Override
				public int compare(ConstraintNetwork arg0, ConstraintNetwork arg1) {
					return arg1.getVariables().length - arg0.getVariables().length;
				}
				@Override
				public void collectData(ConstraintNetwork[] allMetaVariables) { }
			};
			// no value ordering
			ValueOrderingH valOH = new ValueOrderingH() {
				@Override
				public int compare(ConstraintNetwork o1, ConstraintNetwork o2) { return 0; }
			};
			resourcesMap.put(resourceNames[i], new SimpleReusableResource(varOH, valOH, capacities[i], this, resourceNames[i]));
		}

		// for every SRR just created, couple it with a vector of variables
		for (SimpleReusableResource rr : resourcesMap.values()) currentResourceUtilizers.put(rr,new HashMap());
	}
	
	protected SimpleDomain(int[] capacities, String[] resourceNames, String domainName, String everything) {
		this(capacities, resourceNames, domainName);
		this.everything = everything;
	}
	
	public void addResourceUtilizers(SimpleReusableResource rr, HashMap hm) {
		currentResourceUtilizers.put(rr,hm);
	}

	public void addResourceUtilizer(SimpleReusableResource rr, Variable var, Integer amount) {
		currentResourceUtilizers.get(rr).put(var,amount);
	}
	
	public void addResourceMap(String resourcename, SimpleReusableResource simpleReusableResource){
		resourcesMap.put(resourcename, simpleReusableResource);
	}
	
	public void addOperator(SimpleOperator r) {
		operators.add(r);
	}

	public SimpleOperator[] getOperators() {
		return operators.toArray(new SimpleOperator[operators.size()]);
	}		

	@Override
	public ConstraintSolver getGroundSolver() {
		return (ActivityNetworkSolver)this.metaCS.getConstraintSolvers()[0];
	}

	@Override
	public ConstraintNetwork[] getMetaVariables() {
		ActivityNetworkSolver groundSolver = (ActivityNetworkSolver)getGroundSolver();//(ActivityNetworkSolver)this.metaCS.getConstraintSolvers()[0];
		Vector ret = null;
		// for every variable that is marked as UNJUSTIFIED a ConstraintNetwork is built
		for (Variable task : groundSolver.getVariables()) {
			if (task.getMarking().equals(markings.UNJUSTIFIED)) {
				ConstraintNetwork nw = new ConstraintNetwork(null);
				nw.addVariable(task);
				if (ret == null) ret = new Vector();
				ret.add(nw);
			}
		}
		if (ret == null) return null;
		return ret.toArray(new ConstraintNetwork[ret.size()]);
	}

	
	protected ConstraintNetwork expandOperator(SimpleOperator possibleOperator, SymbolicVariableActivity problematicActivity) {
		ConstraintNetwork activityNetworkToReturn = new ConstraintNetwork(null);
		ActivityNetworkSolver groundSolver = (ActivityNetworkSolver)getGroundSolver();

		String possibleOperatorHead = possibleOperator.getHead();
		String possibleOperatorHeadSymbol = possibleOperatorHead.substring(possibleOperatorHead.indexOf("::")+2, possibleOperatorHead.length());
		String possibleOperatorHeadComponent = possibleOperatorHead.substring(0, possibleOperatorHead.indexOf("::"));
		Variable headActivity = null;

		boolean problematicActIsEffect = false;
		Variable[] operatorTailActivitiesToInsert = new Variable[0];

		if (possibleOperator.getRequirementActivities() != null) {
			operatorTailActivitiesToInsert = new Variable[possibleOperator.getRequirementActivities().length];

			for (int i = 0; i < possibleOperator.getRequirementActivities().length; i++) {
				String possibleOperatorTail = possibleOperator.getRequirementActivities()[i];
				String possibleOperatorTailComponent = possibleOperatorTail.substring(0, possibleOperatorTail.indexOf("::"));				
				String possibleOperatorTailSymbol = possibleOperatorTail.substring(possibleOperatorTail.indexOf("::")+2, possibleOperatorTail.length());

				//If this req is the prob act, then insert prob act
				if (possibleOperatorTailComponent.equals(problematicActivity.getComponent()) && possibleOperatorTailSymbol.equals(problematicActivity.getSymbolicVariable().getSymbols()[0])) {
					operatorTailActivitiesToInsert[i] = problematicActivity;
					problematicActIsEffect = true;
				}
				//else make a new var prototype and insert it
				else {
					VariablePrototype tailActivity = new VariablePrototype(groundSolver, possibleOperatorTailComponent, possibleOperatorTailSymbol);
					operatorTailActivitiesToInsert[i] = tailActivity;
					if (possibleOperator instanceof PlanningOperator) {
						if (((PlanningOperator)possibleOperator).isEffect(possibleOperatorTail)) {
							tailActivity.setMarking(markings.JUSTIFIED);
						}
						else {
							tailActivity.setMarking(markings.UNJUSTIFIED);
						}
					}
					else {
						tailActivity.setMarking(markings.UNJUSTIFIED);
					}
				}
			}

			//Also add head if the prob activity was unified with an effect
			if (problematicActIsEffect) {
				headActivity = new VariablePrototype(groundSolver, possibleOperatorHeadComponent, possibleOperatorHeadSymbol);
				headActivity.setMarking(markings.JUSTIFIED);
			}

			Vector allenIntervalConstraintsToAdd = new Vector();

			for (int i = 0; i < possibleOperator.getRequirementConstraints().length; i++) {
				if (possibleOperator.getRequirementConstraints()[i] != null) {
					AllenIntervalConstraint con = (AllenIntervalConstraint)possibleOperator.getRequirementConstraints()[i].clone();
					if (problematicActIsEffect) con.setFrom(headActivity);
					else con.setFrom(problematicActivity);
					con.setTo(operatorTailActivitiesToInsert[i]);
					allenIntervalConstraintsToAdd.add(con);
				}
			}
			for (AllenIntervalConstraint con : allenIntervalConstraintsToAdd) activityNetworkToReturn.addConstraint(con);
		}

		Vector toAddExtra = new Vector();
		for (int i = 0; i < operatorTailActivitiesToInsert.length+1; i++) {
			AllenIntervalConstraint[][] ec = possibleOperator.getExtraConstraints();
			if (ec != null) {
				AllenIntervalConstraint[] con = ec[i];
				for (int j = 0; j < con.length; j++) {
					if (con[j] != null) {
						AllenIntervalConstraint newCon = (AllenIntervalConstraint) con[j].clone();
						if (i == 0) {
							if (problematicActIsEffect) newCon.setFrom(headActivity);
							else newCon.setFrom(problematicActivity);
						}
						else {
							newCon.setFrom(operatorTailActivitiesToInsert[i-1]);
						}
						if (j == 0) {
							if (problematicActIsEffect) newCon.setTo(headActivity);
							else newCon.setTo(problematicActivity);
						}
						else {
							newCon.setTo(operatorTailActivitiesToInsert[j-1]);
						}
						toAddExtra.add(newCon);
					}
				}
			}
		}

		for (Variable v : operatorTailActivitiesToInsert) activityNetworkToReturn.addVariable(v);
		if (!toAddExtra.isEmpty()) {
			for (AllenIntervalConstraint con : toAddExtra) activityNetworkToReturn.addConstraint(con);
		}

		int[] usages = possibleOperator.getUsages();
		if (usages != null) {
			for (int i = 0; i < usages.length; i++) {
				if (usages[i] != 0) {
					HashMap utilizers = currentResourceUtilizers.get(resourcesMap.get(resourceNames[i]));
					if (problematicActIsEffect) utilizers.put(headActivity, usages[i]);
					else utilizers.put(problematicActivity, usages[i]);
					activityNetworkToReturn.addVariable(problematicActivity);
				}
			}
		}
		return activityNetworkToReturn;						
	}

	public void addSensor(String sensor) {
		this.sensors.add(sensor);
	}
	
	public String[] getSensors() {
		return this.sensors.toArray(new String[this.sensors.size()]);
	}

	public void addActuator(String actuator) {
		this.actuators.add(actuator);
	}

	public String[] getActuators() {
		return this.actuators.toArray(new String[this.actuators.size()]);
	}

	public void addContextVar(String cv) {
		this.contextVars.add(cv);
	}
	
	public String[] getContextVars() {
		return this.contextVars.toArray(new String[this.contextVars.size()]);
	}

	public boolean isSensor(String component) {
		if (sensors.contains(component)) return true;
		return false;
	}
		
	public boolean isActuator(String component) {
		if (actuators.contains(component)) return true;
		return false;
	}

	public boolean isContextVar(String component) {
		if (contextVars.contains(component)) return true;
		return false;
	}

	private Vector filterUnifications(Vector possibleUnifications) {
		Vector ret = new Vector();
		for (SymbolicVariableActivity act : possibleUnifications) {
			if (act.getTemporalVariable().getLET() >= filteringTime) {
				ret.add(act);
			}
		}
		return ret;
	}
	
	protected ConstraintNetwork[] getUnifications(SymbolicVariableActivity activity) {
		ActivityNetworkSolver groundSolver = (ActivityNetworkSolver)getGroundSolver();//(ActivityNetworkSolver)this.metaCS.getConstraintSolvers()[0];
		Variable[] acts = groundSolver.getVariables();
				
		Vector possibleUnifications = new Vector();
		for (Variable var : acts) {
			if (!var.equals(activity)) {
				SymbolicVariableActivity act = (SymbolicVariableActivity)var;
				String problematicActivitySymbolicDomain = activity.getSymbolicVariable().getSymbols()[0];
				if (act.getComponent().equals(activity.getComponent())) {
					String[] actSymbols = act.getSymbolicVariable().getSymbols();
					for (String symbol : actSymbols) {
						if (problematicActivitySymbolicDomain.contains(symbol)) {
							if (act.getMarking().equals(markings.JUSTIFIED)) {
								possibleUnifications.add(act);
							}
							break;
						}
					}
				}
			}
		}
		//return getUnifications(activity,possibleUnifications);
		return getUnifications(activity,filterUnifications(possibleUnifications));
	}
	
	private ConstraintNetwork[] getUnifications(SymbolicVariableActivity activity, Vector possibleUnifications) {
		Vector unifications = new Vector();
		for (SymbolicVariableActivity act : possibleUnifications) {
			ConstraintNetwork oneUnification = new ConstraintNetwork(null);
			AllenIntervalConstraint equals = new AllenIntervalConstraint(AllenIntervalConstraint.Type.Equals);
			equals.setFrom(activity);
			equals.setTo(act);
			oneUnification.addConstraint(equals);
//			SymbolicValueConstraint eqValue = new SymbolicValueConstraint(SymbolicValueConstraint.Type.EQUALS);
//			eqValue.setFrom(activity);
//			eqValue.setTo(act);
//			oneUnification.addConstraint(eqValue);
			unifications.add(oneUnification);
            //highest priority
            oneUnification.setAnnotation(2);
		}
		if (unifications.isEmpty()) return null;
		return unifications.toArray(new ConstraintNetwork[unifications.size()]);
	}

	@Override
	public ConstraintNetwork[] getMetaValues(MetaVariable metaVariable) {
		Vector retPossibleConstraintNetworks = new Vector();
		ConstraintNetwork problematicNetwork = metaVariable.getConstraintNetwork();
		SymbolicVariableActivity problematicActivity = (SymbolicVariableActivity)problematicNetwork.getVariables()[0];
		
		logger.finest("Getting metavalues for " + problematicActivity);
		
		Vector operatorsConsNetwork = new Vector();
		Vector unificationConsNetwork = new Vector();
		
		//If it's a sensor, it needs to be unified
		if (isSensor(problematicActivity.getComponent())) {
			logger.finest(problematicActivity.getComponent() + " is a Sensor - adding unifications");
			ConstraintNetwork[] unifications = this.getUnifications(problematicActivity);
			if (unifications != null)
				for (ConstraintNetwork cn : unifications) cn.setAnnotation(2);
            //But before returning all the unifications (which could be the empty set),
            // also add the expansions of PlanningOperators that have this problematic
            // activity as an AchievedState
            String problematicActivitySymbolicDomain = problematicActivity.getSymbolicVariable().getSymbols()[0];
            for (SimpleOperator r : operators) {
                if (r instanceof PlanningOperator) {
                    for (String reqState : r.getRequirementActivities()) {
                        String operatorEffect = reqState;
                        String opeatorEffectComponent = operatorEffect.substring(0, operatorEffect.indexOf("::"));
                        String operatorEffectSymbol = operatorEffect.substring(operatorEffect.indexOf("::")+2, operatorEffect.length());
                        if (((PlanningOperator)r).isEffect(reqState)) {
                            if(problematicActivity.getComponent().equals(opeatorEffectComponent) ) {
                                if(problematicActivitySymbolicDomain.equals(operatorEffectSymbol)) {
                                    ConstraintNetwork newResolver = expandOperator(r,problematicActivity);
                                    newResolver.annotation = r;
                                    //middle priority
                                    newResolver.setAnnotation(1);
                                    retPossibleConstraintNetworks.add(newResolver);

                                }
                            }
                        }
                    }
                }

            }
            if (null != unifications)  {
                retPossibleConstraintNetworks.addAll(Arrays.asList(unifications));
            }
			return retPossibleConstraintNetworks.toArray(new ConstraintNetwork[retPossibleConstraintNetworks.size()]);
		}
						
		//Find all expansions
		for (SimpleOperator r : operators) {
			String problematicActivitySymbolicDomain = problematicActivity.getSymbolicVariable().getSymbols()[0];
			String operatorHead = r.getHead();
			String opeatorHeadComponent = operatorHead.substring(0, operatorHead.indexOf("::"));
			String operatorHeadSymbol = operatorHead.substring(operatorHead.indexOf("::")+2, operatorHead.length());
			if (opeatorHeadComponent.equals(problematicActivity.getComponent())) {
				if (problematicActivitySymbolicDomain.contains(operatorHeadSymbol)) {
					ConstraintNetwork newResolver = expandOperator(r,problematicActivity);
					//middle priority
					newResolver.setAnnotation(1);
					newResolver.setSpecilizedAnnotation(r);
					operatorsConsNetwork.add(newResolver);
				}
			}
			
			if (r instanceof PlanningOperator) {
				for (String reqState : r.getRequirementActivities()) {
					String operatorEffect = reqState;
					String opeatorEffectComponent = operatorEffect.substring(0, operatorEffect.indexOf("::"));
					String operatorEffectSymbol = operatorEffect.substring(operatorEffect.indexOf("::")+2, operatorEffect.length());
					if (((PlanningOperator)r).isEffect(reqState)) {
						if (opeatorEffectComponent.equals(problematicActivity.getComponent())) {
							if (problematicActivitySymbolicDomain.contains(operatorEffectSymbol)) {
								ConstraintNetwork newResolver = expandOperator(r,problematicActivity);
								newResolver.annotation = r;
								//middle priority
								newResolver.setAnnotation(1);
								retPossibleConstraintNetworks.add(newResolver);
							}
						}
					}
				}
			}
		}
		
		logger.finest(problematicActivity.getComponent() + " is not a Sensor - adding expansions");
		
		//If it's a context var, it needs to be unified (or expanded, see above) 
		if (isContextVar(problematicActivity.getComponent())) {
			//System.out.println("CONTEXTVAR: " + problematicActivity.getComponent());
			logger.finest(problematicActivity.getComponent() + " is a ContextVariable - adding unifications");
			ConstraintNetwork[] unifications = getUnifications(problematicActivity);
			if (unifications != null) {
				for (ConstraintNetwork oneUnification : unifications) {
					retPossibleConstraintNetworks.add(oneUnification);
					//highest priority
					oneUnification.setAnnotation(2);
				}
			}
		}
		
		//If it's a context var, it needs to be unified (or expanded, see above)
		else if (isActuator(problematicActivity.getComponent())) {
			//System.out.println("ACTUATOR: " + problematicActivity.getComponent());
			logger.finest(problematicActivity.getComponent() + " is an Actuator - adding unifications");
			ConstraintNetwork[] unifications = getUnifications(problematicActivity);
			if (unifications != null) {
				for (ConstraintNetwork oneUnification : unifications) {
					retPossibleConstraintNetworks.add(oneUnification);
					//highest priority
					oneUnification.setAnnotation(2);
				}
			}
		}

		retPossibleConstraintNetworks.addAll(unificationConsNetwork);
		retPossibleConstraintNetworks.addAll(operatorsConsNetwork);				
		
		if (operatorsConsNetwork.isEmpty()) {
			//Actuator, but no expansions available - so justified by default
			if (isActuator(problematicActivity.getComponent())) {
				logger.finest(problematicActivity.getComponent() + " is an Actuator but has no available expansions - activity is directly supported");
				ConstraintNetwork nullActivityNetwork = new ConstraintNetwork(null);
				nullActivityNetwork.setSpecilizedAnnotation(false);
				//least priority
				nullActivityNetwork.setAnnotation(0);
				retPossibleConstraintNetworks.add(nullActivityNetwork);
			}
		}
		
		if (!retPossibleConstraintNetworks.isEmpty()) {
			return retPossibleConstraintNetworks.toArray(new ConstraintNetwork[retPossibleConstraintNetworks.size()]);
		}
		logger.finest(problematicActivity.getComponent() + " HAS NO RESOLVERS, will FAIL!");
		return null;
	}

	@Override
	public void markResolvedSub(MetaVariable con, ConstraintNetwork metaValue) {
		if (con.getConstraintNetwork().getVariables().length != 0)
			con.getConstraintNetwork().getVariables()[0].setMarking(markings.JUSTIFIED);
	}

	@Override
	public void draw(ConstraintNetwork network) {
		// TODO Auto-generated method stub	
	}

	public HashMap getResources() {
		return resourcesMap;
	}

	// Given a variable act, it returns all the resources that are currently exploited by the variable
	public SimpleReusableResource[] getCurrentReusableResourcesUsedByActivity(Variable act) {
		Vector ret = new Vector();
		for (SimpleReusableResource rr : currentResourceUtilizers.keySet()) {
			if (currentResourceUtilizers.get(rr).containsKey(act)) 
				ret.add(rr);
		}
		return ret.toArray(new SimpleReusableResource[ret.size()]);
	}

	public int getResourceUsageLevel(SimpleReusableResource rr, Variable act) {
		return currentResourceUtilizers.get(rr).get(act);
	}
	
	public HashMap> getAllResourceUsageLevel(){
		return currentResourceUtilizers;
	}

	public void resetAllResourceAllocation(){
		currentResourceUtilizers = new HashMap>();
		for (SimpleReusableResource rr : resourcesMap.values()) currentResourceUtilizers.put(rr,new HashMap());

	}
	
	@Override
	public String toString() {
		String ret = this.getClass().getSimpleName() + " " + this.name;
		//		ret += "\nResources:\n";
		//		for (SimpleReusableResource rr : resourcesMap.values())
		//			ret += "  " + rr + "\n";
		//		for (SimpleOperator op : operators) {
		//			ret += "--- Operator:\n";
		//			ret += op + "\n";
		//		}
		return ret;
	}

	@Override
	public String getEdgeLabel() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object clone() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isEquivalent(Constraint c) {
		// TODO Auto-generated method stub
		return false;
	}

	public static String instantiateVariable(String var) {
		return var.substring(var.indexOf('?'));
	}
	
	/**
	 * Creates a {@link SimpleOperator} from a textual specification (used by the
	 * domain parser).
	 * @param textualSpecification A textual specification of an operator
	 * @param resources The resources (identifiers of {@link SimpleReusableResource}s) used in this operator.
	 * @param planningOp Whether this is a {@link PlanningOperator} or a {@link SimpleOperator}.
	 * @return A {@link SimpleOperator} build according to the textual specification.
	 */
	private static SimpleOperator parseOperator(String textualSpecification, String[] resources, boolean planningOp) {
		HashMap requiredStates = new HashMap();
		String head = null;
		Vector constraints = new Vector();
		Vector froms = new Vector();
		Vector tos = new Vector();
		int[] resourceRequirements = new int[resources.length];
		HashMap effects = new HashMap();

		String[] headElement = parseKeyword("Head", textualSpecification);
		head = headElement[0].trim();

		String[] requiredStateElements = parseKeyword("RequiredState", textualSpecification);
		for (String reqElement : requiredStateElements) {
			String reqKey = reqElement.substring(0,reqElement.indexOf(" ")).trim();
			String reqState = reqElement.substring(reqElement.indexOf(" ")).trim();
			requiredStates.put(reqKey, reqState);
			effects.put(reqKey,false);
		}

		String[] achievedStateElements = parseKeyword("AchievedState", textualSpecification);
		for (String achElement : achievedStateElements) {
			String achKey = achElement.substring(0,achElement.indexOf(" ")).trim();
			String achState = achElement.substring(achElement.indexOf(" ")).trim();
			requiredStates.put(achKey, achState);
			effects.put(achKey,true);
		}

		String[] constraintElements = parseKeyword("Constraint", textualSpecification);
		for (String conElement : constraintElements) {
			String constraintName = null;
			Vector bounds = null;
			if (conElement.contains("[")) {
				constraintName = conElement.substring(0,conElement.indexOf("[")).trim();
				String boundsString = conElement.substring(conElement.indexOf("["),conElement.lastIndexOf("]")+1);
				String[] splitBounds = boundsString.split("\\[");
				bounds = new Vector();
				for (String oneBound : splitBounds) {
					if (!oneBound.trim().equals("")) {
						String lbString = oneBound.substring(oneBound.indexOf("[")+1,oneBound.indexOf(",")).trim();
						String ubString = oneBound.substring(oneBound.indexOf(",")+1,oneBound.indexOf("]")).trim();
						long lb, ub;
						if (lbString.equals("INF")) lb = org.metacsp.time.APSPSolver.INF;
						else if (lbString.startsWith("?")) lb = Long.parseLong(instantiateVariable(lbString));
						else lb = Long.parseLong(lbString);
						if (ubString.equals("INF")) ub = org.metacsp.time.APSPSolver.INF;
						else if (ubString.startsWith("?")) ub = Long.parseLong(instantiateVariable(ubString));
						else ub = Long.parseLong(ubString);
						bounds.add(new Bounds(lb,ub));
					}
				}
			}
			else {
				constraintName = conElement.substring(0,conElement.indexOf("(")).trim();
			}
			String from = null;
			String to = null;
			String fromSeg = null;
			if (constraintName.equals("Duration")) {
				from = conElement.substring(conElement.indexOf("(")+1, conElement.indexOf(")")).trim();
				to = from;
			}
			else {
				fromSeg = conElement.substring(conElement.indexOf("("));
				from = fromSeg.substring(fromSeg.indexOf("(")+1, fromSeg.indexOf(",")).trim();
				to = fromSeg.substring(fromSeg.indexOf(",")+1, fromSeg.indexOf(")")).trim();
			}

			AllenIntervalConstraint con = null;
			if (bounds != null) {
				con = new AllenIntervalConstraint(AllenIntervalConstraint.Type.valueOf(constraintName),bounds.toArray(new Bounds[bounds.size()]));
			}
			else con = new AllenIntervalConstraint(AllenIntervalConstraint.Type.valueOf(constraintName));
			constraints.add(con);
			froms.add(from);
			tos.add(to);
		}

		String[] resourceElements = parseKeyword("RequiredResource", textualSpecification);
		for (String resElement : resourceElements) {
			String requiredResource = resElement.substring(0,resElement.indexOf("(")).trim();
			int requiredAmount = Integer.parseInt(resElement.substring(resElement.indexOf("(")+1,resElement.indexOf(")")).trim());
			for (int k = 0; k < resources.length; k++) {
				if (resources[k].equals(requiredResource)) {
					resourceRequirements[k] = requiredAmount;
				}
			}

		}

		class AdditionalConstraint {
			AllenIntervalConstraint con;
			int from, to;
			public AdditionalConstraint(AllenIntervalConstraint con, int from, int to) {
				this.con = con;
				this.from = from;
				this.to = to;
			}
			public void addAdditionalConstraint(SimpleOperator op) {
				op.addConstraint(con, from, to);
			}
		}

		//What I have:
		//constraints = {During, Duration, Before}
		//froms = {Head, Head, req1}
		//tos = {req1, Head, req2}
		//requirements = {req2 = Robot1::At(room), req1 = Robot1::MoveTo()}

		//pass this to constructor
		String[] requirementStrings = new String[requiredStates.keySet().size()];
		boolean[] effectBools = new boolean[requiredStates.keySet().size()];
		AllenIntervalConstraint[] consFromHeadtoReq = new AllenIntervalConstraint[requiredStates.keySet().size()];
		//Vector consFromHeadToReq = new Vector();
		Vector acs = new Vector();
		HashMap reqKeysToIndices = new HashMap();

		int reqCounter = 0;
		for (String reqKey : requiredStates.keySet()) {
			String requirement = requiredStates.get(reqKey);
			requirementStrings[reqCounter] = requirement;
			reqKeysToIndices.put(reqKey,reqCounter);
			if (planningOp) {
				if (effects.get(reqKey)) effectBools[reqCounter] = true;
				else effectBools[reqCounter] = false;
			}
			reqCounter++;
		}

		for (int i = 0; i < froms.size(); i++) {
			//Head -> Head
			if (froms.elementAt(i).equals("Head") && tos.elementAt(i).equals("Head")) {
				AdditionalConstraint ac = new AdditionalConstraint(constraints.elementAt(i), 0, 0);
				acs.add(ac);
			}
			//req -> req
			else if (!froms.elementAt(i).equals("Head") && !tos.elementAt(i).equals("Head")) {
				String reqFromKey = froms.elementAt(i);
				String reqToKey = tos.elementAt(i);
				int reqFromIndex = reqKeysToIndices.get(reqFromKey);
				int reqToIndex = reqKeysToIndices.get(reqToKey);
				AllenIntervalConstraint con = constraints.elementAt(i);
				AdditionalConstraint ac = new AdditionalConstraint(con, reqFromIndex+1, reqToIndex+1);
				acs.add(ac);
			}
			//req -> Head
			else if (!froms.elementAt(i).equals("Head") && tos.elementAt(i).equals("Head")) {
				String reqFromKey = froms.elementAt(i);
				int reqFromIndex = reqKeysToIndices.get(reqFromKey);
				AllenIntervalConstraint con = constraints.elementAt(i);
				AdditionalConstraint ac = new AdditionalConstraint(con, reqFromIndex+1, 0);
				acs.add(ac);
			}
			//Head -> req
			else if (froms.elementAt(i).equals("Head") && !tos.elementAt(i).equals("Head")) {
				AllenIntervalConstraint con = constraints.elementAt(i);
				String reqToKey = tos.elementAt(i);
				consFromHeadtoReq[reqKeysToIndices.get(reqToKey)] = con;
			}
		}

		//Call constructor
		SimpleOperator ret = null;
		if (!planningOp) ret = new SimpleOperator(head,consFromHeadtoReq,requirementStrings,resourceRequirements);
		else ret = new PlanningOperator(head,consFromHeadtoReq,requirementStrings,effectBools,resourceRequirements);
		for (AdditionalConstraint ac : acs) ac.addAdditionalConstraint(ret);
		return ret;
	}
	
	protected static String[] parseKeyword(String keyword, String everything) {
		Vector elements = new Vector();
		int lastElement = everything.lastIndexOf(keyword);
		while (lastElement != -1) {
			int bw = lastElement;
			int fw = lastElement;
			boolean skip = false;
			while (everything.charAt(--bw) != '(') { 
				if (everything.charAt(bw) != ' ' && everything.charAt(bw) != '(') {
					everything = everything.substring(0,bw);
					lastElement = everything.lastIndexOf(keyword);
					skip = true;
					break;
				}
			}
			if (!skip) {
				int parcounter = 1;
				while (parcounter != 0) {
					if (everything.charAt(fw) == '(') parcounter++;
					else if (everything.charAt(fw) == ')') parcounter--;
					fw++;
				}
				String element = everything.substring(bw,fw).trim();
				element = element.substring(element.indexOf(keyword)+keyword.length(),element.lastIndexOf(")")).trim();
				if (!element.startsWith(",") && !element.trim().equals("")) elements.add(element);
				everything = everything.substring(0,bw);
				lastElement = everything.lastIndexOf(keyword);
			}
		}
		return elements.toArray(new String[elements.size()]);		
	}

	protected static HashMap processResources (String[] resources) {
		HashMap ret = new HashMap();
		for (String resourceElement : resources) {
			String resourceName = resourceElement.substring(0,resourceElement.indexOf(" ")).trim();
			int resourceCap = Integer.parseInt(resourceElement.substring(resourceElement.indexOf(" ")).trim());
			ret.put(resourceName, resourceCap);
		}
		return ret;
	}

	/**
	 * Parse a user-defined keyword in the domain, in the form (UserKeyword value1 [value2 ... valueN])
	 * @param keyword The keyword to parse, i.e., UserKeyword
	 * @return An array of value lists, one for each element with the user keyword, e.g., ["value11 value12", "value21 value22 value23", "value31", ...]
	 */
	public String[] parseUserKeyword(String keyword) {
		return parseKeyword(keyword, this.everything);
	}

	/**
	 * Parses a domain file (see domains/testDomain.ddl for an example), instantiates
	 * the necessary {@link MetaConstraint}s and adds them to the provided {@link SimplePlanner}.
	 * @param sp The {@link SimplePlanner} that will use this domain.
	 * @param filename Text file containing the domain definition. 
	 */
	public static SimpleDomain parseDomain(MetaConstraintSolver sp, String filename, Class domainType) {
		String everything = null;
		try {
			BufferedReader br = new BufferedReader(new FileReader(filename));
			try {
				StringBuilder sb = new StringBuilder();
				String line = br.readLine();
				while (line != null) {
					if (!line.trim().startsWith("#")) {
						sb.append(line);
						sb.append('\n');
					}
					line = br.readLine();
				}
				everything = sb.toString();
				String name = parseKeyword("Domain", everything)[0];
				String[] resourceElements = parseKeyword("Resource", everything);
				HashMap resources = processResources(resourceElements);
				String[] simpleOperators = parseKeyword("SimpleOperator", everything);
				String[] planningOperators = parseKeyword("PlanningOperator", everything);
				String[] sensors = parseKeyword("Sensor", everything);
				String[] actuators = parseKeyword("Actuator", everything);
				//String[] controllable = parseKeyword("Controllable", everything);

				String[] contextVars = parseKeyword("ContextVariable", everything);

                String[] timelinesString = parseKeyword("TimelinesToShow", everything);
                String[] timelines = null;
                if (timelinesString.length > 0) {
                    timelines =timelinesString[0].split("\\s");
                }

				int[] resourceCaps = new int[resources.keySet().size()];
				String[] resourceNames = new String[resources.keySet().size()];
				int resourceCounter = 0;
				for (String rname : resources.keySet()) {
					resourceNames[resourceCounter] = rname;
					resourceCaps[resourceCounter] = resources.get(rname);
					resourceCounter++;
				}

				System.out.println(domainType);
				SimpleDomain dom = null;
				if (domainType.equals(SimpleDomain.class)) {
					dom = new SimpleDomain(resourceCaps, resourceNames, name, everything);
				}
				else if (domainType.equals(FluentBasedSimpleDomain.class)) {
					dom = new FluentBasedSimpleDomain(resourceCaps, resourceNames, name, everything);
				}
				else if (domainType.equals(ProactivePlanningDomain.class)) {
					dom = new ProactivePlanningDomain(resourceCaps, resourceNames, name, everything);
				}

                ValueOrderingH valOH = new ValueOrderingH() {
                    @Override
                    public int compare(ConstraintNetwork arg0, ConstraintNetwork arg1) {
                        //Return unifications first
                        if (arg0.getAnnotation() != null && arg1.getAnnotation() != null) {
                            if (arg0.getAnnotation() instanceof Integer && arg1.getAnnotation() instanceof Integer) {
                                int annotation1 = ((Integer)arg0.getAnnotation()).intValue();
                                int annotation2 = ((Integer)arg1.getAnnotation()).intValue();
//                                System.out.println("............................ Returning " + (annotation2-annotation1));
                                return annotation2-annotation1;
                            }
                        }
                        //Return unifications first
                        //TODO: maybe this is superfluous...
                        return arg0.getVariables().length - arg1.getVariables().length;
                    }
                };

                //No variable ordering
                VariableOrderingH varOH = new VariableOrderingH() {
                    @Override
                    public int compare(ConstraintNetwork o1, ConstraintNetwork o2) { return 0; }
                    @Override
                    public void collectData(ConstraintNetwork[] allMetaVariables) { }
                };


                dom.setValOH(valOH);
                dom.setVarOH(varOH);
				
				for (String sensor : sensors) dom.addSensor(sensor);
				for (String act : actuators) dom.addActuator(act);
				for (String cv : contextVars) dom.addContextVar(cv);
				for (String operator : simpleOperators) {
					dom.addOperator(SimpleDomain.parseOperator(operator,resourceNames,false));
				}
				for (String operator : planningOperators) {
					dom.addOperator(SimpleDomain.parseOperator(operator,resourceNames,true));
				}
				//... and we also add all its resources as separate meta-constraints
				for (Schedulable sch : dom.getSchedulingMetaConstraints()) sp.addMetaConstraint(sch);

				//This adds the domain as a meta-constraint of the SimplePlanner
				sp.addMetaConstraint(dom);
                if (null != timelines) {
                    for (String timeline : timelines) dom.addTimeline(timeline);
                }


				return dom;
			}
			finally { br.close(); }
		}
		catch (FileNotFoundException e) { e.printStackTrace(); }
		catch (IOException e) { e.printStackTrace(); }
		return null;
	}

    private void addTimeline(String timeline) {
        this.timelines.add(timeline);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy