Exemplo n.º 1
0
        static void Main(string[] args)
        {
            string inputDir = @"C:\CSSLWaferFab\Input\";

            string outputDir = @"C:\CSSLWaferFab\Output\WaferFabSim\";

            string parameters = @"FittedEPTParameters - 2019-8-1_4months.csv";

            DateTime initialDateTime = new DateTime(2019, 8, 1);

            Settings.WriteOutput = true;
            Settings.FixSeed     = true;

            ShellModel WaferFabSim = new ShellModel(outputDir);

            // Load WaferFab settings
            AutoDataReader reader = new AutoDataReader(inputDir + @"CSVs\", inputDir + @"SerializedFiles\");

            WaferFabSettings waferFabSettings = reader.ReadWaferFabSettings(parameters, true, true, DispatcherBase.Type.EPTOVERTAKING);

            waferFabSettings.SampleInterval       = 1 * 60 * 60; // seconds
            waferFabSettings.LotStartsFrequency   = 1;           // hours
            waferFabSettings.UseRealLotStartsFlag = true;

            // MIVS Settings
            //waferFabSettings.WIPTargets = reader.ReadWIPTargets(waferFabSettings.LotSteps, "WIPTargets.csv");
            //waferFabSettings.MIVSjStepBack = 2;
            //waferFabSettings.MIVSkStepAhead = 2;

            // Read Initial Lots
            WaferFabSim.ReadRealSnaphots(inputDir + @$ "SerializedFiles\RealSnapShots_2019-{initialDateTime.Month}-1_2019-{initialDateTime.Month + 1}-1_1h.dat");
            waferFabSettings.InitialRealLots = WaferFabSim.RealSnapshotReader.RealSnapshots.Where(x => x.Time.Date == initialDateTime).OrderBy(x => x.Time).First().GetRealLots(1);

            // Experiment settings
            ExperimentSettings experimentSettings = new ExperimentSettings();

            int count = waferFabSettings.InitialRealLots.Where(x => x.StartTime == null).Count();

            experimentSettings.NumberOfReplications = 30;
            experimentSettings.LengthOfReplication  = 121 * 24 * 60 * 60; // seconds
            experimentSettings.LengthOfWarmUp       = 0 * 60 * 60;        // seconds

            // Connect settings
            WaferFabSim.MyWaferFabSettings = waferFabSettings;

            WaferFabSim.MyExperimentSettings = experimentSettings;

            // Run simulation
            WaferFabSim.RunSimulation();

            // Report summary
            SimulationReporter reporter = WaferFabSim.MySimulation.MakeSimulationReporter();

            reporter.PrintSummaryToFile();
            reporter.PrintSummaryToConsole();
        }
Exemplo n.º 2
0
        static void Main(string[] args)
        {
            string inputDir = @"C:\Users\nx008314\OneDrive - Nexperia\Work\WaferFab\";

            string outputDir = @"C:\CSSLWaferFab\";

            Settings.Output  = true;
            Settings.FixSeed = true;

            ShellModel WaferFabSim = new ShellModel(inputDir, outputDir);

            // Load WaferFab settings
            //ManualDataReader reader = new ManualDataReader(inputDir + "CSVs");
            AutoDataReader reader = new AutoDataReader(inputDir + "Auto");

            WaferFabSettings waferFabSettings = reader.ReadWaferFabSettings();

            waferFabSettings.SampleInterval       = 1 * 60 * 60; // seconds
            waferFabSettings.LotStartsFrequency   = 1;           // hours
            waferFabSettings.UseRealLotStartsFlag = true;

            // Read Initial Lots
            WaferFabSim.ReadRealSnaphots(inputDir + @"SerializedFiles\RealSnapshots_2019-12-1_2020-1-1_1h.dat");

            waferFabSettings.InitialRealLots = WaferFabSim.RealSnapshotReader.RealSnapshots.First().RealLots;

            // Experiment settings
            ExperimentSettings experimentSettings = new ExperimentSettings();

            experimentSettings.NumberOfReplications = 1;
            experimentSettings.LengthOfReplication  = 1 * 24 * 60 * 60; // seconds
            experimentSettings.LengthOfWarmUp       = 0 * 60 * 60;      // seconds

            // Connect settings
            WaferFabSim.MyWaferFabSettings = waferFabSettings;

            WaferFabSim.MyExperimentSettings = experimentSettings;

            // Run simulation
            WaferFabSim.RunSimulation();

            // Report summary
            SimulationReporter reporter = WaferFabSim.MySimulation.MakeSimulationReporter();

            reporter.PrintSummaryToFile();
            reporter.PrintSummaryToConsole();
        }
Exemplo n.º 3
0
        public static void RunNormalSimulation()
        {
            string inputDir  = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\", "Parameters", ParametersDirectory));
            string outputDir = @"C:\CSSLWaferFab\Output\RLToyFab\";

            CSSL.Modeling.Settings.WriteOutput = true;

            // Fab settings
            //IDataReader reader = new DataReader1(inputDir);
            IDataReader    reader         = new DataReader2(inputDir);
            ToyFabSettings toyFabSettings = reader.ReadToyFabSettings();

            // Build Fab
            Simulation sim = new Simulation("RLToyFab", outputDir);

            // Experiment settings
            sim.MyExperiment.NumberOfReplications = 10;
            sim.MyExperiment.LengthOfWarmUp       = LengthOfWarmUp;
            sim.MyExperiment.LengthOfReplication  = LengthOfReplication;

            // Build the model
            ToyFab toyFab = new ToyFab(sim.MyModel, "WaferFab")
            {
                LotSteps       = toyFabSettings.LotSteps,
                LengthOfWarmUp = LengthOfWarmUp
            };

            AddWorkStations(toyFab, toyFabSettings, sim);

            foreach (var sequence in toyFabSettings.Sequences)
            {
                toyFab.AddSequence(sequence.Key, sequence.Value);
            }

            toyFab.SetLotGenerator(new LotGenerator(toyFab, "LotGenerator", NumberOfLots));

            sim.Run();

            // Report summary
            SimulationReporter reporter = sim.MakeSimulationReporter();

            reporter.PrintSummaryToFile();
            reporter.PrintSummaryToConsole();
        }
Exemplo n.º 4
0
        static void Main(string[] args)
        {
            string inputDirectory   = @"C:\CSSLWaferFab\Input\WSC2021paper";
            string outputDirectory  = @"C:\CSSLWaferFab\Output\WSC2021paper";
            string eptParameterFile = @"FittedEPTParameters - 2019-6-1.csv";

            List <string> workcenters = new List <string> {
                "PHOTOLITH", "FURNACING", "DRY ETCH"
            };
            List <string> SOvsLDO = new List <string> {
                "SO", "LDO"
            };

            //List<string> SOvsLDO = new List<string> { "LDO"};

            foreach (string wc in workcenters)
            {
                WaferFabSettings waferFabSettings = Deserializer.DeserializeWaferFabSettings(Path.Combine(inputDirectory, "SerializedFiles", $"WaferFabSettings_{wc}_WithLotStarts.dat"));

                foreach (string overtaking in SOvsLDO)
                {
                    bool lotStepOvertaking = overtaking == "SO" ? false : true;

                    #region Initializing simulation
                    Simulation simulation = new Simulation(wc, outputDirectory);
                    #endregion

                    #region Experiment settings
                    simulation.MyExperiment.NumberOfReplications = 10;
                    simulation.MyExperiment.LengthOfReplication  = 60 * 60 * 24 * 91; // September and October
                    simulation.MyExperiment.LengthOfWarmUp       = 60 * 60 * 24 * 30;
                    DateTime initialDateTime = new DateTime(2019, 08, 01);
                    #endregion

                    #region WaferFab settings

                    EPTDistributionReader distributionReader = new EPTDistributionReader(Path.Combine(inputDirectory, "CSVs"), waferFabSettings.WorkCenters, waferFabSettings.LotStepsPerWorkStation);

                    waferFabSettings.WCServiceTimeDistributions = distributionReader.GetServiceTimeDistributions(eptParameterFile);
                    waferFabSettings.WCOvertakingDistributions  = distributionReader.GetOvertakingDistributions(lotStepOvertaking);
                    waferFabSettings.WCDispatcherTypes[wc]      = DispatcherBase.Type.EPTOVERTAKING;


                    #endregion

                    #region Make starting lots
                    AutoDataReader dataReader = new AutoDataReader(Path.Combine(inputDirectory, "Auto"), Path.Combine(inputDirectory, "SerializedFiles"));

                    #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 observers
                    LotOutObserver lotOutObserver = new LotOutObserver(simulation, wc + "_" + overtaking + "LotOutObserver");
                    dispatcher.Subscribe(lotOutObserver);
                    OptimiserObserver optimiserObserver = new OptimiserObserver(simulation, "TotalQueueObserver");
                    workCenter.Subscribe(optimiserObserver);
                    #endregion

                    #region Read initial lots
                    //RealSnapshotReader reader = new RealSnapshotReader();

                    //List<RealSnapshot> realSnapshots = reader.Read(Path.Combine(inputDirectory, "SerializedFiles", reader.GetRealSnapshotString(initialDateTime)), 1);

                    //RealSnapshot realSnapShot = realSnapshots.Where(x => x.Time == initialDateTime).First();

                    //List<string> lotSteps = workCenter.LotSteps.Select(x => x.Name).ToList();

                    //List<RealLot> initialRealLots = realSnapShot.GetRealLots(1).Where(x => lotSteps.Contains(x.IRDGroup)).ToList();

                    //List<Lot> initialLots = initialRealLots.Select(x => x.ConvertToLotArea(0, waferFabSettings.Sequences, initialDateTime)).ToList();

                    //waferFab.InitialLots = initialLots;
                    #endregion

                    simulation.Run();

                    #region Reporting
                    SimulationReporter reporter = simulation.MakeSimulationReporter();

                    reporter.PrintSummaryToConsole();
                    #endregion
                }
            }
        }
Exemplo n.º 5
0
        static void Main(string[] args)
        {
            List <string> workcenters = new List <string>()
            {
                "BACKGRIND", "BATCH UP", "CMP", "DICE", "DRY ETCH", "ELEC TEST", "EVAPORATION", "FURNACING", "IMPLANT",
                "INSPECTION", "LPCVD", "MERCURY", "NITRIDE DEP", "OFF LINE INK", "PACK", "PHOTOLITH", "PROBE", "REPORTING",
                "SAMPLE TEST", "SPUTTERING", "WET ETCH"
            };

            DateTime initialDateTime = new DateTime(2019, 10, 1);

            string inputDirectory = @"C:\CSSLWaferFab\Input";

            string outputDirectory = @"C:\CSSLWaferFab\Output\WaferFabArea";

            string eptParameterFile = @"FittedEPTParameters - 2019-6-1.csv";

            RealSnapshotReader reader = new RealSnapshotReader();

            List <RealSnapshot> realSnapshots = reader.Read(Path.Combine(inputDirectory, "SerializedFiles", reader.GetRealSnapshotString(initialDateTime)), 1);

            RealSnapshot realSnapShot = realSnapshots.Where(x => x.Time == initialDateTime).First();

            //workcenters = new List<string>() {"INSPECTION"};
            foreach (string workcenter in workcenters)
            {
                #region Parameters

                string wc = workcenter;

                bool isFitted = false; // true = fitted, false = optimised

                bool lotStepOvertaking = true;
                #endregion

                #region Initializing simulation
                Simulation simulation = new Simulation(wc, outputDirectory);
                #endregion

                #region Experiment settings
                simulation.MyExperiment.NumberOfReplications = 30;

                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 WaferFab settings
                WaferFabSettings waferFabSettings = Deserializer.DeserializeWaferFabSettings(Path.Combine(inputDirectory, "SerializedFiles", $"WaferFabSettings_{wc}_WithLotStarts.dat"));

                EPTDistributionReader distributionReader = new EPTDistributionReader(Path.Combine(inputDirectory, "CSVs"), waferFabSettings.WorkCenters, waferFabSettings.LotStepsPerWorkStation);

                waferFabSettings.WCServiceTimeDistributions    = distributionReader.GetServiceTimeDistributions(eptParameterFile);
                waferFabSettings.WCOvertakingDistributions     = distributionReader.GetOvertakingDistributions(lotStepOvertaking);
                waferFabSettings.WCDispatcherTypes[workcenter] = DispatcherBase.Type.EPTOVERTAKING;


                #endregion

                #region Make starting lots
                AutoDataReader dataReader = new AutoDataReader(Path.Combine(inputDirectory, "Auto"), Path.Combine(inputDirectory, "SerializedFiles"));
                #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
                List <RealLot> initialRealLots = realSnapShot.GetRealLots(1).Where(x => x.LotActivity.WorkStation == wc).ToList();

                waferFab.InitialLots = initialRealLots.Select(x => x.ConvertToLotArea(0, waferFabSettings.Sequences, initialDateTime)).ToList();

                // Add observers
                LotOutObserver lotOutObserver = new LotOutObserver(simulation, wc + "_LotOutObserver");
                dispatcher.Subscribe(lotOutObserver);

                TotalQueueObserver totalQueueObserver = new TotalQueueObserver(simulation, wc + "_TotalQueueObserver");
                workCenter.Subscribe(totalQueueObserver);
                #endregion

                simulation.Run();

                #region Reporting
                SimulationReporter reporter = simulation.MakeSimulationReporter();

                reporter.PrintSummaryToConsole();
                #endregion
            }
        }
Exemplo n.º 6
0
        private static void Experiment(string control, DateTime startDate, string experimentOutputDirectory, bool dynamic, bool stochastic, double weightA, double weightB, double weightC, Dictionary <string, double> deterministicNonProductiveTimesRMS, Dictionary <string, double> deterministicNonProductiveTimesARMS, int CPTimeLimit = 0)
        {
            string     outputDir = experimentOutputDirectory;
            Simulation sim       = new Simulation("LithographyAreaSim", outputDir);

            // Parameters
            double simulationLength  = 30 * 24 * 3600 + 1;
            string productionControl = control;

            // The experiment part
            sim.MyExperiment.LengthOfReplication = simulationLength;
            sim.MyExperiment.LengthOfWarmUp      = 0;
            if (stochastic)
            {
                sim.MyExperiment.NumberOfReplications = 1;
            }
            else
            {
                sim.MyExperiment.NumberOfReplications = 1;
            }

            // The model part

            // Create lithographyarea
            LithographyArea lithographyarea = new LithographyArea(sim.MyModel, "LithographyArea", startDate, simulationLength, dynamic, stochastic, weightA, weightB, weightC, deterministicNonProductiveTimesRMS, deterministicNonProductiveTimesARMS);

            // Property dispatcherBase
            DispatcherBase dispatcher = null;

            // Create chosen dispatcher
            if (productionControl == "FIFO")
            {
                dispatcher = new FIFODispatcher(lithographyarea, "FIFODispatcher");
            }
            else if (productionControl == "EDD")
            {
                dispatcher = new EDDDispatcher(lithographyarea, "EDDDispatcher");
            }
            else if (productionControl == "SPT")
            {
                dispatcher = new SPTDispatcher(lithographyarea, "SPTDispatcher");
            }
            else if (productionControl == "CurrentProductionControl")
            {
                dispatcher = new CurrentDispatcher(lithographyarea, "CurrentDispatcher");
            }
            else if (productionControl == "ILPScheduling")
            {
                dispatcher = new ILPSchedulingDispatcher(lithographyarea, "ILPSchedulingDispatcher");
            }
            else if (productionControl == "CPScheduling")
            {
                dispatcher = new CPDispatcher(lithographyarea, "CPDispatcher", CPTimeLimit);
            }

            // Set dispatcher
            lithographyarea.SetDispatcher(dispatcher);

            // Create and set lotGenerator
            LotGenerator lotGenerator = new LotGenerator(lithographyarea, "LotGenerator", dispatcher);

            lithographyarea.SetLotGenerator(lotGenerator);

            // Create and set machines
            lithographyarea.AddMachine(new Machine(lithographyarea, "StepCluster#1", dispatcher, 1));
            lithographyarea.AddMachine(new Machine(lithographyarea, "StepCluster#2", dispatcher, 2));
            lithographyarea.AddMachine(new Machine(lithographyarea, "StepCluster#3", dispatcher, 3));
            lithographyarea.AddMachine(new Machine(lithographyarea, "ASML#4", dispatcher, 4));
            lithographyarea.AddMachine(new Machine(lithographyarea, "StepCluster#5", dispatcher, 5));
            lithographyarea.AddMachine(new Machine(lithographyarea, "ASML#6", dispatcher, 6));
            lithographyarea.AddMachine(new Machine(lithographyarea, "StepCluster#7", dispatcher, 7));
            lithographyarea.AddMachine(new Machine(lithographyarea, "StepCluster#8", dispatcher, 8));
            lithographyarea.AddMachine(new Machine(lithographyarea, "ASML#9", dispatcher, 9));
            lithographyarea.AddMachine(new Machine(lithographyarea, "StepCluster#10", dispatcher, 10));
            lithographyarea.AddMachine(new Machine(lithographyarea, "StepCluster#11", dispatcher, 11));
            lithographyarea.AddMachine(new Machine(lithographyarea, "StepCluster#13", dispatcher, 12));

            // The observer part

            LithographyAreaObserver lithographyAreaObserver = new LithographyAreaObserver(sim, startDate);

            lithographyarea.Subscribe(lithographyAreaObserver);

            foreach (Machine machine in lithographyarea.Machines)
            {
                MachineObserver machineObserver = new MachineObserver(sim, startDate);
                machine.Subscribe(machineObserver);
            }

            // Run

            sim.Run();

            // The reporting part

            SimulationReporter reporter = sim.MakeSimulationReporter();

            reporter.PrintSummaryToFile();
            reporter.PrintSummaryToConsole();
        }
Exemplo n.º 7
0
        static void Main(string[] args)
        {
            Simulation sim = new Simulation("SomeSimulation", @"C:\CSSL");

            Settings.WriteOutput = false;

            Settings.NotifyObservers = true;

            // Parameters...

            double dispatchTime                  = 1E-3;
            double lambda                        = 100;
            int    numberServerpools             = 10;
            int    numberServerpoolsToChooseFrom = 10;

            // The experiment part...

            sim.MyExperiment.NumberOfReplications = 3;
            sim.MyExperiment.LengthOfReplication  = 10;
            sim.MyExperiment.LengthOfWarmUp       = 2;

            // The model part...

            DataCenter dataCenter = new DataCenter(sim.MyModel, "DataCenter");

            for (int i = 0; i < numberServerpools; i++)
            {
                dataCenter.AddServerpool(new ServerPool(dataCenter, $"Serverpool_{i}"));
            }

            Dispatcher dispatcher = new Dispatcher(dataCenter, "Dispatcher", new ExponentialDistribution(1), double.PositiveInfinity, dataCenter.ServerPools, dispatchTime, numberServerpoolsToChooseFrom);

            dataCenter.SetDispatcher(dispatcher);

            JobGenerator jobGenerator = new JobGenerator(dataCenter, "JobGenerator", new ExponentialDistribution(lambda), dispatcher);

            dataCenter.SetJobGenerator(jobGenerator);

            // The observer part...

            DispatcherObserver dispatcherObserver = new DispatcherObserver(sim);

            dispatcher.Subscribe(dispatcherObserver);

            DataCenterObserver dataCenterObserver = new DataCenterObserver(sim);

            dataCenter.Subscribe(dataCenterObserver);

            foreach (ServerPool serverpool in dataCenter.ServerPools)
            {
                ServerPoolObserver serverpoolObserver = new ServerPoolObserver(sim);
                serverpool.Subscribe(serverpoolObserver);
            }

            // Run...

            sim.Run();

            // The reporting part...

            SimulationReporter reporter = sim.MakeSimulationReporter();

            reporter.PrintSummaryToFile();
            reporter.PrintSummaryToConsole();
        }
Exemplo n.º 8
0
        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);
        }