DEVS Assignment 

Practical Information

  • Due Date: Tuesday 3 January 2024, before 23:59. (Do note you are given more time because of the Christmas holidays!)
  • Team Size: 2 (pair design/programming)! Please contact the TA ASAP if you encounter any team issues.
    Note that as of the 2017-2018 Academic Year, each International student should team up with "local" (i.e., whose Bachelor degree was obtained at the University of Antwerp).
  • Submission Information: Only one member of each team submits a full solution. This must be a compressed archive (ZIP, RAR, TAR.GZ...) that includes your report and all models, images, code and other sources that you used to crate your solution. Do not submit any executables. The report may be either HTML or PDF and must be accompanied by all images. When an image is unreadable in your report and missing/unreadable from your submission archive, you will not receive any points for that task. Make sure to mention the names and student IDs of both team members. The other team member must submit a single HTML file containing only the coordinates of both team members. You may use this template. This will allow us to put in grades for both team members in BlackBoard.
  • Submission Medium: BlackBoard. Beware that BlackBoard's clock may differ slightly from yours. If BlackBoard is not reachable due to an (unpredicted) maintenance, you submit your solution via e-mail to the TA. Make sure all group members are in CC!
  • Contact / TA: Randy Paredis.

Goals

This assignment will make you familiar with modelling, simulation and performance analysis in Classic DEVS. You will learn to use modelling patterns to construct a discrete-event simulation on which specific statistics can be obtained and analyzed. Furthermore, you get more insights in how real-world problems can be transformed to abstractions (i.e., models). This assignment is to be completed with PythonPDEVS. A detailed documentation is available online (so no need to run Sphinx yourself!). Take a look at the "Application to Queueing Systems" example to get started with PythonPDEVS. This assignment completes the Car Traffic usage context that was introduced in the previous assignments.

ATTENTION!

Python does not enforce the usage of the PythonPDEVS library! Instead, it is perfectly possible to bypass its functionality and still yield a valid result. These results will not be seen as a valid DEVS modelling and therefore not grant you any points for that part of the solution.

  • Please read the documentation of everything you use! If the documentation explicitly states you cannot do something, don't!
  • You are strongly encouraged to read the documentation of the AtomicDEVS and all of its functions that you use (i.e., extTransition, intTransition, timeAdvance and outputFnc).
  • Make sure that you do not change/override any of the AtomicDEVS/CoupledDEVS members!
  • All mutable variables of an AtomicDEVS should be part of that DEVS' state. All immutable variables should be outside the state.
  • The timeAdvance and outputFnc functions need to be deterministic and should not change the state of the model(s).
  • Sometimes implicit state changes can happen (i.e., internally in RNGs; or when using the next function...). It is up to you to identify when this happens and to prevent it from occurring when it's not allowed.

Some statistics:

  • In the year 2021-2022, students lost up to 46.4% of their points due to not following these rules.
  • In the year 2022-2023, students lost up to 47.3% of their points due to not following these rules. In fact, there was only one student that did not make any mistakes against them.
  • This year, you can lose up to 46% of your points due to not following these rules.

An issue we see appearing quite often: DEVS comes from Discrete EVent system Specification, hence the "S" is part of this abbreviation! Both in singular and plural form, we speak of DEVS: one Coupled DEVS can contain multiple Atomic DEVS. DEV (without the "S") means "Discrete EVent", which is a family of formalisms, instead of one specific formalism. Please use the correct spelling to avoid being marked wrong!

Note: All images used in this assignment are vector images (*.svg). You can open them in another tab if anything is not immediately readable.

Note: Aspects marked in blue are edits to the assignment, clarifying explanations.

Note: Aspects marked in green are edits to the assignment, clarifying explanations for the 2nd term.

Problem Statement

