Zur Haupt­na­vi­ga­ti­on sprin­gen [Alt]+[0] Zum Sei­ten­in­halt sprin­gen [Alt]+[1]

Al­go­rith­men mit op­ti­ma­ler Lö­sung

So viel­fäl­tig wie die Pro­ble­me sind auch die Lö­sungs­an­sät­ze. Es gibt eine Viel­zahl von Stan­dard­al­go­rith­men zur Lö­sung ty­pi­scher Gra­phen­pro­ble­me. Grund­sätz­lich muss man dabei un­ter­schei­den, ob das Ziel ist, die per­fek­te/beste Lö­sung zu fin­den oder ob es aus­rei­chend ist, eine gute Nä­he­rungs­lö­sung zu fin­den. In vie­len Fäl­len kann die beste Lö­sung nicht er­mit­telt wer­den, da der Zeit­be­darf zu groß wäre (siehe Ka­pi­tel Lauf­zeit­ver­hal­ten).

Tie­fen­su­che / Brei­ten­su­che

Tie­fen- und Brei­ten­su­che taucht im Bil­dungs­plan im Zu­sam­men­hang mit Bäu­men und mit Gra­phen auf. Da Bäume spe­zi­el­le Gra­phen sind, lässt sich die Tie­fen- bzw. Brei­ten­su­che von Gra­phen auch auf Bäume an­wen­den. In der Schu­le wird man aber ver­mut­lich zu­nächst Bäume be­han­deln und erst da­nach die Gra­phen. Damit müs­sen die Al­go­rith­men von Bäu­men auf Gra­phen er­wei­tert wer­den. Die Be­schrei­bung der Al­go­rith­men auf Bäu­men fin­den Sie im Hin­ter­grund zu den ADTs im Ka­pi­tel Bäume.

Breitensuche

Brei­ten­su­che (ei­ge­nes Werk): grün = fer­tig be­ar­bei­tet, tür­kis = in toDo-Liste Bei der Be­ar­bei­tung des Kno­ten 2 durf­ten der Kno­ten 3 (schon be­ar­bei­tet) und die Kno­ten 4 und 6 (schon in toDo-Liste) der toDo-Liste nicht hin­zu­ge­fügt wer­den.
ZPG In­for­ma­tik [CC BY-SA 4.0 DE], aus 1_gra­phen_hin­ter­grund.odt

Über­trägt man diese Al­go­rith­men auf all­ge­mei­ne Gra­phen, tre­ten zwei Pro­ble­me auf:

  • Es gibt in einem Gra­phen kei­nen aus­ge­zeich­ne­ten Kno­ten, der der Wur­zel des Bau­mes ent­spricht. Man be­ginnt die Al­go­rith­men mit einem be­lie­bi­gen Start­kno­ten (hier Kno­ten 0).
  • Auf­grund der Zy­klen im Gra­phen kann man bei der Ab­ar­bei­tung auf Kno­ten sto­ßen kann, die schon be­ar­bei­tet oder zu­min­dest der toDo-Liste hin­zu­ge­fügt wur­den. Man kann bei der Tie­fen­su­che sogar bis zu­rück zum Start­kno­ten ge­lan­gen. Das ist bei Bäu­men nicht mög­lich. Damit diese Kno­ten nicht er­neut be­ar­bei­tet oder mehr­fach der toDo-Liste hin­zu­ge­fügt wer­den, kenn­zeichnet man sie als schon be­sucht.

Brei­ten­su­che kann man also gut mit dem ADT Schlan­ge, Tie­fen­su­che mit dem ADT Sta­pel rea­li­sie­ren. Tie­fen­su­che lässt sich au­ßer­dem gut re­kur­siv im­ple­men­tie­ren, indem der Bearbeitungs­algorithmus mit dem als nächs­tes aus­zu­wer­ten­den Kno­ten er­neut auf­ge­ru­fen wird. Erst nach Rück­kehr von der Re­kur­si­on wird der nächs­te Nach­bar­kno­ten be­ar­bei­tet. Sucht man in einem Gra­phen also nach einem Kno­ten, der eine be­stimm­te Be­din­gung er­füllt (At­tri­but(k) ist wahr), er­ge­ben sich ne­ben­ste­hen­de Pseudo­codes für die Tie­fen- und Brei­ten­su­che:

