|
Objects in this document may appear out of sequence if not viewed with Internet Explorer |
|
ORMSware NMOD Primer: Chapter 20 |
|
Close all other open windows. Click Figure 21 to open a separate window showing a newer version of our example model. This version has several contrived twists to the problem, just to show you more of NMOD. While the problem may be made-up at this point, we do not think connecting the dots from what you see here to real situations will be too difficult. While the model appears pretty much the same as before pictorially, we have changed its objectives, and as a result, Object ID's of some of the arcs, and the names and content of some of the nodes have changed as well. |
|
|
Figure 21 |
To begin with, the names of the networks in the model have changed. The top network is now called the ProductionCost network. n[2]'s Type has been changed to Network and the network which n[2] refers to is now called the PiecesRequired network. In this network we use probability distributions to determine the number of widgets required by products A and B, introducing the notion of modeling randomness/uncertainty into our discussion.
We are now using the model not only to calculate cost per piece, but also to develop schedules to facilitate just-in-time (JIT) production. We repeat n[2] to create production requests every hour using arc [8]. Each time n[2] is repeated, it triggers execution of PeicesReuqired [sub]network to determine the total number of pieces in each production request. In n[2] we also draw the JIT point for each production batch, again, from a probability distribution.
So, the number of pieces in each batch requested and the time available to produce each batch are both random variables. These two random variables cause variation in the total cost per piece. We will explain this further shortly.
In addition to the randomness of quantity and time-to-produce, we influence the total cost further by using a production speed policy. Since we know optimal production rate from the previous version of the model, we want to use that knowledge to minimize the cost of production of each batch, provided there is sufficient time to run a batch at optimal production rate.
We have put a time delay expression on a[7] so that a surrogate (representing a batch) traveling along it will not reach n[5] until it is time (on conceptual clock) to start production of a given batch to meet its JIT requirement. In addition to calculating total costs, we are using [5] to also show the start and finish time of each production batch and to compare the incremental cost of accelerated production when there is insufficient time to produce a batch at optimal production rate as derived from previous version of the model.
We have also put in a few lines of code here and there (we will point them out soon) that will track the number of machines in use at any given time to support the production requests arriving every hour, and therefore, the maximum number of machines required to meet widget delivery requirements (based on production requests observed during a given model run).
As mentioned previously, most of these new twists may seem rather odd, but they serve to illustrate what can be done with NMOD. For example, putting a time delay on [7] and setting the Duration property of [5] to production duration of each batch may seem to serve no purpose to some readers. But, if you reflect on it, you are likely to come up with instances (such as, say, developing cashflow statements and working capital requirements for an operation) where such capabilities can be quite useful.
|
Note: An added benefit of using NMOD rather than spreadsheet to analyze (say) cashflows is the flexibility it provides in investigating issues such as the value of compressing delays between cash outflows for an activity and cash inflows produced by that activity. Altering cashflow delays in a spreadsheet model requires making cumbersome structural changes manually. With NMOD, altering cashflow delays is just a matter of changing one or two input values (Duration properties), which makes it easy to use search procedures to find best answers. |
Let us take a look at the new NET file now to understand the model further before examining the feedback file from model execution. Click here to open PrimerSubNetNET.TXT window. Let us start with the top network's Start node, n[6]Initializations.
As you can see from the references to tables towards the top of the Trans code block, we are using a third table in this version of our example problem. This table is a little different from the tables we have used before.
|
More about Excel tables |
Notice in Widgets table below that several cells in the table have dashes in them. NMOD's GetTable
procedure needs a dash in every blank cell to load table data correctly.
When GetTable sees a dash in a cell, it sets the value in that cell to
equal the largest number possible of the dbl KIND (see columns 2 and 3
in rows 4 thru 7 corresponding to cells c52:d55).
|
Note: Some people may have expected NMOD to fill these cells with zeros. We chose filling dashed cells with largest number of the relevant KIND possible, because in Operations Research/Management Science (ORMS) we often use what is known as Big M (a very big number) to block any undesirable or infeasible connection between two points from entering a given solution. It is easier to put zeros where we want zeros, compared to entering large numbers where we want Big Ms. |
You may recall from rules listed in Chapter 16 (Using Microsoft Excel for inputs)
that on rows containing a table, there
should be no entries in columns to the right of the last column of a table.
|
|
Figure 22 |
As you can see above, we have entries to the right of the data cells (B49:D55) in the table highlighted in yellow. As you will see in the feedback file, because of those entries to the right of column D in rows 49-55, NMOD's GetTable procedure deduces that the table has 4 columns rather than 3.
To see this, click here to open a separate window (PrimerSubNet1NMOD.TXT), showing a feedback file of this model. Scan down or search for {Table.D}Widgets. Next, find 4 column(s) in {Table.D}Widgets. Since GetTable found 1. Triangular distribution after the 3rd column of data, GetTable has deduced that there are 4 columns in this table.
Skip down to Data in table section. The next line shows that GetTable has determined that the rows of the table run from 1 to 7 and that its columns run from 1 to 4. At the end of each row section describing the table in the feedback file, notice that GetTable is reading the number of each note in column E, considering them to be numerical data entries in the 4th column of the table. Since this is a table of dbl KIND, GetTable loads the first number it finds in each cell (separated by a succeeding blank or comma) into the corresponding table element in the model.
In the case of entries in column E in the spreadsheet, GetTable loads the numbers in front of each note in every row of the Excel table. If column E did not start with a number in each row, NMOD would have aborted execution saying that it found character data in numeric field.
The advantage of putting numbers this way in a comment column to the right of a table is that it makes it easy to set up the logic for relating values in the table to scalar variables in model logic. You can see this in PrimerSubNetNET.TXT window after the GetTable statements in the Trans property section of [6].
|
Notes 1. Before going to that, take a quick look at the statement for OPENing a file (PrSbNtResults.TXT) for writing desired results to a file other than the default feedback file. 2. Another even easier way to synchronize this (initialization) kind of data in Excel table with table elements in NMOD is to put meaningful row labels in short form in the first column of the table. You can see examples of this in Chapter 6 (Converting spreadsheet model to NMOD model) in Hands-on Tutorial section. |
&D.AWidgetsLo, &D.AWidgetsML, and &D.AWidgetsHi are parameters of a triangular probability distribution for drawing the number of widgets requested for Product A in each production batch. In Figure 22 table you can see that these parameters are in row 1, columns 1, 2 and 3 of the Widgets table. Look in PrimerSubNetNET.TXT window to see how the table cells are connected to Global properties in the model.
There is no modeling reason why we have related table values to these scalars. We could have used table references directly wherever we used corresponding scalars. For example, we could have used {t.D}Widgets(5,1) wherever we used &D.BestProductionRate. The only reason for using a scalar was to make the model easy to follow without having to look up what, for example, {t.D}Widgets(5,1) means.
You will notice towards the end of [6]'s Trans property block that we initialize certain Global properties for tracking the use of machines and the number of batches remaining to be processed during a model run. You will see their use as we go through the rest of the model.
|
Creating customer arrivals at any node or arc |
Notice the call to Arrival procedure at the very end of [6]'s Trans property. This is the same procedure NMOD calls when entities enter Arrival nodes. Both arguments (bigSur and bigTkn) are optional. We could have omitted them, but we included it here so that we can discuss it.
Whenever Arrival procedure is called, it does the following:
|
Caution The ID of a surrogate when it triggers a network object is always assumed to be contained in variable bigSur and its token's ID is assumed to be in variable bigTkn, both of big integer KIND. When NETrans translates Surrogate and Customer properties in NET and ADD files, it uses symbols bigSur and bigTkn to generate corresponding code in the model's F95 file. If the symbol bigTkn is used as the second argument in an Arrival call, and the analyst defines anything in terms of a customer/token property after the Arrival call, the value of bigTkn will be different after the call and all references to token will actually apply to the token created for the new customer, not the one with which the triggering surrogate entered the network object. On the other hand, if bigTkn is not used in the Arrival call, customer token properties will continue to be those of the token the surrogate was representing when it entered the network object. The user can get around this, if necessary, by declaring a local big KIND integer variable (or using a user-defined global, customer or surrogate property of big KIND) to store and retrieve the entering token ID value to achieve whatever s/ he has in mind. If you do need to get to that much detail, this will be one of the rare occasions when it is helpful to look at code generated for the relevant network object in the model's F95 file to figure out how best to handle such a situation. And that would mean that you are an advanced NMOD user! |
Let us look now at execution of [6] in the feedback file in PrimerSubNet1NMOD.TXT window. This feedback was captured while executing the model for just one batch request (i.e. with the value of &R.MaxBatches set to 1). That will give us a good feel for the model before checking out the results of running multiple batches.
Jump to the top of the window and scan down several lines or search for Start of model execution feedback and S2-T0-C0 executing Start node on first page/network 6 ProductionCost.[6]Initializations. With what you already know about how NMOD executes nodes, switch between PrimerSubNetNET.TXT and PrimerSubNet1NMOD.TXT windows to follow the execution of [6]. You may want to skip through the loading of the three tables.
There are no feedback statements (except automatic feedback of tables loading) until we reach the bottom of the Trans property code block for [6]. You have already seen the Arrival call at the bottom of Trans block. Arrival procedure issues a message (0.000000000000000E+00 ***>> Customer arrival <<***) which you can see in the feedback file. The zero is the time on conceptual clock at the time of this arrival. This, happening in the first node, is the arrival of the very first customer (production request) into the system.
Rest of the arrivals happen at the end of each execution of a[8]. Go to [8]'s code block in PrimerSubNetNET.TXT window. Look at its SignalTarget procedure property. Recall that SignalTarget property of an arc executes only right after the surrogate executing that arc comes out of Events queue. Notice here that we did not use any arguments in the Arrival call, because there is nothing we want to do with the new Customer ID or Token ID of the surrogate during the execution of this network object. There was no need to use the first argument, since our surrogate of interest to us in this situation is the surrogate that triggers this arc object.
|
Note: Even if we omit the second argument, we can still get the new value of the relevant surrogate's Token ID property by using NMOD-provided TokenID function. This is a big KIND integer function. Function argument is the ID value of the Surrogate of interest. |
With the Arrival calls on this arc and in [6], every time a surrogate enters n[2], it introduces a new customer (production request) into the system.
|
Creating customer departures at any node or arc |
While we do not have an example to present here, we would like to mention that just as one can create an Arrival at any node or arc, one can also create a Departure at any node or arc, by making a direct CALL to NMOD's Departure procedure. The statement required to do this is:
|
CALL Departure ( bigSur, bigTkn ) |
Both arguments are optional. If bigSur is absent, NMOD assumes that the relevant surrogate is the one currently active. If bigTkn is present, NMOD switches the token of the relevant surrogate to bigTkn. If it is not present, NMOD switches the surrogate's token to default Token ID of 0. The departing customer, and the token that is taken out of circulation are those associated with the relevant surrogate when the call to Departure takes place.
| Caution: Notice that the bigTkn argument is an optional output in Arrival and an optional input in Departure. There is no default assumed for bigTkn in the case of Arrival (relevant surrogate's Token ID is used, instead). The default is 0 in the case of Departure. |
|
Duration properties of nodes and arcs |
While we are still at [8], let us look at its Duration property. We have defined it to be &D.TimeBetweenRequests which was set equal to {t.D}Widgets(4,1) in [6]. You can verify from Figure 22 that this value is 1. We could have simply entered 1 in the Duration field of the dialog box for this arc in Visio, but setting it up the way we have gives us the flexibility to change this Duration property from Excel and re-execute the model without having to compile and link it again to renew the model's EXE file. [8] executes only when the value of &R.MaxBatches is > 1 (because every time [2] executes, #R.Batch takes on the value of the new customer's ID, and &L.NextBatch will be set to True in SignalTarget property of [2] only if #R.Batch < &R.MaxBatches).
Now, let us look at Duration property of a[7] and then the Duration property of n[5]. On a[7], the Duration property has been entered in the form of an expression in [7]'s Visio dialog box as {MaxF(#D.ProductionStartTime - Time(), 0.0_dbl)}...
MaxF is an exposed generic NMOD function for finding the greater of two values of the same KIND. In this case the first value is the difference between the desired production start time and current time, and the second value is 0. Notice that the second value has been entered as 0.0_dbl. The _dbl casts 0 (decimal and trailing zero are required; else, you will get an error message) as a real/floating point value of the dbl KIND.
The reason why we used this function instead of just #D.ProductionStartTime - Time() is just in case the round-off error in evaluating this expression produces a very tiny negative value when the values on both sides of the minus sign are the same. A Duration property cannot have a negative value.
Purpose of the delay on [7] is to prevent surrogates traveling along [7] from reaching [5] before their respective JIT production start times. In case you are wondering why there is no such delay on a[10] terminating at [5], the reason is that since [7] and [10] are AND arcs, when surrogate of a customer reaches [2] through [10], NMOD will make it wait in [2]'s Convergence queue until the surrogate along [7] reaches [2]. Therefore there is no reason to do Duration calculations on both arcs.
Notice also that [7]'s Duration property has additional logic in it for writing a feedback statement. You may recall our discussion earlier that the analyst can use any property to execute any desired code to control model behavior.
Let us now look at the one remaining positive (> 0) Duration property in the model. Go to code block for [5]. You can verify later that the value of #D.TimeToProduce is set in [2]'s Trans property.
The reason why we introduced time dimension into this model is to show how to use it to model dynamic aspects of an operation, enhancing the value of a model. We will explain this with two examples. The first case is already incorporated into this model, as explained immediately below. We will explain the second case after that to show what can be done to make a model such as this more useful.
Because of the time dimension in the model by way of Duration properties, it is easy for us to figure out how many machines are needed to support the operation with the kind of production requests it receives. All we have to do to get this information is to insert a few simple statements into the Duration and SignalTarget properties of [5].
|
Note: We could have inserted the last two lines of logic in [5]'s Duration property in Trans property instead, because execution of Duration property follows immediately after Trans property in real time, and at the same conceptual time. Therefore, the machines in use when Trans property is executed for a customer will be exactly the same as the machines in use when Duration property is executed for that customer. |
NMOD puts the surrogate in Events queue immediately after executing Duration property of [5]. So, by inserting the two statements under the nop line in [5]'s Duration, we are updating the number of machines in use when a new batch goes into production. Recall that we delay the arrival of surrogates to this node until the JIT production time of their respective customers (batches) by using the Duration property of [7]. So, incrementing the count of machines in use at this point accurately reflects how many machines are in simultaneous use to support all ongoing JIT requirements at that conceptual point in time.
To keep accurate count of machines in simultaneous use, we have to also decrement the number of machines in use as soon as a batch is complete. After holding a batch in Events queue for the duration of its production, NMOD takes the surrogate representing the batch out of the queue and executes the SignalTarget property of [5] for that customer (batch). The machine used to produce that batch becomes available at that point and this fact is expressed by the statement &R.MachinesInUse = &R.MachinesInUse - 1 in [5]'s SignalTarget property.
You can see the results of our WRITE statements in [2] and [5] by clicking here to open PrSbNt1Results.TXT window. Results written to the left of the page are from [2] and results indented to the right are from [5]. Notice that the maximum machines in use during this model run is listed at the bottom of the results. We can use this result, for example, to expand the model to incorporate capital information related to the machines required for the operation.
|
Dynamic and static aspects of a model |
Another potential use of time dimension we promised to explain is showing cashflows from this operation. We can create another network in the model running simultaneously to show the material requirements for the widgets and the associated cash outflows necessary to support production requirements. We can easily introduce time factors to delay outflows of accounts payable for materials, labor, etc. as well as delays involved in collection of accounts receivable. We can then analyze the tradeoffs in expanding accounts payable and compressing accounts receivable cycle times.
We hope you noticed in the explanation above that a model can contain networks describing both static and dynamic aspects of an operation. Materials requirement network of a widget is likely to be a stationary part of the model while the cashflow networks will be part of the dynamic side of the model.
| Network nodes, Return nodes and surrogate's network call stack |
We explained briefly the execution of Network type nodes in Chapter 5 (Execution of Network Type nodes), but wanted to delay detailed discussion of execution of referenced networks until now. Switch to Figure 21 PrimerSubNetVSD window and look at ProductionCost.[2] whose Node Type is Network. When a surrogate enters this node, NMOD sends it to the [implicitly] referenced PiecesRequired network.
Switch to PrimerSubNet1NMOD.TXT window and jump to Event 2 mark. Messages indicate (finished temporal arc...) that a signal has arrived at n[2] from [6]Initializations and that NMOD has recognized [2] as a Network node, which references PiecesRequired network.
As NMOD sends the surrogate to the next lower level in the hierarchy of networks in this model, it pushes information about the referencing node into a stack property of the surrogate. You can see NMOD's feedback from this activity and the arrival of the surrogate in the referenced network's Start node.
By the way, stk%bigStkLev,stk%bigStkCur 1 5 is feedback from NMOD that this surrogate's network hierarchy stack is 1 level deep and that current memory allocation for its stack is 5 levels deep. If and when the stack depth needs to go higher than 5 levels, NMOD will automatically grab another 5 levels of stack memory for this surrogate, and so on.
|
Note: A network can be referenced from any number of other networks or from itself. Also, a network can be called from more than one node in the same referencing network. This is another reason why Visio object ID, instead of node name, is used to uniquely identify each node. If node names had to be unique, we could not reference the same network from more than one node in the same referencing network. We could have made referenced network name a Node property, but all things considered, including problems associated with conditionally displaying that property value for easy communication in our simple Visio interface, our current approach for uniquely identifying objects with Visio-assigned object numbers edged out other choices. |
You can follow along through feedback under Event 9 mark to see how surrogates traverse PiecesRequired network for Customer 1 (by switching as necessary among PrimerSubNet1NMOD.TXT, PrimerSubNetNET.TXT, and PrimerSubNetVSD windows). Feedback below Event 10 mark shows the completion of the Return node in PiecesRequired network. The next few statements show how NMOD pulls return control information from the surrogate's network hierarchy stack. Notice that when the surrogate returns from the referenced network, NMOD executes n[2] as if it were a Normal node.
Follow along to Event 11 mark to the message ~~~No signal to a[12], since Customer ID is <=1. This message is our custom feedback message in SignalTarget property of [2]. Following that, notice our message Create another batch request? F. NMOD has determined that the test #R.Batch < &R.MaxBatches evaluates to False, and that therefore, there are no more production requests. As you can see, this logic in SignalTarget property is executed before the Branch properties of successor arcs of [2] are evaluated. When NMOD evaluates Branch property of a[8], its branch condition evaluates to False as indicated a few lines later in the PrimerSubNet1NMOD.TXT window.
As you can see from the explanations above, a Network node contains in it the Network it references as well as all of the properties of a Normal node.
|
Uncertainty/risk modeling |
We can model risk/uncertainty with NMOD. Close PrimerSubNet1NMOD.TXT window and click here to open a separate PrimerSubNet10NMOD.TXT window to display feedback from executing PrimerSubNet model for 10 requests coming in 1 hour apart (recall that we had set &D.TimeBetweenRequests = 1).
To understand the feedback from modeling uncertainty let us first go to the PiecesRequired network. We need to switch among PrimerSubNet10NMOD.TXT, PrimerSubNetNET.TXT, and PrimerSubNetVSD windows as necessary while going through this explanation. Go to PiecesRequired.[1] in PrimerSubNetNET.TXT and PrimerSubNetVSD windows first. Notice the logic for determining the number of widgets necessary to support the production of Product A for the customer (batch) represented by the surrogate.
We are using Triangular probability distribution to draw the number of widgets to request for Product A. The three parameters used in the distribution are smallest possible, most-likely, and highest possible number of widgets that will be demanded for Product A in any given request. Switch to PrimerSubNet10NMOD.TXT window and look below Event 4 mark for our B:@D.Widgets message from n[2].
|
MergeSum function |
Follow along to Event 9 mark. Recall our discussion in Chapter 19 (Reinforcing concepts through PrimerSig's feedback file) about active merging logic at convergence nodes. There you saw explicit logic we wrote to sum up values of a property from different surrogates. We wanted to show you that before showing you the exposed NMOD function MergeSum which accomplishes the same thing requiring less work from the analyst.
Switch to PrimerSubNetNET.TXT window and skip to the end to see how this works. Look at the Merging procedure property for PiecesRequired.[4]. Recall that NMOD repeats Merging procedure property of a Convergence node the number of times equaling the number of AND incidents required for convergence. In this case, the required number of AND incidents is 2.
The first time NMOD calls [4]'s Merging procedure (with the convergence triggering surrogate), MergeSum initializes the summation value to the value of the triggering surrogate's referenced property (viz. the value 18.91718477948823 stored in @D.Widgets). For each remaining surrogate coming out of the Convergence queue MergeSum adds the referenced property value to the previous summation result. In this case S2-T1-C1 had arrived from [2] where @D.Widgets was determined to be 30.70728106935378. As you can see, the final summation value is as indicated by our custom feedback message Mrg:#D.PiecesRequired 49.62446584884202.
|
Notes 1. If you do not recall why we use customer property rather than surrogate property to accumulate the sum, it will be a good idea to review Active merging logic at convergence nodes section of Chapter 19 (Reinforcing concepts through PrimerSig's feedback file). 2. Similar to MergeSum procedure, NMOD also offers MergeProd which computes products of given property of all surrogates converging at a node. 3. Both MergeSum and MergeProd can be applied to reg, big, sng, dbl KINDs as well as logical properties. |
Getting back to our discussion of risk/uncertainty, let us look at ProductionCost.[2]'s Trans property. Look at the second line in the block where we use Uniform probability distribution to determine the time available till the JIT point for any given batch. If you follow rest of the logic in [2]'s Trans property, you will see how the two random variables we have defined so far ( #D.PiecesRequired and the dbl KIND variable dblTimeAvailable local to [2]) contribute to the uncertainty of production costs.
In addition to the cost calculations we discussed in previous sections, another matter of interest to us may be how much our production costs deviate from optimal cost, when only less than optimal time is available to meet the delivery requirement of any given batch. This deviation is calculated at the top of ProductionCost.[5]'s SignalTarget property.
Click here to open PrSbNt10Results.TXT window to study the results of running 10 production requests through the model. The results are self-explanatory. Notice, however, that per its JIT requirement Batch 4 production starts later than Batch 3 and finishes ahead of 3.
We suggest that you scan through to the bottom of the window, where you will find the maximum number of machines in simultaneous use during the run.
|
Monte Carlo simulation and planned variance reduction methods |
If we run the model for more and more requests (i.e. perform Monte Carlo simulation on the uncontrollable and semi-controllable variables in the model), we will get more and more reliable distribution of cost deviations from optimal, giving us better insight for making decisions about how many machines and how much and what level of labor to have on-hand to mitigate risk and reduce costs.
However, we want to run only just enough number of requests through the model to gain some desired degree of confidence that estimates of the deviations from optimal are within a certain acceptable range. The number of requests that must be run through to achieve that confidence can be minimized by using various sampling methods such as regeneration principle, stratified sampling, and estimate convergence detection. These methods are not currently built into NMOD, but they are planned for future versions.
|
Click to go to Chapter 19: Seeing concepts in action in PrimerSig's feedback file |
|
Click to go to Chapter 21: Expressing spreadsheets in terms of logical networks |
|
Click to go to Introduction: NMOD Primer |