You should create a simple DEVS library for analyzing traffic on a road network. Due to the complexity of traffic systems, with many edge cases, the following abstractions will be used.

  • Cars can be modelled as events that travel over roads.
  • Each road is decomposed into small RoadSegments that can (at most) contain a single Car. When multiple Cars are on a RoadSegment, we assume a collission occurred and Cars are piled up in that RoadSegment.
  • The driver of each Car will look at the upcoming RoadSegment to determine if there is a Car in that segment. We will model "looking in front" as sending a Query event and "receiving of this information" as receiving a QueryAck event. The (variable) time delay between the sending of a Query and the receiving of a corresponding QueryAck is called the observation delay (observ_delay). This value mimics the reaction time of the driver. We can increase the observ_delay to accomodate for bad weather situations (e.g., a lot of fog and/or rain).
  • Connecting multiple RoadSegments together (using some additional components and features) will therefore allow for creating complicated road networks.

$velocity$, $distance$ and $time$ are related as follows:
$$\begin{align} &velocity = \dfrac{distance}{time}\qquad& &time = \dfrac{distance}{velocity}\qquad& &distance = velocity\cdot time& \end{align}$$

The following is a detailed description of the components for this library, as well as the corresponding messages/events that are being sent. You are also provided with a small set of tests for these components. You are not allowed to change these tests, hence, it is required for you to follow the component signatures to a T. Note that not all components have tests and that your submission will be corrected using a larger set of tests. How many tests pass/fail will provide you with an estimate for your score on these components. In square brackets, you can find how much each component is worth. This will also give you an estimate of their individual difficulty and complexity.

If you expand on this description, make sure to provide default values to all your custom properties.

components.messages.Car (event) [1%]

This is an event traveling passed between RoadSegments. It is used to model a car. Note that in this abstraction, somewhat counter-intuitively, the road segments are the "active" components, whereas the cars are "passive". This in contrast with an "agent based" abstraction where road segments would be the "passive" components and cars would be "active". This choice was made to allow for efficient simulation, when there are a limited number of road segments and a large number of cars.
This must be a data class, i.e., a class that has a set of fields (for the pythonic way of creating data classes, have a look at this reference).

Fields (click to expand):

Each Car has at least the following fields/parameters. It may have more, but certainly not less. When constructing a car, this should be the order of parameters from the __init__ function.

ID (UUID/int/...)
A unique identifier to uniquely distinguish between cars.
v_pref (float)
The preferred velocity of the car. This is the velocity the car tries to obtain whenever possible.
dv_pos_max (float)
The maximal amount of acceleration possible for this Car on a single RoadSegment. Notice that this is not actually an acceleration, but more of a velocity delta (i.e., its SI unit is in $\dfrac{m}{s}$). Feel free to choose your own values, but 28 is a good suggestion.
dv_neg_max (float)
The maximal amount of deceleration possible for this Car on a single RoadSegment. Notice that this is not actually an acceleration, but more of a velocity delta (i.e., its SI unit is in $\dfrac{m}{s}$). Feel free to choose your own values, but 21 is a good suggestion.
departure_time (float)
The (simulation) time at which the Car is created. This value is set afterwards, by the Generator.
distance_traveled (float)
The total distance that the Car has traveled. This value is updated during simulation.
v (float)
The current velocity. By default, it is initialized to be the same as v_pref, but may change during the simulation. This value is used for all the distance computations etc.
no_gas (bool)
Indicator that the Car needs gas. Will be used later in the assignment.
destination (str)
The target destination of the Car. This will help for path planning etc in a more detailed library. Later on in the assignment, this value will be used for CrossRoads.

components.messages.Query (event) [1%]

Represents the driver watching to the RoadSegment in front.
Must be a data class, i.e., a class that has a set of fields (for the pythonic way of creating data classes, have a look at this reference).

Fields (click to expand):

Each Query has at least the following fields/parameters. It may have more, but certainly not less. When constructing a car, this should be the order of parameters from the __init__ function.

ID (UUID/int/...)
The unique identifier of the Car that sends this Query.

components.messages.QueryAck (event) [1%]

Event that answers a Query. This is needed to actually obtain the information of the upcoming RoadSegment. The Query/QueryAck logic can therefore be seen as "polling".
Must be a data class, i.e., a class that has a set of fields (for the pythonic way of creating data classes, have a look at this reference).