Code für Tiefensuche und Breitensuche

Code für Tie­fen­su­che und Brei­ten­su­che
ZPG In­for­ma­tik [CC BY-SA 4.0 DE], aus 1_gra­phen_hin­ter­grund.odt

Ach­tung: Man muss bei der Im­ple­men­tie­rung der Al­go­rith­men immer be­ach­ten, ob es sich um einen ge­rich­te­ten oder un­ge­rich­te­ten Gra­phen han­delt.

Bei­spie­le für Al­go­rith­men:

Brei­ten­su­che:

Zy­klen­su­che, Al­go­rith­mus A von Moore, Di­jk­s­tra (wobei Kno­ten in einer Prio­ri­täts­schlan­ge ge­spei­chert wer­den), Zu­sam­men­hang eines Gra­phen

Tie­fen­su­che:

Zu­sam­men­hang eines Gra­phen, Zy­klen­su­che

Back­tracking (Brute-Force-An­satz)

Ein grund­sätz­li­cher Lö­sungs­an­satz, der für sehr viele Pro­blem­stel­lun­gen an­wend­bar ist, ist das Back­tracking. Im Bil­dungs­plan des Leis­tungs­fachs fin­det es sich unter 3.​3.​2.​3 Re­kur­si­on (6) "das Prin­zip des Back­trackings an­hand einer ge­eig­ne­ten Pro­blem­stel­lung (zum Bei­spiel Acht-Damen-Pro­blem, Ma­gi­sche Qua­dra­te, Zy­klen­su­che) er­läu­tern". Mit dem Bei­spiel "Zy­klen­su­che" ist der Bezug zu den Gra­phen auch im Bil­dungs­plan her­ge­stellt.

Back­tracking lie­fert immer die per­fek­te/beste Lö­sung eines Pro­blems. Back­tracking ist im Prin­zip sys­te­ma­ti­sches Pro­bie­ren aller Mög­lich­kei­ten ("Brute Force"). Wenn es für eine end­li­che Zahl von Ent­schei­dun­gen je­weils end­lich viele Mög­lich­kei­ten gibt, kann man für jede Ent­schei­dung der Reihe nach alle Va­ri­an­ten durch­pro­bie­ren. Dies ist bei den Gra­phen­pro­ble­men na­he­zu immer der Fall. Ent­we­der wird für jeden Kno­ten eine Ent­schei­dung ge­trof­fen (z.B. wel­chen Weg man wei­ter­geht, ob er zu einer Teil­men­ge da­zu­ge­hö­ren soll oder nicht oder in wel­cher Farbe einer vor­ge­ge­be­nen Farb­pa­let­te er ge­färbt wer­den soll) oder für jede Kante (soll sie zum Mi­ni­mal Span­ning Tree da­zu­ge­hö­ren oder nicht, ge­hört sie zu einem Weg oder nicht).

Beim Back­tracking wird also z.B. mit einem Start­kno­ten be­gon­nen und die erste Ent­schei­dung ge­trof­fen. Hier­für wählt man die erste Mög­lich­keit (z.B. Kno­ten 1 be­kommt Farbe 1). Da­nach geht man zum nächs­ten Kno­ten und trifft dort die Ent­schei­dung. Auch hier pro­biert man sys­te­ma­tisch alle Mög­lich­kei­ten durch (z.B. Farbe 1 ist bei Kno­ten 2 nicht er­laubt, daher wird Farbe 2 pro­biert). So­bald man eine zu­läs­si­ge Mög­lich­keit ge­fun­den hat, geht man zur drit­ten Ent­schei­dung über. Soll­te es gar keine zu­läs­si­ge Mög­lich­keit mehr geben, geht man einen Schritt zu­rück (daher der Name des Lö­sungs­an­sat­zes) und pro­biert dort die nächs­te Mög­lich­keit. Hat man für den gan­zen Gra­phen zu­läs­si­ge Ent­schei­dun­gen ge­trof­fen, dann ist die Lö­sung des Pro­blems ge­fun­den.

