public void AddResult(Dictionary <WIPDepDistParameters, Tuple <double, double> > results, Dictionary <string, Distribution> parameters, Tuple <double, double> result) { EPTDistribution dist = (EPTDistribution)parameters.First().Value; WIPDepDistParameters x = dist.Par; results.Add(x, result); }
// Mean and variance set in base are wrong and should not be used. This distribution does not have a single mean and variance, since it is WIP-dependent public EPTDistribution(WIPDepDistParameters parameters) : base(parameters.Tmax, parameters.Cmax) { Par = parameters; Distributions = new Dictionary <int, Distribution>(); for (int WIP = 1; WIP <= Par.UBWIP; WIP++) { Distributions.Add(WIP, new GammaDistribution(MeanAtWIP(WIP), VarianceAtWIP(WIP))); //Console.WriteLine($"WIP: {WIP}, {MeanAtWIP(WIP)} \t {Math.Sqrt(VarianceAtWIP(WIP)/ (MeanAtWIP(WIP) * MeanAtWIP(WIP)))}"); } }
/// <summary> /// Write all evaluated paramater configurations to file /// </summary> public void WriteAllSolutions(Dictionary <WIPDepDistParameters, Tuple <double, double> > solutions, string wc) { using (StreamWriter writer = new StreamWriter(Path.Combine(outputDirectory, $"{wc}_parameters.txt"))) { writer.WriteLine("LBWIP,UBWIP,Tmin,Tmax,Tdecay,Cmin,Cmax,Cdecay,AverageQL,StdQL"); foreach (KeyValuePair <WIPDepDistParameters, Tuple <double, double> > solution in solutions) { WIPDepDistParameters pars = solution.Key; Tuple <double, double> result = solution.Value; writer.WriteLine(pars.LBWIP + "," + pars.UBWIP + "," + pars.Tmin + "," + pars.Tmax + "," + pars.Tdecay + "," + pars.Cmin + "," + pars.Cmax + "," + pars.Cdecay + "," + result.Item1 + "," + result.Item2); } } }
/// <summary> /// Write current and best parameter configurations to file. /// </summary> public void WriteFinalSolutions(Dictionary <string, Distribution> currentPar, Tuple <double, double> currentRes, Dictionary <string, Distribution> bestPar, Tuple <double, double> bestRes, string wc) { using (StreamWriter writer = new StreamWriter(Path.Combine(outputDirectory, $"{wc}_best_parameters.txt"))) { writer.WriteLine("Parameters,LBWIP,UBWIP,Tmin,Tmax,Tdecay,Cmin,Cmax,Cdecay,AverageQL,StdQL"); EPTDistribution dist = (EPTDistribution)currentPar.First().Value; WIPDepDistParameters par = dist.Par; writer.WriteLine($"Current,{par.LBWIP},{par.UBWIP},{par.Tmin},{par.Tmax},{par.Tdecay},{par.Cmin},{par.Cmax},{par.Cdecay},{currentRes.Item1},{currentRes.Item2}"); dist = (EPTDistribution)bestPar.First().Value; par = dist.Par; writer.WriteLine($"Best,{par.LBWIP},{par.UBWIP},{par.Tmin},{par.Tmax},{par.Tdecay},{par.Cmin},{par.Cmax},{par.Cdecay},{bestRes.Item1},{bestRes.Item2}"); } }
public Dictionary <string, Distribution> CopyParameters(Dictionary <string, Distribution> parameters) { EPTDistribution dist = (EPTDistribution)parameters.First().Value; WIPDepDistParameters x = dist.Par; WIPDepDistParameters pars = new WIPDepDistParameters { LBWIP = x.LBWIP, UBWIP = x.UBWIP, Tmin = x.Tmin, Tmax = x.Tmax, Tdecay = x.Tdecay, Cmin = x.Cmin, Cmax = x.Cmax, Cdecay = x.Cdecay }; Dictionary <string, Distribution> copiedParameters = new Dictionary <string, Distribution> { { wc, new EPTDistribution(pars) } }; return(copiedParameters); }
public Dictionary <string, Distribution> GetServiceTimeDistributions(string eptParameterFile) { Dictionary <string, Distribution> dict = new Dictionary <string, Distribution>(); Dictionary <string, WIPDepDistParameters> parameters = new Dictionary <string, WIPDepDistParameters>(); // Read fitted WIP dependent EPT parameters from csv using (StreamReader reader = new StreamReader(Path.Combine(directory, eptParameterFile))) { string[] headers = reader.ReadLine().Trim(',').Split(','); while (!reader.EndOfStream) { WIPDepDistParameters par = new WIPDepDistParameters(); string[] data = reader.ReadLine().Trim(',').Split(','); for (int i = 0; i < data.Length; i++) { if (headers[i] == "WorkStation") { if (!workcenters.Contains(data[i])) { throw new Exception($"Waferfab does not contain workcenter {data[i]}"); } par.WorkCenter = data[i]; } if (headers[i] == "wip_min") { par.LBWIP = (int)double.Parse(data[i]); } if (headers[i] == "wip_max") { par.UBWIP = (int)double.Parse(data[i]); } if (headers[i] == "t_min") { par.Tmin = double.Parse(data[i]); } if (headers[i] == "t_max") { par.Tmax = double.Parse(data[i]); } if (headers[i] == "t_decay") { par.Tdecay = double.Parse(data[i]); } if (headers[i] == "c_min") { par.Cmin = double.Parse(data[i]); } if (headers[i] == "c_max") { par.Cmax = double.Parse(data[i]); } if (headers[i] == "c_decay") { par.Cdecay = double.Parse(data[i]); } } parameters.Add(par.WorkCenter, par); } } foreach (string wc in workcenters) { dict.Add(wc, new EPTDistribution(parameters[wc])); } return(dict); }
public Dictionary <string, Distribution> GenerateNeighbour(Dictionary <string, Distribution> currentPar, double temp) { EPTDistribution dist = (EPTDistribution)currentPar.First().Value; WIPDepDistParameters x = dist.Par; WIPDepDistParameters par = new WIPDepDistParameters { WorkCenter = wc }; UniformDistribution parDist = new UniformDistribution(0, Parameter.TotalWeight); double u = parDist.Next(); // x is the original parameter set (input), par is a neighbouring parameter set // Change one parameter based on a probability if (isInRange("LBWIP", u)) { par.LBWIP = (int)Math.Max(1, newValue("LBWIP", x.LBWIP)); } else { par.LBWIP = x.LBWIP; } if (isInRange("UBWIP", u)) { par.UBWIP = (int)Math.Max(1, newValue("UBWIP", x.UBWIP)); } else { par.UBWIP = x.UBWIP; } if (isInRange("Tmin", u)) { par.Tmin = newValue("Tmin", x.Tmin); } else { par.Tmin = x.Tmin; } if (isInRange("Tmax", u)) { par.Tmax = newValue("Tmax", x.Tmax); } else { par.Tmax = x.Tmax; } if (isInRange("Tdecay", u)) { par.Tdecay = newValue("Tdecay", x.Tdecay); } else { par.Tdecay = x.Tdecay; } if (isInRange("Cmin", u)) { par.Cmin = newValue("Cmin", x.Cmin); } else { par.Cmin = x.Cmin; } if (isInRange("Cmax", u)) { par.Cmax = newValue("Cmax", x.Cmax); } else { par.Cmax = x.Cmax; } if (isInRange("Cdecay", u)) { par.Cdecay = newValue("Cdecay", x.Cdecay); } else { par.Cdecay = x.Cdecay; } Dictionary <string, Distribution> neighbour = new Dictionary <string, Distribution> { { wc, new EPTDistribution(par) } }; return(neighbour); bool isInRange(string parName, double u) { Parameter parameter = ParConfig[parName]; double pLower = parameter.CumulativeWeight - parameter.Weight; double pUpper = parameter.CumulativeWeight; if (u > pLower && u <= pUpper) { return(true); } else { return(false); } } double newValue(string parName, double value) { // Use Min-max feature scaling to determine the half width size of the new value // Large range at high temps (50%), small range at low temps (10%) double halfWidth = (0.5 - 0.1) * temp / maxTemp + 0.1; Parameter parameter = ParConfig[parName]; double lowerBound = Math.Max(parameter.LowerBound, value - value * halfWidth); double upperBound = Math.Min(parameter.UpperBound, value + value * halfWidth); UniformDistribution valueDist = new UniformDistribution(lowerBound, upperBound); return(valueDist.Next()); } }
public EPTDistribution CheckInitialDistBounds(EPTDistribution dist) { WIPDepDistParameters x = dist.Par; // For each initial value, check if it is within bounds. If not, set to closest bound if (x.Tmin < ParConfig["Tmin"].LowerBound) { x.Tmin = ParConfig["Tmin"].LowerBound; } else if (x.Tmin > ParConfig["Tmin"].UpperBound) { x.Tmin = ParConfig["Tmin"].UpperBound; } if (x.Tmax < ParConfig["Tmax"].LowerBound) { x.Tmax = ParConfig["Tmax"].LowerBound; } else if (x.Tmax > ParConfig["Tmax"].UpperBound) { x.Tmax = ParConfig["Tmax"].UpperBound; } if (x.Tdecay < ParConfig["Tdecay"].LowerBound) { x.Tdecay = ParConfig["Tdecay"].LowerBound; } else if (x.Tdecay > ParConfig["Tdecay"].UpperBound) { x.Tdecay = ParConfig["Tdecay"].UpperBound; } if (x.Cmin < ParConfig["Cmin"].LowerBound) { x.Cmin = ParConfig["Cmin"].LowerBound; } else if (x.Cmin > ParConfig["Cmin"].UpperBound) { x.Cmin = ParConfig["Cmin"].UpperBound; } if (x.Cmax < ParConfig["Cmax"].LowerBound) { x.Cmax = ParConfig["Cmax"].LowerBound; } else if (x.Cmax > ParConfig["Cmax"].UpperBound) { x.Cmax = ParConfig["Cmax"].UpperBound; } if (x.Cdecay < ParConfig["Cdecay"].LowerBound) { x.Cdecay = ParConfig["Cdecay"].LowerBound; } else if (x.Cdecay > ParConfig["Cdecay"].UpperBound) { x.Cdecay = ParConfig["Cdecay"].UpperBound; } EPTDistribution newDist = new EPTDistribution(x); return(newDist); }
public Tuple <double, double> RunSim(Dictionary <string, Distribution> dict) { EPTDistribution dist = (EPTDistribution)dict.First().Value; WIPDepDistParameters x = dist.Par; waferFabSettings.WCServiceTimeDistributions = new Dictionary <string, Distribution> { { wc, new EPTDistribution(x) } }; #region Initializing simulation Simulation simulation = new Simulation("CSSLWaferFabArea", outputDirectory); #endregion #region Experiment settings simulation.MyExperiment.NumberOfReplications = 10; DateTime finalDateTime = new DateTime(2019, initialDateTime.Month + 2, 1); simulation.MyExperiment.LengthOfReplication = (finalDateTime - initialDateTime).TotalSeconds; // Number of seconds between two months simulation.MyExperiment.LengthOfWarmUp = 60 * 60 * 24 * 0; #endregion #region Building the model WaferFab waferFab = new WaferFab(simulation.MyModel, "WaferFab", new ConstantDistribution(60 * 60 * 24), initialDateTime); WorkCenter workCenter = new WorkCenter(waferFab, $"WorkCenter_{wc}", waferFabSettings.WCServiceTimeDistributions[wc], waferFabSettings.LotStepsPerWorkStation[wc]); // Connect workcenter to WIPDependentDistribution EPTDistribution distr = (EPTDistribution)waferFabSettings.WCServiceTimeDistributions[wc]; distr.WorkCenter = workCenter; EPTOvertakingDispatcher dispatcher = new EPTOvertakingDispatcher(workCenter, workCenter.Name + "_EPTOvertakingDispatcher", waferFabSettings.WCOvertakingDistributions[wc]); workCenter.SetDispatcher(dispatcher); // Connect workcenter to OvertakingDistribution waferFabSettings.WCOvertakingDistributions[wc].WorkCenter = workCenter; waferFab.AddWorkCenter(workCenter.Name, workCenter); // Sequences foreach (var sequence in waferFabSettings.Sequences) { waferFab.AddSequence(sequence.Key, sequence.Value); } // LotSteps waferFab.LotSteps = waferFab.Sequences.Select(x => x.Value).Select(x => x.GetCurrentStep(0)).ToDictionary(x => x.Name); // LotGenerator waferFab.SetLotGenerator(new LotGenerator(waferFab, "LotGenerator", new ConstantDistribution(60), true)); // Add lotstarts waferFab.LotStarts = waferFabSettings.LotStarts; // Add initial lots if (useInitialLots) { List <Lot> initialLotsDeepCopy = initialLots.ConvertAll(x => new Lot(x)); waferFab.InitialLots = initialLotsDeepCopy; } // Add observers OptimiserObserver optimiserObs = new OptimiserObserver(simulation, wc + "_TotalQueueObserver"); workCenter.Subscribe(optimiserObs); // Total queue for workcenter #endregion simulation.Run(); #region Reporting SimulationReporter reporter = simulation.MakeSimulationReporter(); reporter.PrintSummaryToConsole(); #endregion Tuple <double, double> results = new Tuple <double, double>(optimiserObs.QueueLengthStatistic.Average(), optimiserObs.QueueLengthStatistic.StandardDeviation()); return(results); }