Coverage for moptipyapps/prodsched/rop_multisimulation.py: 92%
25 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-12 08:11 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-12 08:11 +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;
79servicelevel;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
87utilization.mean;0.8028541903189094;0.7763654043603625;0.9032477434521591;\
880.7930399866318019;0.7489356574262395;0.7991766715886103;0.856983874648282;\
890.7192467665817516;0.7636631798947845;0.9405380117151168;0.717662602426817;\
900.7288606270267851;0.8136069049000355;0.8757770434930767
91-------- Instance 1: 'mfc_10_13_10000_0xc8' -------
92stat;total;product_0;product_1;product_2;product_3;product_4;product_5;\
93product_6;product_7;product_8;product_9
94trp.min;5.948427591903055;7.773461678094918;8.104543866997119;\
959.933972266073852;9.004947959652782;8.776700665666795;9.975332333055121;\
965.948427591903055;20.799002041634594;17.964307940585968;24.272536333651715
97trp.mean;35.167924925950125;27.18841637847806;33.27855240987676;\
9829.982146375833715;30.449231453771148;29.084101384288005;32.62138736043257;\
9922.83061361662951;46.50691768018183;45.7665440237148;53.59331009237047
100trp.max;95.9013844625315;67.73174100731194;75.85471491774206;\
10173.69881984770018;68.71451528269608;71.21493108382583;76.23405217026357;\
10248.44126891105043;95.9013844625315;80.51310862833998;93.74247469991224
103trp.sd;15.01651152311082;12.1357409577245;11.927832420121684;\
10412.110870983620881;12.231352766383868;11.422631005468508;10.870562799044663;\
1056.991683919460075;12.90335326836488;10.608823203464715;13.923445407906742
106cwt.min;0.029403377815469867;0.33968352876763674;0.8012226423225002;\
1070.4169237064834306;0.04608099701363244;0.13958597264536365;\
1080.1427841231916318;0.031861988642049255;0.04509163852708298;\
1090.029403377815469867;0.30706729430312407
110cwt.mean;9.125995226441729;7.635949273012871;8.099259381058715;\
11110.53104684412949;12.0613536196739;6.755248335968917;3.3923317916747693;\
1125.694018876707761;9.678250496815913;9.407512664676307;1.8529460623847172
113cwt.max;47.02757613742506;26.69298476563017;23.81131382935382;\
11433.68826448411983;47.02757613742506;21.765393608298837;8.465947593324927;\
11527.96794209550535;41.19798755026659;26.935112545980246;4.7028845058594015
116cwt.sd;8.312790326182888;5.699569122267945;7.46568137298234;\
1177.984381269231696;12.256771187209509;5.163135442961999;2.273816079756312;\
1186.655405008762987;8.35629247653758;7.251352236700332;1.9462759372992589
119servicelevel;0.9067748363222317;0.8929577464788733;0.9696969696969697;\
1200.7905982905982906;0.8695652173913043;0.8978723404255319;0.9854651162790697;\
1210.9276410998552822;0.8256484149855908;0.9142053445850914;0.9944367176634215
122stocklevel.mean;26.506300325777048;2.3225382137372628;3.7298268255006812;\
1231.2114694030566133;2.055027916866671;2.1359308723688653;3.803260303815258;\
1241.7840029880750334;1.5544812126506562;2.4214269649529525;5.488335624753054
125fulfilled.rate;1;1;1;1;1;1;1;1;1;1;1
126utilization.mean;0.807148475748266;0.7868543497811389;0.9044317782418774;\
1270.8033818248605281;0.7596125889483434;0.8088468279639388;0.8356338884488432;\
1280.7140483213425692;0.7588804801210093;0.9422462544368143;0.7228749764278876;\
1290.7537235522221261;0.8221827015767551;0.880212640355627
131>>> y2 = space.create()
132>>> y2 = y2.from_stream(data)
133>>> for s in to_stream(y2):
134... if "time" not in s:
135... print(s)
136-------- Instance 0: 'mfc_10_13_10000_0x64' -------
137stat;total;product_0;product_1;product_2;product_3;product_4;product_5;\
138product_6;product_7;product_8;product_9
139trp.min;7.148698771011368;7.148698771011368;9.851247306791265;\
1408.427300405584901;7.732987823144867;9.070787436894534;11.245150186528008;\
1417.548472763230166;17.99718923960154;19.843363570212205;21.06416134257961
142trp.mean;32.97790594850951;24.596468674329277;30.563844531997784;\
14327.279429397719902;27.79703033632461;26.77907139640676;31.011169285683117;\
14422.68822054678187;43.68592626657671;44.53906054313191;50.332354253457126
145trp.max;81.85722054558573;61.64176267270341;81.27718406438362;\
14659.59867846381849;61.89396888322699;58.814665098144815;58.66937148871966;\
14746.20656698190578;81.15104324107142;78.27784582696768;81.85722054558573
148trp.sd;13.469211388152745;9.448650489856151;10.895076940486566;\
1499.109918454636354;9.52161563781995;9.01547173838026;9.813054414557046;\
1507.002160286247719;10.716869779123178;10.334832333293049;\
15111.999775884280249
152cwt.min;0.005395059989496076;0.9780139529375447;0.2348135728352645;\
1530.03942528753759689;0.20585198680419126;0.5507500551393605;\
1540.13329136607262626;0.2233135479809789;0.005395059989496076;\
1550.363337511282225;0.39745336452870106
156cwt.mean;6.3170778026045005;7.056731365091693;5.2182919382446675;\
1576.87124683902964;9.079584429859228;5.9399972995436725;3.4793130259088376;\
1585.078417615955683;6.087077618707137;6.0301712727273555;0.39745336452870106
159cwt.max;30.3947134928394;18.927977914853727;14.788743864707612;\
16026.82679173953329;30.3947134928394;20.036018396819145;10.330677260388256;\
16114.073472667324495;24.646629221033436;21.919009444512994;\
1620.39745336452870106
163cwt.sd;5.5974909506906085;4.221610650071981;4.562515459731836;\
1646.170158967232;8.323952010113258;4.890025309334268;2.5970717405650108;\
1653.9630879947212585;5.290686494450313;5.719967055634048;
166servicelevel;0.9444205701188941;0.9545454545454546;0.9840579710144928;\
1670.8876080691642652;0.9431137724550899;0.9317851959361393;\
1680.9789325842696629;0.9251412429378532;0.8884180790960452;0.9510086455331412;\
1690.9985994397759104
170stocklevel.mean;28.41820760852814;2.560290636738579;3.9957232241217637;\
1711.3649189126423142;2.3827363444008087;2.402699293752699;3.8512931890069;\
1721.7423245168807433;1.641365095584735;2.6211003662097;5.8557560291898945
173fulfilled.rate;1;1;1;1;1;1;1;1;1;1;1
174utilization.mean;0.8028541903189094;0.7763654043603625;0.9032477434521591;\
1750.7930399866318019;0.7489356574262395;0.7991766715886103;0.856983874648282;\
1760.7192467665817516;0.7636631798947845;0.9405380117151168;0.717662602426817
177-------- Instance 1: 'mfc_10_13_10000_0xc8' -------
178stat;total;product_0;product_1;product_2;product_3;product_4;product_5;\
179product_6;product_7;product_8;product_9
180trp.min;5.948427591903055;7.773461678094918;8.104543866997119;\
1819.933972266073852;9.004947959652782;8.776700665666795;9.975332333055121;\
1825.948427591903055;20.799002041634594;17.964307940585968;24.272536333651715
183trp.mean;35.167924925950125;27.18841637847806;33.27855240987676;\
18429.982146375833715;30.449231453771148;29.084101384288005;32.62138736043257;\
18522.83061361662951;46.50691768018183;45.7665440237148;53.59331009237047
186trp.max;95.9013844625315;67.73174100731194;75.85471491774206;\
18773.69881984770018;68.71451528269608;71.21493108382583;76.23405217026357;\
18848.44126891105043;95.9013844625315;80.51310862833998;93.74247469991224
189trp.sd;15.01651152311082;12.1357409577245;11.927832420121684;\
19012.110870983620881;12.231352766383868;11.422631005468508;10.870562799044663;\
1916.991683919460075;12.90335326836488;10.608823203464715;13.923445407906742
192cwt.min;0.029403377815469867;0.33968352876763674;0.8012226423225002;\
1930.4169237064834306;0.04608099701363244;0.13958597264536365;\
1940.1427841231916318;0.031861988642049255;0.04509163852708298;\
1950.029403377815469867;0.30706729430312407
196cwt.mean;9.125995226441729;7.635949273012871;8.099259381058715;\
19710.53104684412949;12.0613536196739;6.755248335968917;3.3923317916747693;\
1985.694018876707761;9.678250496815913;9.407512664676307;1.8529460623847172
199cwt.max;47.02757613742506;26.69298476563017;23.81131382935382;\
20033.68826448411983;47.02757613742506;21.765393608298837;8.465947593324927;\
20127.96794209550535;41.19798755026659;26.935112545980246;4.7028845058594015
202cwt.sd;8.312790326182888;5.699569122267945;7.46568137298234;\
2037.984381269231696;12.256771187209509;5.163135442961999;2.273816079756312;\
2046.655405008762987;8.35629247653758;7.251352236700332;1.9462759372992589
205servicelevel;0.9067748363222317;0.8929577464788733;0.9696969696969697;\
2060.7905982905982906;0.8695652173913043;0.8978723404255319;0.9854651162790697;\
2070.9276410998552822;0.8256484149855908;0.9142053445850914;0.9944367176634215
208stocklevel.mean;26.506300325777048;2.3225382137372628;3.7298268255006812;\
2091.2114694030566133;2.055027916866671;2.1359308723688653;3.803260303815258;\
2101.7840029880750334;1.5544812126506562;2.4214269649529525;5.488335624753054
211fulfilled.rate;1;1;1;1;1;1;1;1;1;1;1
212utilization.mean;0.807148475748266;0.7868543497811389;0.9044317782418774;\
2130.8033818248605281;0.7596125889483434;0.8088468279639388;0.8356338884488432;\
2140.7140483213425692;0.7588804801210093;0.9422462544368143;0.7228749764278876
217>>> x2 = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
218>>> ms.decode(x2, y)
219>>> for s in to_stream(y):
220... if "time" not in s:
221... print(s)
222-------- Instance 0: 'mfc_10_13_10000_0x64' -------
223stat;total;product_0;product_1;product_2;product_3;product_4;product_5;\
224product_6;product_7;product_8;product_9
225trp.min;6.6579246980854805;6.6579246980854805;10.040428073632938;\
2269.144356382177648;8.296261623940154;7.667382695110064;7.49579069264837;\
2278.581919683902015;19.249891132463745;18.452787187654394;18.901212658200166
228trp.mean;30.74716064960712;22.55644591592345;28.15643187379386;\
22925.157306197204942;25.891453823516155;24.656654627623602;28.280298002722372;\
23021.884096260231306;41.33149767348687;42.01272258331701;47.0432009577156
231trp.max;79.69814356608413;50.3897190429866;60.417297663587306;\
23258.155910569312255;57.205821481757084;52.45021315253325;59.77053868767143;\
23343.246354315288954;71.73764560662357;68.38738538621237;79.69814356608413
234trp.sd;12.157985067348928;7.639186573173071;8.568931718969022;\
2357.973929260222244;8.038036986999414;7.925969997080636;8.599986516235049;\
2366.097255369156319;9.856734625477339;8.9409753618694;10.274842345336927
237cwt.min;0.007410165035253158;0.010823749293649598;0.05938309523889984;\
2380.07244315036041371;0.007410165035253158;0.007457627479197981;\
2390.040943728912679944;0.03445897573783441;0.03898586586547026;\
2400.08116594846524094;0.14281174169173028
241cwt.mean;16.08134651193112;9.407819301031829;13.599570996899798;\
2429.281088119494319;11.11399938015249;10.30717585037071;13.666658677426005;\
2438.030271931727988;21.81659380310111;22.632166486797452;28.69724449522347
244cwt.max;68.13273609246335;34.22959482141596;54.775201309764725;\
24540.73069593375112;41.04427051696348;38.24440503984806;42.85895780219471;\
24631.703705121431085;53.001747956494;51.120920634961294;68.13273609246335
247cwt.sd;11.41034407109861;6.914971921203133;8.553611465539651;\
2486.705681452336642;7.5489609746268345;7.570333206165438;8.32656793004751;\
2496.081437849778869;10.3176054520999;9.98985948404976;12.586922189036457
250servicelevel;0.23005300100272166;0.3877840909090909;0.26811594202898553;\
2510.30979827089337175;0.312874251497006;0.3439767779390421;\
2520.22752808988764045;0.384180790960452;0.009887005649717515;\
2530.03170028818443804;0.03361344537815126
254stocklevel.mean;1.673940782484679;0.31292966720234844;0.20715377564649276;\
2550.13834460042719282;0.25115561718382967;0.2398635057643522;\
2560.19840432550798928;0.2850204974085108;0.0023773765165652936;\
2570.011388858983845954;0.027302557843551636
258fulfilled.rate;0.9988540323735855;0.9985795454545454;1;0.9985590778097982;\
2591;1;0.9971910112359551;1;0.9971751412429378;0.9985590778097982;\
2600.9985994397759104
261utilization.mean;0.794909162274783;0.7763654043603625;0.9081892364495642;\
2620.7918425686625462;0.7331739301471062;0.7835902639278088;0.8346169766930579;\
2630.7124249384600392;0.7575113250154277;0.9306191609379052;0.7105158404571978;\
2640.7189580123724747;0.8151628323728414;0.8608486197158479
265-------- Instance 1: 'mfc_10_13_10000_0xc8' -------
266stat;total;product_0;product_1;product_2;product_3;product_4;product_5;\
267product_6;product_7;product_8;product_9
268trp.min;6.553059261284034;6.553059261284034;10.108606281321954;\
2699.703090589753629;11.174354779162059;8.321303147977233;11.439845494670408;\
2708.009630409889724;15.112291339387411;21.10066493332215;26.25138351485475
271trp.mean;35.457717990887495;27.190617501492195;33.285557575397284;\
27229.938089184363303;30.57060178357617;29.855403667616407;33.96324823266337;\
27322.77623364751058;47.106553173547205;45.91880621944926;53.65085012387992
274trp.max;88.07784608736165;56.968128655076725;67.76184441039186;\
27558.983867721681236;56.352778532964294;60.30516528044609;62.48506657539656;\
27647.527002503284166;76.8993130774079;72.71943839738833;88.07784608736165
277trp.sd;13.47506267495003;9.02066756428428;9.843605381506345;\
2789.041655339468601;8.972226014586374;9.64262838980214;9.682655730390962;\
2796.905743095003228;10.732554367883997;9.649376408388306;11.415428192248845
280cwt.min;0.006287345835517044;0.12899921433927375;0.12664124934963183;\
2810.018981504710609443;0.012018201038699772;0.006287345835517044;\
2820.07326658304918965;0.03329370768551598;0.687625592607219;\
2830.16628305106132757;0.8814572391811453
284cwt.mean;19.616157243489514;12.54124700723885;17.17954158092728;\
28512.797030006049777;14.78523355299519;14.531965580117795;17.509595977311385;\
2868.869499446666719;27.071380519490486;26.35203858982817;34.65830156782526
287cwt.max;74.59018342258969;41.182989166839434;49.26013039123245;\
28842.677472406387096;43.76841772841544;45.64997544083144;50.08378847398126;\
28934.685042479895856;58.25570602393418;58.60214532455484;74.59018342258969
290cwt.sd;12.79311806936005;8.220650581141385;10.036535907608853;\
2918.032836405284439;8.961327098641396;9.01894965593242;9.987307711032216;\
2926.809774156819015;11.394609551985406;11.22216829037131;13.382242351946935
293servicelevel;0.15328778821520067;0.2563380281690141;0.15728715728715728;\
2940.1581196581196581;0.17251051893408134;0.2170212765957447;0.1555232558139535;\
2950.40086830680173663;0.004322766570605188;0.004219409282700422;\
2960.012517385257301807
297stocklevel.mean;1.0688209713197157;0.1893746360753341;0.13978209374798592;\
2980.07751886834182369;0.1308059798092467;0.13779442473717082;\
2990.11712916644109925;0.2719222690871477;0.00018993221962948934;\
3000.0012621122002660092;0.003041488660012029
301fulfilled.rate;0.9981497295758611;0.9985915492957746;0.9985569985569985;1;1;\
3021;0.998546511627907;1;0.9971181556195965;0.9929676511954993;0.9958275382475661
303utilization.mean;0.8082338028980605;0.7868543497811389;0.9051603252768642;\
3040.8134939422379659;0.7566700358581937;0.8167982234100564;0.8509976451640071;\
3050.7133318620183866;0.7462458169886501;0.9583484128790276;0.7312103174404826;\
3060.7339761871684062;0.8127215565516549;0.8812307628999528
307"""
308from typing import Final
310import numpy as np
311from moptipy.api.encoding import Encoding
312from pycommons.types import type_error
314from moptipyapps.prodsched.multistatistics import (
315 MultiStatistics,
316 MultiStatisticsSpace,
317)
318from moptipyapps.prodsched.rop_simulation import ROPSimulation
319from moptipyapps.prodsched.statistics_collector import StatisticsCollector
322class ROPMultiSimulation(Encoding):
323 """A multi-simulation that caches the results for reuse."""
325 def __init__(self, space: MultiStatisticsSpace) -> None:
326 """
327 Instantiate the multi-statistics decoding.
329 :param instances: the packing instance
330 """
331 if not isinstance(space, MultiStatisticsSpace):
332 raise type_error(space, "space", MultiStatisticsSpace)
333 #: the statistics collectors
334 col: Final[tuple[StatisticsCollector, ...]] = tuple(
335 StatisticsCollector(inst) for inst in space.instances)
336 #: the simulations and collectors
337 self.__simulations: Final[tuple[tuple[
338 ROPSimulation, StatisticsCollector], ...]] = tuple(
339 (ROPSimulation(inst, col[i]), col[i])
340 for i, inst in enumerate(space.instances))
341 #: the internal space
342 self.__space: Final[MultiStatisticsSpace] = space
344 def decode(self, x: np.ndarray, y: MultiStatistics) -> None:
345 """
346 Map a ROP setting to a multi-statistics.
348 This method uses an internal cache: The same re-order points will
349 yield the same statistics.
351 :param x: the array
352 :param y: the Gantt chart
353 """
354 # First we map the vector to a tuple of integers.
355 x_tuple: Final[tuple[int, ...]] = tuple(map(int, x))
357 # If we get here, the ROP is new.
358 # So we simulate it.
359 for i, (sim, col) in enumerate(self.__simulations):
360 col.set_dest(y.per_instance[i])
361 sim.ctrl_reset()
362 sim.set_rop(x_tuple)
363 sim.ctrl_run()
365 # The simulation is completed. We can now cache the result.
366 cached: Final[MultiStatistics] = self.__space.create()
367 self.__space.copy(cached, y)
369 def __str__(self) -> str:
370 """
371 Get the name of this decoding.
373 :return: `"rms"`
374 :rtype: str
375 """
376 return "rms"