#!/usr/bin/perl print qq§Content-Type: text/html §;

In Anlehnung an die Problemstellung der Autoren Prof. Sieghart Ocker, StD. Lothar Schöttle und StD. Werner Simon in ihrem Buch Informatik - Algorithmen und ihre Programmierung[1] wird im Folgenden die Simulation von Warteschlangen auf der Ebene der Cobol - Programmierung durchgeführt.


Folgende Problemstellung wird im Weiteren die Programmierung beeinflussen :

Problemstellung : In den Schalterraum einer Bank kommen pro Minute durchschnittlich vier Kunden und stellen sich an demjenigen Schalter an, vor dem die wenigsten Leute stehen.

Die Anzahl der geöffneten Schalter variiert, daher wird diese vom Anwender eingegeben. Da auch die Dauer im wesentlichen von vielerlei Faktoren abhängig ist, soll auch sie eine frei wählbare Variable darstellen.

Während der Simulation sind wichtige Auswertungskriterien festzuhalten :
1. Wann hat der Kunde die Schalterhalle / den Schalter betreten ?
2. Welchen Schalter hat der Kunde gewählt, also welcher Schalter hat zum Zeitpunkt des Eintritts die kleinste Anzahl von wartenden Kunden ?
3. Wie lange muß der Kunde bis zu seiner Bedienung warten ?
4. Wann verläßt der Kunde die Schalter ?

Für den Auswertenden ist es ferner von Interesse, bei Beendigung des Programms
1. einen Überblick über die von ihm gewählte Zeitspanne,
2. die Anzahl der in dieser Zeit gekommenen Kunden,
3. Durchschnittswerte über die Wartezeit der Kunden und
4. einen Durchschnittswert über die Länge der Warteschlange zu erhalten. Diese Werte gilt es also auszugeben und als Programmvariablen zu speichern.

Aus Vereinfachungsgründen wird die gegebene Zeitspanne in Zeiteinheiten (ZE) zerlegt. Außerdem nehmen wir an, daß nur zu Beginn einer solchen Zeiteinheit der Schalter betreten und entsprechend am Ende einer Zeiteinheit verlassen wird. Es betritt immer nur ein Kunde die Schalterhalle. Als Zeiteinheit gilt : eine ZE = 5 Sekunden.
Die Wahrscheinlichkeit, daß ein Kunde die Halle betritt beträgt 1/3. Es kommt folglich alle 3 Zeiteinheiten zu einem Eintritt. Die Bedienungszeit wird folgenden relativen Häufigkeiten zugeordnet.

Bedienungszeit

4 ZE

6 ZE

8 ZE

10 ZE

12 ZE

14 ZE

16 ZE

relative Häufigkeit

0,1

0,1

0,2

0,2

0,2

0,1

0,1


Die Verarbeitung der Daten soll kurz mit folgenden Schaubild erläutert werden :


Schalter
1

Schalter
2

Schalter
3

Schalter
4

Schalter
5

Zustand

Kunden-

position 1

4

1

0

0

0

wird bedient

Kunden-

position 2

12

6

0

0

0

wartet

Kunden-

position 3

0

14

0

0

0

wartet

Kunden-

position 4

0

0

0

0

0

wartet

Kunden-

position 5

0

0

0

0

0

wartet

...

...

...

...

...

...

...


An Schalter 1 steht ein Kunde, dessen Bedienung noch 4 Zeiteinheiten andauert, hinter diesem Kunden wartet ein zweiter ; seine Bedienung wir 12 Zeiteinheiten in Anspruch nehmen. An Schalter 2 stehen drei Kunden. Der erste wird in 1 Zeiteinheit bedient sein, seine Nachfolger werden den gleichen Schalter jeweils für 6 bzw. 14 Zeiteinheiten in Anspruch nehmen. Für den dritten Kunden bedeutet dies : "Ich muß noch 7 Zeiteinheiten warten".


