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

1""" 

2A simulator for multiple runs of the ROP scenario. 

3 

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`. 

11 

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`. 

20 

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. 

28 

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 

34 

35>>> inst1 = sample_mfc_instance(seed=100) 

36>>> inst2 = sample_mfc_instance(seed=200) 

37 

38>>> instances = (inst1, inst2) 

39>>> space = MultiStatisticsSpace(instances) 

40>>> ms = ROPMultiSimulation(space) 

41 

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 

122 

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 

201 

202 

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 

287 

288import numpy as np 

289from moptipy.api.encoding import Encoding 

290from pycommons.types import type_error 

291 

292from moptipyapps.prodsched.multistatistics import ( 

293 MultiStatistics, 

294 MultiStatisticsSpace, 

295) 

296from moptipyapps.prodsched.rop_simulation import ROPSimulation 

297from moptipyapps.prodsched.statistics_collector import StatisticsCollector 

298 

299 

300class ROPMultiSimulation(Encoding): 

301 """A multi-simulation that caches the results for reuse.""" 

302 

303 def __init__(self, space: MultiStatisticsSpace) -> None: 

304 """ 

305 Instantiate the multi-statistics decoding. 

306 

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 

321 

322 def decode(self, x: np.ndarray, y: MultiStatistics) -> None: 

323 """ 

324 Map a ROP setting to a multi-statistics. 

325 

326 This method uses an internal cache: The same re-order points will 

327 yield the same statistics. 

328 

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)) 

334 

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() 

342 

343 # The simulation is completed. We can now cache the result. 

344 cached: Final[MultiStatistics] = self.__space.create() 

345 self.__space.copy(cached, y) 

346 

347 def __str__(self) -> str: 

348 """ 

349 Get the name of this decoding. 

350 

351 :return: `"rms"` 

352 :rtype: str 

353 """ 

354 return "rms"