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++": 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