PageRenderTime 30ms CodeModel.GetById 17ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/farmR/src/java/src/jfm/model/FreeTimeComponent.java

https://code.google.com/p/javawfm/
Java | 178 lines | 137 code | 13 blank | 28 comment | 16 complexity | e7ada892fe7d269a981086713ed2f1fd MD5 | raw file
  1/**
  2 * 
  3 */
  4package jfm.model;
  5
  6import java.util.*;
  7
  8import jfm.lp.ConstraintBuilder;
  9import jfm.lp.LPX;
 10import jfm.lp.MatrixElement;
 11import jfm.lp.MatrixRow;
 12import jfm.lp.MatrixVariable;
 13import jfm.lp.ModelComponent;
 14import jfm.model.Crop.CropCopy;
 15import jfm.model.Types.CropType;
 16import jfm.model.Types.*;
 17import jfm.model.Types.ObjectiveType;
 18import jfm.model.Types.WorkabilityType;
 19/** Model for free time available in each period. 
 20 * At present this tends to give results where the farmer gets huge amounts of freetime. 
 21 * This is because we don't yet model the possibility of casual or contract labour to 
 22 * take the need for permanent contractors down during peak times. 
 23 * @author iracooke
 24 *
 25 */
 26public class FreeTimeComponent extends ModelComponent {
 27	private ArrayList<Double> preferenceWeights = new ArrayList<Double>();
 28	private Map<Integer,MatrixVariable> freeTimeByPeriod = new HashMap<Integer,MatrixVariable>();
 29	public FreeTimeComponent(){
 30		super(ModelComponent.MCType.FREETIME);
 31		requireObjective(ObjectiveType.FREETIME);
 32		addConstraintBuilder(new FreeTimeVResourcesConstraint());
 33		addConstraintBuilder(new FreeTimeMaxConstraint());
 34	}
 35	public FreeTimeComponent copy(){
 36		return new FreeTimeComponent();
 37	}
 38	public void setFormulaVariables(){}
 39
 40	public Map<Integer,Double> getSolvedFreeTime(){
 41		Map<Integer,Double> ft=new HashMap<Integer,Double>();
 42		for(Integer p:freeTimeByPeriod.keySet()){
 43			ft.put(p,freeTimeByPeriod.get(p).solution());
 44		}
 45		return ft;
 46	}
 47	
 48	/** Ensures that the farmer cannot have more than his entire life in free time. 
 49	 * This avoids an infeasibility which could occur if you put too much value 
 50	 * on free time and the model would hire labour to provide it */
 51	public final class FreeTimeMaxConstraint extends ConstraintBuilder {
 52		public FreeTimeMaxConstraint(){
 53			super(ConstraintBuilder.CBType.FREETIMEMAX,ModelComponent.MCType.FREETIME);
 54		}
 55		protected void build(){
 56			Farm parent = getParent();
 57			Location loc = parent.location();
 58			int numPeriods=parent.numPeriods;
 59			int row=matrix.numRows();			
 60			// Get this from workers
 61			HashMap<WorkerSubType,Worker> wmap=parent.workers.getWorkers(WorkerType.LABOUR);
 62			if ( !wmap.containsKey(WorkerSubType.FARMER)){
 63				throw new Error("Can't add constraint to free time objective because no Farmer WorkerSubType defined ");
 64			}
 65			Worker fmrp=wmap.get(WorkerSubType.FARMER);
 66			for ( int p=0;p<numPeriods;p++){ // Loop Periods 
 67				MatrixRow rp=new MatrixRow(0,0,LPX.LPX_LO,
 68						row,"FreeTime","Freetime_in_p_"+p);
 69				matrix.addRow(rp);	
 70				row++;
 71
 72				rp.addElement(new MatrixElement(freeTimeByPeriod.get(p).column(),-1)); // Free time being used as free time
 73				double avail=loc.availableFreeTimeHours(p);				
 74				rp.addElement(new MatrixElement(fmrp.getDependentColumn(0),avail)); // Total free time available
 75			}
 76		}
 77	}
 78	
 79	public final class FreeTimeVResourcesConstraint extends ConstraintBuilder {
 80		public FreeTimeVResourcesConstraint(){
 81			super(ConstraintBuilder.CBType.FREETIMEVRESOURCES,ModelComponent.MCType.FREETIME);
 82		}
 83		protected void build(){
 84			Farm parent = getParent();
 85			CroppingComponent cropping = parent.cropping;
 86			Location location = parent.location();
 87			int numPeriods=parent.numPeriods;
 88			int row=matrix.numRows();			
 89			// Get this from workers
 90			HashMap<WorkerSubType,Worker> wmap=parent.workers.getWorkers(WorkerType.LABOUR);
 91			if ( !wmap.containsKey(WorkerSubType.FARMER)){
 92				throw new Error("Can't add constraint to free time objective because no Farmer WorkerSubType defined ");
 93			}
 94			Worker fmrp=wmap.get(WorkerSubType.FARMER);
 95			HashMap<Integer,MatrixRow> rowlist = new HashMap<Integer,MatrixRow>();
 96			MatrixRow rp=null;
 97			for ( int p=0;p<numPeriods*Farm.maxYears;p++){ // Loop Periods 
 98				int periodicp = Farm.wrapPeriod(p,numPeriods);
 99				if ( !rowlist.containsKey(periodicp)){
100					rp=new MatrixRow(0,0,LPX.LPX_LO,
101							row,"FreeTime","Freetime_in_"+p);
102					matrix.addRow(rp);	
103					rowlist.put(periodicp, rp);
104					row++;
105				}
106				rp=rowlist.get(periodicp);
107				rp.addElement(new MatrixElement(freeTimeByPeriod.get(periodicp).column(),-1)); // Free time being used as free time
108				double avail=location.availableFreeTimeHours(periodicp);				
109				rp.addElement(new MatrixElement(fmrp.getDependentColumn(0),avail)); // Total free time available
110				// And we need to account for time freed up by other workers 
111				for ( Worker otherlab:wmap.values()){
112					if ( otherlab.subType!=WorkerSubType.FARMER){
113						// Work hours not free time hours
114						rp.addElement(new MatrixElement(otherlab.getDependentColumn(0),location.availableHours(periodicp)));
115					}
116				}
117				for(CropYear cropyr:cropping.cropYears()){
118					CropCopy cp=cropping.getCrop(cropyr.base).getCopy(cropyr.copyYear);
119					List<Operation> cpOps=cp.operations();
120					int numops = cpOps.size();
121					for ( int o=0;o<numops;o++){ // Loop operations for this crop
122						Operation op = cpOps.get(o);
123						if ( op.unfoldedAllowedSet().contains(p) && op.requiresWorker(WorkerType.LABOUR)){	
124							double required=op.workrate(location)*op.numRequiredForWorkerType(WorkerType.LABOUR);
125							rp.addElement(new MatrixElement(op.getDependentColumn(p),-required)); // Free time used up by work
126						}
127					}
128				}
129			}
130		}
131	} 
132	
133	/* (non-Javadoc)
134	 * @see jfm.lp.ModelComponent#initializeStructure()
135	 */
136	@Override
137	protected void initializeStructure() {
138		freeTimeByPeriod.clear();
139		
140		Farm parent = getParent();
141		// If pref weights not set then just use the default
142		if ( preferenceWeights.size()==0){
143			for(int p=0;p<parent.numPeriods;p++){
144				preferenceWeights.add(1.0);
145			}
146		}
147		
148		if ( preferenceWeights.size()!=parent.numPeriods){
149			throw new Error("preference weights on free time do not match the number of periods ");
150		}
151		for (int p=0;p<parent.numPeriods;p++){
152			MatrixVariable newVariable=new MatrixVariable(preferenceWeights.get(p),
153					0.0,0.0,
154					LPX.LPX_LO,LPX.LPX_CV,matrix.numCols(),ObjectiveType.FREETIME);
155		newVariable.setTag("ft_"+p);
156		matrix.addVariable(newVariable);	
157		freeTimeByPeriod.put(p,newVariable);
158		}
159	}
160
161	/* (non-Javadoc)
162	 * @see jfm.lp.ModelComponent#name()
163	 */
164	@Override
165	protected String name() {		
166		return "Free Time";
167	}
168
169	/* (non-Javadoc)
170	 * @see jfm.lp.ModelComponent#updateStructure()
171	 */
172	@Override
173	protected void updateStructure() {
174		// TODO Auto-generated method stub
175
176	}
177
178}