Tiwtorial VI: Rhwydweithiau Cyfyngedig

Dychmygwch ffatri gweithgynhyrchu sy'n cynhyrchu stolion:

  • Pob 4 eiliad mae sedd yn cyrraedd ar gludfelt.

  • Mae'r cludfelt yn cynnwys tair gweithfan.

  • Wrth bob gweithfan mae coes yn cael ei chysylltu.

  • Mae cysylltu coes yn cymryd cyfnod o amser ar hap rhwng 3 eiliad a 5 eiliad.

  • Rhwng gweithfannau (a cyn y weithfan gyntaf) mae'r cludfan ond digon hir i dal 3 stôl.

  • Os yw'r cludfelt cyn y weithfan gyntaf yn llawn, mae stolion newydd yn cwympo i'r llawr ac yn torri.

  • Os yw'r stôl yn gorffen 'gwasanaeth' ar weithfan, ond nid oes lle ar y cludfelt, mae angen i'r stôl yna aros wrth y weithfan nes daeth lle ar y cludfan. Tra bod y blocio yma yn digwydd, ni all y weithfan yna cydosod unrhyw mwy o stolion. (Mae manylion llawn ar flocio ar gael fan hyn.)

Mae pob stôl sy'n torri yn costio'r ffatri 10c mewn pren gwastraff. Rydyn ni angen gwybod faint o stolion sy'n cwympo i'r llawr a thorri pob awr mae'r ffatri'n weithredol, ac felly'r gost gymedrig pob awr. Yn gyntaf, diffiniwn ni'r Network. Mae rhwydwaith cyfyngedig fel hwn wedi'i chynrychioli gan bron yr un gwrthrych Network a rhwydwaith anghyfyngedig, ond nawr ychwanegwn ni'r allweddair queue_capacities:

>>> import ciw
>>> N = ciw.create_network(
...     1rrival_distributions=[ciw.dists.Deterministic(4.0),
...                            ciw.dists.NoArrivals(),
...                            ciw.dists.NoArrivals()],
...     service_distributions=[ciw.dists.Uniform(3, 5),
...                            ciw.dists.Uniform(3, 5),
...                            ciw.dists.Uniform(3, 5)],
...     routing=[[0.0, 1.0, 0.0],
...              [0.0, 0.0, 1.0],
...              [0.0, 0.0, 0.0]],
...     number_of_servers=[1, 1, 1],
...     queue_capacities=[3, 3, 3]
... )

Mae'r amser mae'n cymryd i atodi coes i stôl (yr amser gwasanaeth) wedi'i samplu o ddosraniad unffurf. Mae'r dosraniad yma yn samplu pob gwerth rhwng terfyn isaf a therfyn uchaf. Nodwch yr unedau amser fan hyn yw eiliadau.

Pan efelychwn ni hwn, gallwn weld gwybodaeth am y blocio, er enghraifft y cyfnod o amser gwariodd stôl wedi'i flocio ym mhob nod. I weld hwn, gadewch i ni efelychu'r system am 20 munud:

>>> ciw.seed(2)
>>> Q = ciw.Simulation(N)
>>> Q.simulate_until_max_time(1200)
>>> recs = Q.get_all_records()

>>> blockages = [r.time_blocked for r in recs]
>>> max(blockages)
1.402303...

Gwelwn fod yn 20 munud y cyfnod macsimwm gwariodd stôl wedi'i flocio yn weithfan oedd 1.5 eiliad.

Gallwn weld y wybodaeth ar y stolion a wnaeth cwympo bant o'r cludfelt gan ddefnyddio priodwedd rejection_dict y gwrthrych Simulation. Geiriadur yw hwn, sy'n mapio rhifau nod i eiriaduron. Mae'r geiriaduron yma yn mapio rhifau dosbarthau cwsmer i restrau o ddyddiadau a chafodd cwsmeriaid eu gwrthod:

>>> Q.rejection_dict
{1: {0: [1020.0, 1184.0]}, 2: {0: []}, 3: {0: []}}

Yn y rhediad yma cafodd 3 stôl eu gwrthod (cwympo i'r llawr gan nad oedd lle ar y cludfelt) wrth Nod 1, ar ddyddiadau 740, 960, a 1140. I gael nifer y stolion a chafodd eu gwrthod, cymerwch hyd y rhestr yma:

>>> len(Q.rejection_dict[1][0])
2

Rhedwn 8 arbrawf, a ffeindiwn nifer o wrthodion yr awr. Cymerwn amser-twymo o 10 munud. Ni fydd amser-oeri yn briodol gan ein bod ni'n recordio gwrthodion, sy'n digwydd ar y pwynt cyrraedd:

>>> broken_stools = []
>>> for trial in range(8):
...     ciw.seed(trial)
...     Q = ciw.Simulation(N)
...     Q.simulate_until_max_time(4200)
...     num_broken = len([r for r in Q.rejection_dict[1][0] if r > 600])
...     broken_stools.append(num_broken)

>>> broken_stools
[9, 10, 6, 9, 4, 7, 10, 3]

>>> sum(broken_stools)/len(broken_stools)
7.25

Ar gyfartaledd mae 7.25 stôl yn torri pob awr; yn costio 72.5c yr awr ar gyfartaledd.

Mae system cydosod newydd, yn costio £2500, yn gallu lleihau amrywiant yn amser atodi coes, fel bod hwn yn cymryd rhwng 3.5 a 4.5 eiliad i atodi coes. Faint o oriau gweithredu sydd angen ar y ffatri i ennill nôl yr arian a wnaeth y system newydd gostio?

Yn gyntaf, o dan y system newydd faint o stolion rydym yn disgwyl torri pob awr?:

>>> N = ciw.create_network(
...     arrival_distributions=[ciw.dists.Deterministic(4.0)],
...                            ciw.dists.NoArrivals(),
...                            ciw.dists.NoArrivals()],
...     service_distributions=[ciw.dists.Uniform(3.5, 4.5),
...                            ciw.dists.Uniform(3.5, 4.5),
...                            ciw.dists.Uniform(3.5, 4.5)],
...     routing=[[0.0, 1.0, 0.0],
...              [0.0, 0.0, 1.0],
...              [0.0, 0.0, 0.0]],
...     number_of_servers=[1, 1, 1],
...     queue_capacities=[3, 3, 3]
... )

>>> broken_stools = []
>>> for trial in range(8):
...     ciw.seed(trial)
...     Q = ciw.Simulation(N)
...     Q.simulate_until_max_time(4200)
...     num_broken = len([r for r in Q.rejection_dict[1][0] if r > 600])
...     broken_stools.append(num_broken)

>>> sum(broken_stools) / len(broken_stools)
0.875

Felly mae'r system newydd yn safio 6.375 stôl yr awr, tua 63.75c yr awr. Felly fe fydd yn cymryd \(2500/0.6375 \approx 3921.57\) awr gweithredu i'r system talu ar gyfer y system newydd.