private bool CostIncreasesWithNewDate(TimelinessOpComp1 leastCostTOC) { //Rule 3. If the leastCostToc total costs don't increase when //the actual date is moved ahead to overcome overlap, it's the best bool bCostIsMoreWithNewActualDate = true; TimelinessOpComp1 dateOpComp = this.BestOpComps.Last(ocb => ocb.ProbableFinishDate > leastCostTOC.PlannedStartDate); if (dateOpComp != null) { TimelinessOpComp1 newDateOpComp = new TimelinessOpComp1(leastCostTOC); bCostIsMoreWithNewActualDate = TimelinessOpComp1.TimelinessPenaltyIncreasesUsingNewDate( newDateOpComp, dateOpComp.ProbableFinishDate); } if (bCostIsMoreWithNewActualDate == false) { //keep the existing least cost, but reset penalty and dates if (dateOpComp != null) { TimelinessOpComp1.SetTimelinessPenaltyNewActualDate(leastCostTOC, dateOpComp.ProbableFinishDate); } } return(bCostIsMoreWithNewActualDate); }
private void MakeBestMachineryCombos(List <TimelinessTimePeriod1> timelinessTimePeriods, int[] state, double[][] problemData) { List <TimelinessOpComp1> uniqueTimelinessOpComps = new List <TimelinessOpComp1>(); //best unique opcomp for (int t = 0; t < state.Length; ++t) { //feasible opcomp int w = state[t]; TimelinessOpComp1 newBestOC = this.WOpComps.ElementAtOrDefault(w); TimelinessOpComp1 newUniqueOC = this.TOpComps.ElementAtOrDefault(t); newUniqueOC.TimelinessOpComps = new List <TimelinessOpComp1>(); //match to parent uniqueOC newUniqueOC.TimelinessOpComps.Add(newBestOC); uniqueTimelinessOpComps.Add(newUniqueOC); } //build a stateful new collection of best ocs //refactor: they have to go with correct tp, so use a subroutine to add foreach (TimelinessTimePeriod1 tp in timelinessTimePeriods) { //add them to end of collection this.BestTimelinessTimePeriods.Add(tp); //make sure this is a byref that changes internal collection TimelinessTimePeriod1 newTP = this.BestTimelinessTimePeriods .ElementAtOrDefault(this.BestTimelinessTimePeriods.Count - 1); //start a new list newTP.TimelinessOpComps = new List <TimelinessOpComp1>(); foreach (TimelinessOpComp1 bestoc in uniqueTimelinessOpComps) { //add it to end of collection (each besttoc has one member of besttoc.tocs that is best) newTP.TimelinessOpComps.Add(bestoc); } } }
private bool CostIsMoreWithNewActualDate(TimelinessOpComp1 leastCostTOC) { bool bCostIsMoreWithNewActualDate = true; foreach (var boc in this.BestOpComps) { //these are mach1inputs that inherit from a base input if (boc.Inputs != null) { if (leastCostTOC.Inputs != null) { List <Machinery1Input> sameBOCs = new List <Machinery1Input>(); foreach (var bocinput in boc.Inputs) { Machinery1Input machInput = (Machinery1Input)bocinput; sameBOCs.Add(machInput); } foreach (var locinput in leastCostTOC.Inputs) { Machinery1Input machlocInput = (Machinery1Input)locinput; bCostIsMoreWithNewActualDate = BIMachinery2aStockCalculator.HasPowerInput(machlocInput, sameBOCs); if (bCostIsMoreWithNewActualDate == false) { bCostIsMoreWithNewActualDate = BIMachinery2aStockCalculator.HasNonPowerInput(machlocInput, sameBOCs); } else { return(true); } } } } } return(bCostIsMoreWithNewActualDate); }
private TimelinessOpComp1 CopyTimelinessOpComp(TimelinessOpComp1 existingTimelinessOpComp) { TimelinessOpComp1 newTimelinessOpComp = null; if (existingTimelinessOpComp != null) { //the properties of newTOC can be safely changed newTimelinessOpComp = new TimelinessOpComp1(existingTimelinessOpComp); newTimelinessOpComp.CopyCalculatorProperties(existingTimelinessOpComp); newTimelinessOpComp.XmlDocElement = existingTimelinessOpComp.XmlDocElement; newTimelinessOpComp.CopyTotalCostsProperties(existingTimelinessOpComp); newTimelinessOpComp.CopyTimelinessOC1Properties(existingTimelinessOpComp); //these are filled dynamically (after ordering, optimization) newTimelinessOpComp.TimelinessOpComps = new List <TimelinessOpComp1>(); //inputs shouldn't be changed, only the parent timelinessopcomp is changed newTimelinessOpComp.Inputs = new List <Input>(); if (existingTimelinessOpComp.Inputs != null) { foreach (var input in existingTimelinessOpComp.Inputs) { //this is byref, so don't change the inputs newTimelinessOpComp.Inputs.Add(input); } } } return(newTimelinessOpComp); }
private static double TotalMachineryCost(TimelinessOpComp1 initialTimelinessOCStock, Machinery1Input powerinput, Machinery1Input nonpowerinput) { double totalCost = 0; if (nonpowerinput.Constants.HPPTOMax > powerinput.Constants.HPPTOMax) { //powerinput - implement combos that are not possible must have a zero total cost //zero total cost tells best state to keep looking for a different combo totalCost = 0; } else { //stay consistent with other object structures used List <Machinery1Input> machInputs = new List <Machinery1Input>(); machInputs.Add(powerinput); machInputs.Add(nonpowerinput); //total costs are operating costs plus allocated overhead plus timeliness //on a per acre or per hectare basis //need to run oc costs so that the power input and non power have same field capacity totalCost = OpCompCostPerUnitArea(machInputs) + TimelinessCostPerUnitArea(initialTimelinessOCStock, machInputs); } return(totalCost); }
private static double TotalMachineryCost(TimelinessOpComp1 uniqueTOC, TimelinessOpComp1 feasibleTOC) { double totalCost = 0; //these are total costs (multiplied by input.ocamount or aohamount, inputtimes //and oc.amount) not cost per unit area totals foreach (var foc in uniqueTOC.TimelinessOpComps) { //note: foc.CalculatorId = parentTOC.Id and foc.Id is randomid if (feasibleTOC.Id == foc.Id) { //this feasibletoc belongs to this uniqueToc totalCost = feasibleTOC.TotalOC + feasibleTOC.TotalAOH + feasibleTOC.TimelinessPenaltyCost; break; } else { //never allow a zero cost oc in best state totalCost = 0; } } return(totalCost); }
private TimelinessOpComp1[][] MakeDynamicCostData(List <TimelinessTimePeriod1> timelinessTimePeriods) { //feasible opcomps are first member of array (w) TimelinessOpComp1[][] result = new TimelinessOpComp1[this.WOpComps.Count][]; //could also declare as: type double[,] = int w = 0; //unique opcomps are the second array member (t) for (w = 0; w < result.Length; ++w) { result[w] = new TimelinessOpComp1[this.TOpComps.Count]; } //the problem matrix w = 0; int t = 0; double dbTotalCost = 0; foreach (var feasibleOC in this.WOpComps) { //any feasible oc that is not a child of the unique oc has a cost of zero foreach (var uniqueOC in this.TOpComps) { //dbTotalCost = TotalMachineryCost(uniqueOC, feasibleOC); result[w][t] = feasibleOC; //MakeDynamicCostMember(result[w][t], //w, t, uniqueOC, feasibleOC); t++; } t = 0; w++; } //example array (last member can't be chosen) //result[0][0] = 7.55; result[0][1] = 3.89; result[0][2] = 0; return(result); }
private void ReSetCurrentState() { this.CurrentStateOpComps.Clear(); //current state always starts with beststate and then sees //if changing the current feasible opcomp lowers best state foreach (TimelinessOpComp1 oc in this.BestOpComps) { //new collections are needed because the members //will be changed anytime an actual date has to be changed TimelinessOpComp1 newUniqueTimelinessOpComp = CopyTimelinessOpComp(oc); //ascending order by finishdate (start date is the same) if (oc.TimelinessOpComps != null) { int i = 0; foreach (TimelinessOpComp1 foc in oc.TimelinessOpComps) { if (i == 0) { TimelinessOpComp1 newFeasibleTimelinessOpComp = CopyTimelinessOpComp(foc); newUniqueTimelinessOpComp.TimelinessOpComps.Add(newFeasibleTimelinessOpComp); } i++; } } //add it to the currentstate collections this.CurrentStateOpComps.Add(newUniqueTimelinessOpComp); } }
private double[][] MakeProblemData(TimelinessOpComp1 initialTimelinessOCStock) { // the problem matrix //powerInputs are the first member of array (w) double[][] result = new double[this.PowerInputs.Count][]; //could also declare as: type double[,] = //nonpowerinputs are the second array member (t) for (int w = 0; w < result.Length; ++w) { result[w] = new double[this.NonPowerInputs.Count]; } //add the total cost value for each array index int i = 0; int j = 0; double dbTotalCost = 0; foreach (var powerinput in this.PowerInputs) { foreach (var nonpowerinput in this.NonPowerInputs) { dbTotalCost = TotalMachineryCost(initialTimelinessOCStock, powerinput, nonpowerinput); result[i][j] = dbTotalCost; j++; } j = 0; i++; } //example array //result[0][0] = 7.55; result[0][1] = 3.89; result[0][2] = 22.00; return(result); }
private TimelinessOpComp1 RunMoreCostLeastCostRules(TimelinessOpComp1 uniqueOpComp, int bestId) { //these rules start changing start and finish dates, with potential penalties TimelinessOpComp1 leastCostTOC = uniqueOpComp.TimelinessOpComps .FirstOrDefault(boc => boc.Id == bestId); if (leastCostTOC == null) { return(leastCostTOC); } //Rule 3. If the leastCostToc total costs, including the remaining BestCostCombos, //don't increase when the actual date is moved ahead to overcome overlap, it's the best bool bCostIsMoreWithNewActualDate = CostIncreasesWithNewDate(leastCostTOC); if (bCostIsMoreWithNewActualDate == false) { //leastCostTOC has reset penalty and dates to new date return(leastCostTOC); } //Rule 4. If all of the best opcomp's inputs are different than the overlapping //opcomps, no overlap, it's the best, so return it return(leastCostTOC); }
private TimelinessOpComp1 RunNoCostLeastCostRules(TimelinessOpComp1 uniqueOpComp, int bestId) { TimelinessOpComp1 leastCostTOC = uniqueOpComp.TimelinessOpComps .FirstOrDefault(boc => boc.Id == bestId); if (leastCostTOC == null) { return(leastCostTOC); } //Rule 1. If the best opcomp's StartDate is later than all of this.BestComps //finish dates, no overlap, it's the best, so return it bool bHasOverlap = this.BestOpComps .Any(ocb => ocb.ProbableFinishDate > leastCostTOC.PlannedStartDate); if (bHasOverlap == false) { return(leastCostTOC); } //Rule 2. If all of the best opcomp's inputs are different than the overlapping //opcomps, no overlap, it's the best, so return it bool bHasSameEquipment = HasSameEquipment(leastCostTOC); if (bHasSameEquipment == false) { return(leastCostTOC); } return(null); }
private static double TotalMachineryCost(TimelinessOpComp1 feasibleTOC) { double totalCost = feasibleTOC.TotalOC + feasibleTOC.TotalAOH + feasibleTOC.TimelinessPenaltyCost; return(totalCost); }
private void SetOrderedTOCs( List <TimelinessTimePeriod1> timelinessTimePeriods) { List <TimelinessOpComp1> opCompsDateOrdered = new List <TimelinessOpComp1>(); //make ascending date order collections IOrderedEnumerable <TimelinessTimePeriod1> ascendingTPs = timelinessTimePeriods.OrderBy(tp => tp.Date); //get all of the tocs available in all tps List <TimelinessOpComp1> allTOCS = new List <TimelinessOpComp1>(); foreach (TimelinessTimePeriod1 tp in ascendingTPs) { foreach (TimelinessOpComp1 aoc in tp.TimelinessOpComps) { allTOCS.Add(aoc); } } //order them by ascending startdate (this becomes the required order) IOrderedEnumerable <TimelinessOpComp1> ascendingOCs = allTOCS.OrderBy(oc => oc.PlannedStartDate); foreach (TimelinessOpComp1 oc in ascendingOCs) { //new collections are needed because the members //will be changed anytime an actual date has to be changed TimelinessOpComp1 newUniqueTimelinessOpComp = CopyTimelinessOpComp(oc); TimelinessOpComp1 newUnique2TimelinessOpComp = CopyTimelinessOpComp(oc); //ascending order by finishdate (start date is the same) if (oc.TimelinessOpComps != null) { IOrderedEnumerable <TimelinessOpComp1> ascendingFOCs = oc.TimelinessOpComps.OrderBy(woc => woc.ProbableFinishDate); int i = 0; foreach (TimelinessOpComp1 foc in ascendingFOCs) { //add the feasible opcomp to the unique opcomp oc.TimelinessOpComps.Add(foc); if (i == 0) { //add it to the optimization collections TimelinessOpComp1 newFeasibleTimelinessOpComp = CopyTimelinessOpComp(foc); newUniqueTimelinessOpComp.TimelinessOpComps.Add(newFeasibleTimelinessOpComp); TimelinessOpComp1 newFeasible2TimelinessOpComp = CopyTimelinessOpComp(foc); newUnique2TimelinessOpComp.TimelinessOpComps.Add(newFeasible2TimelinessOpComp); } i++; } } //add it to the unique collections this.InitialOpComps.Add(oc); this.BestOpComps.Add(newUniqueTimelinessOpComp); this.CurrentStateOpComps.Add(newUnique2TimelinessOpComp); } }
private TimelinessOpComp1 MakeDynamicCostMember(TimelinessOpComp1 previousArrayMember, int currentW, int currentT, TimelinessOpComp1 uniqueOC, TimelinessOpComp1 feasibleOC) { //adjust date by previous array member TimelinessOpComp1 adjustedArrayMember = null; //TimelinessOpComp1 previousArrayMember = null; return(adjustedArrayMember); }
private double SetTotalCostsForCurrentState() { double totalCost = 0; int i = 0; DateTime lastFinishDate = CalculatorHelpers.GetDateShortNow(); foreach (var uniqueOpComp in this.CurrentStateOpComps) { if (uniqueOpComp.TimelinessOpComps != null) { foreach (var feasibleOpComp in uniqueOpComp.TimelinessOpComps) { if (i == 0) { //no dates need to be adjusted for first uniqueopcom totalCost = TotalMachineryCost(feasibleOpComp); } else { //if needed, reset timeliness penalty if (lastFinishDate > feasibleOpComp.ActualStartDate) { TimelinessOpComp1.SetTimelinessPenaltyNewActualDate( feasibleOpComp, lastFinishDate); } else if (feasibleOpComp.PlannedStartDate != feasibleOpComp.ActualStartDate) { //see if the planned start date can be done earlier if (feasibleOpComp.PlannedStartDate > lastFinishDate) { TimelinessOpComp1.SetTimelinessPenaltyNewActualDate( feasibleOpComp, feasibleOpComp.PlannedStartDate); } else { //switch to a date somewhere between existing actual //and planned if (lastFinishDate > feasibleOpComp.PlannedStartDate && lastFinishDate < feasibleOpComp.ActualStartDate) { TimelinessOpComp1.SetTimelinessPenaltyNewActualDate( feasibleOpComp, lastFinishDate); } } } totalCost += TotalMachineryCost(feasibleOpComp); } lastFinishDate = feasibleOpComp.ProbableFinishDate; } i++; } } return(totalCost); }
private TimelinessOpComp1 GetLeastCostOpComp(TimelinessOpComp1 uniqueOpComp) { TimelinessOpComp1 leastCostTOC = null; //loop through collection, selecting lowest cost opcomps double dbBestCost = 0; double dbThisTotalCost = 0; int iBestId = 0; dbBestCost = 0; dbThisTotalCost = 0; //the collections have unique, random ids iBestId = 0; int i = 0; foreach (var feasibleOpComp in uniqueOpComp.TimelinessOpComps) { dbThisTotalCost = TotalMachineryCost(feasibleOpComp); if (i == 0) { dbBestCost = dbThisTotalCost; iBestId = feasibleOpComp.Id; } else { //has to be less cost to change to a potentially later finish date //zero means its not a feasible opcomp if (dbThisTotalCost < dbBestCost && dbThisTotalCost >= 0) { dbBestCost = dbThisTotalCost; iBestId = feasibleOpComp.Id; } } i++; } //return the best opcomp leastCostTOC = RunNoCostLeastCostRules(uniqueOpComp, iBestId); if (leastCostTOC != null) { return(leastCostTOC); } //else //{ // return leastCostTOC; // //leastCostTOC = RunMoreCostLeastCostRules(uniqueOpComp, iBestId); //} //null means no easy solution, run annealizing optimization with dynamic prices return(leastCostTOC); }
private double SetTotalCostsForCurrentState(int uniqueOpCompIndex, int feasibleOpCompIndex) { double totalCost = 0; //reset current state to the current best state ReSetCurrentState(); if (this.InitialOpComps[uniqueOpCompIndex] != null) { TimelinessOpComp1 newFeasibleTimelinessOpComp = CopyTimelinessOpComp( this.InitialOpComps[uniqueOpCompIndex].TimelinessOpComps[feasibleOpCompIndex]); if (newFeasibleTimelinessOpComp != null) { //clear the current feasible opcomp this.CurrentStateOpComps[uniqueOpCompIndex].TimelinessOpComps.Clear(); //add new one this.CurrentStateOpComps[uniqueOpCompIndex].TimelinessOpComps.Add(newFeasibleTimelinessOpComp); totalCost = SetTotalCostsForCurrentState(); } } return(totalCost); }
private static double TimelinessCostPerUnitArea(TimelinessOpComp1 initialTimelinessOCStock, List <Machinery1Input> machInputs) { //run new TimelinessCost penalty calculations using this combination of machinery double timelinessCostPerUnitArea = 0; double powerInputOCAmount = machInputs.FirstOrDefault().OCAmount; if (powerInputOCAmount != initialTimelinessOCStock.FieldCapacity) { TimelinessOpComp1 timelinessCalculator = new TimelinessOpComp1(initialTimelinessOCStock); //date only changes when npvcalcor is run timelinessCalculator.AddCalculationsProperties(powerInputOCAmount, initialTimelinessOCStock.PlannedStartDate); timelinessCostPerUnitArea = powerInputOCAmount * timelinessCalculator.TimelinessPenaltyCostPerHour; } else { timelinessCostPerUnitArea = powerInputOCAmount * initialTimelinessOCStock.TimelinessPenaltyCostPerHour; } return(timelinessCostPerUnitArea); }
private void SetBestState() { this.BestOpComps.Clear(); foreach (TimelinessOpComp1 oc in this.CurrentStateOpComps) { //new collections are needed because the members //will be changed anytime an actual date has to be changed TimelinessOpComp1 newUniqueTimelinessOpComp = CopyTimelinessOpComp(oc); //ascending order by finishdate (start date is the same) if (oc.TimelinessOpComps != null) { foreach (TimelinessOpComp1 foc in oc.TimelinessOpComps) { TimelinessOpComp1 newFeasibleTimelinessOpComp = CopyTimelinessOpComp(foc); newUniqueTimelinessOpComp.TimelinessOpComps.Add(newFeasibleTimelinessOpComp); } } //add it to the best collections this.BestOpComps.Add(newUniqueTimelinessOpComp); } }
public void RunOptimization( TimelinessOpComp1 initialTimelinessOCStock, List <Machinery1Input> machineryInputs) { BestMachineryCombos = new Dictionary <Machinery1Input, Machinery1Input>(); try { random = new Random(0); this.ErrorMessage = string.Empty; this.PowerInputs = machineryInputs.FindAll(m => m.FuelCost > 0); this.NonPowerInputs = machineryInputs.FindAll(m => m.FuelCost <= 0); if (this.PowerInputs.Count > 0 && this.NonPowerInputs.Count > 0) { // total cost index for problem definition double[][] problemData = MakeProblemData(initialTimelinessOCStock); //state represents a solution int array where the index is the nonpowerimplement and the value is the powerimplement //(powerinput - implement combos that are not possible must have a zero total cost) int[] state = RandomState(problemData); double energy = Energy(state, problemData); //best state is the least cost vector of 1 power input and 1 non power inputs int[] bestState = state; double bestEnergy = energy; int[] adjState; double adjEnergy; int iteration = 0; //the higher these are, the longer the algorithm runs //the longer the algo runs the more optimal the solution int maxIteration = 1000000; double currTemp = 10000.0; // cooling rate double alpha = 0.995; while (iteration < maxIteration && currTemp > 0.0001) { adjState = AdjacentState(state, problemData); adjEnergy = Energy(adjState, problemData); if (adjEnergy < bestEnergy) { bestState = adjState; bestEnergy = adjEnergy; } // [0, 1.0) double p = random.NextDouble(); if (AcceptanceProb(energy, adjEnergy, currTemp) > p) { state = adjState; energy = adjEnergy; } // cool down; annealing schedule currTemp = currTemp * alpha; ++iteration; } //temperature has cooled to (almost) zero at final iteration MakeBestMachineryCombos(bestState, problemData); } else { this.ErrorMessage = Errors.GetMessage("RESOURCESTOCKS_NOPOWERORNONPOWERINPUTS"); } } catch (Exception ex) { this.ErrorMessage = string.Concat(Errors.GetMessage("RESOURCESTOCKS_NOSIMULATEDANNEALING"), ex.ToString()); } }