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