Hoofdstuk 11.3 Algoritmen: Zoeken in een netwerk
Jan 21, 2016
Hoofdstuk 11.3
Algoritmen:Zoeken in een netwerk
Routeplanner
Klik startpunt
Klik eindpunt
Programmabepaalt route
Klik nieuwstartpunt...
start
eind
start
Spoorwegkaart:
Modellering
Zoek de “beste” route
elk traject heeft “kosten”;route met laagste totaalprijs
is de beste
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 350stad Amsterdam 250 310stad Apeldoorn 420 330weg Amersfoort Apeldoorn 43weg Amsterdam Hilversum 29weg 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
class RouteZoeker : Form
Belangrijke object-typen
class Stadclass Wegclass Padclass Netwerk
met in elke klasse: een constructor-methode een methode Teken
om zichzelf te tekenen ...
met EventHandler voor: teken klik
Klasse-ontwerp
wat is ...
wat kan ...
en hoe ?
een object
member-variabelen
methode-headers
methode-bodies
De klasse RouteZoeker
class RouterZoeker : Form{ Netwerk netwerk;
Stad stad1;
Pad pad;
“het” netwerk
de “blauwe” stadof null
het “rode” padof null
Button b;TextBox t;Label lab;
we tekenenalles zelf!
void klik(..., MouseEventArgs mea) { ...... }void teken(..., PaintEventArgs pea) { ...... }
Event-handlers
De klasse Netwerk
class Netwerk {
Stad [ ] Steden;
ICollection<Weg> Wegen;
alle stedenop de kaartalle stedenop de kaart
we gaan per stadalle uitgaande
wegen bewaren
ICollection<Stad> Steden;
De klasse Stad
class Stad {
string Naam;
ICollection<Weg> Wegen;
Point Plek;Utrecht
De klasse Weg
class Weg {
Stad Doel;
int Kosten;
De klasse Pad
class Pad {
IList<Stad> Steden;
Stad Hier;Pad Rest;int Kosten;
null
ongeveer eenLinkedList,maar dan
zelfgemaakt
Methoden van Stadclass Stad { String Naam; Point Plek;
ICollection<Weg> wegen;
Stad ({
}void Teken (Graphics gr, Brush br){
Naam = s; Plek = p;String s, Point p )
Wegen = new LinkedList<Weg> ( );
gr . FillRectangle(br , Plek.X-5, Plek.Y-5, 10, 10 );gr . DrawString (Naam, font, br , Plek + new Size(6,-15) );
Utrecht
}
static Font font = new ...
Methoden van Weg
class Weg { Stad Doel; int Kosten;
Weg ({}
void Teken (Graphics gr, Pen pen ){
}
Doel =s; Kosten = k;Stad s, int k )
gr . DrawLine ( pen, bron.Plek,Doel.Plek );
, Stad bron )
wordt nietgetekend
Methoden van Pad
class Pad { Stad Hier; Pad Rest; int Kosten;
Pad ({
}void Teken (Graphics gr, Brush br, Pen pen){
}
Hier = s; Rest = r; Kosten = k;Stad s, Pad r, int k )
Hier . Teken (gr, br);
totale kostenvan het pad
if (Rest != null) Kosten += Rest.Kosten;
if (Rest != null){
}Rest . Teken (gr, br, pen);
gr.DrawLine( pen, Hier.Plek, Rest.Hier.Plek );
Methoden van Netwerk
class Netwerk { ICollection<Stad> Steden;
Netwerk ( ){}void Teken (Graphics gr){
}
Steden = new LinkedList<Stad> ( );
foreach ( Stad stad in Steden ){
}
stad . Teken (gr, Brushes.Black);foreach ( Weg w in stad.wegen )
w.Teken (gr, Pens.Black, stad)
bron
Methoden van RouteZoeker
class RouteZoeker { Netwerk netwerk; Stad stad1; Pad pad;
init ( ){}void teken (object o, PaintEventArgs pea){ Graphics gr = pea.Graphics;
}
netwerk = new Netwerk(); stad1=null; pad=null;
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 280stad Amersfoort 330 350stad Amsterdam 250 310stad Apeldoorn 420 330stad Arnhem 410 380weg Arnhem Zutphen 29weg Zutphen Deventer 16weg Deventer Zwolle 31weg Amsterdam Weesp 14weg Weesp Hilversum 15weg Hilversum Amersfoort 16
commando locatie
kosten
Opbouw van het Netwerk
void Lees (string filenaam ) {
while ( (regel=sr.ReadLine()) != null ){ string [] r = regel.Split(" ",
StringSplitOptions.RemoveEmpty );
if (r[0] == "stad"){
}else{
new Point( int.Parse(r[2]), int.Parse(r[3]) ) );
this . bouwStad (r[1]
this.bouwWeg( r[1], r[2], int.Parse(r[3]) );
} } }
if (r.Length==4)
StreamReader sr = new StreamReader(filenaam);
Opbouw van het Netwerkvoid bouwStad (string naam, Point p) {
}
Stad st = new Stad(naam, p);
void bouwWeg (string van, string naar, int kosten) {
}
Steden . Add (st);
Stad st1 = this . vindStad (van);Stad st2 = this . vindStad (naar);st1 . BouwWeg (st2, kosten);st2 . BouwWeg (st1, kosten);
Netwerk’s
Stad’s
void BouwWeg(Stad doel, int k){
}
Wegen . Add (new Weg(doel, k) );
class Stad {
Opbouw van het NetwerkStad vindStad (String naam) {
}
foreach ( Stad st in Steden ){
}
if ( st.naam == naam )return st ;
return null ;
Stad VindStad (Point p) { foreach ( Stad st in steden )
{
}
if (
return st ;
return null ;
p.X-st.Plek.X < 5 && p.Y-st.Plek.Y <5 )
Math.abs( )Math.abs( )
Interactie in RouteZoekerclass RouteZoeker : Form { Netwerk netwerk;
Stad stad1;Pad pad;
void klik (..., MouseEventArgs mea){
}
mea.Locationnetwerk . VindStad( );
Stad s =
if (stad1==null)else
stad1 = s;pad = netwerk . ZoekPad (stad1,
s );
this . Invalidate ();
{ stad1 = null; }
if ( s != null ){
}
eerste klikof
tweede klik?
Het zoek-algoritme
maak een stapel vannog-niet-complete,
maar veelbelovendepaden
Pad ZoekPad (Stad begin, Stad eind){ Stack<Pad> paden = new Stack<Pad>();
Het zoeken begint...Pad pad;pad = new Pad(begin, null, 0);
null
null
0
hij is nietgroot...
maar welveelbelovend!
paden . push (pad);
Onderzoek paden uit stapel...
while ( paden.Count > 0 )Pad pad = paden . pop();if (pad.Hier==eind) return pad;
beter = new Pad(paden . Push(beter);
pad . Hier . Wegen
foreach ( Weg weg in
weg.Doel, pad, weg.Kosten);
return null;
{
}
{
}
)
Pas op:
foreach ( Weg weg in pad.Hier.Wegen ){
}
beter = new Pad(paden . Push(beter);
weg.Doel, pad, weg.Kosten);
één van de wegen kom jenet vandaan!
if ( ! pad . Bevat (weg.Doel) ){
}
niet in eenkringetje zoeken!
while ( ... ){ pad = ... if (compleet) return pad; for (...) if ( !kring ) paden.Push(...)}return null;
Niet de eerste oplossing,maar de beste zoeken!
while ( ... ){ pad = ... if (compleet) return pad; for (...) if ( !kring ) paden.Push(...)}return null;
beste = null;
return beste;
beste=pad;if (beter) beste=pad;
&& !zinloos)
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 (...) );
wegen = new SortedSet<Weg>(
ordenen qua afstand tot doel
Verbetering van het algoritme
De meest veelbelovendeeerst onderzoeken
Dus in volgorde vanafstand tot naar pushen
class Stad : IComparer<Weg> {{ int Compare( Weg a, Weg b) { return this.afstand(b.doel) – this.afstand(a.doel); }
);pad.Hier.Wegen
, naar
moet eenlComparer zijn
Routezoeker compleet!