private Csúcs TerminálisCsúcsKeresés() { // Amíg a nyílt csúcsok halmaza nem nem üres. while (Nyilt.Count != 0) { // Ez a legnagyobb mélységű nyílt csúcs. Csúcs C = Nyilt.Pop(); // Ezt kiterjesztem. List <Csúcs> újCsucsok = C.Kiterjesztes(); foreach (Csúcs D in újCsucsok) { // Ha megtaláltam a terminális csúcsot, akkor kész vagyok. if (D.TerminálisCsúcsE()) { return(D); } // Csak azokat az új csúcsokat veszem fel a nyíltak közé, // amik nem szerepeltek még sem a zárt, sem a nyílt csúcsok halmazában. // A Contains a Csúcs osztályban megírt Equals metódust hívja. if (!Zárt.Contains(D) && !Nyilt.Contains(D)) { Nyilt.Push(D); } } // A kiterjesztett csúcsot átminősítem zárttá. Zárt.Add(C); } return(null); }
bool körFigyelés; // Ha hamis, végtelen ciklusba eshet. public MélységiKeresés(Csúcs startCsúcs, bool körFigyelés) : base(startCsúcs) { Nyilt = new Stack <Csúcs>(); Nyilt.Push(startCsúcs); // kezdetben csak a start csúcs nyílt Zárt = new List <Csúcs>(); // kezdetben a zárt csúcsok halmaza üres this.körFigyelés = körFigyelés; }
static void Main(string[] args) { Csúcs startCsúcs; GráfKereső kereső; AbsztraktÁllapot k = new BuvosKeresztAllapot(); startCsúcs = new Csúcs(k); Console.WriteLine("A kereső egy 20 mélységi korlátos és emlékezetes backtrack."); kereső = new BackTrack(startCsúcs, 20, true); kereső.megoldásKiírása(kereső.Keresés()); Console.ReadLine(); }
// Alkalmazza az összes alkalmazható operátort. // Visszaadja az így előálló új csúcsokat. public List <Csúcs> Kiterjesztes() { List <Csúcs> újCsúcsok = new List <Csúcs>(); for (int i = 0; i < OperátorokSzáma(); i++) { // Új gyermek csúcsot készítek. Csúcs újCsúcs = new Csúcs(this); // Kiprobálom az i.dik alapoperátort. Alkalmazható? if (újCsúcs.SzuperOperátor(i)) { // Ha igen, hozzáadom az újakhoz. újCsúcsok.Add(újCsúcs); } } return(újCsúcsok); }
// Ezt csak akkor szabad használni, ha biztos, hogy az állapottér gráfban nincs kör! // Különben valószínűleg végtelen ciklust okoz. private Csúcs TerminálisCsúcsKeresésGyorsan() { while (Nyilt.Count != 0) { Csúcs C = Nyilt.Pop(); List <Csúcs> ujCsucsok = C.Kiterjesztes(); foreach (Csúcs D in ujCsucsok) { if (D.TerminálisCsúcsE()) { return(D); } // Ha nincs kör, akkor felesleges megnézni, hogy D volt-e már nyíltak vagy a zártak közt. Nyilt.Push(D); } // Ha nincs kör, akkor felesleges C-t zárttá minősíteni. } return(null); }
/// <summary> /// Kiíratja a megoldást egy terminális csúcs alapján. /// Feltételezi, hogy a terminális csúcs szülő referenciáján felfelé haladva eljutunk a start csúcshoz. /// A csúcsok sorrendjét megfordítja, hogy helyesen tudja kiírni a megoldást. /// Ha a csúcs null, akkor kiírja, hogy nincs megoldás. /// </summary> /// <param name="egyTerminálisCsúcs"> /// A megoldást képviselő terminális csúcs vagy null. /// </param> public void megoldásKiírása(Csúcs egyTerminálisCsúcs) { if (egyTerminálisCsúcs == null) { Console.WriteLine("Nincs megoldás"); return; } // Meg kell fordítani a csúcsok sorrendjét. Stack <Csúcs> megoldás = new Stack <Csúcs>(); Csúcs aktCsúcs = egyTerminálisCsúcs; while (aktCsúcs != null) { megoldás.Push(aktCsúcs); aktCsúcs = aktCsúcs.GetSzülő(); } // Megfordítottuk, lehet kiírni. foreach (Csúcs akt in megoldás) { Console.WriteLine(akt); } }
// A körfigyelés alapértelmezett értéke igaz. public MélységiKeresés(Csúcs startCsúcs) : this(startCsúcs, true) { }
// A kereső algoritmus rekurzív megvalósítása. // Mivel rekurzív, ezért a visszalépésnek a "return null" felel meg. private Csúcs Keresés(Csúcs aktCsúcs) { int mélység = aktCsúcs.GetMélység(); // mélységi korlát vizsgálata if (korlát > 0 && mélység >= korlát) { return(null); } // emlékezet használata kör kiszűréséhez Csúcs aktSzülő = null; if (emlékezetes) { aktSzülő = aktCsúcs.GetSzülő(); } while (aktSzülő != null) { // Ellenőrzöm, hogy jártam-e ebben az állapotban. Ha igen, akkor visszalépés. if (aktCsúcs.Equals(aktSzülő)) { return(null); } // Visszafelé haladás a szülői láncon. aktSzülő = aktSzülő.GetSzülő(); } if (aktCsúcs.TerminálisCsúcsE()) { // Megvan a megoldás, vissza kell adni a terminális csúcsot. return(aktCsúcs); } // Itt hívogatom az alapoperátorokat a szuper operátoron // keresztül. Ha valamelyik alkalmazható, akkor új csúcsot // készítek, és meghívom önmagamat rekurzívan. for (int i = 0; i < aktCsúcs.OperátorokSzáma(); i++) { // Elkészítem az új gyermek csúcsot. // Ez csak akkor lesz kész, ha alkalmazok rá egy alkalmazható operátort is. Csúcs újCsúcs = new Csúcs(aktCsúcs); // Kipróbálom az i.dik alapoperátort. Alkalmazható? if (újCsúcs.SzuperOperátor(i)) { // Ha igen, rekurzívan meghívni önmagam az új csúcsra. // Ha nem null értéket ad vissza, akkor megvan a megoldás. // Ha null értéket, akkor ki kell próbálni a következő alapoperátort. Csúcs terminális = Keresés(újCsúcs); if (terminális != null) { // Visszaadom a megoldást képviselő terminális csúcsot. return(terminális); } // Az else ágon kellene visszavonni az operátort. // Erre akkor van szükség, ha az új gyermeket létrehozásában nem lenne klónozást. // Mivel klónoztam, ezért ez a rész üres. } } // Ha kipróbáltam az összes operátort és egyik se vezetett megoldásra, akkor visszalépés. // A visszalépés hatására eggyel feljebb a következő alapoperátor kerül sorra. return(null); }
// emlékezetes kereső public BackTrack(Csúcs startCsúcs, bool emlékezetes) : this(startCsúcs, 0, emlékezetes) { }
// mélységi korlátos kereső public BackTrack(Csúcs startCsúcs, int korlát) : this(startCsúcs, korlát, false) { }
// nincs mélységi korlát, se emlékezet public BackTrack(Csúcs startCsúcs) : this(startCsúcs, 0, false) { }
bool emlékezetes; // Ha igaz, emlékezetes kereső. public BackTrack(Csúcs startCsúcs, int korlát, bool emlékezetes) : base(startCsúcs) { this.korlát = korlát; this.emlékezetes = emlékezetes; }
private Csúcs startCsúcs; // A start csúcs csúcs. // Minden gráfkereső a start csúcsból kezd el keresni. public GráfKereső(Csúcs startCsúcs) { this.startCsúcs = startCsúcs; }
public override bool Equals(Object obj) { Csúcs cs = (Csúcs)obj; return(állapot.Equals(cs.állapot)); }
// Egy új gyermek csúcsot készít. // Erre még meg kell hívni egy alkalmazható operátor is, csak azután lesz kész. public Csúcs(Csúcs szülő) { állapot = (AbsztraktÁllapot)szülő.állapot.Clone(); mélység = szülő.mélység + 1; this.szülő = szülő; }
Csúcs szülő; // A szülőkön felfelé haladva a start csúcsig jutok. // Konstruktor: // A belső állapotot beállítja a start csúcsra. // A hívó felelőssége, hogy a kezdő állapottal hívja meg. // A start csúcs mélysége 0, szülője nincs. public Csúcs(AbsztraktÁllapot kezdőÁllapot) { állapot = kezdőÁllapot; mélység = 0; szülő = null; }