Nach Ablauf einer Zeiteinheit werden die Zeiteinheiten in der ersten Zeile um 1 verringert. Im o.a. Beispiel würde sich bei Schalter 2 dann 0 ergeben, d.h. der Schalter wäre für den folgenden Kunden frei. Kunde 2 wird Kunde 1, Kunde 3 zu Kunde 2 und Kunde 3 wird mit einer NULL ausgefüllt.
Der folgende Code bietet die Ausarbeitung des oben beschriebenen Problems. Wörter die fest zum COBOL-Wortschatz gehören sind schwarz, Variablen und von mir eingefügte Klauseln sind blau hervorgehoben. Interne Unterprogramme habe ich rot eingefärbt, Divisionen grün. Der Übersicht halber ist folgende Programmstruktur stark verkürzt.

HAUPTSEGMENT : WSCHLANGE


$SET ANS85
IDENTIFICATION DIVISION.
PROGRAM-ID. Simulation von Warteschlangen.
AUTHOR. Richard Kiewert.
DATE-WRITTEN. 12.06.98.
DATE-COMPILED. 12.06.98.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
DECIMAL-POINT IS COMMA.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 Bedienungszeit.
05 Kunde occurs 5.
10 Schalter PIC 99 Occurs 20.
01 kundenzahl PIC 99 Occurs 50 value 0.
01 Schlangenlaenge PIC 99V9 Occurs 50.
01 A-Schlangenlaenge PIC Z9,9 Occurs 50 just right.
01 Wartesumme PIC 99999V9 Value 0.
01 A-Wartesumme PIC ZZZZ9,9.
01 Wartezeit PIC 999 value 0.
01 Kundensumme PIC 999 value 0.
01 A-Kundensumme PIC ZZ9,9.

01 Schalterzahl PIC 9 value 0.
01 E-Zeiteinheiten PIC Z9.
01 Zeiteinheiten PIC 99 value 0.
01 A-Zeiteinheiten PIC Z9,9.
01 Zeitzaehler PIC 99 VALUE 1.
01 Kundennr PIC 99 Value 1.
01 Schalternr PIC 99 Value 1.
01 A-Schalternr PIC Z9 Value 1.
01 Zufall PIC 999v999.
01 Bedienungsdauer PIC 99 value 0.
01 kuerzeste-Schlange PIC 99 value 0.
01 Cursor-Position PIC 9999 Value 0201.
01 dummy PIC x.
01 Ausgabezeile.
05 FILLER PIC XXXXXX.
05 A-Zeitzaehler PIC 99.
05 FILLER PIC XXXXXXXXXXX.
05 A-kuerzeste-Schlange PIC 99.
05 FILLER PIC XXXXXXXXXXX.
05 A-Wartezeit PIC 99.
05 FILLER PIC XXXXXXXXXXX.
05 A-Bedienungsdauer PIC 99.
PROCEDURE DIVISION.
display space upon crt.
display "**************************************" at 1020.
display "* *" at 1120.
display "* S I M U L A T I O N *" at 1220.
display "* V O N *" at 1320.
display "* W A R T E S C H L A N G E N *" at 1420.
display "* *" at 1520.
display "* von Richard F. Kiewert, BA196i *" at 1620.
display "* *" at 1720.
display "**************************************" at 1820.
display " Taste ..." at 2020.
accept dummy at 0101.


