|
- 10 REM CPM-PERT PROGRAM FROM INTERFACE AGE, FEB. 1981
- 12 REM WRITTEN BY RICHARD PARRY
- 14 REM ADAPTED TO MICROSOFT BASIC BY CHARLES H STROM
- 16 REM
- 17 REM NOTE: PRINTER OPERATION REQUIRES LOADING SETUP.ASM BEFORE MBASIC
- 18 REM *INITIALIZE NORMAL DISTRIBUTION CONSTANTS
- 20 RN=15: RS=SQR(3/RN)
- 25 CL$=CHR$(27)+CHR$(28): REM CHARACTER STRING TO HOME CURSOR & CLEAR SCREEN
- 30 REM **************
- 40 REM * INPUT DATA *
- 50 REM **************
- 55 PRINT CL$
- 60 INPUT "CPM or PERT Simulation (C/P) "; Q$
- 65 INPUT "Do you want a HARD-COPY record (Y/N)"; HC$: HC$=LEFT$(HC$,1)
- 66 IF HC$="Y"THEN PRINT "NOTE - SETUP.ASM MUST BE LOADED BEFORE MBASIC OR PRINTER WILL NOT FUNCTION!"
- 68 PRINT
- 70 INPUT "Number of Activities"; N
- 80 DIM ML(N), MO(N), MP(N), CP(N), ME(N), SD(N), IC(20)
- 90 DIM S(N), F(N), D(N), E(N), L(N), F1(N)
- 100 FOR I=1 TO N
- 110 PRINT CL$: PRINT "ACTIVITY"; I: PRINT
- 120 REM * GO TO INPUT DATA ROUTINE
- 130 GOSUB 1920
- 140 NEXT I
- 150 PRINT CL$: INPUT "Would you like to examine or edit the input data (Y/N)";Q1$
- 160 IF LEFT$(Q1$,1) = "N" THEN 430
- 170 REM *SORT INPUT DATA
- 180 GOSUB 2080
- 190 REM **********************
- 200 REM * DISPLAY INPUT DATA *
- 210 REM **********************
- 215 IF HC$="Y" THEN POKE 37,195
- 220 PRINT CL$: IF LEFT$(Q$,1)<>"C" THEN 280
- 230 PRINT "ACTIVITY # FROM TO DURATION"
- 240 FOR I = 1 TO N
- 250 PRINT TAB(5); I; TAB(15); S(I); TAB(25); F(I); TAB(35); D(I)
- 260 NEXT I
- 270 GOTO 340
- 280 PRINT "ACTIVITY # FROM TO ML MO MP"
- 290 FOR I = 1 TO N
- 300 PRINT TAB(5); I; TAB(15); S(I); TAB(25); F(I);
- 310 PRINT TAB(35); ML(I); TAB(45); MO(I); TAB(55); MP(I)
- 320 NEXT I
- 330 PRINT
- 340 POKE 37,201:PRINT: INPUT "Would you like to edit an activity (Y/N)"; Q1$
- 350 IF LEFT$(Q1$,1) = "N" THEN 430
- 360 REM * EDIT MODE
- 370 PRINT: INPUT "What activity needs alteration (0 to end)"; I
- 380 IF I=0 THEN 150
- 390 REM * GO TO INPUT DATA ROUTINE
- 400 GOSUB 1920
- 410 GOTO 370
- 420 REM * GO TO SORT ROUTINE
- 430 GOSUB 2080
- 440 IF LEFT$(Q$,1) <>"C" THEN 760
- 450 REM ***********************************************************
- 460 REM * CRITICAL PATH ANALYSIS REQUESTED. PERFORM CRITICAL PATH *
- 470 REM * ANALYSIS ONCE AND DISPLAY RESULTS. *
- 480 REM ***********************************************************
- 490 GOSUB 2340
- 500 C2=0
- 505 IF HC$="Y" THEN POKE 37,195
- 510 PRINT CL$: PRINT "CP ANALYSIS IS:"
- 520 PRINT: PRINT: PRINT "FROM","TO","EST","LFT","FLOAT": PRINT
- 530 FOR I = 1 TO N
- 540 PRINT S(I),F(I),E(S(I)),L(F(I)),F1(I)
- 550 NEXT I
- 560 PRINT "THE CRITICAL PATH LENGTH IS ";PL
- 570 PRINT: PRINT "THE CRITICAL PATH IS:": PRINT"FROM","TO": PRINT
- 580 FOR I = 1 TO N
- 590 IF F1(I) = 0 THEN 610
- 600 NEXT I
- 610 PRINT S(I),F(I): C2=C2+1: IF I>N THEN 650
- 620 FOR M= 1 TO N
- 630 IF S(M)=F(I) AND F1(M) = 0 THEN I=M: GOTO 610
- 640 NEXT M
- 650 IF C1<>C2 THEN PRINT: PRINT "THERE IS MORE THAN ONE CRITICAL PATH"
- 660 PRINT: POKE 37,201
- 670 INPUT "Would you like to edit an activity or stop program (E/S)"; Q1$
- 680 IF LEFT$(Q1$,1) = "E" THEN PRINT: GOTO 220:
- 690 END
- 700 REM *****************************************************************
- 710 REM * PERT SIMULATION REQUESTED. PERFORM CRITICAL PATH ANALYSIS THE *
- 720 REM * NUMBER OF TIMES SPECIFIED. STORE PATH LENGTHS AND INCREMENT *
- 730 REM * ACTIVITIES WHICH APPEAR ON CRITICAL PATH. CONSTRUCT HISTOGRAM *
- 740 REM * AND DISPLAY RESULTS. *
- 750 REM *****************************************************************
- 760 FOR I = 1 TO N
- 770 REM * COMPUTE MEAN OF EACH ACTIVITY
- 780 ME(I) = (MO(I)+4*ML(I)+MP(I))/6
- 790 REM * COMPUTE STANDARD DEVIATION OF EACH ACTIVITY
- 800 SD(I) = (MP(I)-MO(I))/6
- 810 NEXT I
- 820 REM * COMPUTE MOST OPTIMISTIC PATH LENGTH
- 830 DU=0: FOR I=1 TO N: CP(I)=0: E(I)=0: L(I)=0: NEXT I
- 840 FOR I = 1 TO N
- 850 D(I)=MO(I)
- 860 NEXT I
- 870 GOSUB 2340
- 880 BC=PL
- 890 REM * COMPUTE MOST PESSIMISTIC PATH LENGTH
- 900 DU=0: FOR I=1 TO N: CP(I)=0: E(I)=0: L(I)=0: NEXT I
- 910 FOR I = 1 TO N
- 920 D(I)=MP(I)
- 930 NEXT I
- 940 GOSUB 2340
- 950 WC=PL
- 960 REM * INITIALIZ KEY VARIABLES
- 970 DU=0: FOR I = 1 TO N: CP(I)=0: E(I)=0: L(I)=0: NEXT I
- 980 LS=0: HS=0: FOR I=1 TO 20: IC(I)=0: NEXT I
- 990 REM * INITIALIZE RANDOM NUMBER GENERATOR
- 1000 RANDOMIZE
- 1010 REM * PROPOSE # OF TRANSACTIONS AS 20 TIMES # OF ACTIVITIES
- 1020 PRINT "Number of transactions should be >= "; 20*N
- 1030 INPUT "Number of transactions"; NS
- 1040 PRINT: PRINT "++SIMULATION IN PROGRESS++"
- 1050 REM ***********************
- 1060 REM * CONSTRUCT HISTOGRAM *
- 1070 REM ***********************
- 1080 REM * SET APPROPRIATE INTERVAL (I.E. INTEGER >=1)
- 1090 LL=INT(BC)
- 1100 IF WC-BC<=20 THEN IN=1
- 1110 IN=INT((WC-BC)/20)+1
- 1120 REM **********************
- 1130 REM * PERFORM SIMULATION *
- 1140 REM **********************
- 1150 TC=100
- 1160 FOR K=1 TO NS
- 1170 IF K=TC THEN PRINT "++SIMULATION IN PROGRESS++", TC: TC=TC+100
- 1180 FOR J=1 TO N
- 1190 S=0: E(J)=0: L(J)=0
- 1200 IF ML(J)=0 THEN D(J)=0: GOTO 1250
- 1210 FOR I=1 TO RN
- 1220 S=S+2*RND-1
- 1230 NEXT I
- 1240 D(J)=ME(J)+SD(J)*S*RS
- 1250 NEXT J
- 1260 GOSUB 2340
- 1270 REM * FIND INTERVAL FOR THIS PATH LENGTH
- 1280 I3=(PL-LL)/IN+2
- 1290 IF I3<1 THEN LS=LS+1: GOTO 1330
- 1300 IF I3>20 THEN HS=HS+1: GOTO 1330
- 1310 I3=INT(I3)
- 1320 IC(I3)=IC(I3)+1
- 1330 NEXT K
- 1340 REM **************************************
- 1350 REM * PRINT FREQUENCY DISTRIBUTION TABLE *
- 1360 REM **************************************
- 1365 IF HC$="Y" THEN POKE 37,195
- 1370 PRINT CL$: PRINT "++FREQUENCY DISTRIBUTION TABLE++": PRINT
- 1380 PRINT "Most OPTIMISTIC path length"; BC
- 1390 PRINT "Most PESSIMISTIC path length"; WC
- 1400 PRINT "Number of transactions LOWER than histogram range ";LS
- 1410 PRINT "Number of transactions HIGHER than histogram range ";HS: PRINT
- 1420 PRINT " INTERVAL FREQ. PCT."
- 1430 I1=LL-IN: I2=LL
- 1440 FOR M=1 TO 20
- 1450 PRINT"=>";I1;"<";I2;TAB(20);IC(M);TAB(30);INT(.5+100*IC(M)/NS)
- 1460 I1=I1+IN: I2=I2+IN
- 1470 NEXT M
- 1480 REM *******************
- 1490 REM * PRINT HISTOGRAM *
- 1500 REM *******************
- 1510 REM * COMPUTE HISTOGRAM SCALE FACTOR
- 1520 SC=0: LO=18: J=0: LL=INT(BC)
- 1530 FOR M=1 TO 20
- 1540 IF IC(M)>SC THEN SC=IC(M)
- 1550 NEXT M
- 1560 SC=50/SC
- 1570 X$="PATH LENGTH"
- 1580 PRINT: PRINT: PRINT TAB(24); "++ HISTOGRAM ++": PRINT
- 1590 PRINT TAB(18);"RELATIVE FREQUENCY OF PATH LENGTHS"
- 1600 PRINT TAB(LO); "+------------------------------------------------+"
- 1610 FOR M=1 TO 20
- 1620 HM=IC(M)*SC
- 1630 FOR K=1 TO 3
- 1640 J=J+1: PRINT MID$(X$,J,1);TAB(2);
- 1650 IF K=2 THEN PRINT ">=";LL-IN;"<";LL;: LL=LL+IN
- 1660 PRINT TAB(LO);
- 1670 IF IC(M)=0 THEN PRINT: GOTO 1720
- 1680 FOR I=1 TO HM
- 1690 PRINT "*";
- 1700 NEXT I
- 1710 PRINT
- 1720 NEXT K
- 1730 NEXT M
- 1740 REM ***************************
- 1750 REM * PRINT ACTIVITY ANALYSIS *
- 1760 REM ***************************
- 1770 PRINT: PRINT
- 1780 PRINT TAB(10); "+++ CP ACTIVITY ANALYSIS TABLE +++": PRINT
- 1790 PRINT "ACTIVITY # FROM TO CP FREQ. PCT."
- 1800 FOR I=1 TO N
- 1810 PRINT TAB(5);I;TAB(15);S(I);TAB(25);F(I);
- 1820 PRINT TAB(35);CP(I);TAB(45);INT(.5+100*CP(I)/NS)
- 1830 NEXT I
- 1840 PRINT: PRINT "DUPLICATE critical paths occurred";DU;"times."
- 1850 PRINT: POKE 37,201
- 1860 INPUT "Would you like to edit an activity or stop program (E/S)"; Q1$
- 1870 IF LEFT$(Q1$,1)="E" THEN PRINT: GOTO 220
- 1880 END
- 1890 REM **********************
- 1900 REM * INPUT DATA ROUTINE *
- 1910 REM **********************
- 1920 INPUT "FROM";S(I)
- 1930 INPUT "TO";F(I)
- 1940 IF F(I)>N THEN PRINT "++END NODE # NOT <= # OF ACTIVITIES++":GOTO 1930
- 1950 IF S(I)>F(I) THEN PRINT "++START NODE MUST BE < END NODE++":GOTO 1920
- 1960 IF LEFT$(Q$,1)="C" THEN INPUT "DURATION";D(I): GOTO 2040
- 1970 INPUT "MOST LIKELY";ML(I)
- 1980 REM * CHECK FOR DUMMY ACTIVITY
- 1990 IF ML(I)=0 THEN MO(I)=0: MP(I)=0: GOTO 2040
- 2000 INPUT "MOST OPTIMISTIC"; MO(I)
- 2010 IF MO(I)>ML(I) THEN PRINT "++MO MUST BE <= ML++": GOTO 2000
- 2020 INPUT "MOST PESSIMISTIC"; MP(I)
- 2030 IF MP(I)<ML(I) THEN PRINT "++MP MUST BE >= ML++": GOTO 2020
- 2040 RETURN
- 2050 REM *************************************
- 2060 REM * SORT DATA USING START NODE AS KEY *
- 2070 REM *************************************
- 2080 PRINT: PRINT "SORTING IN PROGRESS": PRINT
- 2090 SW=0
- 2100 FOR I=1 TO N-1
- 2110 J=I+1
- 2120 IF S(I)<=S(J) THEN 2200
- 2130 EX=S(I): S(I)=S(J): S(J)=EX
- 2140 EX=F(I): F(I)=F(J): F(J)=EX
- 2150 EX=D(I): D(I)=D(J): D(J)=EX
- 2160 EX=ML(I): ML(I)=ML(J): ML(J)=EX
- 2170 EX=MO(I): MO(I)=MO(J): MO(J)=EX
- 2180 EX=MP(I): MP(I)=MP(J): MP(J)=EX
- 2190 SW=1
- 2200 NEXT I
- 2210 IF SW=1 THEN 2090
- 2220 RETURN
- 2230 REM *************************************************************
- 2240 REM * THE FOLLOWING SUBROUTINE IS USED BY BOTH THE CPM ANALYSIS *
- 2250 REM * AS WELL AS THE PERT SIMULATION ANALYSIS. WHILE THE CPM *
- 2260 REM * ANALYSIS CALLS THE ROUTINE ONLY ONCE, THE SIMULATION *
- 2270 REM * CALLS THE ROUTINE THE NUMBER OF TIMES REQUESTED BY THE *
- 2280 REM * USER. THE EARLIEST, LATEST, AND FLOAT TIMES ARE COMPUTED *
- 2290 REM * AND FROM THIS DATA THE CRITICAL PATH LENGTH AND CRITICAL *
- 2300 REM * PATH ARE CALCULATED. DUPLICATE CRITICAL PATHS ARE ONLY *
- 2310 REM * COUNTED ONCE. *
- 2320 REM *************************************************************
- 2330 REM * COMPUTE EARLIEST STARTING TIME
- 2340 C1=0: C2=0: PL=0
- 2350 FOR I=1 TO N
- 2360 M1=E(S(I))+D(I)
- 2370 IF E(F(I))<=M1 THEN E(F(I))=M1
- 2380 NEXT I
- 2390 REM * COMPUTE LATEST FINISHING TIME
- 2400 L(F(N))=E(F(N))
- 2410 FOR I=N TO 1 STEP -1
- 2420 L1=S(I): M2=L(F(I))-D(I)
- 2430 IF L(L1)>=M2 OR L(L1)=0 THEN L(L1)=M2
- 2440 NEXT I
- 2450 REM * COMPUTE FLOAT TIME
- 2460 FOR I=1 TO N
- 2470 F1(I)=L(F(I))-E(S(I))-D(I)
- 2480 IF F1(I)<.0001 THEN F1(I)=0: C1=C1+1
- 2490 NEXT I
- 2500 REM * COMPUTE CRITICAL PATH LENGTH
- 2510 FOR I=1 TO N
- 2520 IF L(F(I))>PL THEN PL=L(F(I))
- 2530 NEXT I
- 2540 REM * COMPUTE CRITICAL PATH
- 2550 FOR I=1 TO N
- 2560 IF F1(I)=0 THEN 2580
- 2570 NEXT I
- 2580 C2=C2+1: CP(I)=CP(I)+1
- 2590 IF I>N THEN 2630
- 2600 FOR M=1 TO N
- 2610 IF S(M)=F(I) AND F1(M)=0 THEN I=M: GOTO 2580
- 2620 NEXT M
- 2630 IF C1<>C2 THEN DU=DU+1
- 2640 RETURN
|