- PROGRAM
- DEFINITION
- CONTROL
- LOGIC
- END.
- PROGRAM
- “Title of program can be typed here”
- DEFINITION – This is where you define everything.
- RESOURCES – Things that do the work and can be seized, to the exclusion of others:
- loader1: RESOURCE = {CAPACITY = 3, QUEUE = line3}; “Generate a resource named loader1, which will do work on entities as they come through the system, and which can be seized by the entities to the exclusion of other entities. This resource has the ability to handle 3 customers at once, and uses a non-standard queue (specified as bigline.) The special queue must have been previously defined above this statement.”loader2: RESOURCE = {CAPACITY = 6}; “Generate a resource which can handle 6 trucks at once, using a standard unnamed default queue having unlimited space.”
- loader3: RESOURCE = { }; “Generate a resource with a default capacity = 1, using a standard (unnamed) queue having unlimited room to stand in line”
- GATES – Things that open and close, and block the progress of entities:
- gate1: GATE = {STATUS = CLOSE, DISCIPLINE = FIFO}; “Generate a gate, which can be used to stop the flow of entities if closed. The gate can be born closed, as here, or open, and can release entities FIFO or LIFO.”
- LABELS – Code line indicators – gives you the ability to have your customer skip lines of code you don’t want them to read:
- LABELS = {starthere, checkgate, stuckintraffic, goleft, gostraight, firstline, line1}; “Places (lines of code) to branch to in the program. Labels are actually line labels, such as line1. This could be a line label. A label is a line identifier like a street address. For example if I told you to GOTO 2117 Texas Ave. you would know exactly where to go. If I told you to go to Room 217, you would know exactly where to go. Similarly if you tell an entity to GOTO line1, that’s what he will do – transfer control to the line of code preceded by the label line1: Label names MUST be preceded by a letter, i.e. a810 is a legal label name, whereas 810 is not.
- LOCAL AND GLOBAL VARIABLES – Local variables (ATTRIBUTES) are personalized variables, accessible only to an individual entity. Global variables are community property, and are accessible to all entities.
- ATTRIBUTES = {wantstoturnleft = 0, size = 1, color = 5}; “wantstoturnleft, size and color are attributes (local variable names) made up by the programmer. An attribute is a “personal” variable, and every entity born has his own personal value. In this case, as entities are born they will all be born with the following (for example) personal attributes: they don’t want to turn left (wantstoturnleft=0), they are the size of a car (size=1), and they are blue (color=5). If you ran an entity past the statement: size = 2, then that entity, and that entity only would have its size changed to the size of a truck (size = 2.) All other entities would remain unchanged.”
- moneymade = 400; “A global variable name made up by the programmer, and initialized as 400. A global variable is one that can be viewed and changed by any entity running around in the system. Thus if an entity later came by and was told moneymade = moneymade + 40, he would change moneymade to 440. Then if a second entity came by and was told the same thing, moneymade would be changed to 480.”
- payperload = 36.1; “Another global variable name”
- RESOURCES – Things that do the work and can be seized, to the exclusion of others:
- CONTROL – How to tell the computer program how long to run, etc.
- STOPTIME = 240; “How many units of time you wish to run the simulation. Here, the simulation will run 240 nanoseconds, or 240 days, or whatever. This is where, in effect, you set the units of time for the model. Every other time in the model must agree with the units used here.”
- LOGIC – How you tell the computer what to do:
- THE ARRIVE STATEMENT – Bringing entities into the system to work for you:
- ARRIVE{TIME = CUNIFORM(0.5,6.5)}; “Borns multiple entities (people, policemen, cars, trucks, computers, etc.) wherein their interarrival times form a continuous uniform distribution between 0.5 and 6.5 seconds, or minutes, or eons. Additional entities continue to be born using this distribution as long as the simulation runs.”
- ARRIVE{TIME = EXPD(2)}; “Borns repetitive entities having an exponential distribution with a mean of 2 days. Additional entities continue to be born as long as the simulation runs.”
- ARRIVE{TIME = 0, LIMIT = 6}; “Note you MUST put a LIMIT here!!! Borns 6 entities at the beginning of the simulation, at time = 0 minutes, then quits borning entities.”
- ARRIVE{TIME = 8}; “Borns repetitive entities, one every 8.00000 days, exactly.”
- ARRIVE{TIME = 0 MAX NORMAL(20,6)}; “Borns repetitive entities with a normal distribution having a mean of 20 seconds and a sigma of 6 seconds, for as long as the simulation continues.”
- ARRIVE{TIME = 0 MAX NORMAL(20,6), LIMIT = 32}; “Borns repetitive entities with a normal distribution having a mean of 20 seconds and a sigma of 6 seconds, for as long as the simulation continues or until a maximum of 32 entities have been generated, whichever comes first. The 0 MAX is used to insure that a negative interarrival time is not generated.”
- ARRIVE{TIME = NORMAL(500,3)}; “Probably ok, since 500-3*3 is pretty far from negative.”
- ARRIVE{TIME = NORMAL(5,2)}: “Note: VERY DANGEROUS! Will probably crash the system.”
- SEIZING RESOURCES TO THE EXCLUSION OF OTHER ENTITIES:
- SEIZE{NAME = loader1}; “This tells the entity who read the statement to seize one unit of capacity from the resource loader1, if possible. If not possible because all of loader1’s capacity is in use, stand in the default queue associated with loader1 until able to do so.”
- SEIZE{NAME = loader2, UNITS = 2}; “Seize 2 UNITS from loader2 if available, and stand in the default queue associated with loader2 until able to do so.”
- SEIZE{NAME = loader3, UNITS = 2, REXCESS = ifresourceisbusy, QEXCESS = ifqueueisfull }; “Seize 2 UNITS from loader3 if possible. If the resource is busy, or if you cannot get the 2 requested units then go to the line of code labeled ifresourceisbusy:, and if the queue is full go to ifqueueisfull:. Note that to use QEXCESS, the queue associated with loader2 MUST be a special “named” queue, since un-named queues have, by default, infinite capacity, and hence cannot get full, and will thus never appear to get full. The REXCESS can be used to send entities to special lines of code where they can be given special consideration if they are unwilling to wait in line. For example they can be DEPARTed, they can be sent to do something else while the line gets shorter and then come back later, etc.”
- RELEASE – Releasing the resource so others can use it after you are through with it:
- RELEASE{NAME = loader1}; “After having seized the resource named loader1, release it so other entities can use it.”
- RELEASE{NAME = loader2, UNITS = 2}; “After having seized two units from the resource named loader2, release them so other entities can use them. Note that if you have someone SEIZE a resource, they must release it before DEPARTing.”
- WAIT – Waiting while something gets done:
- WAIT{TIME = 1}; “Tell the entity which reads this line to wait 1 year (month, nanosecond, etc.)before proceeding to the next line.”
- WAIT{TIME = CUNIFORM(9,11)}; “Tell the entity to wait a continuous random time, between 9 and 11 seconds. The result will be for her to wait 9.11, 10.47, 10.99 nanoseconds, etc.”
- WAIT{TIME = DUNIFORM(9,11)}; “Tell the entity to wait a discrete random time, between 9 and 11. The result will be 9, 10, 10, 11, 9, 11, etc.”
- WAIT{TIME = 0 MAX NORMAL(10,2)}; “Wait for a random time, normally distributed, with a mean of 10, and a sigma of 2.”
- WAIT{TIME = EXPD(3)}; “Wait for a random time, exponentially distributed, with a mean of 3.”
- WAIT{TIME = 3 + EXPD(2) + repairtime}; “Wait for some appropriate time.”
- CLOCKTIME – Seeing what time it is during the simulation:
- time1 = CLOCKTIME; “Look up at the master clock on the wall and see what time it is now, and store it under the variable named time1.”
- time2 = CLOCKTIME; “Look up at the master clock and see what time it is now.”
- GENERAL CALCULATIONS:
- timeittook = time2 – time1; “Compute how long it took to do the preceding lines.”
- cost = cost + 300*(time2-time1); Cost is a variable, either local (an attribute) or global. If you initialized it in the DEFINITION block using cost = 0, it is global. If you initialized it in the DEFINITION block using an ATTRIBUTES = {cost}; then it is local, and there is one personal “cost” for every entity.
- value = EXP(LN(LOG10(SQR(SQRT(ABS(FLOOR(junk))))))); “Takes the exp of the natural log of the log base 10 of the squared of the square root of the absolute value of the floor of junk and puts it in value.”
- FLOW CONTROL – Testing and directing entities to locations depending on what is happening in the model:
- IF statementistrue THEN GOTO trueline ELSE GOTO falseline (This branches to trueline if statementistrue is true, and branches to falseline if statementistrue is false.)
- IF statementistrue THEN GOTO trueline (This branches to trueline if statementistrue is true, and if statementistrue is false, drops down to the next statement immediately below this one.
- IF USED[counter1:QUEUE] <= USED[counter2:QUEUE] THEN GOTO getcounter1 ELSE GOTO getcounter2; “This statement tests the number of people in counter1’s default queue, to see if it is currently smaller than the number of people in counter2’s default queue. If so, the entity is directed to go to the line of code labeled getcounter1, and if not he is sent to getcounter2. Note that here the queues are default, standard, unnamed queues.”
- IF((junk1 > junk2) AND ((a<b) OR (a>junk2))) THEN a = b ELSE a = 2*b; “Logical assignment. Note use of parentheses WHICH ARE REQUIRED!”
- IF((junk1 > junk2) AND ((a=b) OR (a>junk2))) THEN GOTO label1; “Logical branch.”
- IF cars > 2 THEN SETGATE{NAME=cargate, STATUS=CLOSED} ELSE GOTO gate1;
- IF junk1 < junk2 THEN GOTO cat;
- IF turnleft = 1 THEN GOTO leftturn ELSE GOTO straight; “If logical branch.”
- GOTO leftturnlabel; “Direct the entity to go to the line of code labeled leftturnlabel .”
- LABELS – Using labels on lines of code, to identify where you want your customer to go for the next command.:
- leftturnlabel: a = a+b; “A line of code labeled leftturnlabel, where an entity can be sent.”
- straightlabel: a = a-b;
- DEPART – Removing the entity from the system after you are finished with it:
- DEPART{ }; “Departs the entity, releasing its memory back to the memory pool.”
- GATES – Things such as red lights that can be opened and closed. Used to impede (appropriately) the progress of entities:
- SETGATE{NAME = gate1, STATUS = OPEN/CLOSE/INVERT}; “Opens and closes a gate named gate1.”
- TESTGATE{NAME = dog}; “Tests to see if the gate named dog is open. If so, proceed to the next line of code. If not, stay behind the gate, continuously checking its status, and do not proceed until someone, somewhere, opens it.”
- TESTGATE{NAME = gate1, IFCLOSED = gohere}; “Tests to see if gate1 is open. If so, proceed to the next line of code. If not, send the entity to the line of code labeled gohere. IFCLOSED can be used to send the entity to a gohere: WAIT=1; timedelay = timedelay+1; GOTO backwhereicamefrom loop to count how many minutes the entity had to wait for the gate to open.
END. “Note the period at the end of the END statement. It is required.”
- THE ARRIVE STATEMENT – Bringing entities into the system to work for you:
Typical Output:
MOR/DS 1.00
Date: 4/13/99 Time: 18:39:11
E:\JUNK1\bestmac1.txt
MODEL DESCRIPTION
****************************************************
PROGRAM
“McDondalds with two counters – simple, default que”
“d:\homework\422\bestmac1.bos”
“Last run 4/11/99 – uses valid queue statements”
DEFINITION
counter1:RESOURCE = {};
counter2:RESOURCE = {};
LABELS = {getcounter1,getcounter2};
CONTROL
STOPTIME=240;
WATCHLIST = {counter1,counter2};
LOGIC
[ 1] ARRIVE {TIME=CUNIFORM(0.5,1)}; [ 2] IF USED[counter1:QUEUE] <= USED[counter2:QUEUE] [ 3] THEN GOTO getcounter1 [ 4] ELSE GOTO getcounter2; [ 5]getcounter1: SEIZE {NAME = counter1}; [ 6] WAIT {TIME = 30 + EXPD(22)}; [ 7] RELEASE {NAME = counter1}; [ 8] DEPART{ }; [ 9] [ 10]getcounter2: SEIZE{NAME = counter2}; [ 11] WAIT {TIME = 0 MAX NORMAL(3,2)}; [ 12] RELEASE {NAME = counter2}; [ 13] DEPART{ }; [ 14 END.—————————————————-
Simulation Clock : 240.00
Block Information
___Stmt___Line______Label________Name___Total___Current
1 1 ARRIVE 318 1
2 2 IF 317 0
3 3 GOTO 120 0
4 4 GOTO 197 0
5 5 GETCOUNTER SEIZE 120 114
6 6 WAIT 6 1
7 7 RELEASE 5 0
8 8 DEPART 5 5
9 10 GETCOUNTER SEIZE 197 113
10 11 WAIT 84 1
11 12 RELEASE 83 0
12 13 DEPART 83 83