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.
Car s can be modelled as events that travel over roads.
- Each road is decomposed into small
RoadSegment s that can (at most) contain a single Car .
When multiple Car s are on a RoadSegment ,
we assume a collission occurred and Car s 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
RoadSegment s 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 RoadSegment s.
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 QueryAck s 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 RoadSegment s.
|
|
components.roadsegment.RoadSegment (Atomic DEVS) [10%]
Represents a small stretch of road that can only contain a single Car .
When multiple Car s are on a RoadSegment , we assume the Car s 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
Car s on this RoadSegment . Even though the existence of
multiple Car s 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
Car s 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 Car s 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
Car s, 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., Car s 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
QueryAck s 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 Car s. This component allows cars to enter the system.
The inter-arrival time (IAT) for the Car s 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
Car s. A random destination will be selected.
limit (int)
- Upper limit of the number of
Car s 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 Car s 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
Car s to collect.
It can be useful to already compute some statistics upon the arrival of new Car s.
|
|
components.sidemarker.SideMarker (Atomic DEVS) [3%]
Marks all inputted QueryAck s 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 RoadSegment s 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
QueryAck s.
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
QueryAck s again, at the same time as they were entered.
|
|
components.fork.Fork (Atomic DEVS, inherits from RoadSegment ) [3%]
Allows Car s to choose between multiple RoadSegment s.
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 Car s need gas.
It can store an infinite amount of Car s, 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
-
Car s 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.
Car s 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
Car s, 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
Car s exit the crossroads at the
right time.
Input Ports (click to expand)
car_in_cr
-
Car s can enter on this segment as if it were the normal car_in
port. However, this port is only used for Car s 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
Car s that must stay on the crossroads. In essence,
these are all the Car s 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 CrossRoadSegment s
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 CrossRoadSegment s 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
CrossRoadSegment s.
v_max (float)
- The maximal allowed velocity on the
CrossRoads .
observ_delay (float)
- The
observ_delay for the CrossRoadSegment s. Defaults 0.1.
Input Ports (click to expand)
car_in_*
-
Car s 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
Car s 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 Car s 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 Car s 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.
- (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.
- (22% total | 10% for the model)
Create a single
RoadStretch (a Coupled DEVS), that starts with a Generator ,
has a variable amount of RoadSegment s, 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
Car s? 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?
- (27% total | 10% for the model)
Construct and simulate a 4-way
CrossRoads , linked to 4 Generator s and 4 Collector s.
Add at least 3 sequential RoadSegment s 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
CrossRoadSegment s? 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 Car s 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.
- (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
|