Coverage for moptipyapps/prodsched/rop_multisimulation.py: 92%
25 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-05-28 09:42 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-05-28 09:42 +0000
1"""
2A simulator for multiple runs of the ROP scenario.
4Re-Order-Point (ROP) scenarios are such that for each product, a value `X` is
5provided. Once there are no more than `X` elements of that product in the
6warehouse, one new unit is ordered to be produced.
7Therefore, we have `n_products` such `X` values.
8A simulation in this scenario is implemented in
9:mod:`~moptipyapps.prodsched.rop_simulation` as class
10:class:`~moptipyapps.prodsched.rop_simulation.ROPSimulation`.
12This module here provides the functionality to simulate this ROP-approach
13over *multiple* instances (:class:`~moptipyapps.prodsched.instance.Instance`).
14It acts as an :class:`~moptipy.api.encoding.Encoding` that converts a re-order
15point into an instance of
16:class:`~moptipyapps.prodsched.multistatistics.MultiStatistics` which can then
17be used as basis to compute the values of (potentially multiple)
18objective functions, such as those given in package
19:mod:`~moptipyapps.prodsched.objectives`.
21Now, doing a multi-simulation is costly.
22It takes from half a second to several seconds.
23It is unlikely that we can do more than a million in any run of an
24optimization algorithm.
25Therefore, we use an internal caching mechanism to store all the input
26vectors and output statistics.
27This may consume quite some memory, but it might be faster.
29>>> from moptipyapps.prodsched.mfc_generator import sample_mfc_instance
30>>> from moptipyapps.prodsched.mfc_generator import Product
31>>> from moptipyapps.prodsched.mfc_generator import Station
32>>> from moptipyapps.utils.sampling import Gamma
33>>> from moptipyapps.prodsched.multistatistics import to_stream
35>>> inst1 = sample_mfc_instance(seed=100)
36>>> inst2 = sample_mfc_instance(seed=200)
38>>> instances = (inst1, inst2)
39>>> space = MultiStatisticsSpace(instances)
40>>> ms = ROPMultiSimulation(space)
42>>> x1 = np.array([4, 6, 3, 4, 4, 6, 3, 5, 6, 10])
43>>> y = space.create()
44>>> ms.decode(x1, y)
45>>> data = list(to_stream(y))
46>>> for s in data:
47... if "time" not in s:
48... print(s)
49-------- Instance 0: 'mfc_10_13_10000_0x64' -------
50stat;total;product_0;product_1;product_2;product_3;product_4;product_5;\
51product_6;product_7;product_8;product_9
52trp.min;7.148698771011368;7.148698771011368;9.851247306791265;\
538.427300405584901;7.732987823144867;9.070787436894534;11.245150186528008;\
547.548472763230166;17.99718923960154;19.843363570212205;21.06416134257961
55trp.mean;32.97790594850951;24.596468674329277;30.563844531997784;\
5627.279429397719902;27.79703033632461;26.77907139640676;31.011169285683117;\
5722.68822054678187;43.68592626657671;44.53906054313191;50.332354253457126
58trp.max;81.85722054558573;61.64176267270341;81.27718406438362;\
5959.59867846381849;61.89396888322699;58.814665098144815;58.66937148871966;\
6046.20656698190578;81.15104324107142;78.27784582696768;81.85722054558573
61trp.sd;13.469211388152745;9.448650489856151;10.895076940486566;\
629.109918454636354;9.52161563781995;9.01547173838026;9.813054414557046;\
637.002160286247719;10.716869779123178;10.334832333293049;\
6411.999775884280249
65cwt.min;0.005395059989496076;0.9780139529375447;0.2348135728352645;\
660.03942528753759689;0.20585198680419126;0.5507500551393605;\
670.13329136607262626;0.2233135479809789;0.005395059989496076;\
680.363337511282225;0.39745336452870106
69cwt.mean;6.3170778026045005;7.056731365091693;5.2182919382446675;\
706.87124683902964;9.079584429859228;5.9399972995436725;3.4793130259088376;\
715.078417615955683;6.087077618707137;6.0301712727273555;0.39745336452870106
72cwt.max;30.3947134928394;18.927977914853727;14.788743864707612;\
7326.82679173953329;30.3947134928394;20.036018396819145;10.330677260388256;\
7414.073472667324495;24.646629221033436;21.919009444512994;\
750.39745336452870106
76cwt.sd;5.5974909506906085;4.221610650071981;4.562515459731836;\
776.170158967232;8.323952010113258;4.890025309334268;2.5970717405650108;\
783.9630879947212585;5.290686494450313;5.719967055634048;
79fill.rate;0.9444205701188941;0.9545454545454546;0.9840579710144928;\
800.8876080691642652;0.9431137724550899;0.9317851959361393;\
810.9789325842696629;0.9251412429378532;0.8884180790960452;0.9510086455331412;\
820.9985994397759104
83stocklevel.mean;28.41820760852814;2.560290636738579;3.9957232241217637;\
841.3649189126423142;2.3827363444008087;2.402699293752699;3.8512931890069;\
851.7423245168807433;1.641365095584735;2.6211003662097;5.8557560291898945
86fulfilled.rate;1;1;1;1;1;1;1;1;1;1;1
87-------- Instance 1: 'mfc_10_13_10000_0xc8' -------
88stat;total;product_0;product_1;product_2;product_3;product_4;product_5;\
89product_6;product_7;product_8;product_9
90trp.min;5.948427591903055;7.773461678094918;8.104543866997119;\
919.933972266073852;9.004947959652782;8.776700665666795;9.975332333055121;\
925.948427591903055;20.799002041634594;17.964307940585968;24.272536333651715
93trp.mean;35.167924925950125;27.18841637847806;33.27855240987676;\
9429.982146375833715;30.449231453771148;29.084101384288005;32.62138736043257;\
9522.83061361662951;46.50691768018183;45.7665440237148;53.59331009237047
96trp.max;95.9013844625315;67.73174100731194;75.85471491774206;\
9773.69881984770018;68.71451528269608;71.21493108382583;76.23405217026357;\
9848.44126891105043;95.9013844625315;80.51310862833998;93.74247469991224
99trp.sd;15.01651152311082;12.1357409577245;11.927832420121684;\
10012.110870983620881;12.231352766383868;11.422631005468508;10.870562799044663;\
1016.991683919460075;12.90335326836488;10.608823203464715;13.923445407906742
102cwt.min;0.029403377815469867;0.33968352876763674;0.8012226423225002;\
1030.4169237064834306;0.04608099701363244;0.13958597264536365;\
1040.1427841231916318;0.031861988642049255;0.04509163852708298;\
1050.029403377815469867;0.30706729430312407
106cwt.mean;9.125995226441729;7.635949273012871;8.099259381058715;\
10710.53104684412949;12.0613536196739;6.755248335968917;3.3923317916747693;\
1085.694018876707761;9.678250496815913;9.407512664676307;1.8529460623847172
109cwt.max;47.02757613742506;26.69298476563017;23.81131382935382;\
11033.68826448411983;47.02757613742506;21.765393608298837;8.465947593324927;\
11127.96794209550535;41.19798755026659;26.935112545980246;4.7028845058594015
112cwt.sd;8.312790326182888;5.699569122267945;7.46568137298234;\
1137.984381269231696;12.256771187209509;5.163135442961999;2.273816079756312;\
1146.655405008762987;8.35629247653758;7.251352236700332;1.9462759372992589
115fill.rate;0.9067748363222317;0.8929577464788733;0.9696969696969697;\
1160.7905982905982906;0.8695652173913043;0.8978723404255319;0.9854651162790697;\
1170.9276410998552822;0.8256484149855908;0.9142053445850914;0.9944367176634215
118stocklevel.mean;26.506300325777048;2.3225382137372628;3.7298268255006812;\
1191.2114694030566133;2.055027916866671;2.1359308723688653;3.803260303815258;\
1201.7840029880750334;1.5544812126506562;2.4214269649529525;5.488335624753054
121fulfilled.rate;1;1;1;1;1;1;1;1;1;1;1
123>>> y2 = space.create()
124>>> y2 = y2.from_stream(data)
125>>> for s in to_stream(y2):
126... if "time" not in s:
127... print(s)
128-------- Instance 0: 'mfc_10_13_10000_0x64' -------
129stat;total;product_0;product_1;product_2;product_3;product_4;product_5;\
130product_6;product_7;product_8;product_9
131trp.min;7.148698771011368;7.148698771011368;9.851247306791265;\
1328.427300405584901;7.732987823144867;9.070787436894534;11.245150186528008;\
1337.548472763230166;17.99718923960154;19.843363570212205;21.06416134257961
134trp.mean;32.97790594850951;24.596468674329277;30.563844531997784;\
13527.279429397719902;27.79703033632461;26.77907139640676;31.011169285683117;\
13622.68822054678187;43.68592626657671;44.53906054313191;50.332354253457126
137trp.max;81.85722054558573;61.64176267270341;81.27718406438362;\
13859.59867846381849;61.89396888322699;58.814665098144815;58.66937148871966;\
13946.20656698190578;81.15104324107142;78.27784582696768;81.85722054558573
140trp.sd;13.469211388152745;9.448650489856151;10.895076940486566;\
1419.109918454636354;9.52161563781995;9.01547173838026;9.813054414557046;\
1427.002160286247719;10.716869779123178;10.334832333293049;\
14311.999775884280249
144cwt.min;0.005395059989496076;0.9780139529375447;0.2348135728352645;\
1450.03942528753759689;0.20585198680419126;0.5507500551393605;\
1460.13329136607262626;0.2233135479809789;0.005395059989496076;\
1470.363337511282225;0.39745336452870106
148cwt.mean;6.3170778026045005;7.056731365091693;5.2182919382446675;\
1496.87124683902964;9.079584429859228;5.9399972995436725;3.4793130259088376;\
1505.078417615955683;6.087077618707137;6.0301712727273555;0.39745336452870106
151cwt.max;30.3947134928394;18.927977914853727;14.788743864707612;\
15226.82679173953329;30.3947134928394;20.036018396819145;10.330677260388256;\
15314.073472667324495;24.646629221033436;21.919009444512994;\
1540.39745336452870106
155cwt.sd;5.5974909506906085;4.221610650071981;4.562515459731836;\
1566.170158967232;8.323952010113258;4.890025309334268;2.5970717405650108;\
1573.9630879947212585;5.290686494450313;5.719967055634048;
158fill.rate;0.9444205701188941;0.9545454545454546;0.9840579710144928;\
1590.8876080691642652;0.9431137724550899;0.9317851959361393;\
1600.9789325842696629;0.9251412429378532;0.8884180790960452;0.9510086455331412;\
1610.9985994397759104
162stocklevel.mean;28.41820760852814;2.560290636738579;3.9957232241217637;\
1631.3649189126423142;2.3827363444008087;2.402699293752699;3.8512931890069;\
1641.7423245168807433;1.641365095584735;2.6211003662097;5.8557560291898945
165fulfilled.rate;1;1;1;1;1;1;1;1;1;1;1
166-------- Instance 1: 'mfc_10_13_10000_0xc8' -------
167stat;total;product_0;product_1;product_2;product_3;product_4;product_5;\
168product_6;product_7;product_8;product_9
169trp.min;5.948427591903055;7.773461678094918;8.104543866997119;\
1709.933972266073852;9.004947959652782;8.776700665666795;9.975332333055121;\
1715.948427591903055;20.799002041634594;17.964307940585968;24.272536333651715
172trp.mean;35.167924925950125;27.18841637847806;33.27855240987676;\
17329.982146375833715;30.449231453771148;29.084101384288005;32.62138736043257;\
17422.83061361662951;46.50691768018183;45.7665440237148;53.59331009237047
175trp.max;95.9013844625315;67.73174100731194;75.85471491774206;\
17673.69881984770018;68.71451528269608;71.21493108382583;76.23405217026357;\
17748.44126891105043;95.9013844625315;80.51310862833998;93.74247469991224
178trp.sd;15.01651152311082;12.1357409577245;11.927832420121684;\
17912.110870983620881;12.231352766383868;11.422631005468508;10.870562799044663;\
1806.991683919460075;12.90335326836488;10.608823203464715;13.923445407906742
181cwt.min;0.029403377815469867;0.33968352876763674;0.8012226423225002;\
1820.4169237064834306;0.04608099701363244;0.13958597264536365;\
1830.1427841231916318;0.031861988642049255;0.04509163852708298;\
1840.029403377815469867;0.30706729430312407
185cwt.mean;9.125995226441729;7.635949273012871;8.099259381058715;\
18610.53104684412949;12.0613536196739;6.755248335968917;3.3923317916747693;\
1875.694018876707761;9.678250496815913;9.407512664676307;1.8529460623847172
188cwt.max;47.02757613742506;26.69298476563017;23.81131382935382;\
18933.68826448411983;47.02757613742506;21.765393608298837;8.465947593324927;\
19027.96794209550535;41.19798755026659;26.935112545980246;4.7028845058594015
191cwt.sd;8.312790326182888;5.699569122267945;7.46568137298234;\
1927.984381269231696;12.256771187209509;5.163135442961999;2.273816079756312;\
1936.655405008762987;8.35629247653758;7.251352236700332;1.9462759372992589
194fill.rate;0.9067748363222317;0.8929577464788733;0.9696969696969697;\
1950.7905982905982906;0.8695652173913043;0.8978723404255319;0.9854651162790697;\
1960.9276410998552822;0.8256484149855908;0.9142053445850914;0.9944367176634215
197stocklevel.mean;26.506300325777048;2.3225382137372628;3.7298268255006812;\
1981.2114694030566133;2.055027916866671;2.1359308723688653;3.803260303815258;\
1991.7840029880750334;1.5544812126506562;2.4214269649529525;5.488335624753054
200fulfilled.rate;1;1;1;1;1;1;1;1;1;1;1
203>>> x2 = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
204>>> ms.decode(x2, y)
205>>> for s in to_stream(y):
206... if "time" not in s:
207... print(s)
208-------- Instance 0: 'mfc_10_13_10000_0x64' -------
209stat;total;product_0;product_1;product_2;product_3;product_4;product_5;\
210product_6;product_7;product_8;product_9
211trp.min;6.6579246980854805;6.6579246980854805;10.040428073632938;\
2129.144356382177648;8.296261623940154;7.667382695110064;7.49579069264837;\
2138.581919683902015;19.249891132463745;18.452787187654394;18.901212658200166
214trp.mean;30.74716064960712;22.55644591592345;28.15643187379386;\
21525.157306197204942;25.891453823516155;24.656654627623602;28.280298002722372;\
21621.884096260231306;41.33149767348687;42.01272258331701;47.0432009577156
217trp.max;79.69814356608413;50.3897190429866;60.417297663587306;\
21858.155910569312255;57.205821481757084;52.45021315253325;59.77053868767143;\
21943.246354315288954;71.73764560662357;68.38738538621237;79.69814356608413
220trp.sd;12.157985067348928;7.639186573173071;8.568931718969022;\
2217.973929260222244;8.038036986999414;7.925969997080636;8.599986516235049;\
2226.097255369156319;9.856734625477339;8.9409753618694;10.274842345336927
223cwt.min;0.007410165035253158;0.010823749293649598;0.05938309523889984;\
2240.07244315036041371;0.007410165035253158;0.007457627479197981;\
2250.040943728912679944;0.03445897573783441;0.03898586586547026;\
2260.08116594846524094;0.14281174169173028
227cwt.mean;16.08134651193112;9.407819301031829;13.599570996899798;\
2289.281088119494319;11.11399938015249;10.30717585037071;13.666658677426005;\
2298.030271931727988;21.81659380310111;22.632166486797452;28.69724449522347
230cwt.max;68.13273609246335;34.22959482141596;54.775201309764725;\
23140.73069593375112;41.04427051696348;38.24440503984806;42.85895780219471;\
23231.703705121431085;53.001747956494;51.120920634961294;68.13273609246335
233cwt.sd;11.41034407109861;6.914971921203133;8.553611465539651;\
2346.705681452336642;7.5489609746268345;7.570333206165438;8.32656793004751;\
2356.081437849778869;10.3176054520999;9.98985948404976;12.586922189036457
236fill.rate;0.23005300100272166;0.3877840909090909;0.26811594202898553;\
2370.30979827089337175;0.312874251497006;0.3439767779390421;\
2380.22752808988764045;0.384180790960452;0.009887005649717515;\
2390.03170028818443804;0.03361344537815126
240stocklevel.mean;1.673940782484679;0.31292966720234844;0.20715377564649276;\
2410.13834460042719282;0.25115561718382967;0.2398635057643522;\
2420.19840432550798928;0.2850204974085108;0.0023773765165652936;\
2430.011388858983845954;0.027302557843551636
244fulfilled.rate;0.9988540323735855;0.9985795454545454;1;0.9985590778097982;\
2451;1;0.9971910112359551;1;0.9971751412429378;0.9985590778097982;\
2460.9985994397759104
247-------- Instance 1: 'mfc_10_13_10000_0xc8' -------
248stat;total;product_0;product_1;product_2;product_3;product_4;product_5;\
249product_6;product_7;product_8;product_9
250trp.min;6.553059261284034;6.553059261284034;10.108606281321954;\
2519.703090589753629;11.174354779162059;8.321303147977233;11.439845494670408;\
2528.009630409889724;15.112291339387411;21.10066493332215;26.25138351485475
253trp.mean;35.457717990887495;27.190617501492195;33.285557575397284;\
25429.938089184363303;30.57060178357617;29.855403667616407;33.96324823266337;\
25522.77623364751058;47.106553173547205;45.91880621944926;53.65085012387992
256trp.max;88.07784608736165;56.968128655076725;67.76184441039186;\
25758.983867721681236;56.352778532964294;60.30516528044609;62.48506657539656;\
25847.527002503284166;76.8993130774079;72.71943839738833;88.07784608736165
259trp.sd;13.47506267495003;9.02066756428428;9.843605381506345;\
2609.041655339468601;8.972226014586374;9.64262838980214;9.682655730390962;\
2616.905743095003228;10.732554367883997;9.649376408388306;11.415428192248845
262cwt.min;0.006287345835517044;0.12899921433927375;0.12664124934963183;\
2630.018981504710609443;0.012018201038699772;0.006287345835517044;\
2640.07326658304918965;0.03329370768551598;0.687625592607219;\
2650.16628305106132757;0.8814572391811453
266cwt.mean;19.616157243489514;12.54124700723885;17.17954158092728;\
26712.797030006049777;14.78523355299519;14.531965580117795;17.509595977311385;\
2688.869499446666719;27.071380519490486;26.35203858982817;34.65830156782526
269cwt.max;74.59018342258969;41.182989166839434;49.26013039123245;\
27042.677472406387096;43.76841772841544;45.64997544083144;50.08378847398126;\
27134.685042479895856;58.25570602393418;58.60214532455484;74.59018342258969
272cwt.sd;12.79311806936005;8.220650581141385;10.036535907608853;\
2738.032836405284439;8.961327098641396;9.01894965593242;9.987307711032216;\
2746.809774156819015;11.394609551985406;11.22216829037131;13.382242351946935
275fill.rate;0.15328778821520067;0.2563380281690141;0.15728715728715728;\
2760.1581196581196581;0.17251051893408134;0.2170212765957447;0.1555232558139535;\
2770.40086830680173663;0.004322766570605188;0.004219409282700422;\
2780.012517385257301807
279stocklevel.mean;1.0688209713197157;0.1893746360753341;0.13978209374798592;\
2800.07751886834182369;0.1308059798092467;0.13779442473717082;\
2810.11712916644109925;0.2719222690871477;0.00018993221962948934;\
2820.0012621122002660092;0.003041488660012029
283fulfilled.rate;0.9981497295758611;0.9985915492957746;0.9985569985569985;1;1;\
2841;0.998546511627907;1;0.9971181556195965;0.9929676511954993;0.9958275382475661
285"""
286from typing import Final
288import numpy as np
289from moptipy.api.encoding import Encoding
290from pycommons.types import type_error
292from moptipyapps.prodsched.multistatistics import (
293 MultiStatistics,
294 MultiStatisticsSpace,
295)
296from moptipyapps.prodsched.rop_simulation import ROPSimulation
297from moptipyapps.prodsched.statistics_collector import StatisticsCollector
300class ROPMultiSimulation(Encoding):
301 """A multi-simulation that caches the results for reuse."""
303 def __init__(self, space: MultiStatisticsSpace) -> None:
304 """
305 Instantiate the multi-statistics decoding.
307 :param instances: the packing instance
308 """
309 if not isinstance(space, MultiStatisticsSpace):
310 raise type_error(space, "space", MultiStatisticsSpace)
311 #: the statistics collectors
312 col: Final[tuple[StatisticsCollector, ...]] = tuple(
313 StatisticsCollector(inst) for inst in space.instances)
314 #: the simulations and collectors
315 self.__simulations: Final[tuple[tuple[
316 ROPSimulation, StatisticsCollector], ...]] = tuple(
317 (ROPSimulation(inst, col[i]), col[i])
318 for i, inst in enumerate(space.instances))
319 #: the internal space
320 self.__space: Final[MultiStatisticsSpace] = space
322 def decode(self, x: np.ndarray, y: MultiStatistics) -> None:
323 """
324 Map a ROP setting to a multi-statistics.
326 This method uses an internal cache: The same re-order points will
327 yield the same statistics.
329 :param x: the array
330 :param y: the Gantt chart
331 """
332 # First we map the vector to a tuple of integers.
333 x_tuple: Final[tuple[int, ...]] = tuple(map(int, x))
335 # If we get here, the ROP is new.
336 # So we simulate it.
337 for i, (sim, col) in enumerate(self.__simulations):
338 col.set_dest(y.per_instance[i])
339 sim.ctrl_reset()
340 sim.set_rop(x_tuple)
341 sim.ctrl_run()
343 # The simulation is completed. We can now cache the result.
344 cached: Final[MultiStatistics] = self.__space.create()
345 self.__space.copy(cached, y)
347 def __str__(self) -> str:
348 """
349 Get the name of this decoding.
351 :return: `"rms"`
352 :rtype: str
353 """
354 return "rms"