For instance, for a given simulation we can assume that the number
of machines (servers) does not alter, so we give it the value of 1 as we
want to investigate the scenario with one machine.
However, while we can say that jobs arrive at a rate of four times
per hour, or every 15 min, that isn’t strictly realistic.
Sometimes there are interruptions to the deliveries. A forklift truck
might drop the timber when loading it from the lorry, or there may be a
physical blockage preventing the wood being placed next to the
machine.
Similarly, the time taken to process the timber won’t always take
15 min. This is just an approximation that—on average—takes 15 min.
Sometimes the timber might blunt the cutting blades of the machine,
and it will take longer to inish the operation. When the tooling is
freshly sharpened the machining time will be less than 15 min.
We want our simulationto take account of these variances, and we
do this by specifying a distribution function. This tells the simulation
to use a variety of values, whose mean is the arrival rate that we are
suggesting.
So, for an arrival rate of 15 min, the simulation will generate a set of
values that vary, but have a mean of 15 min.
This allows the simulation to be more realistic as it will take
account of naturally occurring variations in waiting and processing
times.
We are now ready to build the simulation.
5.5 Building the Simulation in Ciw
Create a new text ile called timber_conversion.py We shall enter some
snippets of code now to quickly create a simulation to produce some
results. Try not to worry about some of the details just yet as they will
be explained later. What is important is to execute a simulation so that
we can start to understand the timber conversion process better. First,
we specify the arrival and service distributions, along with the quantity
of servers:
Python Code
You might have noticed that the value contained in
[ciw.dists.Exponential(0.1)] does not seem to relate to an arrival rate
of 6 times per hour. This distributionfunction requires a decimal value,
so we divide the arrival rate of 6 (arrivals per hour) and divide it by 60
(the number of minutes in an hour).
Similarly, for the service time, the rate of processing per hour is 4
and is represented as 4/60 = 0.067.
The next piece of code to add is:
Python Code
This is an instruction to tell the computer to create a simulation and to
run it for a simulated time of one shift (8 h/480 min).
That is all that is required to create the simulation. However, there
are no instructions to tell the computer to report the results. The
following program code does this.
Python Code
There are three results that are reported (look for the ‘print’ keyword).
First, the average waiting time in minutes for each job. Second, the
average time taken to process each job in minutes. Finally, the average
utilisationof the machine (server) as a percentage.
When you execute your simulation you should see the following
results in the console:
This tells us that on average, a job took nearly 13 min to process and
had to wait approximately 52 min in the queue. The machine was
operating for most of the time (99.7%).
This is excellent for a shop loor supervisor who has to report the
percentage of time that a machine spends idle. Hardly any downtime
for the machine in this scenario.
However, let us use the simulation to start investigating different
scenarios.
We shall now explore the effect of increasing the number of
machines from one to two.
Edit the following line to increase the number of servers
(machines) to 2:
If we execute the simulation again we observe the following results:
We can see that the addition of an extra machine has dramatically
reduced the wait timefrom 52 min to around 9 min. The utilisation of
the two resources has also fallen to 68%, meaning that machining
resources are idle for approximately 32% of the shift.
While there is a reduction in waiting time, and therefore the overall
lead time to delivery of a product, there is the additional capital cost of
extra plant. Depending on how the machine is operated, there may also
be extra labour required to run both machines at the same time.
The shop loor supervisor has a conversation with the company
owner, and it is clear that there is no cash with which to purchase
another machine. The next course of action is to try and increase the
output of the timber conversion process. The service timeis
15 minutes, which means that 4 jobs per hour are processed. What
difference would it make if we could process 5 jobs per hour?
Edit the following line to re lect a service rate of 5 jobs per hour
(5/60=0.08):
Here are the results:
The machine utilisationhas increased, but the waiting time is much
less than it was with a service time of 15 minutes. This illustrates that
there is a signi icant bene it to be had by making even small changes to
the service time of a process. This thinking is central to ‘lean
manufacturing’ techniques, where potential opportunities for the
removal of wasteare identi ied. There might be some different tooling
that enables the timber to be cut at a faster rate, or there might be a
better way of organising the material so that the cutting-to-length
operation is optimised for the fewest cuts.
5.6 Con idence
Once we have built a simulation, it is important that we are con ident
that it represents the situation that we are modelling.
If we look at the results we have observed so far, what do we notice
about the average processing time?
We have obtained three different values: 12.6, 14.2 and 11.3 min.
This is a signi icant variation, and it suggests that the simulation might
not be taking a suf icient number of scenarios into account.
For a given scenario, there is a time when the simulation queue is
empty, and then partially complete, until a steady state of operation is
achieved. Similarly, towards the end of a simulations there will be a
number of jobs that have not been completed. When we report the
statistics of how the process has performed, we are collecting the data
for jobs that have been completed.
Depending on the time require to ‘wind-up’ and ‘wind-down’ a
simulation, there could be a disproportionate effect on the
performance that we observe. This would decrease our con idence in
ability of the simulation to be used as a tool for experimentation.
We deal with this in two ways. First, we run the simulation for a
longer simulation time and then report only the performance from the
system once it is in a steady state of operation. For our 8 h shift, we
could add an hour before the start and at the end for warm-up and cool-
down periods.
Second, we can run the simulation many times, altering a number
(called a ‘seed’) so that each run has some variation introduced into it.
Create a new ile called ‘timber_conversion_2.py’ and enter
the following code:
Python Code
Execute the code and you will observe the following results:
You can now edit the variable <runs=1000> to change the number of
times that the simulation executes.
At lower values for <runs> you will notice variability in the
statistics that are reported. As the value of <runs> increases the
statistics start to stabilise. This indicates that we can have con idence
that the simulation is providing results that we can trust. This is
regarded as good practice for the modelling and simulation of systems.
5.7 Conclusion
We have looked at the application of queueingto the modellingof an
industrial process. This approach is straightforward to use and enables
the parameters of a simulation to be speci ied.
This speci ication can then be used with a simulation tool, and in
this chapter we have used Ciw to quickly construct a simulation that
represents our queueing model.
As the simulation runs we can collect summary statistics that can
help us understand the interrelationships between parameters such as
job arrival rates, processing times and the number of resources
available to do the work. We can then explore different scenarios by
changing these parameters, and this can help us understand what the
limits of the system might be.
Exploring different situations via simulations is an inexpensive and
quick way to ind the limits of a system, or to identify new possibilities.
For example, you might want to ind ways of increasing the output of a
factory temporarily to complete a particular rush order for an
important customer.
You know that you can increase capacity by adding another shift or
by buying new plant. But you might want to know how many additional
operators you need to bring in to complete the extra work. You’ll also
want to see how this might affect the impact on the rest of the orders
for other customers.
A simulation can help you determine the quantity of extra resource
required to complete the job, while balancing the consequences of this
on the rest of the system.
While you might not be able to buy, install and commission new
plant quickly enough, you would be in a better position to decide
whether to outsource some of the work or not.
A more strategicconsider the potential impact of the sales team’s
forecastfor the next quarter; you could use this forecast to investigate
the demands that could be made on your business resources, and then
be in a position to justify the acquisition of new plant or additional
staf ing.
5.8 Learning Activities
Exercise
Using the program code from above, experiment with different
values. You can change the parameters for the number of simulation
runs for instance, but you can also change the ‘shift length’; this
refers to the amount of simulated time that the program executes.
Simulation code allows us to try out different values quickly, to
see what the different effects might be. This is convenient when we
have a speci ic question to answer. However, we often need to
perform deeper analysis of a a simulation model, and in such cases it
is useful to record the effects of our changes.
Try to adopt good practice by recording the values that you
change, noting the effects of these changes in a table. This habit will
help you when your models increase in complexity.
Some good questions to ask of this model could be:
1.
What is the effect on machine utilisation as the arrival rate of
jobs declines?
2.
How would you ind an optimum set of values to ensure that the
system is balanced?
Extension exercise
When you start to build simulations, you quickly gain a deeper
appreciation of the dynamics of systems. An important part of
simulation is being able to discover and then communicates the
results of your simulation.
Using the program code above plus the details available in Ciw
documentation, develop some additional information to report.
For example, it would be interesting to see what the average
length of the queue is before the machine. This will then tell us what
the total inventory that is being processed amounts to (Work in
Progress).
The code currently reports the average (mean) of a set of values.
Enhance the reporting to include additional summary statistics such
as standard deviation.
© Springer Nature Switzerland AG 2021
R. Hill, S. Berry, Guide to Industrial Analytics, Texts in Computer Science
https://doi.org/10.1007/978-3-030-79104-9_6
6. From Process to System Simulation
Richard Hill1 and Stuart Berry2
(1) Department of Computer Science, University of Hudders ield,
Hudders ield, UK
(2) Department of Computing and Mathematics, University of Derby,
Derby, UK
Richard Hill
Email: [email protected]
6.1 Simulating Industrial Systems
In the previous chapter we looked at the concept of queueing as an
industrial process. Queues are an effective way of representing
dynamic systems that receive an input, process that input and then
produce an output. As such, they lend themselves to the modelling of
processes or services within organisations.
When we are faced with a complex problem to be solved, we often
try and simplify the representation of the object or system under
scrutiny. We can look at a situation in the most abstract way possible,
or we can delve deep into the system and model one tiny aspect of it in
great detail.
For example, we could model an entire business with just one
queue; the business would take in orders, process those orders, and we
could produce a set of results using a simulation like we built in the
previous chapter.
This scenario might work, in that if the order mix and the demand
patterns were stable and the production processes were relatively
predictable, a one-queue model would suf ice. It would be limited in
what it could tell us though, as there would not be a suf icient number
of variables to experiment with. In the real-world, modelling an entire
business as a single queue is somewhat similar to the high-level
analysis that an accountant could perform with a set of spreadsheets.
We tend to be motivated to model and simulate an organisation
when we feel the need to understand it better. Modelling the
organisation as a set of queues is a good way of achieving improved
understanding. The process of modelling itself is often enlightening, as
are the questions that it prompts us to ask production personnel as we
build the model.
Queues therefore allow us to model a system at different levels, and
this leads to a range of opportunities to comprehend what is going on
in an organisation.
Rather than abstracting the business as one queue, we could look at
divisions, sections or departments, depending on how the business is
subdivided. Problems often provide the impetus for improvement, and
that improvement usually requires more scrutiny than we can
currently perform.
Therefore, the focus of your modelling may be a particular ‘problem’
process; the machining centre that cannot keep up with the rest of the
factory, or the sales order processing clerk who always seems to be
behind.
Queues do enable a modular approach to improve the visibility we
have of a business. We can take a top-down approach where we
partition the business broadly into functions that we model as
separate queues. Or, we can select individual processes that we want to
look at in more detail.
All of the above requires us to extend the one-queue approach to
modelling of the previous chapter, so that we can look at collections of
queues, both individually and as a whole. The ‘whole’ is the system
under scrutiny, whether it be the whole business, a division,
department, or a manufacturing cell. We usually refer to a collection of
connected queues as a queueing network.
Fortunately, much of what we have learned in the previous chapter
applies to the creation of a queueing network, so as before, new
concepts will be introduced as we explore an example scenario.
6.2 Example: Joinery Manufacturer
The ‘timber conversion’ process from the previous chapter is a model
of part of a larger manufacturing process. A joinery manufacturer
manufactures make-to-order hardwood window frames for building
companies. Orders are received and processed through three distinct
production processes as shown in Fig. 6.1.
Fig. 6.1 Window frame production in a joinery factory
Workstation 1 (WS1) is the timber conversion process modelled in
the previous chapter, where lengths of wood are pro iled (shaped)
and cut to length.
Workstation 2 (WS2) receives the output from Workstation 1 and
prepares the ends for assembly by cutting mortice and tenon joints.
Workstation 3 (WS3) takes the timber components and assembles
them into a completed window frame, thus completing the order.
Using a queueing approach to modelling we have three queues: one
queue for each workstation. The output of WS1 feeds WS2, and the
output of WS2 feeds the input of WS3. The production line is expressed
as a queueing model is in Fig. 6.2.
Fig. 6.2 Production line described as a series of three queues
To complete the speci ication of the queueing network, we need to
identify the arrival and service rates, as well as the number of servers,
for each queue.
Re lection activity
What is the arrival rate for items entering WS2?
When we modelled the single queue for timber conversion in the
previous example, we speci ied the rate at which jobs arrived, this
being 6 times per hour, or every 10 mins. We also reasoned that there
would be natural variability around this schedule, and therefore the
actual arrival rate would be based on the exponential distribution, with
a mean of 6 times per hour.
In this extended scenario, WS2 receives its jobs directly from WS1.
Therefore, the arrival rate at WS2 is determined by whatever the
output rate is from WS1.
The same goes for the arrival rate for WS3, who receives its input
from the output from WS2.
Therefore, we should not be specifying a separate arrival rate for
the downstream workstations as these are determined by how the
whole queuing network operates.
However, we can specify the service (process) time for WS2 and
WS3, and we can also specify the capacity of each by quantifying the
number of servers available.
6.3 Building the Simulation
As before, we shall take the speci ication for the model and implement
this as a simulation using Ciw.
First of all we create the arrival_distributions. We need to
specify an arrival distribution for each of the queues that represent a
workstation. In this example we have three workstations represented
by three queues.
The arrival rate for the irst workstation is 6 times per hour. The
arrival rate for the remaining queues is determined by the irst queue,
so we do not specify a separate arrival rate for WS2 and WS3. Instead
we use the ciw.dists.NoArrivals() declaration.
This tells Ciw that jobs only enter the systems via WS1, and that
WS2 and WS3 do not receive jobs from outside of the system.
Python Code
The service distributions (range of processing times) are summarised
in Table 6.1.
Table 6.1 Process times for each workstation
Workstation Process time
WS1—Pro ile and cut to length Exponential distribution with a mean of 15 mins
WS2—Mortice and tenon Exponential distribution with a mean of 30 mins
WS3—Assemble window frame Uniform distribution between 15 and 19 mins
This is written in Ciw as follows:
Program code
We now specify the servers for each of the queues. As before there is
one machine at Workstation 1. There is one machine at Workstation 2.
Workstation 3 is where the timber components are assembled into a
completed frame. This area contains three people and thus is
represented by 3 servers. As we have speci ied individual arrival and
service distributions, we also declare the servers with the
number_of_servers statement:
The last bit of information to complete the model is to specify the
routing of the job. A production routing is a way of describing how an
item is processed through different operations. The production routing
for this scenario is shown in Table 6.2.
Table 6.2 Operations for each workstation
Workstation Operations
WS1—Pro ile Shape timber for cill pro ile Shape timber for jamb pro ile Shape timber for rail
and cut to pro ile Cut cill section to length Cut jamb section to length Cut rail section to
length length
WS2—Mortice Mortice cill section Mortice top rail section Tenon side rail section Tenon jamb
and tenon section
WS3— Glue components Assemble frame and cramp Af ix beading
Assemble
window frame
For the simulation, we need to specify the order in which the
queues are executed. From the production routing the order
progresses from WS1, through WS2 to WS3.
The routing is speci ied as an nxn matrix, where n = the number of
nodes in the network. Each node represents a separate queue, which in
our example equates to WS1–WS3.
In turn, we take each queue and identify the probability that a
queue transitions from the previous one. So, for the irst queue in our
example (WS1) we compile a set of values as follows:
The probability that node 1 transitions to itself (WS1 to WS1) is
zero. The probability that node 1 transitions to node 2 (WS1 to WS2) is
1.0, or 100%. The probability that node 1 transitions to node 3 (WS1 to
WS3) is zero.
For WS2 we have:
The probability that node 2 transitions to node 1 (WS2 to WS1) is zero.
The probability that node 2 transitions to node 2 (WS2 to WS2) is zero.
The probability that node 2 transitions to node 3 (WS2 to WS3) is
100%.
For WS3 we have:
The probability that node 3 transitions to node 1 (WS3 to WS1) is zero.
The probability that node 3 transitions to node 2 (WS3 to WS2) is zero.
The probability that node 3 transitions to node 3 (WS3 to WS3) is zero.
Each of the lists of values for the individual workstations is now
brought together into a matrix:
This example has shown an exhaustive approach to arriving at the
routing matrix for the system model. In practice, we locate the points
of transition for a particular routing and insert ‘1.0’, which would give:
The remaining spaces are then completed with zeroes. This becomes
intuitive after a couple of attempts.
Finally, we should recognise that as the simulation stands, there is
an assumption that the queue capacity is in inite—there is no limit on
the number of jobs that can wait for an operation. This is not realistic,
and organisations often have restricted capacity for the storage of
items. In Ciw we use queue_capacities=[] to specify a limit for
each of the queues in the system. For this system we shall specify a
maximum queue length of 3 jobs for each process.
Program code
Even with only two additional queues on top of the single queue in the
previous chapter, the system is becoming more complex to visualise.
Communicating the performance of the model as well as the results
of any experimentation are a fundamental part of simulation. We need
to see the results so that we can verify the suitability of a model, but we
may also need something to show what we have discovered to others.
If communication of the insights is hampered, it is unlikely that any
resulting course of action will garner support from the relevant
stakeholders.
Since we are simulating a system of three workstations, it is likely
that we shall be interested in the utilisation of each of those
workstations in relation to each other, which suggests at least one type
of visualisation.
We can report the overall time that a job spends queueing and being
processed. It would also be useful to count the quantity of jobs that
have been completed at the end of a shift.
Again, as in the previous example we should include the ability to
conduct a number of experiments to explore what the steady-state
performance of the system is. We still might want to investigate what a
‘cold-start’ looks like though, for instance if the shift starts and the
system has no jobs in progress (or ‘work in progress’ (WIP)) as it is
typically referred to).
As the number of runs increases it is useful to have some feedback
to the console that the simulation is working, otherwise there may be
nothing to see for a while. We can obtain this feedback by adding
progress_bar=True to the main simulation call:
To assist with visualisation of the results, the simulation produces a
bar chart of the proportion of each workstation that has been utilised
during the simulation, as per Fig. 6.3.
Fig. 6.3 Resource utilisation for each workstation
From the irst run of the simulation there is an imbalance of activity
across the workstations.
Question
A total of 31 jobs were completed during the shift. How would you
change the simulation to investigate ways of achieving a more
balanced distribution of work?
The complete program listing is as follows:
Python Code
6.4 Managing Resource Utilisation
In this example of a manufacturing system we have seen that there is
an inherent imbalance of resource utilisation. Even if the capacity of
the assembly workstation is reduced to 1 person (saving two staff), the
utilisation of workstation 2 still only amounts to approximately 30%.
This presents at least three opportunities for the business to
consider. First, can the operator of workstation 2 be redeployed for
some of the 70% of the time that they appear to be idle?
Second, can the machinery of WS1 be modi ied to include jointing
as part of the process. This would extend the processing time at WS1,
but would also eliminate the queue time and process time at WS2.
Third, can the business ind new orders that require processing at
WS2, but not WS1? For example, can pre-shaped lengths of timber be
bought in, bypassing WS1?
Opportunity one would probably warrant some investigation with
the production staff. There may be some training and reskilling
required to explore before any further experiments can be conducted.
Similarly, opportunity two would require some research into the
feasibility of combining the irst two workstations. There is likely to be
a cost associated with this approach and that is where the simulation
can help identify whether suf icient value can be achieved.
The third opportunity is an interesting scenario. There may be a
market that exists whereby other timber conversion operations
require mortice and tenon jointing as a service. Or, there may be a
supplier that can deliver ready-shaped blanks that are in the same
state as those that are produced by WS1. The business could therefore
consider buying ready-shaped blanks in standard sizes and dedicating
the in-house WS1 to be reserved for bespoke jobs, with custom sizes.
To explore the potential of the situation, we need to look at how we
might modify the model of the system.
Figure 6.4 shows how the model needs to change. WS1 accepts raw
timber and the output from this goes straight to WS2 as before. WS2
now accepts pre-shaped timber blanks directly from an external
supplier in addition to the output from WS1.
Fig. 6.4 Modi ied queueing model to re lect the introduction of pre-formed timber blanks, which
are processed along with timber blanks produced by WS1, at WS2
As far as the product routing is concerned there are no changes
required. The only change is to add an arrival rate to WS2 so that it can
accept the blanks.
We therefore modify the simulation as follows:
Python Code
The difference in resource utilisation is summarised in Fig. 6.5 and
Table 6.3.
The addition of bought-in pre-shaped timber blanks to WS2 enables
the spare capacity to be utilised to a greater extent. This has the
additional bene it of increasing the low of materials into WS3,
resulting in the number of jobs completed each shift rising from 31 to
75. Overall, the resource utilisation is better balanced across the
system.
Fig. 6.5 Resource utilisation for each workstation after introducing pre-shaped timber blanks
Table 6.3 Workstation utilisation before and after introduction of bought-in pre-formed timber
blanks
Resource utilisation Resource utilisation with bought-in blanks
WS1: 91 WS1: 91
WS2: 30 WS2: 72
WS3: 32 WS3: 77
6.5 Product Mixes
A common query for a manufacturing plant is whether the sales
function should sell a particular type of product, or perhaps run a sales
promotion. The product that is sold might make the least demand on
the factory, or it might balance the utilisation of resources when
combined with orders of other types.
Alternatively there might be a desire to examine the feasibility of
adding a new product type to the existing portfolio, to assess what the
potential for pro itability might be. This can be helpful for businesses
that experience variability in sales in relation to the season.
For instance, a gas heating boiler manufacturer might expect to sell
more units during the winter period and might therefore make to stock
during the summer period. If the boiler manufacturer added a gas
barbecue to its product line, it might expect to sell these during spring
and summer and therefore could make these items for stock during the
winter months.
This strategy would keep the factory work level more stable by
manufacturing different (but similar) products that require the same
manufacturing resources to produce. We shall now extend the window
manufacturing example to investigate what the impact of introducing a
new product might be on the factory resources.
6.5.1 Sash Windows
The sales team have identi ied a potential new market for sash
windows, which are different to the window frames that are made at
present. Most of the manufacturing processes are similar between the
two products, with the addition of a workstation to machine the
sashes. These products will not be processed by the existing morticing
workstation, but they will take longer to assemble at the last stage of
manufacture.
The proposed factory layout now requires four workstations
in total as shown in Fig. 6.6. Existing windows follow the established
route. Sash windows require a different process at stage two of their
manufacture and are routed to WS3 before returning to be assembled
alongside the plain window frames at WS4. The proposed routings are
given in Table 6.4. As before, we shall consider the arrival distributions
for our simulation.
Fig. 6.6 Production line modi ied to manufacture two distinct types of product
Table 6.4 Production routings for plain window frames and sash window frames
Workstation Plain window frame Sash window frame
WS1—Pro ile and cut X X
WS2—Mortice X
WS3—Sash X
WS4—Assemble X X
Plain window frame orders arrive at WS1 every 10 min. Sash
windows arrive at WS1 every 30 min.
In the previous examples we have speci ied arrival distributions for
each of the workstations in the model, but we have assumed only one
type of product. We are now interested in two discrete product types.
Ciw has the concept of ‘customer classes’ which we use to identify
different product types in this simulation. All classes are numbered
from zero upwards.
We shall assume that plain window frames are ‘Class 0’ and sash
windows are represented by ‘Class 1’.
We also assume that we are only modelling products that are made
totally in-house, so the remaining workstations (WS2, WS3 and WS4)
have ‘NoArrivals()’ as their arrival distributions.
Python Code
The arrival distributions are declared independently for each customer
class. We shall now specify the service distributions.
For the processing time, we know that plain window frames are not
processed by WS3, so we declare a dummy distribution using
ciw.dists.Deterministic(0.0) for node 3.
Similarly we do the same for node 2 (WS2) for the sash window,
that does not pass through this process.
Python Code
We then specify the remainder of the simulation set-up.
We assume a capacity of 1 for each WS to start with. Each of the
products is routed differently, and this is declared in the ‘routing’
section, as before for each of the customer classes.
Finally some queue capacities are set to constrain how much
product material is drawn into the factory as WIP.
Python Code
The remainder of the simulation is mostly as before, with the addition
of reporting for the additional workstation.
Python Code
After running the simulation you should see the following results:
These numbers and the associated bar chart illustrate a resource
utilisation imbalance similar to what we observed in the previous
example. At that stage we added machined timber blanks to bypass
WS1 and go straight for morticing. As before, we can experiment with
different input parameters to see how the system behaves.
One of the associated questions that is common from sales
functions is ‘what is the lead time to delivery of product X?’
Our simulation does not report this at present and as any
production supervisor knows that if we manage a factory to maximise
the resource utilisation, we shall ind it more dif icult to produce items
on time for customers.
Since we have speci ied our products as separate classes in Ciw, we
can report the average time that the product spends waiting in the
system.
We append the following to the main simulation loop:
This calculates the average time that each product spends waiting
within the system.
We can report this to the console as follows:
Finally, it has just occurred to you that there is no con irmation that
you have speci ied the routing correctly.
Question
How can you be sure that the individual products go to the relevant
workstations for processing?
In the following code we test each class to see if it is present at the
nodes which represent the correct route. For the plain window frames
this means that material arrives at WS1, WS2 and WS4, which are
represented by nodes 1, 2 and 4, respectively.
Sash windows are routed through WS1, WS3 and WS4, giving nodes
1, 3 and 4.
If the products are routed correctly, ‘True’ is returned to the
console.
You can experiment with the lists visited_by_plain_window
and
visited_by_sash_window to verify the routings.
The inal program code listing is:
Python Code
Running the simulation will give the following output:
6.6 Conclusion