Sucht man bei einem Op­ti­mie­rungs­pro­blem die beste Lö­sung und nicht nur ir­gend­ei­ne, darf man das Ver­fah­ren nicht ab­bre­chen, so­bald man eine Lö­sung ge­fun­den hat, son­dern muss alle Lö­sun­gen be­stim­men und sich die bis dahin beste Lö­sung mer­ken.

Wich­tig ist dabei nur, dass in der Ent­schei­dungs­fol­ge jeder Kno­ten/Kante ma­xi­mal ein­mal vor­kom­men darf, da sonst un­end­lich viele Ent­schei­dun­gen not­wen­dig sein könn­ten. Eine Tie­fen­su­che würde dann un­end­lich wei­ter­ge­hen. Daher ist es bei Gra­phen oft sinn­voll, die Kno­ten als "be­sucht" zu kenn­zeich­nen, um zu wis­sen, wel­che Kno­ten schon aus­ge­wer­tet wur­den.

Back­tracking kann man sehr gut re­kur­siv im­ple­men­tie­ren. Für jeden Ent­schei­dungs­schritt ruft sich der Back­trackin­gal­go­rith­mus re­kur­siv auf. Bei Gra­phen­al­go­rith­men wäre der Zu­stand z der Zu­stand des Gra­phen, also die Kno­ten­wer­te und die Mar­kie­run­gen der Kno­ten und Kan­ten:
  public Zustand loese(Zustand z) {
     aktuellerZustand = z;
     if (z.istErkennbarFalsch()) {
       return null;
     }
     if (z.istZielzustand()) {
       return z;
     }
     for (int i=0; i< z.getAnzahlMoeglichkeiten(); i++ ) {
       Zustand z2 = z.erzeugeKopie();
       z2.waehleMoeglichkeit(i);
       Zustand erg = loese(z2);
       if (erg != null) {
         return erg;
       }
     }
     return null;
   }

Eine gute Dar­stel­lung des Back­tracking-Prin­zips fin­det man beim Ma­the­pris­ma der Uni Wup­per­tal unter http://​www.​ma­the­pris­ma.​uni-​wup­per­tal.​de/​Mo­du­le/​BackTr/​index.​htm (Ab­ge­ru­fen 07.05.2020).

Mit Back­tracking kann man z.B. das Pro­blem des Hand­lungs­rei­sen­den (Ha­mil­ton-Kreis), das Fin­den eines Euler-Zuges, das Kar­ten­fär­be­pro­blem, das Fin­den einer do­mi­nie­ren­den Menge und vie­les mehr lösen.

Lauf­zeit­ana­ly­se des Back­tracking-An­sat­zes

Nach­teil des Back­trackings ist seine Lauf­zeit. Da im schlimms­ten Fall alle Mög­lich­kei­ten durch­pro­biert wer­den müs­sen, steigt die Lauf­zeit mit der An­zahl der Kno­ten/Kan­ten ex­po­nen­ti­ell.

An­zahl der Va­ri­an­ten:

n Kno­ten/Kan­ten, m Ent­schei­dungs­mög­lich­kei­ten => mn Va­ri­an­ten

Das führt z.B. bei der Suche einer do­mi­nie­ren­den Menge auf einem Gra­phen mit 100 Kno­ten dazu, dass man 2100 = 1,3*1030 Va­ri­an­ten tes­ten muss (es gibt für jeden Kno­ten zwei Mög­lich­kei­ten: Ein Kno­ten ge­hört ent­we­der zur do­mi­nie­ren­den Menge oder nicht). Das ist selbst mit schnel­len Rech­nern nicht prak­ti­ka­bel. Bei an­de­ren Pro­ble­men ist die Basis oft grö­ßer und damit der Zeit­auf­wand noch höher, da es mehr Mög­lich­kei­ten bei jeder ein­zel­nen Ent­schei­dung gibt. In sinn­vol­ler Zeit durch­führ­bar sind daher Al­go­rith­men mit ex­po­nen­ti­el­ler Lauf­zeit nicht. Aber viel­leicht gibt es ja bes­se­re Al­go­rith­men...

 

Hin­ter­grund­in­for­ma­tio­nen: Her­un­ter­la­den [odt][990 KB]

 

Wei­ter zu P=NP?