perform Eingabe.
display space upon crt.
move 1 to Zeitzaehler.
PERFORM SIMULATION UNTIL Zeitzaehler > ZEITEINHEITEN.
Perform Ausgabe.
stop run.
Eingabe.
display space upon crt.
display "Wieviele Schalter hat die Bank (1 - 5) :" at 0513
accept Schalterzahl at 0560.
if schalterzahl < 1 or > 5 then
display "ACHTUNG : Es sind nur Zahlen von 1 bis 5 erlaubt." at
0613
display "Taste ..." at 2165
accept dummy
go to Eingabe
end-if.
display "Wie viele Zeiteinheiten (max. 20) :"
at 0713.
accept E-Zeiteinheiten at 0759.
move E-Zeiteinheiten to Zeiteinheiten.
If Zeiteinheiten < 1 or > 21 then
display "ACHTUNG : Es sind nur Zahlen von 1 bis 20 erlaubt." at
0812
display "Taste ..." at 2165
accept dummy
display space upon crt
go to Eingabe
end-if.
SIMULATION.
display "Zeit in ZE Schalter Wartezeit Bedienungszeit"
at 0102.
move 0 to zufall.
call "zufallsz" using zufall.
Cancel "zufallsz".
compute zufall = zufall / 10.
If zufall < 0,33 then
ADD 1 to Kundensumme
Perform ZeitBedienung
Perform Schlange
Perform Warten
move Zeitzaehler to A-Zeitzaehler
move kuerzeste-Schlange to A-kuerzeste-schlange
move Wartezeit to A-Wartezeit
move Bedienungsdauer to A-Bedienungsdauer
display Ausgabezeile at Cursor-Position
add 100 to Cursor-Position
END-IF.
move 1 to schalternr.
perform until schalternr > Schalterzahl
IF Kundenzahl (schalternr) > 0 THEN
add Kundenzahl(schalternr) to Schlangenlaenge(schalternr)
subtract 1 from Schalter(schalternr, 1)
IF Schalter(schalternr, 1) = 0 THEN
Perform Kunden-nachruecken
END-IF
END-IF

add 1 to SCHALTERNR
END-PERFORM.
add 1 To Zeitzaehler.
ZeitBedienung.
move 0 to zufall.
call "zufallsz" using zufall.
cancel "Zufallsz". compute zufall = zufall / 10.
Evaluate Zufall
when 0,00 thru 0,1 move 4 to Bedienungsdauer
when 0,11 thru 0,2 move 6 to Bedienungsdauer
when 0,21 thru 0,4 move 8 to Bedienungsdauer
when 0,41 thru 0,6 move 10 to Bedienungsdauer
when 0,61 thru 0,8 move 12 to Bedienungsdauer
when 0,81 thru 0,9 move 14 to Bedienungsdauer
when 0,91 thru 1,0 move 16 to Bedienungsdauer
END-Evaluate.
Schlange.
move 1 to kuerzeste-Schlange.
move 1 to SCHALTERNR.
perform until SCHALTERNR > Schalterzahl
IF Kundenzahl(kuerzeste-Schlange) >
Kundenzahl(SCHALTERNR) then
move SCHALTERNR to kuerzeste-Schlange
END-IF
add 1 to SCHALTERNR
end-perform.
add 1 to Kundenzahl(kuerzeste-Schlange).
move kundenzahl(kuerzeste-Schlange) to Kundennr.
move Bedienungsdauer to Schalter(Kuerzeste-Schlange, kundennr).
Warten.
If Kundenzahl(Kuerzeste-Schlange) > 1 Then
move 0 to Wartezeit
move 1 to Kundennr
perform until Kundennr > (Kundenzahl(kuerzeste-Schlange) - 1)
add Schalter(kuerzeste-schlange, kundennr) to
Wartezeit
add 1 to kundennr
end-perform
add Wartezeit to Wartesumme
end-if.

