mdl convert

This commit is contained in:
Shrek Requiem 2025-02-16 13:44:09 -05:00
parent 9d7064f762
commit 6775dfcb27
3 changed files with 695 additions and 0 deletions

View File

@ -0,0 +1,3 @@
import pysd
model = pysd.read_vensim('./vensim/bes.mdl')

Binary file not shown.

692
vensim/bes.py Normal file
View File

@ -0,0 +1,692 @@
"""
Python model 'bes.py'
Translated using PySD
"""
from pathlib import Path
import numpy as np
from pysd.py_backend.statefuls import Integ
from pysd import Component
__pysd_version__ = "3.14.2"
__data = {"scope": None, "time": lambda: 0}
_root = Path(__file__).parent
component = Component()
#######################################################################
# CONTROL VARIABLES #
#######################################################################
_control_vars = {
"initial_time": lambda: 0,
"final_time": lambda: 120,
"time_step": lambda: 1,
"saveper": lambda: time_step(),
}
def _init_outer_references(data):
for key in data:
__data[key] = data[key]
@component.add(name="Time")
def time():
"""
Current time of the model.
"""
return __data["time"]()
@component.add(
name="FINAL TIME", units="Month", comp_type="Constant", comp_subtype="Normal"
)
def final_time():
"""
The final time for the simulation.
"""
return __data["time"].final_time()
@component.add(
name="INITIAL TIME", units="Month", comp_type="Constant", comp_subtype="Normal"
)
def initial_time():
"""
The initial time for the simulation.
"""
return __data["time"].initial_time()
@component.add(
name="SAVEPER",
units="Month",
limits=(0.0, np.nan),
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={"time_step": 1},
)
def saveper():
"""
The frequency with which output is stored.
"""
return __data["time"].saveper()
@component.add(
name="TIME STEP",
units="Month",
limits=(0.0, np.nan),
comp_type="Constant",
comp_subtype="Normal",
)
def time_step():
"""
The time step for the simulation.
"""
return __data["time"].time_step()
#######################################################################
# MODEL VARIABLES #
#######################################################################
@component.add(
name="Noise", comp_type="Auxiliary", comp_subtype="Normal", depends_on={"time": 1}
)
def noise():
return float(np.random.uniform(0, 5, size=()))
@component.add(
name="Demand",
units="loaves/Day",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={"base_demand": 1, "noise": 1},
)
def demand():
return base_demand() + noise()
@component.add(
name="Amplitude of Seasonal Variations",
units="loaves",
comp_type="Constant",
comp_subtype="Normal",
)
def amplitude_of_seasonal_variations():
return 30
@component.add(name="phi", units="radians", comp_type="Constant", comp_subtype="Normal")
def phi():
return 0
@component.add(
name="Base Demand", units="loaves/Day", comp_type="Constant", comp_subtype="Normal"
)
def base_demand():
return 200
@component.add(
name="Sigma", units="loaves/Day", comp_type="Constant", comp_subtype="Normal"
)
def sigma():
return 5
@component.add(name="Period", units="days", comp_type="Constant", comp_subtype="Normal")
def period():
return 7
@component.add(
name="Available Workers",
units="workers",
comp_type="Constant",
comp_subtype="Normal",
)
def available_workers():
return 2
@component.add(
name="Base Rate", units="loaves/Day", comp_type="Constant", comp_subtype="Normal"
)
def base_rate():
return 200
@component.add(
name="Lead Time Sugar", units="days", comp_type="Constant", comp_subtype="Normal"
)
def lead_time_sugar():
return 1
@component.add(
name="Bread Production",
units="loaves/Day",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={"base_rate": 1, "minresource": 1, "labour_efficiency": 1},
)
def bread_production():
return float(np.minimum(base_rate(), minresource())) * labour_efficiency()
@component.add(
name="Water Safety", units="litres", comp_type="Constant", comp_subtype="Normal"
)
def water_safety():
return 300
@component.add(
name="Sugar Purchase",
units="kg",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={
"bread_production": 1,
"suger_per_loaf": 1,
"sugar_safety": 1,
"sugar": 1,
"lead_time_sugar": 1,
},
)
def sugar_purchase():
return float(
np.maximum(
0,
(bread_production() * suger_per_loaf() + sugar_safety() - sugar())
/ lead_time_sugar(),
)
)
@component.add(
name="Flour per Loaf", units="kg/loaf", comp_type="Constant", comp_subtype="Normal"
)
def flour_per_loaf():
return 0.3
@component.add(
name="Suger per Loaf", units="kg/loaf", comp_type="Constant", comp_subtype="Normal"
)
def suger_per_loaf():
return 0.02
@component.add(
name="MinSugarWater",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={"sugar": 1, "suger_per_loaf": 1, "water_per_loaf": 1, "water": 1},
)
def minsugarwater():
return float(np.minimum(sugar() / suger_per_loaf(), water() / water_per_loaf()))
@component.add(
name="Yeast Purchase",
units="kg",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={
"bread_production": 1,
"yeast_per_loaf": 1,
"yeast_safety": 1,
"yeast": 1,
"lead_time_yeast": 1,
},
)
def yeast_purchase():
return float(
np.maximum(
0,
(bread_production() * yeast_per_loaf() + yeast_safety() - yeast())
/ lead_time_yeast(),
)
)
@component.add(
name="Labour Efficiency",
units="Dmnl",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={"available_workers": 1, "workers_required": 1},
)
def labour_efficiency():
return float(np.minimum(1, available_workers() / workers_required()))
@component.add(
name="Water",
units="litres",
comp_type="Stateful",
comp_subtype="Integ",
depends_on={"_integ_water": 1},
other_deps={
"_integ_water": {
"initial": {},
"step": {"water_purchase": 1, "water_per_loaf": 1, "bread_production": 1},
}
},
)
def water():
return _integ_water()
_integ_water = Integ(
lambda: water_purchase() - bread_production() * water_per_loaf(),
lambda: 2000,
"_integ_water",
)
@component.add(
name="Water Cost", units="$/litre", comp_type="Constant", comp_subtype="Normal"
)
def water_cost():
return 0.001
@component.add(
name="Lead Time Water", units="days", comp_type="Constant", comp_subtype="Normal"
)
def lead_time_water():
return 1
@component.add(
name="Lead Time Yeast", units="days", comp_type="Constant", comp_subtype="Normal"
)
def lead_time_yeast():
return 1
@component.add(
name="Water Purchase",
units="litres",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={
"bread_production": 1,
"water_per_loaf": 1,
"water_safety": 1,
"water": 1,
"lead_time_water": 1,
},
)
def water_purchase():
return float(
np.maximum(
0,
(bread_production() * water_per_loaf() + water_safety() - water())
/ lead_time_water(),
)
)
@component.add(
name="Workers Required",
units="workers",
comp_type="Constant",
comp_subtype="Normal",
)
def workers_required():
return 2
@component.add(
name="MinFlourYeast",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={"flour": 1, "flour_per_loaf": 1, "yeast_per_loaf": 1, "yeast": 1},
)
def minflouryeast():
return float(np.minimum(flour() / flour_per_loaf(), yeast() / yeast_per_loaf()))
@component.add(
name="MinResource",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={"minflouryeast": 1, "minsugarwater": 1},
)
def minresource():
return float(np.minimum(minflouryeast(), minsugarwater()))
@component.add(
name="Water per Loaf",
units="litres/loaf",
comp_type="Constant",
comp_subtype="Normal",
)
def water_per_loaf():
return 0.2
@component.add(
name="Waste Bread", units="loaves/Day", comp_type="Constant", comp_subtype="Normal"
)
def waste_bread():
return 2
@component.add(
name="Raw Material Cost",
units="$",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={
"flour_cost": 1,
"flour_purchase": 1,
"sugar_purchase": 1,
"sugar_cost": 1,
"yeast_purchase": 1,
"yeast_cost": 1,
"water_purchase": 1,
"water_cost": 1,
},
)
def raw_material_cost():
return (
flour_cost() * flour_purchase()
+ sugar_cost() * sugar_purchase()
+ yeast_cost() * yeast_purchase()
+ water_cost() * water_purchase()
)
@component.add(
name="Yeast Safety", units="kg", comp_type="Constant", comp_subtype="Normal"
)
def yeast_safety():
return 10
@component.add(
name="Sugar Safety", units="kg", comp_type="Constant", comp_subtype="Normal"
)
def sugar_safety():
return 20
@component.add(
name="Bread",
units="loaves",
comp_type="Stateful",
comp_subtype="Integ",
depends_on={"_integ_bread": 1},
other_deps={
"_integ_bread": {
"initial": {},
"step": {"bread_production": 1, "waste_bread": 1, "sales": 1},
}
},
)
def bread():
return _integ_bread()
_integ_bread = Integ(
lambda: bread_production() - waste_bread() - sales(), lambda: 0, "_integ_bread"
)
@component.add(
name="Flour",
units="kg",
comp_type="Stateful",
comp_subtype="Integ",
depends_on={"_integ_flour": 1},
other_deps={
"_integ_flour": {
"initial": {},
"step": {"flour_purchase": 1, "flour_per_loaf": 1, "bread_production": 1},
}
},
)
def flour():
return _integ_flour()
_integ_flour = Integ(
lambda: flour_purchase() - flour_per_loaf() * bread_production(),
lambda: 1000,
"_integ_flour",
)
@component.add(
name="Flour Cost", units="$/kg", comp_type="Constant", comp_subtype="Normal"
)
def flour_cost():
return 0.5
@component.add(
name="Flour Purchase",
units="kg",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={
"bread_production": 1,
"flour_per_loaf": 1,
"flour_safety": 1,
"flour": 1,
"lead_time_flour": 1,
},
)
def flour_purchase():
return float(
np.maximum(
0,
(bread_production() * flour_per_loaf() + flour_safety() - flour())
/ lead_time_flour(),
)
)
@component.add(
name="Flour Safety", units="kg", comp_type="Constant", comp_subtype="Normal"
)
def flour_safety():
return 200
@component.add(
name="Labour Cost",
units="$",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={"wage_rate": 1, "total_labour_hours": 1},
)
def labour_cost():
return wage_rate() * total_labour_hours()
@component.add(
name="Lead Time Flour", units="days", comp_type="Constant", comp_subtype="Normal"
)
def lead_time_flour():
return 1
@component.add(
name="Maintainance Cost",
units="$",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={"maintainance_rate": 1, "money": 1},
)
def maintainance_cost():
return maintainance_rate() * money()
@component.add(
name="Maintainance Rate",
units="fraction/Day",
comp_type="Constant",
comp_subtype="Normal",
)
def maintainance_rate():
return 0.002
@component.add(
name="Money",
units="$",
comp_type="Stateful",
comp_subtype="Integ",
depends_on={"_integ_money": 1},
other_deps={
"_integ_money": {
"initial": {},
"step": {
"revenue": 1,
"labour_cost": 1,
"maintainance_cost": 1,
"raw_material_cost": 1,
},
}
},
)
def money():
return _integ_money()
_integ_money = Integ(
lambda: revenue() - labour_cost() - maintainance_cost() - raw_material_cost(),
lambda: 100000,
"_integ_money",
)
@component.add(
name="Revenue",
units="$",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={"sales_price": 1, "sales": 1},
)
def revenue():
return sales_price() * sales()
@component.add(
name="Sales",
units="loaves/Day",
comp_type="Auxiliary",
comp_subtype="Normal",
depends_on={"bread": 1, "demand": 1},
)
def sales():
return float(np.minimum(bread(), demand()))
@component.add(
name="Sales Price", units="$/loaf", comp_type="Constant", comp_subtype="Normal"
)
def sales_price():
return 4
@component.add(
name="Sugar",
units="kg",
comp_type="Stateful",
comp_subtype="Integ",
depends_on={"_integ_sugar": 1},
other_deps={
"_integ_sugar": {
"initial": {},
"step": {"sugar_purchase": 1, "suger_per_loaf": 1, "bread_production": 1},
}
},
)
def sugar():
return _integ_sugar()
_integ_sugar = Integ(
lambda: sugar_purchase() - bread_production() * suger_per_loaf(),
lambda: 100,
"_integ_sugar",
)
@component.add(
name="Sugar Cost", units="$/kg", comp_type="Constant", comp_subtype="Normal"
)
def sugar_cost():
return 0.8
@component.add(
name="Total Labour Hours",
units="hours/Day",
comp_type="Constant",
comp_subtype="Normal",
)
def total_labour_hours():
return 16
@component.add(
name="Wage Rate", units="$/Hour", comp_type="Constant", comp_subtype="Normal"
)
def wage_rate():
return 12
@component.add(
name="Yeast",
units="kg",
comp_type="Stateful",
comp_subtype="Integ",
depends_on={"_integ_yeast": 1},
other_deps={
"_integ_yeast": {
"initial": {},
"step": {"yeast_purchase": 1, "yeast_per_loaf": 1, "bread_production": 1},
}
},
)
def yeast():
return _integ_yeast()
_integ_yeast = Integ(
lambda: yeast_purchase() - bread_production() * yeast_per_loaf(),
lambda: 50,
"_integ_yeast",
)
@component.add(
name="Yeast Cost", units="$/kg", comp_type="Constant", comp_subtype="Normal"
)
def yeast_cost():
return 10
@component.add(
name="Yeast per Loaf", units="kg/loaf", comp_type="Constant", comp_subtype="Normal"
)
def yeast_per_loaf():
return 0.01