290 likes | 377 Views
Hoofdstuk 11.3. Algoritmen: Zoeken in een netwerk. Routeplanner. Spoorwegkaart:. Klik startpunt. eind. Klik eindpunt. start. Programma bepaalt route. start. Klik nieuw startpunt. Modellering. elk traject heeft “kosten”; route met laagste totaalprijs is de beste.
E N D
Hoofdstuk 11.3 Algoritmen: Zoeken in een netwerk
Routeplanner • Spoorwegkaart: • Klik startpunt eind • Klik eindpunt start • Programmabepaalt route start • Klik nieuwstartpunt...
Modellering elk traject heeft “kosten”; route met laagste totaalprijs is de beste • Zoek de “beste” route • Opbouw van het netwerkstaat in een file, met: • voor elke stad: naam en coördinaten • voor elke weg: 2 steden, en de kosten • stad Amersfoort 330 350 • stad Amsterdam 250 310 • stad Apeldoorn 420 330 • weg Amersfoort Apeldoorn 43 • weg Amsterdam Hilversum 29 • weg Hilversum Amersfoort 16
Specificatie • Bij eerste muisklik:aangewezen stad is het beginpunttoon die in blauw • Bij tweede muisklik:aangewezen stad is eindpuntbereken de route, en toon die in rood • Bij klik buiten een stad:telt niet mee en 3e, 5e, 7e... en 4e, 6e, 8e...
Opdeling in klassen • Interactieve interface met EventHandler voor: • teken • klik class RouteZoeker : Form • Belangrijke object-typen met in elke klasse: • een constructor-methode • een methode Tekenom zichzelf te tekenen • ... class Stad class Weg class Pad class Netwerk
Klasse-ontwerp wat is ... member-variabelen wat kan ... methode-headers een object en hoe ? methode-bodies
De klasse RouteZoeker class RouterZoeker : Form { “het” netwerk Netwerk netwerk; de “blauwe” stad Stad stad1; of null Pad pad; het “rode” pad of null Button b; TextBox t; Label lab; we tekenenalles zelf! Event-handlers void klik(..., MouseEventArgs mea) { ...... } void teken(..., PaintEventArgs pea) { ...... }
De klasse Netwerk class Netwerk { alle stedenop de kaart alle stedenop de kaart Stad [ ] Steden; ICollection<Stad> Steden; we gaan per stad alle uitgaande wegen bewaren ICollection<Weg> Wegen;
De klasse Stad class Stad { string Naam; Utrecht Point Plek; ICollection<Weg> Wegen;
De klasse Weg class Weg { Stad Doel; int Kosten;
De klasse Pad class Pad { IList<Stad> Steden; Stad Hier; Pad Rest; int Kosten; ongeveer eenLinkedList, maar danzelfgemaakt null
Methoden van Stad class Stad { String Naam; Point Plek; ICollection<Weg> wegen; static Font font = new ... Stad ( { } String s, Point p ) Naam = s; Plek = p; Wegen = new LinkedList<Weg> ( ); void Teken (Graphics gr, Brush br) { gr . FillRectangle(br , Plek.X-5, Plek.Y-5, 10, 10 ); Utrecht gr . DrawString (Naam, font, br , Plek + new Size(6,-15) ); }
Methoden van Weg class Weg { Stad Doel; int Kosten; wordt niet getekend Weg ( { } Stad s, int k ) Doel =s; Kosten = k; void Teken (Graphics gr, Pen pen ) { } , Stad bron ) gr . DrawLine ( pen, bron.Plek, Doel.Plek );
Methoden van Pad class Pad { Stad Hier; Pad Rest; int Kosten; totale kosten van het pad Pad ( { } Stad s, Pad r, int k ) Hier = s; Rest = r; Kosten = k; if (Rest != null) Kosten += Rest.Kosten; void Teken (Graphics gr, Brush br, Pen pen) { } Hier . Teken (gr, br); if (Rest != null) { } gr.DrawLine( pen, Hier.Plek, Rest.Hier.Plek ); Rest . Teken (gr, br, pen);
Methoden van Netwerk class Netwerk { ICollection<Stad> Steden; Netwerk ( ) { } Steden = new LinkedList<Stad> ( ); void Teken (Graphics gr) { } foreach ( Stad stad in Steden ) { } stad . Teken (gr, Brushes.Black); bron foreach ( Weg w in stad.wegen ) w.Teken (gr, Pens.Black, stad)
Methoden van RouteZoeker class RouteZoeker { Netwerk netwerk; Stad stad1; Pad pad; init ( ) { } netwerk = new Netwerk(); stad1=null; pad=null; void teken (object o, PaintEventArgs pea) { Graphics gr = pea.Graphics; } netwerk . teken (gr); if (pad != null) pad . teken(gr, Brushes.Red, Pens.Red); if (stad1 != null) stad1 . teken(gr, Brushes.Blue);
Opbouw van het Netwerk • Lees een file met regels zoals: • stad Almelo 520 280 • stad Amersfoort 330 350 • stad Amsterdam 250 310 • stad Apeldoorn 420 330 • stad Arnhem 410 380 • weg Arnhem Zutphen 29 • weg Zutphen Deventer 16 • weg Deventer Zwolle 31 • weg Amsterdam Weesp 14 • weg Weesp Hilversum 15 • weg Hilversum Amersfoort 16 locatie commando kosten
Opbouw van het Netwerk void Lees (string filenaam ) { StreamReader sr = new StreamReader(filenaam); while ( (regel=sr.ReadLine()) != null ) { string [] r = regel.Split(" ", StringSplitOptions.RemoveEmpty ); if (r.Length==4) if (r[0] == "stad") { } else { this . bouwStad (r[1] new Point( int.Parse(r[2]), int.Parse(r[3]) ) ); this.bouwWeg( r[1], r[2], int.Parse(r[3]) ); } } }
Opbouw van het Netwerk void bouwStad (string naam, Point p) { } Stad st = new Stad(naam, p); Steden . Add (st); Netwerk’s void bouwWeg (string van, string naar, int kosten) { } Stad st1 = this . vindStad (van); Stad st2 = this . vindStad (naar); st1 . BouwWeg (st2, kosten); st2 . BouwWeg (st1, kosten); class Stad { void BouwWeg(Stad doel, int k){ } Wegen . Add ( Stad’s new Weg(doel, k) );
Opbouw van het Netwerk Stad vindStad (String naam) { } foreach ( Stad st in Steden ) { } if ( st.naam == naam ) return st ; returnnull ; Stad VindStad (Point p) { foreach ( Stad st in steden ) { } if ( Math.abs( )Math.abs( ) p.X-st.Plek.X < 5 && p.Y-st.Plek.Y <5 ) return st ; returnnull ;
Interactie in RouteZoeker class RouteZoeker : Form { Netwerk netwerk; Stad stad1; Pad pad; void klik (..., MouseEventArgs mea) { } Stad s = netwerk . VindStad( ); mea.Location if ( s != null ) { } eerste klik of tweede klik? if (stad1==null) else stad1 = s; pad = netwerk . ZoekPad (stad1, s ); { stad1 = null; } this . Invalidate ();
Het zoek-algoritme maak een stapel van nog-niet-complete, maar veelbelovende paden Pad ZoekPad (Stad begin, Stad eind) { Stack<Pad> paden = new Stack<Pad>();
maar wel veelbelovend! hij is niet groot... null null 0 Het zoeken begint... Pad pad; pad = new Pad(begin, null, 0); paden . push (pad);
Onderzoek paden uit stapel... while ( paden.Count > 0 ) { Pad pad = paden . pop(); if (pad.Hier==eind) return pad; foreach ( Weg weg in pad . Hier . Wegen ) { beter = new Pad( paden . Push(beter); weg.Doel, pad, weg.Kosten); } } returnnull;
beter = new Pad( paden . Push(beter); weg.Doel, pad, weg.Kosten); Pas op: niet in eenkringetje zoeken! één van de wegen kom je net vandaan! foreach ( Weg weg in pad.Hier.Wegen ) { } if ( ! pad . Bevat (weg.Doel) ) { }
Niet de eerste oplossing,maar de beste zoeken! beste = null; while ( ... ) { pad = ... if (compleet) return pad; for (...) if ( !kring ) paden.Push(...) } returnnull; while ( ... ) { pad = ... if (compleet) return pad; for (...) if ( !kring ) paden.Push(...) } returnnull; beste=pad; if (beter) beste=pad; && !zinloos) return beste;
Uitwerking • Wat is “beter” ? • Wat is “niet zinloos” ? if ( beste==null || pad.Kosten < beste.Kosten ) beste = pad; if ( beste==null || pad.Kosten + weg.Kosten < beste.Kosten ) paden.Push (new Pad (...) );
Verbetering van het algoritme • De meest veelbelovendeeerst onderzoeken • Dus in volgorde vanafstand totnaarpushen ordenen qua afstand tot doel moet eenlComparer zijn wegen = new SortedSet<Weg>( pad.Hier.Wegen , naar ); class Stad : IComparer<Weg> { { int Compare( Weg a, Weg b) { returnthis.afstand(b.doel) – this.afstand(a.doel); }