public WaferAreaSim(string wc, string eptParameterFile, string inputDirectory, string outputDirectory, DateTime initialDateTime, Optimiser optimiser, bool useInitialLots = false) { this.wc = wc; this.inputDirectory = inputDirectory; this.outputDirectory = outputDirectory; this.initialDateTime = initialDateTime; this.optimiser = optimiser; this.useInitialLots = useInitialLots; #region WaferFab settings waferFabSettings = Deserializer.DeserializeWaferFabSettings(Path.Combine(inputDirectory, "SerializedFiles", $"WaferFabSettings_{wc}_WithLotStarts.dat")); distributionReader = new EPTDistributionReader(Path.Combine(inputDirectory, "CSVs"), waferFabSettings.WorkCenters, waferFabSettings.LotStepsPerWorkStation); // Get initial parameters waferFabSettings.WCServiceTimeDistributions = distributionReader.GetServiceTimeDistributions(eptParameterFile); EPTDistribution initialDist = (EPTDistribution)waferFabSettings.WCServiceTimeDistributions[wc]; InitialParameters = new Dictionary <string, Distribution> { { wc, optimiser.CheckInitialDistBounds(initialDist) } }; waferFabSettings.WCOvertakingDistributions = distributionReader.GetOvertakingDistributions(); #endregion if (useInitialLots) { initialLots = optimiser.GetInitialLots(wc, inputDirectory, outputDirectory, initialDateTime, waferFabSettings); } }
static void Main(string[] args) { string inputDirectory = @"C:\CSSLWaferFab\Input\WSC2021paper"; string outputDirectory = @"C:\CSSLWaferFab\Output\WaferAreaOptimiser"; ReaderWriter readerWriter = new ReaderWriter(inputDirectory, outputDirectory); Dictionary <string, Tuple <double, double> > realQueueLengths = readerWriter.GetRealQueueLengths(); List <string> workCenters = realQueueLengths.Keys.ToList(); // All work centers workCenters = new List <string>() // Remove to evaluate all work centers { "PHOTOLITH", "DRY ETCH" }; foreach (string workCenter in workCenters) { #region Parameters // Model parameters string wc = workCenter; DateTime initialDateTime = new DateTime(2019, 6, 1); string eptParameterFile = @"FittedEPTParameters - 2019-06-01.csv"; bool useInitialLots = true; Settings.WriteOutput = false; // Simulated annealing parameters double temp = 25; double cooldown = 0.993; //0.995 = 1102 solutions, 0.996 = 1378 solutions, 0.997 = 1834 solutions double meanObj = realQueueLengths[wc].Item1; double stdObj = realQueueLengths[wc].Item2; // Dictionary with parameters to optimise and optional weights Dictionary <string, Parameter> parameterConfiguration = new Dictionary <string, Parameter>() { { "LBWIP", new Parameter("LBWIP", false) }, { "UBWIP", new Parameter("UBWIP", false) }, { "Tmin", new Parameter("Tmin", false) }, { "Tmax", new Parameter("Tmax", true) }, { "Tdecay", new Parameter("Tdecay", true) }, { "Cmin", new Parameter("Cmin", true) }, { "Cmax", new Parameter("Cmax", true) }, { "Cdecay", new Parameter("Cdecay", true) } }; #endregion #region Variables and instances Optimiser optimiser = new Optimiser(wc, temp, parameterConfiguration); optimiser.SetBounds(inputDirectory); WaferAreaSim waferAreaSim = new WaferAreaSim(wc, eptParameterFile, inputDirectory, outputDirectory, initialDateTime, optimiser, useInitialLots); Dictionary <string, Distribution> currentPar, nextPar, bestPar; Tuple <double, double> currentRes, nextRes, bestRes; double currentCost, nextCost, bestCost, deltaCost; Dictionary <WIPDepDistParameters, Tuple <double, double> > results = new Dictionary <WIPDepDistParameters, Tuple <double, double> >(); // Save all solutions UniformDistribution uDist = new UniformDistribution(0, 1); #endregion #region Simulated annealing algorithm // Initial model parameters and results currentPar = waferAreaSim.InitialParameters; bestPar = optimiser.CopyParameters(currentPar); currentRes = waferAreaSim.RunSim(currentPar); bestRes = optimiser.CopyResults(currentRes); currentCost = Math.Abs(currentRes.Item1 - meanObj) + 0.5 * Math.Abs(currentRes.Item2 - stdObj); bestCost = currentCost; optimiser.AddResult(results, currentPar, currentRes); // Iterate and evaluate solutions until sufficiently cooled down int i = 0; while (temp > 0.1 && currentCost > Math.Min(1, 0.1 * (meanObj + stdObj))) // If a good solution is found, stop searching { nextPar = optimiser.GenerateNeighbour(currentPar, temp); nextRes = waferAreaSim.RunSim(nextPar); nextCost = Math.Abs(nextRes.Item1 - meanObj) + 0.5 * Math.Abs(nextRes.Item2 - stdObj); optimiser.AddResult(results, nextPar, nextRes); if (nextCost < currentCost) // New solution is better than current, accept new solution { currentPar = optimiser.CopyParameters(nextPar); currentRes = optimiser.CopyResults(nextRes); currentCost = nextCost; if (nextCost < bestCost) // New solution is better best, accept new best solution { bestPar = optimiser.CopyParameters(nextPar); bestRes = optimiser.CopyResults(nextRes); bestCost = nextCost; } } else { deltaCost = nextCost - currentCost; if (uDist.Next() < Math.Pow(Math.E, -deltaCost / temp)) // Accept solution if u ~ U[0,1] < e^-(dC/T) { currentPar = optimiser.CopyParameters(nextPar); currentRes = optimiser.CopyResults(nextRes); currentCost = nextCost; } } temp = temp * cooldown; // Reduce temperature i++; Console.WriteLine("\nResults for area {0}.", wc); Console.WriteLine("Iteration: {0}. Temperature {1}", i, temp); Console.WriteLine("Evaluated solution: {0}, {1}", nextRes.Item1, nextRes.Item2); Console.WriteLine("Current solution: {0}, {1}", currentRes.Item1, currentRes.Item2); Console.WriteLine("Best solution: {0}, {1}\n", bestRes.Item1, bestRes.Item2); } #endregion #region Write results to file // Write all results to a text file readerWriter.WriteAllSolutions(results, wc); // Write the best and current solution to a text file readerWriter.WriteFinalSolutions(currentPar, currentRes, bestPar, bestRes, wc); #endregion } }