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

javax.constraints.scheduler.impl.BasicActivity Maven / Gradle / Ivy

The newest version!
//=============================================
// J A V A  C O M M U N I T Y  P R O C E S S
// 
// J S R  3 3 1
// 
// Specification
// 
//============================================= 
package javax.constraints.scheduler.impl;

import java.util.Vector;

import javax.constraints.Constraint;
import javax.constraints.Solution;
import javax.constraints.Var;
import javax.constraints.VarBool;
import javax.constraints.scheduler.Activity;
import javax.constraints.scheduler.ConstraintActivityResource;
import javax.constraints.scheduler.Resource;
import javax.constraints.scheduler.ResourceDisjunctive;
import javax.constraints.scheduler.ResourceDisjunctivePool;
import javax.constraints.scheduler.ResourcePool;
import javax.constraints.scheduler.ResourceType;
import javax.constraints.scheduler.Schedule;

/**
 * This class represents constrained scheduling activities.
 * 
 */

public class BasicActivity extends SchedulingObject implements Activity {

	private final Var start;
	
	private int solutionStart;

	private final Var end;
	
	private int solutionEnd;

	private final Var durationVar;

	private final int duration;

	private Object object;

	private Vector resourceConstraints;
	
	String startName() {
		return name+".start";
	}
	String endName() {
		return name+".end";
	}
	String durationName() {
		return name+".duration";
	}

	public BasicActivity(ScheduleImpl problem, String name, int from, int to) {
		super(problem);
		setName(name);
		if (from < problem.getStart() || from >= to || to > problem.getEnd())
			throw new RuntimeException("Activity " + name + "[" + from + ":" + to
					+ ") is invalid");
		start = problem.variable(startName(), from, to);
		end = problem.variable(endName(), from, to);
		duration = to - from;
		durationVar = problem.variable(durationName(), 0, to - from + 1);
		object = null;
		initialize();
	}

	public BasicActivity(ScheduleImpl problem, String name, int duration) {
		super(problem);
		setName(name);
		if (duration > problem.getDuration())
			throw new RuntimeException("Activity " + name + " duration=" + duration
					+ " is larger than " + problem.getDuration());
		start = problem.variable(startName(), problem.getStart(), problem.getEnd());
		end = problem.variable(endName(), problem.getStart(), problem.getEnd());
		this.duration = duration;
		durationVar = problem.variable(durationName(), duration, duration);
		object = null;
		initialize();
	}

	protected void initialize() {
		solutionStart = -1; // not defined
		solutionEnd = -1; // not defined
		getSchedule().post(end, "=", start.plus(duration));
		//getSchedule().post(new Var[] {end,start.negative()},"=", duration);// removed plus to be used with a linear solver
		resourceConstraints = new Vector();
	}

	public int getDuration() {
		return duration;
	}

	public Var getDurationVar() {
		return durationVar;
	}

	public Var getEnd() {
		return end;
	}

	public int getEndMax() {
		return end.getMax();
	}

	public Var getStart() {
		return start;
	}

	public int getStartMin() {
		return start.getMin();
	}

	public Object getObject() {
		return object;
	}
	
	public void setObject(Object object) {
		this.object = object;
	}

	// Precedence constraints
	public Constraint start(String oper, Activity act2) {
		return start(oper, act2, 0);
	}

	public Constraint start(String oper, Activity act2, int offset) {
		Schedule s = getSchedule();
		Var var1 = this.getStart();
		Var var2 = act2.getStart();
		if (oper.equals(">")) {
			var1 = this.getStart();
			var2 = act2.getEnd().minus(1);
		} else if (oper.equals(">=")) {
			var1 = this.getStart();
			var2 = act2.getStart();
		} else if (oper.equals("<=")) {
			var1 = this.getStart();
			var2 = act2.getStart();
		} else if (oper.equals("<")) {
			var1 = this.getEnd().minus(1);
			var2 = act2.getStart();
		} else if (oper.equals("=")) {
			var1 = this.getStart();
			var2 = act2.getStart();
		}
		
//		if (offset == 0)
//			return s.linear(var1, oper, var2);
//		
//		return s.post(new Var[] { var1, var2.negative() }, oper, offset); // removed "plus" to be used with a linear solver

		Var var2off = var2;
		if (offset != 0)
			var2off = var2.plus(offset);
		
		return s.linear(var1, oper, var2off);
		
		
	}
	
	public Constraint diff(Activity act2) {
		
		Constraint c1 = this.start(">",act2);
		Constraint c2 = act2.start(">",this);
		return c1.or(c2);
	}
	
	public Constraint start(String oper, int time) {
		Var var = this.getStart();
		return getSchedule().linear(var, oper, time);
	}

