Examples¶
Open these examples in a Google Colaboratory Notebook.
Simulations¶
Simulation models in se-lib are defined as logical nodes in a system and their connections. Function calls enable system dynamics models to be expressed as stocks, flows and auxiliary variables connected in feedback loops. Discrete event models are defined as connected path nodes for entity generation, delays, queues/servers, and termination nodes.
Utilities are provided for output visualization and statistical analysis. Hybrid models and can be developed with relationships between continuous and discrete event parameters.
The following are available online:
se-lib system dynamics examples on Google Colab
Discrete event modeling and simulation on se-lib playground
See the following manuals for further details.
System Dynamics Model¶
# Battle Simulator using Lanchester's Law for Aimed Fire with Reinforcements
init_sd_model(start=0, stop=2, dt=.05)
step_size = 600
add_stock("blue_troops", 1000, inflows=["blue_reinforcements"], outflows=["blue_attrition"])
add_flow("blue_attrition", "red_troops*red_lethality")
add_flow("blue_reinforcements", "step(200, .7)-step(200, 1.2)")
add_auxiliary("blue_lethality", "random.uniform(.7, .9)")
add_stock("red_troops", 800, inflows=["red_reinforcements"], outflows=["red_attrition"])
add_flow("red_attrition", "blue_troops*blue_lethality")
add_flow("red_reinforcements", f"step({step_size}, .3)-step({step_size}, .7)")
add_auxiliary("red_lethality", "random.uniform(.8, 1.0)")
run_model()
save_graph(['blue_troops', 'red_troops'], filename="battle_simulator_troop_levels")
save_graph(["red_attrition", "red_reinforcements", 'blue_attrition', 'blue_reinforcements'], filename="battle_simulator_flow_rates")
Discrete Event Model¶
# electric car charging simulation
init_de_model()
add_source('incoming_cars',
entity_name="Car",
num_entities = 50,
connections={'charger': .7, 'impatient_cars': .3},
interarrival_time='np.random.exponential(5)')
add_server(name='charger',
connections={'payment': 1},
service_time='np.random.uniform(0, 16)',
capacity = 1)
add_delay(name='payment',
delay_time = 'np.random.uniform(1, 3)',
connections={'served_cars': 1},)
add_terminate('served_cars')
add_terminate('impatient_cars')
draw_model_diagram()
model_data, entity_data = run_model()
plot_histogram(model_data['charger']['waiting_times'], xlabel="Charger Waiting Time")
Analyses¶
Quantitative Fault Tree¶
# UUV computed fault tree given probabilities for basic events
uuv_fault_tree = [
("UUV Mission Data Loss", "or", '', ["Communication Loss", "Power Down", "All Sensors Fail"]),
('All Sensors Fail', 'and', '', ['Low Resolution Sensor 1 Fails', 'Low Resolution Sensor 2 Fails', 'High Resolution Sensor 3 Fails']),
('Power Down', 'and', '', ["Main Power Down", "Backup Power Down"]),
('Communication Loss', 'basic', .003),
('Main Power Down', 'basic', .02),
('Backup Power Down', 'basic', .08),
('Low Resolution Sensor 1 Fails', 'basic', .001),
('Low Resolution Sensor 2 Fails', 'basic', .001),
('High Resolution Sensor 3 Fails', 'basic', .003),
]
se.draw_fault_tree_diagram_quantitative(uuv_fault_tree, filename="uuv_quantitative_fault_tree", format="svg")
Critical Path Analysis¶
A critical path can be computed from a set of tasks with associated time durations and dependencies as below.
# tasks, durations and dependencies
tasks = [('A', {'Duration': 3}),
('B', {'Duration': 5}),
('C', {'Duration': 2}),
('D', {'Duration': 3}),
('E', {'Duration': 5})]
task_dependencies = [('A', 'C'),
('B', 'C'),
('A', 'D'),
('C', 'E'),
('D', 'E')]
# create diagram
se.critical_path_diagram(tasks, task_dependencies, filename="critical_path")
Diagrams¶
These examples generate diagrams to be displayed from a Python console or Jupyter Notebook. After importing se-lib, model elements can be specified as simple lists. Element relationships are designated as lists of tuple pairs. The output filenames are optional and used here to generate the included SVG images.
Use Case Model¶
Actors and use cases are first specified in lists. The interactions between actors and use cases are identified by their tuple pairs and drawn accordingly on the diagram.
import selib as se
# system model
system_name = "Course Portal"
actors = ['Student', 'Instructor']
use_cases = ['Post Discussion', 'Take Quiz', 'Create Quiz']
interactions = [('Student', 'Post Discussion'), ('Instructor', 'Post Discussion'), ('Student', 'Take Quiz'), ('Instructor', 'Create Quiz')]
use_case_relationships = []
# create diagram
se.use_case_diagram(system_name, actors, use_cases, interactions, use_case_relationships, filename=system_name+'use case diagram.pdf')
Sequence Model¶
A sequence diagram can be constructed per the following.
# system model
system_name = "Battle Simulator"
actors = ['Battle Planner']
objects = ['main']
actions = [
('Battle Planner', 'main', 'run()'),
('main', 'Battle Planner', 'request for side 1 name'),
('Battle Planner', 'main', 'side 1 name'),
('main', 'Battle Planner', 'request for side 2 name'),
('Battle Planner', 'main', 'side 2 name'),
('main', 'Battle Planner', 'request for side 1 starting level'),
('Battle Planner', 'main', 'side 1 starting level'),
('main', 'Battle Planner', 'request for side 1 lethality coefficient'),
('Battle Planner', 'main', 'side 1 lethality coefficient'),
('main', 'Battle Planner', 'request for side 2 starting level'),
('Battle Planner', 'main', 'side 2 starting level'),
('main', 'Battle Planner', 'request for side 2 lethality coefficient'),
('Battle Planner', 'main', 'side 2 lethality coefficient'),
('main', 'Battle Planner', 'time history of troops and victor'),
]
# create diagram
se.sequence_diagram(system_name, actors, objects, actions, filename=system_name+"_sequence_diagram")
Context Model¶
# system model
system_name = "Python Interpreter with PyML"
external_actors = ["User", "OS", "Graphviz"]
# create context diagram
se.context_diagram(system_name, external_actors, filename="pyml_context_diagram_offline")
Requirements Model¶
# Intelligence, Surveillance, & Reconnaissance Unmanned Underwater Vehicle (ISR UUV) un-numbered requirements
requirements = [("ISR UUV", "Performance"),
("Performance",
("The UUV shall be capable of completing a mission of 6 hours duration.",
"The UUV shall be capable of a top speed of 14 knots.",
"The UUV shall be capable of surviving in an open ocean environment to a depth of 1500 meters.",
"The UUV shall avoid detection.")),
("ISR UUV", "Communication"),
("Communication",
("Mission parameters shall be uploadable to the UUV",
"The UUV shall receive remote commands",
"The UUV shall commence its mission when commanded",
"The UUV shall be capable of transmitting data in a host ship compatible format",
"The UUV shall indicate that it is ready for recovery")),]
# draw requirements diagram as horizontal tree left -> right
se.requirements_diagram(requirements, rankdir='LR', filename="uuv_requirements_tree")
Work Breakdown Structure¶
# project work breakdown structure
wbs_decompositions = [
('Skateboard', 'Hardware'), ('Skateboard', 'Software'), ('Skateboard', 'Integration and Test'),
('Hardware', 'Board'), ('Hardware', 'Wheels'), ('Hardware', 'Mounting'),
('Software', 'OS'), ('Software', 'GPS Driver'), ('Software', 'Route Tracking'),
('Integration and Test', 'Fixed Platform'), ('Integration and Test', 'Street Testing')]
# create diagram
se.wbs_diagram(wbs_decompositions, filename="skateboard_wbs")
Design Structure Matrix¶
tasks = ['Make Board', 'Acquire Wheels', 'Assemble', 'Test']
task_dependencies = [('Make Board', 'Assemble'), ('Acquire Wheels', 'Assemble'), ('Assemble', 'Test'), ('Test', 'Assemble')]
se.design_structure_matrix(tasks, task_dependencies, filename="skateboard_task_dsm_with_feedback")
Read Fault Tree from Excel¶
Portion of example Excel file aav_fault_tree.xlsx:
# read fault tree from Excel file into list of nodes
fault_tree_list = se.read_fault_tree_excel('aav_fault_tree.xlsx')
# create fault tree diagram
se.fault_tree_diagram(fault_tree_list)
Causal Diagram¶
# causal relationships
relationships = [('Available personnel',"Workforce gap", "-"),
('Required personnel',"Workforce gap", "+"),
("Workforce gap", "Hiring rate", "+"),
("Hiring rate", "Available personnel", "+"),
]
# draw diagram
se.causal_diagram(relationships)