### Simple example: Source-Buffer-Machine-Buffer-Sink simulation Source: https://factorysimpy.github.io/FactorySimPy A simple example simulating a machine that gets an item from a buffer and pushes it to one of its output edges after processing. It creates a Source, Machine, Sink, and two Buffers, connects them, and runs the simulation for 10 time units. ```python # System layout # SRC ──> BUF1 ──> MACHINE1 ──> BUF2 ──> SINK import factorysimpy from factorysimpy.nodes.machine import Machine from factorysimpy.edges.buffer import Buffer from factorysimpy.nodes.source import Source from factorysimpy.nodes.sink import Sink env = simpy.Environment() # Initializing nodes SRC= Source(env, id="SRC", flow_item_type="item", inter_arrival_time= 0.8,blocking=False,out_edge_selection="RANDOM" ) MACHINE1 = Machine(env, id="MACHINE1",work_capacity=4, processing_delay=1.1,blocking=False, in_edge_selection="RANDOM",out_edge_selection="RANDOM") SINK= Sink(env, id="SINK" ) # Initializing edges BUF1 = Buffer(env, id="BUF1", store_capacity=4, delay=0.5, mode = "FIFO") BUF2 = Buffer(env, id="BUF2", store_capacity=4, delay=0.5, mode = "FIFO") # Adding connections BUF1.connect(SRC,MACHINE1) BUF2.connect(MACHINE1,SINK) env.run(until=10) ``` -------------------------------- ### Minimal Working Example with Machine and Buffers Source: https://factorysimpy.github.io/FactorySimPy/getting_started Minimal example simulating a machine with two buffers. Creates nodes and edges, connects them, and runs the simulation for 10 time units. ```python # System layout # SRC ──> BUF1 ──> MACHINE1 ──> BUF2 ──> SINK import factorysimpy from factorysimpy.nodes.machine import Machine from factorysimpy.edges.buffer import Buffer from factorysimpy.nodes.source import Source from factorysimpy.nodes.sink import Sink env = simpy.Environment() # Initializing nodes SRC= Source(env, id="SRC", flow_item_type="item", inter_arrival_time= 0.8,blocking=False,out_edge_selection="RANDOM" ) MACHINE1 = Machine(env, id="MACHINE1",work_capacity=4, processing_delay=1.1,blocking=False, in_edge_selection="RANDOM",out_edge_selection="RANDOM") SINK= Sink(env, id="SINK" ) # Initializing edges BUF1 = Buffer(env, id="BUF1", store_capacity=4, delay=0.5, mode = "FIFO") BUF2 = Buffer(env, id="BUF2", store_capacity=4, delay=0.5, mode = "FIFO") # Adding connections BUF1.connect(SRC,MACHINE1) BUF2.connect(MACHINE1,SINK) env.run(until=10) ``` -------------------------------- ### Install FactorySimPy from GitHub Source: https://factorysimpy.github.io/FactorySimPy/getting_started Install SimPy first, then install FactorySimPy from GitHub. Requires Python ≥ 3.8. ```bash pip install simpy ``` ```bash pip install git+https://github.com/FactorySimPy/FactorySimPy.git ``` -------------------------------- ### Simple continuous conveyor example Source: https://factorysimpy.github.io/FactorySimPy/examples Use this example to build a simple factory simulation with a continuous conveyor belt. It sets up a Source, Machine, Sink, Buffer, and ConveyorBelt, connects them, and runs the simulation for 100 time units. The conveyor is configured with capacity 5, speed 1, length 1, and accumulating=True. ```python from factorysimpy.nodes.machine import Machine from factorysimpy.edges.continuous_conveyor import ConveyorBelt from factorysimpy.edges.buffer import Buffer from factorysimpy.nodes.source import Source from factorysimpy.nodes.sink import Sink import random #SRC ──> CONVEYORBELT1 ──> MACHINE1 ───> BUF2 ──>SINK env = simpy.Environment() # Initializing nodes SRC= Source(env, id="SRC", inter_arrival_time=0.3,blocking=True, out_edge_selection="FIRST_AVAILABLE" ) #src= Source(env, id="Source-1", inter_arrival_time=0.2,blocking=True,out_edge_selection=0 ) MACHINE1 = Machine(env, id="MACHINE1", node_setup_time=0, work_capacity=1, blocking=True, processing_delay=0.7, in_edge_selection="FIRST_AVAILABLE", out_edge_selection="ROUND_ROBIN") SINK= Sink(env, id="SINK") # Initializing edges BUFFER1 = Buffer(env, id="BUFFER1", capacity=1, delay=0, mode="FIFO") CONVEYORBELT1 = ConveyorBelt(env, id="CONVEYORBELT1", capacity=5, speed=1, length=1, accumulating=True) # Adding connections CONVEYORBELT1.connect(SRC,MACHINE1) BUFFER1.connect(MACHINE1,SINK) time=100 env.run(until=time) ``` -------------------------------- ### Simple slotted conveyor example Source: https://factorysimpy.github.io/FactorySimPy/examples Use this example to build a simple factory simulation with a slotted conveyor belt. It sets up a Source, Machine, Sink, Buffer, and ConveyorBelt, connects them, and runs the simulation for 100 time units. The conveyor is configured with capacity 5, delay 1, and accumulating=True. ```python from factorysimpy.nodes.machine import Machine from factorysimpy.edges.slotted_conveyor import ConveyorBelt from factorysimpy.edges.buffer import Buffer from factorysimpy.nodes.source import Source from factorysimpy.nodes.sink import Sink import random #SRC ──> CONVEYORBELT1 ──> MACHINE1 ───> BUF2 ──>SINK env = simpy.Environment() # Initializing nodes SRC= Source(env, id="SRC", inter_arrival_time=0.3,blocking=True, out_edge_selection="FIRST_AVAILABLE" ) #src= Source(env, id="Source-1", inter_arrival_time=0.2,blocking=True,out_edge_selection=0 ) MACHINE1 = Machine(env, id="MACHINE1", node_setup_time=0, work_capacity=1, blocking=True, processing_delay=0.7, in_edge_selection="FIRST_AVAILABLE", out_edge_selection="ROUND_ROBIN") SINK= Sink(env, id="SINK") # Initializing edges BUFFER1 = Buffer(env, id="BUFFER1", capacity=1, delay=0, mode="FIFO") CONVEYORBELT1 = ConveyorBelt(env, id="CONVEYORBELT1", capacity=5, delay=1, accumulating=True) # Adding connections CONVEYORBELT1.connect(SRC,MACHINE1) BUFFER1.connect(MACHINE1,SINK) time=100 env.run(until=time) ``` -------------------------------- ### Simulation with ReservablePriorityReqStore Source: https://factorysimpy.github.io/FactorySimPy/extendedresources Complete simulation setup using SimPy and ReservablePriorityReqStore. Defines producer, consumer, and machine processes, then runs the simulation for 5 time units. Demonstrates priority-based reserve_get calls and store operations. ```python # @title Usecase import simpy from ReservablePriorityReqStore import ReservablePriorityReqStore ''' In this simulation, two machines (MachineGreen and MachineOrange) produce new items by consuming specific part. MachineGreen,which produces green balls, requests parts (like yellow and blue balls) with a higher priority, while MachineOrange, which produces orange balls, requests parts (like yellow and red balls) with lower priority. Producers generate red, yellow, and blue balls at defined intervals, and consumers retrieve the assembled green and orange balls from their respective stores.''' # ----- Producer ----- def producer(env, interarrival, store, item_prefix): """Produces items with a given prefix into a store.""" i = 0 while True: yield env.timeout(interarrival) put_req = store.reserve_put() yield put_req item_name = f"{item_prefix}{i+1}" store.put(put_req, item_name) print(f"T={env.now:.2f}: Producer {item_prefix}: added {item_name})") i += 1 # ----- Consumer ----- def consumer(env, interarrival, store, consumer_name): """Consumes items from a store.""" while True: yield env.timeout(interarrival) get_req = store.reserve_get() yield get_req item = store.get(get_req) print(f"T={env.now:.2f}: Consumer {consumer_name}: got item {item}") # ----- Machine ----- def machine(env, delay, input_stores, input_priorities, output_store, output_prefix): """ A machine that requests multiple items from input stores (with optional priorities),waits processing time, and outputs a new item. Args: input_stores (list): list of stores to get inputs from input_priorities (list): list of priorities (None if no priority) output_store: where to put output output_prefix: name prefix for output items """ i = 0 while True: put_req = output_store.reserve_put() yield put_req # Request input items input_requests = [] for store, priority in zip(input_stores, input_priorities): if priority is not None: req = store.reserve_get(priority=priority) else: req = store.reserve_get() input_requests.append(req) print(f"T={env.now:.2f}: Machine {output_prefix}: waiting to yield reserve_get requests") yield env.all_of(input_requests) # Get input items for store, req in zip(input_stores, input_requests): store.get(req) print(f"T={env.now:.2f}: Machine {output_prefix}: got both inputs") yield env.timeout(delay) output_store.put(put_req, f"{output_prefix}{i}") print(f"T={env.now:.2f}: Machine {output_prefix}: finished product is available in its store") i += 1 # ----- Simulation Setup ----- def run_simulation(): env = simpy.Environment() # Create Stores redstore = ReservablePriorityReqStore(env, capacity=5) yellowstore = ReservablePriorityReqStore(env, capacity=1) bluestore = ReservablePriorityReqStore(env, capacity=5) orangestore = ReservablePriorityReqStore(env, capacity=1) greenstore = ReservablePriorityReqStore(env, capacity=1) # Producer setups producer_params = [ (1, redstore, "red"), (2, yellowstore, "yellow"), (1, bluestore, "blue") ] # Consumer setups consumer_params = [ (1, orangestore, "orange"), (1, greenstore, "green") ] # Machine setups machine_params = [ (1, [yellowstore, redstore], [None, None], orangestore, "orange"),#Machine1 (1, [yellowstore, bluestore], [-2, None], greenstore, "green") # Machine2 ] # Start Producers for interarrival, store, prefix in producer_params: env.process(producer(env, interarrival, store, prefix)) # Start Consumers for interarrival, store, name in consumer_params: env.process(consumer(env, interarrival, store, name)) # Start Machines for delay, inputs, priorities, output, prefix in machine_params: env.process(machine(env, delay, inputs, priorities, output, prefix)) # Run Simulation env.run(until=5) # Run it run_simulation() ``` -------------------------------- ### Simple fleet example with constant delays Source: https://factorysimpy.github.io/FactorySimPy/examples Configure a simple factory simulation with a fleet edge. Set inter_arrival_time and processing_delay as constants at node initiation; edge selection can be a constant or a generator function passed as a string. The example runs the environment for 10 time units. ```python # System layout # SRC ──> FLEET1 ──> MACHINE1 ──> BUF2 ──> SINK import factorysimpy from factorysimpy.nodes.machine import Machine from factorysimpy.edges.buffer import Buffer from factorysimpy.edges.fleet import Fleet from factorysimpy.nodes.source import Source from factorysimpy.nodes.sink import Sink env = simpy.Environment() # Initializing nodes SRC= Source(env, id="SRC", inter_arrival_time=0.2,blocking=True, out_edge_selection=0 ) #src= Source(env, id="Source-1", inter_arrival_time=0.2,blocking=True,out_edge_selection=0 ) MACHINE1 = Machine(env, id="MACHINE1",node_setup_time=0,work_capacity=1,blocking=True, processing_delay=0.5,in_edge_selection=0,out_edge_selection="ROUND_ROBIN") SINK= Sink(env, id="SINK") # Initializing edges FLEET1 = Fleet(env, id="FLEET1", capacity=3, delay=1, transit_delay=1.4) BUFFER2 = Buffer(env, id="BUFFER2", capacity=5, delay=0, mode="FIFO") # Adding connections FLEET1.connect(SRC,MACHINE1) BUFFER2.connect(MACHINE1,SINK) time=10 env.run(until=time) ``` -------------------------------- ### Node(env, id, in_edges=None, out_edges=None, node_setup_time=0) Source: https://factorysimpy.github.io/FactorySimPy/nodes Constructor for the Node class. Initializes a node with an environment, identifier, optional input/output edges, and an optional setup time. ```APIDOC ## Node(env, id, in_edges=None, out_edges=None, node_setup_time=0) ### Description Base class to represent an active entity in a manufacturing system, such as machines, splits, or joints. ### Parameters - **env** (simpy.Environment) - Required - The simulation environment. - **id** (str) - Required - Identifier for the node. - **in_edges** (list, default: None) - Optional - List of input edges connected to the node. - **out_edges** (list, default: None) - Optional - List of output edges connected to the node. - **node_setup_time** (int or float, default: 0) - Optional - Initial setup time for the node. Can be an int or float used as a constant delay. ### Raises - TypeError - If the type of `env` or `id` is incorrect. - ValueError - If `node_setup_time` input is invalid. ### Source Code ```python def __init__(self,env,id, in_edges = None, out_edges = None, node_setup_time= 0): # Type checks if not isinstance(env, simpy.Environment): raise TypeError("env must be a simpy.Environment instance") if not isinstance(id, str): raise TypeError("name must be a string") self.env = env self.id = id # Identifier for the node. self.node_setup_time = node_setup_time # Time taken to set up the node. self.in_edges = in_edges # List of input edges connected to the node. self.out_edges = out_edges #List of output edges connected to the node. if isinstance(node_setup_time, (int, float)): self.node_setup_time = node_setup_time else: raise ValueError( "Invalid node_setup_time value. Provide constant ( int or float)." ) ``` ``` -------------------------------- ### Create a 20-machine assembly line with buffers using FactorySimPy constructs Source: https://factorysimpy.github.io/FactorySimPy/examples Use this example to build a 20-machine assembly line with buffers between each machine using FactorySimPy constructs. It defines node, edge, source, and sink keyword arguments, then calls connect_chain_with_source_sink to create the chain and connect_nodes_with_buffers to link the nodes. The simulation runs for 100 time units. ```python # System layout # SRC ──> BUF1 ──> MACHINE1 ──> BUF2 ──> MACHINE2 ──> # ──> BUF3 ──> MACHINE3 ──> BUF4 ──> MACHINE4 ──> ... # . . . . # . . . . # ... BUF19 ──> MACHINE19 ──> BUF20 ──> MACHINE20 ──> SINK # (20 machines in series, each separated by a buffer) import factorysimpy from factorysimpy.nodes.machine import Machine from factorysimpy.edges.buffer import Buffer from factorysimpy.nodes.source import Source from factorysimpy.nodes.sink import Sink from factorysimpy.constructs.chain import connect_chain_with_source_sink, connect_nodes_with_buffers env = simpy.Environment() node_kwargs = { "node_setup_time": 0, "work_capacity": 1, "processing_delay": 0.8, "in_edge_selection": "RANDOM", "out_edge_selection": "FIRST_AVAILABLE" } edge_kwargs = { "store_capacity": 4, "delay": 0, "mode": "LIFO" } source_kwargs = { "inter_arrival_time": 1, "blocking": True, "out_edge_selection": "FIRST_AVAILABLE" } sink_kwargs = { "id": "Sink-1" } # Example for a chain of 1 machine (count=1) nodes, edges, src, sink = connect_chain_with_source_sink( env, count=20, node_cls=Machine, edge_cls=Buffer, source_cls=Source, sink_cls=Sink, node_kwargs=node_kwargs, edge_kwargs=edge_kwargs, source_kwargs = source_kwargs, sink_kwargs= sink_kwargs, prefix="Machine", edge_prefix="Buffer" ) machines, buffers = connect_nodes_with_buffers(nodes, edges, src, sink) env.run(until=100) ``` -------------------------------- ### SimPy simulation with ReservablePriorityReqStore Source: https://factorysimpy.github.io/FactorySimPy/extendedresources Complete example of using ReservablePriorityReqStore in a SimPy environment. It defines an Item class, creates a store with capacity 3, and sets up producer and consumer processes that use reserve_put, reserve_get, and reserve_get_cancel. The simulation runs for 10 time units. ```python import simpy import random from ReservablePriorityReqStore import ReservablePriorityReqStore class Item: """Represents an item to be stored.""" def __init__(self, name): self.name = name # Simulation Setup env = simpy.Environment() itemstore = ReservablePriorityReqStore(env, capacity=3) def producer(env, itemstore, name, priority): """Producer process produces items and puts it in the store.""" yield env.timeout(random.uniform(1, 3)) # Simulate time before producing put_reservation = itemstore.reserve_put(priority=priority) yield put_reservation # Wait for reservation to succeed item = Item(f"{name}") itemstore.put(put_reservation, item) print(f"T={env.now:.2f} : {name} added to store with priority {priority}") def consumer(env, itemstore, name, priority, cancel=False): """Consumer process picks up items from the store.""" get_reservation = itemstore.reserve_get(priority=priority) print(f"T={env.now:.2f} : {name} placed a reserve_get request to store with priority {priority}") if cancel and random.choice([True, False]): itemstore.reserve_get_cancel(get_reservation) print(f"T={env.now:.2f} : {name} CANCELED reservation") return yield get_reservation # Wait for reservation to succeed print(f"T={env.now:.2f} : {name} yielded from store with priority {priority}") yield env.timeout(random.uniform(2, 5)) item = itemstore.get(get_reservation) print(f"T={env.now:.2f} : {name} retrieved {item.name} from store with priority {priority}") # Creating producers and consumers env.process(consumer(env, itemstore, "Consumer1", priority=3, cancel=True)) env.process(consumer(env, itemstore, "Consumer2", priority=1)) env.process(consumer(env, itemstore, "Consumer3", priority=2)) env.process(producer(env, itemstore, "ItemA", priority=2)) env.process(producer(env, itemstore, "ItemB", priority=1)) env.process(producer(env, itemstore, "ItemC", priority=3)) env.run(until=10) ``` -------------------------------- ### PriorityReqStore basic put/get with priorities Source: https://factorysimpy.github.io/FactorySimPy/extendedresources Basic example of PriorityReqStore: two sinks request items with priorities 2 and 1, two sources put items with priorities 2 and 1. Lower priority value yields first; same-priority requests follow FIFO. Output shows that the priority-1 sink receives the priority-1 item first, even though the priority-2 sink requested earlier. ```python import simpy from PriorityReqStore import PriorityReqStore class item: def __init__(self,name): self.name=name def source(name,env,delay,priority=0): i=1 yield env.timeout(delay) item1 = item(name='item'+str(name)+str(i)) print(f'T={env.now:.2f}: Source {name} Going to put an item in store {item1.name} with priority {priority}') yield store.put(item1,priority) i+=2 def sink(name,env,delay,priority): yield env.timeout(delay) print(f'T={env.now:.2f}: Sink {name} placed a get request with priority {priority} in the store') item = yield store.get(priority) print(f'T={env.now:.2f}: Sink {name} Got an item from store {item.name}') env= simpy.Environment() store= PriorityReqStore(env,2) p1= env.process(sink('OUT-1',env,0,2)) p2= env.process(sink('OUT-2',env,0,1)) p3= env.process(source('IN-A',env,1,2)) p4= env.process(source('IN-B',env,1,1)) env.run(until=5) ``` ```text T=0.00: Sink OUT-1 placed a get request with priority 2 in the store T=0.00: Sink OUT-2 placed a get request with priority 1 in the store T=1.00: Source IN-A Going to put an item in store itemIN-A1 with priority 2 T=1.00: Source IN-B Going to put an item in store itemIN-B1 with priority 1 T=1.00: Sink OUT-2 Got an item from store itemIN-A1 T=1.00: Sink OUT-1 Got an item from store itemIN-B1 ``` -------------------------------- ### Initialize Source component Source: https://factorysimpy.github.io/FactorySimPy/basic_components Shows how to create a Source instance with required parameters. The `inter_arrival_time` can be a constant or a function/generator. The `out_edge_selection` can be a string, callable, generator, or constant int. The `blocking` parameter determines whether the source waits for the output edge or discards items when full. ```python import factorysimpy from factorysimpy.nodes.source import Source SRC = Source( env, # Simulation environment id="SRC2", # Unique identifier for the source node inter_arrival_time=0.4, # Time between item generations (can be constant or function/generator) flow_item_type="item", # Type of baseflowitem that the source should generate blocking=False, # If True, waits for output edge to accept item; if False, discards item if the output edge is full out_edge_selection=0 # Strategy or function to select output edge (can be string or callable or genrator or a constant int) ) ``` -------------------------------- ### get(get_event) Source: https://factorysimpy.github.io/FactorySimPy/reservablepriorityreqstore Retrieves an item from the store after a successful reservation. Raises errors if no reservation exists or if the item is None. ```APIDOC ## get(get_event) ### Description Retrieve an item from the store after a successful reservation. This method attempts to retrieve an item associated with a `reserve_get` event. If the reservation exists, it triggers `_trigger_get` to retrieve the item. If successful, `_trigger_reserve_put` is called to process any pending `reserve_put` requests. If the item retrieval fails, an error message is raised. ### Method get ### Parameters - **get_event** (Event) - Required - The reservation event associated with the request. ### Returns - **item** (Object) - The retrieved item if successful, otherwise raises an error. ### Raises - RuntimeError - If no reservations are available in the reservations_get - RuntimeError - If item returned is None ``` -------------------------------- ### Simulation output Source: https://factorysimpy.github.io/FactorySimPy/extendedresources Expected output from the example simulation, showing the sequence of reservation, cancellation, and retrieval events with timestamps and priorities. ```text T=0.00 : Consumer1 placed a reserve_get request to store with priority 3 T=0.00 : Consumer1 CANCELED reservation T=0.00 : Consumer2 placed a reserve_get request to store with priority 1 T=0.00 : Consumer3 placed a reserve_get request to store with priority 2 T=2.14 : ItemB added to store with priority 1 T=2.14 : Consumer2 yielded from store with priority 1 T=2.23 : ItemA added to store with priority 2 T=2.23 : Consumer3 yielded from store with priority 2 T=2.54 : ItemC added to store with priority 3 T=5.40 : Consumer2 retrieved ItemB from store with priority 1 T=6.02 : Consumer3 retrieved ItemA from store with priority 2 ``` -------------------------------- ### Pass generator functions for out_edge_selection and in_edge_selection in FactorySimPy Source: https://factorysimpy.github.io/FactorySimPy/examples Use this example to model edge selection as generator functions that depend on the simulation environment time or node state. The source_out_edge_selector yields 1 on even time steps and 0 on odd steps, while machine_in_edge_selector cycles through the machine's input edge indices. The example wires SRC2 and MACHINE1 to these generator functions and runs the simulation for 10 time units. ```python # System layout # SRC1 ──> BUFFER1 ──┐ # │ # SRC2 ──> BUFFER2 ──┴─> MACHINE1 ──┬─> BUFFER3 ──> SINK1 # │ │ # └─> BUFFER5 ──> SINK3 └─> BUFFER4 ──> SINK2 # import factorysimpy from factorysimpy.nodes.machine import Machine from factorysimpy.edges.buffer import Buffer from factorysimpy.nodes.source import Source from factorysimpy.nodes.sink import Sink env = simpy.Environment() #let the out_edge_selection of the source be a generator function that yields 1 or 0 based on the current time # This generator function will yield 1 if the current time is even, and 0 if it is odd. # This will simulate a scenario where the source alternates between two output edges based on the time. #out_edge_selection as a generator function for machine def machine_out_edge_selector(node, env): while True: if env.now%2==0: yield 1 else: yield 0 #let the in_edge_selection of the machine be a generator function that yields the index of the edge to be selected # This generator function will yield the index of the edge to be selected based on the current time. # The index will be incremented every time the generator is called, and will wrap around when it reaches the number of edges. #in_edge_selection as a generator function for machine def machine_in_edge_selector(node,env): num_edges= len(node.in_edges) i=0 while True: yield i yield i i = (i + 1) % num_edges #let the out_edge_selection of the source be a generator function that yields 1 or 0 based on the current time # This generator function will yield 1 if the current time is even, and 0 if it is odd. #out_edge_selection as a generator function for source def source_out_edge_selector(node, env): while True: if env.now%2==0: yield 1 else: yield 0 # Initializing nodes SRC1= Source(env, id="SRC1", inter_arrival_time=0.7,blocking=False, out_edge_selection="FIRST_AVAILABLE" ) SRC2= Source(env, id="SRC2", inter_arrival_time=0.4,blocking=False, out_edge_selection=None ) MACHINE1 = Machine(env, id="MACHINE1",work_capacity=4, processing_delay=1,in_edge_selection=None,out_edge_selection=None) SINK1= Sink(env, id="SINK1", in_edge_selection="RANDOM" ) SINK2= Sink(env, id="SINK2", in_edge_selection="RANDOM" ) SINK3= Sink(env, id="SINK3", in_edge_selection="FIRST_AVAILABLE" ) #initialising out_edge_selection for source source_out_edge_func = source_out_edge_selector(SRC2,env) SRC2.out_edge_selection = source_out_edge_func #initialising in_edge_selection parameter machine_in_edge_func = machine_in_edge_selector(MACHINE1,env) MACHINE1.in_edge_selection = machine_in_edge_func #initialising in_edge_selection parameter for machine machine_out_edge_func = machine_out_edge_selector(MACHINE1,env) MACHINE1.out_edge_selection = machine_out_edge_func # Initializing edges # Initializing edges BUF1 = Buffer(env, id="BUF1", store_capacity=4, delay=0.5) BUF2 = Buffer(env, id="BUF2", store_capacity=4, delay=0.5) BUF3 = Buffer(env, id="BUF3", store_capacity=4, delay=0.5) BUF4 = Buffer(env, id="BUF4", store_capacity=4, delay=0.5) BUF5 = Buffer(env, id="BUF5", store_capacity=4, delay=0.5) # Adding connections BUF1.connect(SRC1,MACHINE1) BUF2.connect(SRC2,MACHINE1) BUF3.connect(MACHINE1,SINK1) BUF4.connect(MACHINE1,SINK2) BUF5.connect(SRC2,SINK3) env.run(until=10) ``` -------------------------------- ### Instantiate nodes and edges Source: https://factorysimpy.github.io/FactorySimPy/basic_components Creates a Source, Machine, Sink, and two Buffer edges. This is the first step in connecting components. ```python n1 = Source() n2 = Machine() n3 = Sink() e1 = Buffer() e2 = Buffer() ``` -------------------------------- ### Simple FactorySimPy simulation: source-buffer-machine-buffer-sink Source: https://factorysimpy.github.io/FactorySimPy/examples Connects a source, two buffers, a machine, and a sink in a linear flow, then runs the simulation for 10 time units. The source uses a constant inter_arrival_time of 0.8, the machine has a processing_delay of 1.1 and work_capacity of 4, and both buffers use FIFO mode with capacity 4 and delay 0.5. Edge selection is set to 0 for the source and machine input, and "RANDOM" for the machine output. ```python # System layout # SRC ──> BUF1 ──> MACHINE1 ──> BUF2 ──> SINK import factorysimpy from factorysimpy.nodes.machine import Machine from factorysimpy.edges.buffer import Buffer from factorysimpy.nodes.source import Source from factorysimpy.nodes.sink import Sink env = simpy.Environment() # Initializing nodes SRC= Source(env, id="SRC", inter_arrival_time= 0.8,blocking=False,out_edge_selection=0 ) MACHINE1 = Machine(env, id="MACHINE1",work_capacity=4, processing_delay=1.1, in_edge_selection=0,out_edge_selection="RANDOM") SINK= Sink(env, id="SINK" ) # Initializing edges BUF1 = Buffer(env, id="BUF1", store_capacity=4, delay=0.5, mode = "FIFO") BUF2 = Buffer(env, id="BUF2", store_capacity=4, delay=0.5, mode = "FIFO") # Adding connections BUF1.connect(SRC,MACHINE1) BUF2.connect(MACHINE1,SINK) env.run(until=10) ``` -------------------------------- ### ReservablePriorityReqStore(env, capacity=float('inf')) Source: https://factorysimpy.github.io/FactorySimPy/reservablepriorityreqstore Initializes a reservable store with priority-based reservations. The store can hold a specified capacity of items, defaulting to infinity. ```APIDOC ## ReservablePriorityReqStore(env, capacity=float('inf')) ### Description Initializes a reservable store with priority-based reservations. The store can hold a specified capacity of items, defaulting to infinity. ### Constructor Parameters - **env** (Environment) - Required - The SimPy environment. - **capacity** (int, optional) - The maximum number of items the store can hold. Defaults to infinity. ### Attributes - **reserved_events** (list) - Maintains events corresponding to reserved items to preserve item order by index. - **reserve_put_queue** (list) - Queue for managing reserve_put reservations. - **reservations_put** (list) - List of successful put reservations. - **reserve_get_queue** (list) - Queue for managing reserve_get reservations. - **reservations_get** (list) - List of successful get reservations. ``` -------------------------------- ### Pass generator functions as delay parameters in FactorySimPy Source: https://factorysimpy.github.io/FactorySimPy/examples Use this example to pass Python generator functions as delay parameters in FactorySimPy. The source's inter-arrival time is sampled from a Gaussian distribution (mean=2, std=0.5), and the machine's processing delay depends on the time spent in the PROCESSING_STATE: if greater than 7, delay is 0.9; otherwise 1.2. The generator functions are passed as references to the inter_arrival_time and processing_delay parameters. ```python # System layout # SRC ──> BUF1 ──> MACHINE1 ──> BUF2 ──> SINK import random import factorysimpy from factorysimpy.nodes.machine import Machine from factorysimpy.edges.buffer import Buffer from factorysimpy.nodes.source import Source from factorysimpy.nodes.sink import Sink env = simpy.Environment() #let the inter arrival time of the source be a value sampled from a gaussian distribution with mean = 2, std deviation is = 0.5 #Gaussian distribution as a generator function def generate_gaussian_distribution(): while True: yield random.gauss(mu=2,sigma= 0.5) #let the processing delay of the machine be a value function of the duration of the time spent by the machine in processing state #if the time spent in processing state is greater than 7, the processing delay has to take one value in index 0 of the return_vals #if the time spent in processing state is less than or equal to 7, the processing delay has to take the value in index 1 #This behaviour as a generator function def generate_process_delay(node,env): return_vals=[0.9,1.2] while True: if node.stats["total_time_spent_in_states"]["PROCESSING_STATE"]>7: yield return_vals[0] else: yield return_vals[1] # Initializing nodes SRC= Source(env, id="SRC", inter_arrival_time=generate_gaussian_distribution,blocking=False,out_edge_selection=0 ) MACHINE1 = Machine(env, id="MACHINE1",work_capacity=1,processing_delay=None,in_edge_selection="RANDOM",out_edge_selection="RANDOM") processing_delay_func=generate_process_delay(MACHINE1,env) MACHINE1.processing_delay = processing_delay_func SINK= Sink(env, id="SINK" ) # Initializing edges BUF1 = Buffer(env, id="BUF1", store_capacity=4, delay=0.5) BUF2 = Buffer(env, id="BUF2", store_capacity=4, delay=0.5) # Adding connections BUF1.connect(SRC,MACHINE1) BUF2.connect(MACHINE1,SINK) env.run(until=10) ``` -------------------------------- ### Connect chain with source and sink using connect_chain_with_source_sink Source: https://factorysimpy.github.io/FactorySimPy/constructs Creates a production line from source to sink with specified machines and buffers. Uses connect_chain_with_source_sink with parameters like inter_arrival_time, work_capacity, processing_delay, and store_capacity, then runs simulation for 20 time units. Resulting topology is src -> edges[0] -> nodes[1] -> edges[1] -> nodes[2] -> edges[2] -> sink. ```python import simpy from factorysimpy.nodes.machine import Machine from factorysimpy.edges.buffer import Buffer from factorysimpy.nodes.source import Source from factorysimpy.nodes.sink import Sink from factorysimpy.constructs.chain import connect_chain_with_source_sink env = simpy.Environment() # Define parameters for each component source_kwargs = {"inter_arrival_time": 1.0, "blocking": True} node_kwargs = {"work_capacity": 1, "processing_delay": 2.0, "in_edge_selection": "FIRST", "out_edge_selection": "FIRST"} edge_kwargs = {"store_capacity": 5, "delay": 0.5, "mode": "FIFO"} sink_kwargs = {} # Create a chain with 2 machines, 3 buffers, a source, and a sink nodes, edges, src, sink = connect_chain_with_source_sink( env, count=2, node_cls=Machine, edge_cls=Buffer, source_cls=Source, sink_cls=Sink, node_kwargs=node_kwargs, edge_kwargs=edge_kwargs, source_kwargs=source_kwargs, sink_kwargs=sink_kwargs ) machines, buffers = connect_nodes_with_buffers(machines, buffers, src, sink) # Now, nodes and edges are connected in order and connected: # src -> edges[0] -> nodes[1] -> edges[1] -> nodes[2] -> edges[2] -> sink env.run(until=20) ``` -------------------------------- ### Pass Python functions as delay parameters in FactorySimPy Source: https://factorysimpy.github.io/FactorySimPy/examples Use this example to pass Python functions as delay parameters in FactorySimPy. The source's inter_arrival_time is set to a Gaussian distribution function, and the machine's processing_delay is a function that returns different values based on the machine's processing state time. Note that the code references undefined functions (generate_gaussian_distribution, generate_process_delay) and variables (node, simpy) that are not defined in the snippet. ```python # System layout # SRC ──> BUF1 ──> MACHINE1 ──> BUF2 ──> SINK import random import factorysimpy from factorysimpy.nodes.machine import Machine from factorysimpy.edges.buffer import Buffer from factorysimpy.nodes.source import Source from factorysimpy.nodes.sink import Sink env = simpy.Environment() env = simpy.Environment() #let the inter arrival time of the source be a value sampled from a gaussian distribution with mean = 1, std deviation is = 0.25 #Gaussian distribution as a python function def generate_gaussian_distribution(): return random.gauss(mu=1,sigma= 0.25) #let the processing delay of the machine be a value function of the duration of the time spent by the machine in processing state #if the time spent in processing state is greater than 7, the processing delay has to take one value in index 0 of the return_vals #if the time spent in processing state is less than or equal to 7, the processing delay has to take the value in index 1 #This behaviour as a python function def generate_process_delay(): return_vals=[0.9,1.2] if node.stats["total_time_spent_in_states"]["PROCESSING_STATE"]>7: return return_vals[0] else: return return_vals[1] # Initializing nodes SRC= Source(env, id="SRC", inter_arrival_time=generate_gaussian_distribution,blocking=False,out_edge_selection=0 ) MACHINE1 = Machine(env, id="MACHINE1",work_capacity=1,processing_delay=generate_process_delay,in_edge_selection="RANDOM",out_edge_selection="RANDOM") SINK= Sink(env, id="SINK" ) # Initializing edges BUF1 = Buffer(env, id="BUF1", store_capacity=4, delay=0.5) BUF2 = Buffer(env, id="BUF2", store_capacity=4, delay=0.5) # Adding connections BUF1.connect(SRC,MACHINE1) BUF2.connect(MACHINE1,SINK) env.run(until=10) ``` -------------------------------- ### Custom edge selection policy as Python function for Machine and Source Source: https://factorysimpy.github.io/FactorySimPy/examples Use when edge selection policies must be modeled as Python functions. The machine's in_edge_selection and out_edge_selection are functions that return edge indices based on random distributions; the source's out_edge_selection is a function of simulation time. Requires importing random, factorysimpy, and simpy. The example builds a network with two sources, buffers, one machine, and three sinks, then runs the simulation for 10 time units. ```python # System layout # SRC1 ──> BUFFER1 ──┐ # │ # SRC2 ──> BUFFER2 ──┴─> MACHINE1 ──┬─> BUFFER3 ──> SINK1 # │ │ # └─> BUFFER5 ──> SINK3 └─> BUFFER4 ──> SINK2 # import random import factorysimpy from factorysimpy.nodes.machine import Machine from factorysimpy.edges.buffer import Buffer from factorysimpy.nodes.source import Source from factorysimpy.nodes.sink import Sink env = simpy.Environment() #let the in_edge_selection of the machine be a function that yields 1 or 0 based on the value sampled from uniform distribution [0,1] # This function will yield 1 if value 0.5, and 0 if it is otherwise. #in_edge_selection as a function for machine def machine_in_edge_selector(): if random.random()<0.5: return 1 else: return 0 #let the out_edge_selection of the machine be a function that yields the index of the edge to be selected # This function will yield the index of the edge to be selected based on the value sampled from a gaussian dostribution with mean=4 and sigma=1 # it will return 1 is the sampled value is >3, else it will return 0 #out_edge_selection as a function for machine def machine_out_edge_selector(): if random.gauss(mu=4,sigma= 1) >3: return 1 else: return 0 #let the out_edge_selection of the source 2 be a generator function that yields 1 or 0 based on the current time # This generator function will yield 1 if the current time is even, and 0 if it is odd. #out_edge_selection as a function for source def source_out_edge_selector(env): if env.now%2==0: return 1 else: return 0 # Initializing nodes SRC1= Source(env, id="SRC1", inter_arrival_time=0.7,blocking=False, out_edge_selection="FIRST_AVAILABLE" ) SRC2= Source(env, id="SRC2", inter_arrival_time=0.4,blocking=False, out_edge_selection=source_out_edge_selector(env) ) MACHINE1 = Machine(env, id="MACHINE1",work_capacity=4, processing_delay=1,in_edge_selection=machine_in_edge_selector,out_edge_selection=machine_out_edge_selector) SINK1= Sink(env, id="SINK1", in_edge_selection="RANDOM" ) SINK2= Sink(env, id="SINK2", in_edge_selection="RANDOM" ) SINK3= Sink(env, id="SINK3", in_edge_selection="FIRST_AVAILABLE" ) # Initializing edges # Initializing edges BUF1 = Buffer(env, id="BUF1", store_capacity=4, delay=0.5) BUF2 = Buffer(env, id="BUF2", store_capacity=4, delay=0.5) BUF3 = Buffer(env, id="BUF3", store_capacity=4, delay=0.5) BUF4 = Buffer(env, id="BUF4", store_capacity=4, delay=0.5) BUF5 = Buffer(env, id="BUF5", store_capacity=4, delay=0.5) # Adding connections BUF1.connect(SRC1,MACHINE1) BUF2.connect(SRC2,MACHINE1) BUF3.connect(MACHINE1,SINK1) BUF4.connect(MACHINE1,SINK2) BUF5.connect(SRC2,SINK3) env.run(until=10) ```