	public Vector getResourceConstraints() {
		return resourceConstraints;
	}

	public ConstraintActivityResource requires(Resource resource, int capacity) {
		// ConstraintActivityResource c =
		// getSchedule().addConstraintRequire(this, resource,
		// capacity);
		ConstraintActivityResource rc;
		if (resource.getType().equals(ResourceType.CONSUMABLE)) {
		    rc = new ConstraintConsume(this, resource,capacity);
		}
		else {
		    rc = new ConstraintRequire(this, resource,capacity);
		}
		this.getResourceConstraints().add(rc);
		resource.getActivityConstraints().add(rc);
		getSchedule().add(rc);
		rc.post();
		return rc;
	}

	public ConstraintActivityResource requires(Resource resource,
			Var capacityVar) {
		// ConstraintActivityResource c =
		// getSchedule().addConstraintRequire(this, resource,
		// capacityVar);
		ConstraintActivityResource rc; 
		if (resource.getType().equals(ResourceType.CONSUMABLE)) {
            rc = new ConstraintConsume(this,resource,capacityVar);
        }
		else {
            rc = new ConstraintRequire(this,resource,capacityVar);
        }
		this.getResourceConstraints().add(rc);
		resource.getActivityConstraints().add(rc);
		getSchedule().add(rc);
		rc.post();
		return rc;
	}

	public ConstraintActivityResource requires(ResourceDisjunctive resource) {
		return requires(resource, 1);
	}

	public Constraint requires(ResourceDisjunctive[] resources) {
		if (resources.length == 1)
			return requires(resources[0]);
		Schedule schedule = getSchedule();
		Var[] capacityVars = new Var[resources.length];
		for (int i = 0; i < capacityVars.length; i++) {
			capacityVars[i] = schedule.variable(
					getName() + " requires " + resources[i].getName(), 0, 1);
			requires(resources[i], capacityVars[i]);
		}
		Var sum = schedule.sum(capacityVars);
		return getSchedule().post(sum,"=",1);
	}

	public Constraint requires(ResourceDisjunctive resource1,
			ResourceDisjunctive resource2) {
		ResourceDisjunctive[] resources = { resource1, resource2 };
		return requires(resources);
	}

	public Constraint requires(ResourceDisjunctive resource1,
			ResourceDisjunctive resource2, ResourceDisjunctive resource3) {
		ResourceDisjunctive[] resources = { resource1, resource2, resource3 };
		return requires(resources);
	}

	/**
	 * This method posts a constraint that states: this activity requires one
	 * and only one resource from the pool of alternative disjunctive resources.
	 * 
	 * @param pool
	 *            of disjunctive resources
	 * @return the posted constraint
	 */
	public Constraint requires(ResourceDisjunctivePool pool) {
		BasicResourceDisjunctivePool poolI = (BasicResourceDisjunctivePool) pool;
		ResourceDisjunctive[] array = (ResourceDisjunctive[]) poolI.toArray();
		return requires(array);
	}

	/**
	 * This method posts a constraint that states: this activity requires one
	 * and only one resource from the pool of alternative disjunctive resources.
	 * There is an assumption that all resources within the pool are ordered
	 * starting from 0. The parameter-variable indexVar serves as an index
	 * within the "pool" that points to the actually assigned resource.
	 * 
	 * @param pool
	 *            of disjunctive resources
	 * @param indexVar
	 *            a constrained variable
	 * @return the posted constraint
	 */
	public Constraint requires(ResourceDisjunctivePool pool, Var indexVar) {
		BasicResourceDisjunctivePool poolI = (BasicResourceDisjunctivePool) pool;
		if (poolI.size() == 1)
			return requires(poolI.get(0));
		ResourceDisjunctive[] array = (ResourceDisjunctive[]) poolI.toArray();
		Var[] capacityVars = new Var[array.length];
		for (int i = 0; i < capacityVars.length; i++) {
			capacityVars[i] = getSchedule().variableBool(
					getName() + " requires " + array[i].getName());
			requires(array[i], capacityVars[i]);
		}
		getSchedule().postElement(capacityVars, indexVar, "=", 1);
		return getSchedule().post(capacityVars, "=", 1);

	}

	/**
	 * This method posts a constraint that states: this activity requires a
	 * certain integer "capacity" from the pool of alternative resources.
	 * 
	 * @param pool
	 *            of resources
	 * @param capacity
	 *            int
	 * @return the posted constraint
	 */
	public Constraint requires(ResourcePool pool, int capacity) {
		getSchedule()
				.log("Constraint requires(ResourcePool pool, int capacity) not implemented yet");
		return null;
	}