Heading1
Kunden-nachruecken.
subtract 1 from Kundenzahl(SCHALTERNR).
If Kundenzahl(SCHALTERNR) > 0 Then
move 1 to KUNDENNR
perform until KUNDENNR > Kundenzahl(schalternr)
Move Schalter(SCHALTERNR, KUNDENNR + 1) to
Schalter(SCHALTERNR, KUNDENNR )
add 1 to KUNDENNR
end-perform
Move kundenzahl(SCHALTERNR) to KUNDENNR
move 0 to Schalter(SCHALTERNR, KUNDENNR + 1)
END-IF.
Ausgabe.
add 100 to cursor-position.
display "Simulierte Zeitspanne : Zeiteinheiten " at
cursor-position.
add 30 to cursor-position.
move zeiteinheiten to a-zeiteinheiten.
DISPLAY a-Zeiteinheiten at cursor-position.
add 70 to cursor-position.
Display "Gesamtzahl der Kunden : Kunden" at
cursor-position.
add 29 to cursor-position.
move kundensumme to a-kundensumme.
display a-Kundensumme at cursor-position.
add 71 to Cursor-position.
Display "Mittlere Schlangenlängen : " at cursor-position.
add 100 to Cursor-position.
move 1 to SCHALTERNR.
perform until SCHALTERNR > Schalterzahl
compute
schlangenlaenge(SCHALTERNR)=
schlangenlaenge(SCHALTERNR) / Zeiteinheiten
move SCHALTERNR to A-SCHALTERNR
move schlangenlaenge(SCHALTERNR) to
a-schlangenlaenge(SCHALTERNR)
Display " Schalter : Kunden" at
Cursor-position
add 10 to cursor-position
DISPLAY SCHALTERNR at cursor-position
add 20 to Cursor-position
DISPLAY a-schlangenlaenge(SCHALTERNR) at cursor-position
add 70 to cursor-position
add 1 to SCHALTERNR
end-perform.
DISPLAY "Mittlere Wartezeit : Zeiteinheiten / Kunde"
at Cursor-position.
add 27 to cursor-position.
compute wartesumme ROUNDED = wartesumme / Kundensumme.
move wartesumme to a-Wartesumme.

DISPLAY a-wartesumme at cursor-position.

TEILSEGMENT 1 :ZUFALLSZ


$SET ANS85
IDENTIFICATION DIVISION.
PROGRAM-ID. Zufallszahl.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
DECIMAL-POINT IS COMMA.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 zahl1 pic 9(6) value 24298.
01 zahl2 pic 9(6) value 99991.
01 zahl3 pic 9(8) value 199017.
01 anfangswert pic 9(8).
01 rest pic 9(10).
01 rx pic 9(10)V9999999.
01 wert pic 9(10)v9999999.
01 x pic 99999,9999999.
01 zaehler pic 99999 value 0.
01 ganzzahl pic 9(10).
01 wuerfel pic 99999 occurs 6 values 0.
01 prozent pic 99V99 occurs 6 values 0.
01 ergebnis pic 99,99.
01 dummy pic x.
01 laeufe pic 999 value 100.
LINKAGE SECTION.
01 zufall PIC 999v999.
PROCEDURE DIVISION USING ZUFALL.
HAUPTPROGRAMM.
perform with test after until zaehler = laeufe
perform Berechnung
end-perform.
exit program.
Berechnung.
accept anfangswert from time.
add 1 to zaehler.
compute rx=(zahl1 * anfangswert + zahl2) / zahl3.
move rx to ganzzahl.
compute rest rounded = (rx - ganzzahl) * zahl3.
move rest to anfangswert.
compute wert = (10 * rest / zahl3).
move wert to zufall.

Literatur :
Zur Bearbeitung des o.a. Programms habe ich mich folgender Nachschlagewerke bedient :
Titel : Mathematische Methoden in der Technik Stochastische Modelle für Anwender
Herausgeber : J. Lehn H. Neunzert H. Wacker Autor : P. Weiß
Titel : Informatik Algorithmen und ihre Programmierung

Herausgeber : R. Oldenburg Verlag München - Wien


Autor : Professor S. Ocker
StD. L. Schöttle
StD. W. Simon
Titel : Professional COBOL/2 Workbench

Herausgeber : iwt - Verlag München


Autor : Raout Habib


[1] erschienen 1979 im R. Oldenburg Verlag München - Wien