Fields (click to expand):

Each QueryAck has at least the following fields/parameters. It may have more, but certainly not less. When constructing a car, this should be the order of parameters from the __init__ function.

ID (UUID/int/...)
The unique identifier of the Car that queried this data.
t_until_dep (float)
An estimate for the time until the upcoming RoadSegment is available again.
lane (int)
Indicates which lane the current RoadSegment applies to. If a Car wants to "change lanes" in a Fork, this value is used to identify which QueryAcks to take into account.
sideways (bool)
Indicator that this QueryAck does not correspond to the RoadSegment in front, but rather another one the Car needs to keep track of. Defaults to false. Will be used later on in the assignment to allow for merges of RoadSegments.

components.roadsegment.RoadSegment (Atomic DEVS) [10%]

Represents a small stretch of road that can only contain a single Car. When multiple Cars are on a RoadSegment, we assume the Cars crashed into each other. Take a look at the members and port descriptions below for a more detailed explanation.

Parameters (click to expand)
block_name (str)
The name for this model. Must be unique inside a Coupled DEVS.
L (float)
The length of the RoadSegment. Given that the average Car is about 5 meters in length, a good estimate value for L would therefore be 5 meters.
v_max (float)
The maximal allowed velocity on this RoadSegment.
observ_delay (float)
The time it takes to reply to a Query that was inputted. This value mimics the reaction time of the driver. We can increase the observ_delay to accomodate for bad weather situations (e.g., a lot of fog and/or rain). Defaults to 0.1.
priority (bool)
Whether or not this RoadSegment should have priority on a merge with other road segments. Defaults to False.
lane (int)
Indicator of the lane this Roadsegment is currently part of. Defaults to 0.
State (click to expand)

While the state should contain many more fields, the following should at least be there. They are listed here to help you understand the upcoming descriptions.

cars_present (list)
A list for all the Cars on this RoadSegment. Even though the existence of multiple Cars results in a collision, for extensibility purposes a list should be used.
t_until_dep (float)
The time until the current Car (i.e., the first one in cars_present) leaves the RoadSegment. If the Car's velocity is 0, this value is infinity. If no Car is present, this value is 0.
remaining_x (float)
The remaining distance that the current Car (i.e., the first one in cars_present) should still travel on this RoadSegment.
Input Ports (click to expand)
car_in
All Cars are inputted on this port. As soon as a Car arrives, a Query is outputted over the Q_send port. For statistical purposes, the number of Cars that enter this RoadSegment should be maintained.
If there already was a Car on the RoadSegment, a collision occurs. We will make the incredibly bold assumption that a crash results in total vaporization of both Cars, removing them from the simulation. For statistical purposes, the number of crashes in each RoadSegment should be maintained.
Q_recv
Port that receives Query events. Upon arrival of a Query, the RoadSegment waits for observ_delay time before replying a QueryAck on the Q_sack output port. The outputted QueryAck's t_until_dep equals the remaining time of the current Car on the RoadSegment (which can be infinity if the Car's velocity is 0). If there is no Car, t_until_dep equals zero.
Notice that multiple Query events may arrive during this waiting time, all of whom should wait for exactly observ_delay time.
Q_rack
Port that receives QueryAck events. When such an event is received (and the ID corresponds to the Car's ID), the Car updates its velocity v to v_new as follows:
  • Accelerate or decelerate towards the Car's v_pref.
  • v_new should never exceed v_max, nor should it become less than 0 (i.e., Cars will always drive forwards, or stand still).
  • A Car can at most accelerate an amount of dv_pos_max. It can also at most decelerate an amount of dv_neg_max. This is also applicable to the following bullets.
  • If the QueryAck's sideways flag is false:
    • The QueryAck's t_until_dep indicates the time remaining until the next RoadSegment becomes available. To avoid confusion, this value will be called to_no_coll.
    • If the current v_new allows the Car to stay on the RoadSegment as long or longer as t_no_coll, v_new becomes the new v.
    • Otherwise, the Car should decelerate as much as possible to avoid a collision. Thus, the maximum of v - dv_neg_max and remaining_x / t_no_coll becomes the new v.
  • Otherwise, if the QueryAck's sideways flag is true and priority is false, the Car should decelerate as much as possible, unless t_until_dep is 0 (implying there is no car on the other road).
  • Otherwise, if the QueryAck's sideways flag is true and priority is true, no special action should be taken.
  • Note that multiple QueryAcks may be received. If they arrive at the same simulation time (this may not necessarily happen during the same function call), the largest possible v_new should be used as v. Otherwise, the above description will be recomputed for every new QueryAck. This description is independent of the sideways logic! If you are not on a priority road and you get a sideways flag in the QueryAck, you should always decelerate!
Output Ports (click to expand)
car_out
Outputs the Car on this RoadSegment if it has traveled it completely. The Car's distance_traveled should be increased by L.
Q_send
Sends a Query as soon as a new Car arrives on this RoadSegment (if there was no crash). Additionally, a Query is sent every observ_delay time if the Car's v equals 0.
Q_sack
Replies a QueryAck to a Query. The QueryAck's t_until_dep equals the remaining time of the current Car on the RoadSegment (which can be infinity if the Car's velocity is 0). If there is no Car, t_until_dep equals zero. The QueryAck's lane is set w.r.t. the RoadSegment's lane; and the QueryAck's sideways is set to be false here.
Helper methods (click to expand)

You can add as many as you like, but the following must at least be there:

car_enter(Car) -> None
Handles all the logic of a car entering the RoadSegment. Can be called to pre-fill the RoadSegment with a Car.

components.generator.Generator (Atomic DEVS) [7%]

Periodically generates Cars. This component allows cars to enter the system. The inter-arrival time (IAT) for the Cars is given by a uniform distribution. Upon generation, each car is given a preferred velocity v_pref by sampling from a normal distribution.

When a Car is generated, a Query is sent over the Q_send port. As soon as a QueryAck is received, the generated car is output over the car_out port. Next, the Generator waits for some time before generating another Car.
Upon generation, the Car's no_gas is randomly set to be either true or false.

Parameters (click to expand)
block_name (str)
The name for this model. Must be unique inside a Coupled DEVS.
IAT_min (float)
Lower bound for the IAT uniform distribution.
IAT_max (float)
Upper bound for the IAT uniform distribution.
v_pref_mu (float)
Mean of the normal distribution that is used to sample v_pref.
v_pref_sigma (float)
Standard deviation of the normal distribution that is used to sample v_pref.
destinations (list)
A non-empty list of potential (string) destinations for the Cars. A random destination will be selected.
limit (int)
Upper limit of the number of Cars to generate.
Input Ports (click to expand)
Q_rack
Port that receives QueryAck events. When such an event is received, the next Car will be outputted after the QueryAck's t_until_dep time has passed. This way, there will not be any crashes due to a Generator.
Output Ports (click to expand)
car_out
Outputs the newly generated Car. The current simulation time becomes the Car's departure_time.
Q_send
Sends a Query as soon as the newly sampled IAT says so.

components.collector.Collector (Atomic DEVS) [3%]

Collects Cars from the simulation and stores all important information such that statistics can be computed afterwards.

Parameters (click to expand)
block_name (str)
The name for this model. Must be unique inside a Coupled DEVS.
Input Ports (click to expand)
car_in
Port that receives the Cars to collect. It can be useful to already compute some statistics upon the arrival of new Cars.

components.sidemarker.SideMarker (Atomic DEVS) [3%]

Marks all inputted QueryAcks to have sideways set to true. It also immediately outputs the inputted events.
This block should be placed in-between the (Q_sack, Q_rack) connection of two RoadSegments if both want to merge onto a third RoadSegment. While this is a simple component, it is actually a really important component to explicitly denote that you are looking at a RoadSegment that is not in front of you. Keep this separate, to ensure a clean "separation of concerns".

Parameters (click to expand)
block_name (str)
The name for this model. Must be unique inside a Coupled DEVS.
Input Ports (click to expand)
mi
Port that receives QueryAcks. Immediately marks these events to have sideways set to true. Next, it outputs the QueryAck at once.
Output Ports (click to expand)
mo
Port that outputs the QueryAcks again, at the same time as they were entered.

components.fork.Fork (Atomic DEVS, inherits from RoadSegment) [3%]

Allows Cars to choose between multiple RoadSegments. This allows for a simplified form of "lane switching". For the sake of convenience of this assignment, the switching criteria is: output a Car over the car_out2 port if its no_gas member is true.
Given that this block inherits from RoadSegment, all aspects discussed there are also applicable. The description below only focuses on what is new for this component.

The Parameters and Input Ports should be identical to the RoadSegment.

Output Ports (click to expand)
car_out2
Outputs the Car on this RoadSegment if it has traveled it completely and if its no_gas member equals true. The Car's distance_traveled should be increased by L.

components.gasstation.GasStation (Atomic DEVS) [6%]

Represents the notion that some Cars need gas. It can store an infinite amount of Cars, who stay for a certain delay inside an internal queue. This component can be available (default) or unavailable, as described below.

Parameters (click to expand)
block_name
The name for this model. Must be unique inside a Coupled DEVS.
observ_delay
The interval at which the GasStation must poll if the received QueryAck has an infinite delay. Defaults to 0.1.
Input Ports (click to expand)
car_in
Cars can enter the GasStation via this port. As soon as one is entered, it is given a delay time, sampled from a normal distribution with mean 10 minutes and standard deviation of 130 seconds. Cars are required to stay at least 2 minutes in the GasStation. When this delay has passed and when this component is available, a Query is sent over the Q_send port.
Q_rack
When a QueryAck is received, the GasStation waits for QueryAck's t_until_dep time before outputting the next Car over the car_out output. Only then, this component becomes available again. If the waiting time is infinite, the GasStation keeps polling until it becomes finite again.
Output Ports (click to expand)
Q_send
Sends a Query as soon as a Car has waited its delay. Next, this component becomes unavailable, preventing collisions on the RoadSegment after.
car_out
Outputs the Cars, with no_gas set back to false.

components.crossroads.CrossRoadSegment (Atomic DEVS, inherits from RoadSegment) [4%]

Acts as if it were a part of a crossroads. I.e., this is a location where two roads merge and split at the same time. Combining multiple of these segments together results in a CrossRoad.
Given that this block inherits from RoadSegment, all aspects discussed there are also applicable. The description below only focuses on what is new for this component.

Parameters (click to expand)

First, all parameters from RoadSegment should be included here.

destinations (list)
A list of destinations reachable when a car exits the crossroads at this location. This list will be initialized upon creation of the road map and should not be changed afterwards. It is used to make sure Cars exit the crossroads at the right time.
Input Ports (click to expand)
car_in_cr
Cars can enter on this segment as if it were the normal car_in port. However, this port is only used for Cars that were already on the crossroads. Potentially, this information may be stored in the cars_present list, but is merely used for a clean separation and to potentially allow other behaviour in the future.
Output Ports (click to expand)
car_out_cr
Outputs the Cars that must stay on the crossroads. In essence, these are all the Cars that have a destination not in this CrossRoadSegment's destinations field.

components.crossroads.CrossRoads (Coupled DEVS) [7%]

Represents a free-for-all n-way crossroads. The internal representation for a 4-way implementation is as shown below. For the sake of readability, the outer ports are here encoded using North (N), East (E), South (S), West (W); instead of using indexes. This same encoding is used to distinguish between the individual CrossRoadSegments in the image. In your code, "N" should be represented with 0, "E" with 1, etc.

Parameters (click to expand)
block_name (str)
The name for this model. Must be unique inside a (parent) Coupled DEVS.
destinations
A list of lists of destinations for the CrossRoads. The number of sub-lists indicates how many branches the CrossRoads has. Each sub-list is given to the CrossRoadSegments in order. For instance, when you have a value of [["N", "E"], ["S"], ["W", "N"]], there should be 3 branches in this CrossRoads. The first one will get the ["N", "E"] destinations list, the second one will get the ["S"] singleton and the final branch will get ["W", "N"].
L (float)
The length of the individual CrossRoadSegments.
v_max (float)
The maximal allowed velocity on the CrossRoads.
observ_delay (float)
The observ_delay for the CrossRoadSegments. Defaults 0.1.
Input Ports (click to expand)
car_in_*
Cars can enter the crossroads through this port.
The * indicates an integer representing which branch of the crossroads this port will be linked to. For each of the branches, a car_in_* port exists, which links to the same-index CrossRoadSegment.
Q_recv_*
Allows the crossroads to receive Query events on the associated branch.
The * indicates an integer representing which branch of the crossroads this port will be linked to. For each of the branches, a Q_recv_* port exists, which links to the same-index CrossRoadSegment.
Q_rack_*
Allows the crossroads to receive QueryAck events.
The * indicates an integer representing which branch of the crossroads this port will be linked to. For each of the branches, a Q_rack_* port exists, which links to the next-index CrossRoadSegment.
Output Ports (click to expand)
car_out_*
Outputs the Cars on this branch of the crossroads.
The * indicates an integer representing which branch of the crossroads this port will be linked to. For each of the branches, a car_out_* port exists, which comes from the next-index CrossRoadSegment.
Q_send_*
Outputs the Query events on this branch of the crossroads.
The * indicates an integer representing which branch of the crossroads this port will be linked to. For each of the branches, a Q_send_* port exists, which comes from the next-index CrossRoadSegment. The Q_send_* port also links to the Q_recv_* port of the next CrossRoadSegment, making sure Cars can drive without issues over the crossroads.
Q_sack_*
Outputs the QueryAck events on this branch of the crossroads.
The * indicates an integer representing which branch of the crossroads this port will be linked to. For each of the branches, a Q_sack_* port exists, which comes from the same-index CrossRoadSegment. The Q_sack_* port also links to the Q_rack_* port of the previous CrossRoadSegment, making sure Cars can drive without issues over the crossroads.

Tasks

You will need to perform the following tasks step by step. Store (and submit) a copy of your model after each finished (sub-)task. Provide an answer to all the questions asked. In parentheses, you can find how much each task is worth.

  1. (46%) Create all individual components as described above. Try to use the patterns that were discussed in the theory lectures to solve this task. Minimize magic numbers and maximize the usage of OO-programming.
    • It is suggested to ease yourselves into the assignment by first tackling the SideMarker, Collector and Generator (in that order).
    • You have been provided a small set of tests that allow you to verify (part of) the expected functionalities of all blocks. This gives you a point of reference for correctness.
    • Hint: Gradually built all your components and test their behaviour. Do not try to create a system that fully encompasses everything from scratch. This will minimize the amount of required time to complete this assignment.
    • DO NOT USE ANY ASSERT STATEMENTS! If you receive an invalid input, a (silent) discard is expected. You may log this situation, but it should not break your system.
  2. (22% total | 10% for the model) Create a single RoadStretch (a Coupled DEVS), that starts with a Generator, has a variable amount of RoadSegments, and ends in a Collector. In the middle of this RoadStretch, there should be a Fork, where the second output goes into the sequence of RoadSegment, GasStation, RoadSegment. Eventually, this final RoadSegment merges back into the RoadStretch. Don't forget the SideMarker! You may use as many layers of hierarchy as desired for a clean, easily understandable solution. Choose your parameters as realistic as possible. The circled "P" identifies priority. A graphical representation of this system is shown below. (Note: you can use "open image in a new tab" to enlarge.)


    • (2%) Simulate the RoadStretch for a short period of time and observe what happens. Use some logical statistics to make sense of this system.
    • (5% total) Simulate the RoadStretch for a long period of time and observe what happens. Use some logical statistics to make sense of this system.
      • (2%) Compare your results against the previous simulation. Try to be as detailed as possible.
      • (1%) Why would you use a short/long simulation time?
      • (2%) What do you see when you observe/plot the travel times of all the Cars? Why? Try to be as detailed as possible.
    • (5%) What is the order of execution of the Atomic DEVS components? This does not concern the order of execution of the functions. To clarify: if all your components were to have an (internal) transition at the same time, in which order would these happen? (For instance: first RoadSegment 5, then RoadSegment 3, etc...) Why? How would you alter this order of execution? Does this alteration change your previous results?
  3. (27% total | 10% for the model) Construct and simulate a 4-way CrossRoads, linked to 4 Generators and 4 Collectors. Add at least 3 sequential RoadSegments to each input and output branch of the CrossRoads. Then, provide an answer to the following questions.
    • (2%) What is the order of execution of the CrossRoadSegments? Why? How would you alter this order of execution?
    • (5%) The current representation of the CrossRoads is a free-for-all intersection. Clearly describe how you would turn this into a right of way (nl: voorrang van rechts) CrossRoads.
      If no changes are required, clearly describe how right of way is accomplished by design.
      If changes/additions are needed, include a clear and neat schematic representation and clearly describe all important components. Can you identify any (logical) issues in this system?
    • (5%) The current representation of the CrossRoads is a free-for-all intersection. Clearly describe how you would turn an intersection into a roundabout (info: all Cars on the roundabout have priority over incoming traffic).
      If no changes are required, clearly describe how a roundabout is accomplished by design.
      Do you require changes/additions to the CrossRoads coupled DEVS you have built so far? If so, which ones? You may use a clear and neat schematic to show these changes (if any). Can you identify any (logical) issues in this system?
    • (5%) Compare your simulation results (using interesting statistics of your choice) between the original CrossRoads, the right of way implementation, and the roundabout. Try to describe as much as possible.
  4. (5%) Write a report that explains your solution for this assigment. Include all figures and plots; and discuss them. Also clearly indicate which models can be found in which files. Make sure to mention all your hypotheses, assumptions and conclusions. See also the "submission information" at the top of this page.

Notice the inconsistencies used in units (minutes, seconds, kilometers, meters...). It is up to you to do a conversion to SI Units. This way, you can be ensured that no undesired side effects occur from invalid conversions.

It is preferable to use a predefined seed for random number generation. This allows a consistent result when testing and debugging your code. Note that random number generators also do change a state and should therefore only be used where state changes are allowed!
PythonPDEVS comes with an RNG, yet, for the purposes of the assignment Python's or numpy's random will suffice.

While all components of the model are defined above, you are free to choose how these are implemented. As long as the behaviour is equivalent to how it is described here. Sometimes, there are multiple solutions to the same problem, but there are also ambiguities to allow you to make choices in the implementation. Don't choose for the most impressive solution, but rather the easiest and fastest to implement. Don't forget to discuss where and why you made certain choices!

Where possible, use different experiment files to setup your tasks. This allows you to return to previous tasks without issues, as well as referring to specific modules in your report. Also ensure your model is flexible enough to allow all the tasks by simply changing model parameters. If a task requires a (slight) change in the components used, make sure to include all versions of the components.

Your model should work for Classic DEVS, therefore you can ignore the possibilities of parallelism. To simulate using Classic DEVS, you can do the following:

                    sim = Simulator(model)
                    sim.setClassicDEVS()   # <-- IMPORTANT LINE OF CODE!
                    sim.simulate()
                    

Take pride in your work. Make sure your report and all models and images are clearly readable. If a figure is difficult to read, also include the corresponding source files (*.drawio, *.py...). You will not lose points for doing too much, but you will lose points if you do too little.

Do not include the PythonPDEVS package in your submission!

Practical Issues

Maintained by Hans Vangheluwe. Last Modified: 2024/01/29 13:47:54.