	/**
	 * This method posts a constraint that states: this activity requires
	 * certain variable "capacityVar" from the pool of alternative resources.
	 * 
	 * @param pool
	 *            of resources
	 * @param capacityVar
	 *            Var
	 * @return the posted constraint
	 */
	public Constraint requires(ResourcePool pool, Var capacityVar) {
		getSchedule()
				.log("Constraint requires(ResourcePool pool, Var capacityVar) not implemented yet");
		return null;
	}
	
	public void doNotShareResourcesWith(Activity act) {
		Vector rc1 = getResourceConstraints();
		Vector rc2 = act.getResourceConstraints();
		Schedule s = getSchedule();
		if (rc1.size() == 0 || rc2.size()== 0) 
			return;
		for (int i = 0; i < rc1.size(); i++) {
			ConstraintActivityResource ci = (ConstraintActivityResource) rc1.elementAt(i);
			if (ci.getResource() == null)
				continue;
			Var capi = ci.getCapacityVar();
			if (capi == null)
				continue;
			for (int j = 0; j < rc2.size(); j++) {
				ConstraintActivityResource cj = (ConstraintActivityResource) rc2.elementAt(j);
				if (cj.getResource() == null)
					continue;
				if (ci.getResource().getName().equals(cj.getResource().getName())) {
					Var capj = cj.getCapacityVar();
					if (capj == null)
						continue;
					s.post(capi.plus(capj),"<=",1); // removed plus to be used with a linear solver
					//s.post(new Var[] { capi, capj }, "<=", 1);
				}
			}
		}
	}

	public boolean isBound() {
		return start.isBound() && end.isBound();
	}

	/**
	 * @return a String representation of this activity in a form of
	 *         "name [startMin..startMax -- duration --> endMin..endMax)". For
	 *         example, "carpentry[7 -- 2 --> 9)" means that job "carpentry"
	 *         starts at day 7, lasts 2 days and ends on day 9 (not including
	 *         9).
	 * 
	 *         "carpentry[7 -- 2 --> 9) requires resource Joe[2]" additionally
	 *         means that this activity requires a resource with capacity 2.
	 * 
	 *         "masonry[0..12 -- 7 --> 7..19)" means that activity "masonry"
	 *         starts at sometime between 0 and 12, lasts 7 units of time, and
	 *         ends sometime between 7 and 19 (not including 19).
	 * 
	 */
	public String toString() {
		int startMin = getStart().getMin();
		int startMax = getStart().getMax();
		int endMin = getEnd().getMin();
		int endMax = getEnd().getMax();
		StringBuffer buf = new StringBuffer();
		String start;
		if (startMin == startMax)
			start = "" + startMin;
		else {
			if (getSolutionStart() > -1)
				start = "" + getSolutionStart();
			else 
				start = startMin + ".." + startMax;
		}
		String end;
		if (endMin == endMax)
			end = "" + endMin;
		else {
			if (getSolutionEnd() > -1)
				end = "" + getSolutionEnd();
			else 
				end = endMin + ".." + endMax;
		}
		buf.append(getName() + "[" + start + " -- "
				+ getDuration() + " --> " + end + ")");
		Vector rc = getResourceConstraints();
		if (rc.size() > 0) {
			for (int i = 0; i < rc.size(); i++) {
				ConstraintActivityResource c = (ConstraintActivityResource) rc
						.elementAt(i);
				String cap = null;
				if (c.getCapacityVar() == null) {
					cap = "[" + c.getCapacity() + "]";
				} else {
					int capMin = c.getCapacityVar().getMin();
					int capMax = c.getCapacityVar().getMax();
					cap = "[" + capMin
							+ (capMin == capMax ? "" : ".." + capMax)
							+ "]";
				}
				if (cap.equals("[0]"))
					continue;
				// if (i > 0)
				// buf.append(",");
				buf.append(" " + c.getType() + " ");
				buf.append(c.getResource().getName());
				buf.append(cap);
				buf.append(" ");
			}
			buf.append(" in a time");
		}
		return buf.toString();
	}
	
	/**
	 * 
	 * @return a calculated start of this activity 
	 */
	public int getSolutionStart() {
		return solutionStart;
	}
	
	/**
	 * 
	 * Sets a calculated start of this activity 
	 */
	public void setSolutionStart(int start) {
		solutionStart = start;
	}
	
	/**
	 * 
	 * @return a calculated end of this activity 
	 */
	public int getSolutionEnd() {
		return solutionEnd;
	}
	
	/**
	 * 
	 * Sets a calculated end of this activity 
	 */
	public void setSolutionEnd(int end) {
		solutionEnd = end;
	}
	
//	public void save(Solution solution) {
//		int s = solution.getValue(startName());
//		setSolutionStart(s);
//		int e = s + duration;
//		setSolutionEnd(e);
//	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy