Feedback

Adding Testers

PARAMS = {
    "n_programmer": (2, 3, 4),
    "n_tester": (2, 3, 4),
    "p_rework": (0.2, 0.4, 0.6, 0.8),
    …as before…
}

def main():
    random.seed(PARAMS["seed"])
    result = []
    combinations = product(PARAMS["n_programmer"], PARAMS["n_tester"], PARAMS["p_rework"])
    for (n_programmer, n_tester, p_rework) in combinations:
        sweep = {"n_programmer": n_programmer, "n_tester": n_tester, "p_rework": p_rework}
        params = {**PARAMS, **sweep}
        sim = Simulation(params)
        sim.run()
        result.append({
            "params": params,
            "lengths": sim.lengths,
            "jobs": [job.as_json() for job in Job._all],
        })
    json.dump(result, sys.stdout, indent=2)
class Simulation:
    def __init__(self, params):
        self.params = params
        self.env = Environment()
        self.prog_queue = Store(self.env)
        self.test_queue = Store(self.env)
        self.lengths = []
def programmer(sim, worker_id):
    while True:
        job = yield sim.prog_queue.get()
        start = sim.env.now
        yield sim.env.timeout(sim.rand_dev())
        job.n_prog += 1
        job.t_prog += sim.env.now - start
        yield sim.test_queue.put(job)
def tester(sim, tester_id):
    while True:
        job = yield sim.test_queue.get()
        start = sim.env.now
        yield sim.env.timeout(sim.rand_dev())
        job.n_test += 1
        job.t_test += sim.env.now - start
        if sim.rand_rework():
            yield sim.prog_queue.put(job)
        else:
            job.done = True
queue lengths

Programming and testing times

Using Classes

class Simulation:
    …all other code as before…
    def run(self):
        Job.clear()
        self.env.process(self.monitor())
        self.env.process(creator(self))
        self.programmers = [Programmer(self, i) for i in range(self.params["n_programmer"])]
        self.testers = [Tester(self, i) for i in range(self.params["n_tester"])]
        self.env.run(until=self.params["t_sim"])
class Worker:
    def __init__(self, sim, id):
        self.sim = sim
        self.id = id
        self.proc = sim.env.process(self.run())
class Programmer(Worker):
    def run(self):
        while True:
            job = yield self.sim.prog_queue.get()
            job.programmer_id = self.id
            start = self.sim.env.now
            yield self.sim.env.timeout(self.sim.rand_dev())
            job.n_prog += 1
            job.t_prog += self.sim.env.now - start
            yield self.sim.test_queue.put(job)

Exploring Scenarios

class Worker:
    def __init__(self, sim, id):
        self.sim = sim
        self.id = id
        self.queue = Store(sim.env)
        self.proc = sim.env.process(self.run())
class Programmer(Worker):
    def __init__(self, sim, id):
        super().__init__(sim, id)
        self.shared_queue = self.sim.prog_queue  # added

    def run(self):
        while True:
            job = yield from self.choose()  # changed
            job.programmer_id = self.id
            start = self.sim.env.now
            yield self.sim.env.timeout(self.factor() * self.sim.rand_dev())
            job.n_prog += 1
            job.t_prog += self.sim.env.now - start

            # hand off the job
            if job.tester_id is None:
                yield self.sim.test_queue.put(job)
            else:
                yield self.sim.testers[job.tester_id].queue.put(job)
class Worker:
    def choose(self):
        if self.sim.params["scenario"] == "any":
            job = yield self.shared_queue.get()
        elif self.sim.params["scenario"] in ("same", "reduced"):
            job = yield from self.choose_same()
        else:
            assert False, f"unknown scenario {self.sim.params['scenario']}"
        return job
    def choose_same(self):
        req_shared = self.shared_queue.get()
        req_own = self.queue.get()
        result = yield (req_shared | req_own)
        if (len(result.events) == 2) or (req_own in result):
            job = result[req_own]
            req_shared.cancel()
        else:
            job = result[req_shared]
            req_own.cancel()
        return job
three testing scenarios