|
472 | 472 | "id": "33f7e4b8-46d1-4566-8307-2ad945455225", |
473 | 473 | "metadata": {}, |
474 | 474 | "source": [ |
475 | | - "## 4. Model code" |
| 475 | + "## 4. Modified model code\n", |
| 476 | + "\n", |
| 477 | + "We will modify the model code and logic that we have already developed to include a nurse consultation for a proportion of the callers. We create a new function called `nurse_consultation` that contains all the logic. We also need to modify the `service` function so that a proportion of calls are sent to the nurse consultation process. " |
476 | 478 | ] |
477 | 479 | }, |
478 | 480 | { |
|
497 | 499 | }, |
498 | 500 | { |
499 | 501 | "cell_type": "code", |
500 | | - "execution_count": 9, |
501 | | - "id": "564db16d-b2b1-4e2f-b1f3-6ef4b42a59f7", |
| 502 | + "execution_count": null, |
| 503 | + "id": "c65f9197-2319-42a8-81ab-fe0f10ac4534", |
502 | 504 | "metadata": {}, |
503 | 505 | "outputs": [], |
504 | 506 | "source": [ |
505 | | - "def service(identifier, args, env):\n", |
| 507 | + "def nurse_consultation(identifier, env, args):\n", |
506 | 508 | " '''\n", |
| 509 | + " simulates the wait for an consultation with a nurse on the phone.\n", |
| 510 | + "\n", |
| 511 | + " 1. request and wait for a call operator\n", |
| 512 | + " 2. phone consultation (uniform)\n", |
| 513 | + " 3. release nurse and exit system\n", |
| 514 | + " \n", |
| 515 | + " '''\n", |
| 516 | + " trace(f'Patient {identifier} waiting for nurse call back')\n", |
| 517 | + " start_nurse_wait = env.now\n", |
| 518 | + "\n", |
| 519 | + " # request a nurse\n", |
| 520 | + " with args.nurses.request() as req:\n", |
| 521 | + " yield req\n", |
| 522 | + "\n", |
| 523 | + " # record the waiting time for nurse call back\n", |
| 524 | + " nurse_waiting_time = env.now - start_nurse_wait\n", |
| 525 | + " args.results['nurse_waiting_times'].append(nurse_waiting_time)\n", |
| 526 | + "\n", |
| 527 | + " # sample nurse the duration of the nurse consultation\n", |
| 528 | + " nurse_call_duration = args.nurse_dist.sample() \n", |
| 529 | + "\n", |
| 530 | + " trace(f'nurse called back patient {identifier} at ' \\\n", |
| 531 | + " + f'{env.now:.3f}')\n", |
| 532 | + "\n", |
| 533 | + " # schedule process to begin again after call duration\n", |
| 534 | + " yield env.timeout(nurse_call_duration)\n", |
| 535 | + "\n", |
| 536 | + " args.results['total_nurse_call_duration'] += nurse_call_duration\n", |
| 537 | + "\n", |
| 538 | + " trace(f'nurse consultation for {identifier}' \\\n", |
| 539 | + " + f' competed at {env.now:.3f}')" |
| 540 | + ] |
| 541 | + }, |
| 542 | + { |
| 543 | + "cell_type": "code", |
| 544 | + "execution_count": null, |
| 545 | + "id": "56fa8b72-c511-44a8-99d4-d958ef256821", |
| 546 | + "metadata": {}, |
| 547 | + "outputs": [], |
| 548 | + "source": [ |
| 549 | + "def service(identifier, env, args):\n", |
| 550 | + " \"\"\"\n", |
507 | 551 | " simulates the service process for a call operator\n", |
508 | 552 | "\n", |
509 | 553 | " 1. request and wait for a call operator\n", |
510 | 554 | " 2. phone triage (triangular)\n", |
511 | | - " 3. exit system\n", |
512 | | - " \n", |
| 555 | + " 3. release call operator\n", |
| 556 | + " 4. a proportion of call continue to nurse consultation\n", |
| 557 | + "\n", |
513 | 558 | " Params:\n", |
514 | 559 | " ------\n", |
515 | | - " \n", |
516 | | - " identifier: int \n", |
| 560 | + " identifier: int\n", |
517 | 561 | " A unique identifer for this caller\n", |
518 | | - " \n", |
519 | | - " experiment: Experiment\n", |
520 | | - " The settings and input parameters for the current experiment\n", |
521 | | - " \n", |
| 562 | + "\n", |
522 | 563 | " env: simpy.Environment\n", |
523 | 564 | " The current environent the simulation is running in\n", |
524 | 565 | " We use this to pause and restart the process after a delay.\n", |
525 | | - " \n", |
526 | | - " '''\n", |
527 | | - " \n", |
| 566 | + "\n", |
| 567 | + " args: Experiment\n", |
| 568 | + " The settings and input parameters for the current experiment\n", |
| 569 | + "\n", |
| 570 | + " \"\"\"\n", |
| 571 | + "\n", |
528 | 572 | " # record the time that call entered the queue\n", |
529 | 573 | " start_wait = env.now\n", |
530 | | - " \n", |
531 | | - " # request an operator\n", |
| 574 | + "\n", |
| 575 | + " # request an operator - stored in the Experiment\n", |
532 | 576 | " with args.operators.request() as req:\n", |
533 | 577 | " yield req\n", |
534 | | - " \n", |
| 578 | + "\n", |
535 | 579 | " # record the waiting time for call to be answered\n", |
536 | 580 | " waiting_time = env.now - start_wait\n", |
537 | | - " \n", |
538 | | - " # store the results for an experiment \n", |
539 | | - " args.results['waiting_times'].append(waiting_time)\n", |
540 | 581 | "\n", |
541 | | - " trace(f'operator answered call {identifier} at ' \\\n", |
542 | | - " + f'{env.now:.3f}')\n", |
| 582 | + " # store the results for an experiment\n", |
| 583 | + " args.results[\"waiting_times\"].append(waiting_time)\n", |
| 584 | + " trace(f\"operator answered call {identifier} at \" + f\"{env.now:.3f}\")\n", |
543 | 585 | "\n", |
544 | 586 | " # the sample distribution is defined by the experiment.\n", |
545 | | - " call_duration = args.call_dist.sample() \n", |
546 | | - " \n", |
| 587 | + " call_duration = args.call_dist.sample()\n", |
| 588 | + " \n", |
547 | 589 | " # schedule process to begin again after call_duration\n", |
548 | 590 | " yield env.timeout(call_duration)\n", |
549 | | - " \n", |
550 | | - " # update the total call_duration \n", |
551 | | - " args.results['total_call_duration'] += call_duration\n", |
552 | | - " \n", |
| 591 | + "\n", |
| 592 | + " # update the total call_duration\n", |
| 593 | + " args.results[\"total_call_duration\"] += call_duration\n", |
| 594 | + "\n", |
553 | 595 | " # print out information for patient.\n", |
554 | | - " trace(f'call {identifier} ended {env.now:.3f}; ' \\\n", |
555 | | - " + f'waiting time was {waiting_time:.3f}')\n", |
556 | | - " \n", |
557 | | - " # ############################################################\n", |
| 596 | + " trace(\n", |
| 597 | + " f\"call {identifier} ended {env.now:.3f}; \"\n", |
| 598 | + " + f\"waiting time was {waiting_time:.3f}\"\n", |
| 599 | + " )\n", |
| 600 | + "\n", |
| 601 | + " # ##########################################################################\n", |
558 | 602 | " # MODIFICATION NURSE CALL BACK\n", |
559 | 603 | " # does nurse need to call back?\n", |
560 | 604 | " # Note the level of the indented code. \n", |
561 | 605 | " callback_patient = args.callback_dist.sample()\n", |
562 | 606 | "\n", |
563 | 607 | " if callback_patient:\n", |
564 | | - " trace(f'Patient {identifier} waiting for nurse call back')\n", |
565 | | - "\n", |
566 | | - " start_nurse_wait = env.now\n", |
567 | | - "\n", |
568 | | - " # request a nurse\n", |
569 | | - " with args.nurses.request() as req:\n", |
570 | | - " yield req\n", |
571 | | - "\n", |
572 | | - " # record the waiting time for nurse call back\n", |
573 | | - " nurse_waiting_time = env.now - start_nurse_wait\n", |
574 | | - " args.results['nurse_waiting_times'].append(nurse_waiting_time)\n", |
575 | | - "\n", |
576 | | - " # sample nurse the duration of the nurse consultation\n", |
577 | | - " nurse_call_duration = args.nurse_dist.sample() \n", |
578 | | - "\n", |
579 | | - " trace(f'nurse called back patient {identifier} at ' \\\n", |
580 | | - " + f'{env.now:.3f}')\n", |
581 | | - "\n", |
582 | | - " # schedule process to begin again after call duration\n", |
583 | | - " yield env.timeout(nurse_call_duration)\n", |
584 | | - "\n", |
585 | | - " args.results['total_nurse_call_duration'] += nurse_call_duration\n", |
586 | | - "\n", |
587 | | - " trace(f'nurse consultation for {identifier}' \\\n", |
588 | | - " + f' competed at {env.now:.3f}')" |
| 608 | + " env.process(nurse_consultation(identifier, env, args))\n", |
| 609 | + " # ##########################################################################" |
589 | 610 | ] |
590 | 611 | }, |
591 | 612 | { |
|
596 | 617 | "outputs": [], |
597 | 618 | "source": [ |
598 | 619 | "def arrivals_generator(env, args):\n", |
599 | | - " '''\n", |
| 620 | + " \"\"\"\n", |
600 | 621 | " IAT is exponentially distributed\n", |
601 | 622 | "\n", |
602 | 623 | " Parameters:\n", |
603 | 624 | " ------\n", |
604 | 625 | " env: simpy.Environment\n", |
605 | 626 | " The simpy environment for the simulation\n", |
606 | 627 | "\n", |
607 | | - " experiment: Experiment\n", |
| 628 | + " args: Experiment\n", |
608 | 629 | " The settings and input parameters for the simulation.\n", |
609 | | - " '''\n", |
610 | | - "\n", |
611 | | - " # use itertools as it provides an infinite loop \n", |
| 630 | + " \"\"\"\n", |
| 631 | + " # use itertools as it provides an infinite loop\n", |
612 | 632 | " # with a counter variable that we can use for unique Ids\n", |
613 | 633 | " for caller_count in itertools.count(start=1):\n", |
614 | 634 | "\n", |
615 | | - " # the sample distribution is defined by the experiment.\n", |
| 635 | + " # rhe sample distribution is defined by the experiment.\n", |
616 | 636 | " inter_arrival_time = args.arrival_dist.sample()\n", |
617 | 637 | " yield env.timeout(inter_arrival_time)\n", |
618 | 638 | "\n", |
619 | | - " trace(f'call arrives at: {env.now:.3f}')\n", |
| 639 | + " trace(f\"call arrives at: {env.now:.3f}\")\n", |
620 | 640 | "\n", |
621 | | - " # we pass the experiment to the service function\n", |
622 | | - " env.process(service(caller_count, args, env))" |
| 641 | + " # create a service process\n", |
| 642 | + " env.process(service(caller_count, env, args))" |
623 | 643 | ] |
624 | 644 | }, |
625 | 645 | { |
|
0 commit comments