13b. Backtracking
2021-03-22
slides.com/jod/pt_13b
Docent: Jo Devriendt
Assistent: Ann Philips
Coördinator: Joost Vennekens
voornaam.achternaam@kuleuven.be
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Hoe zoekproblemen oplossen?
Bouw een kandidaat stap per stap
- Per stap, test of het onmogelijk is de (partiële) kandidaat verder uit te bouwen tot oplossing
- Indien onmogelijk, keer één of meer bouwstappen terug
- "backtrack"
- ga verder met een nieuwe partiële kandidaat
- Indien test slaagt én kandidaat volledig uitgebouwd, oplossing gevonden
- Indien alle kandidaten overlopen, en allen zijn onmogelijk uit te breiden tot een oplossing, dan geen oplossing mogelijk
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Mini-sudoku
1 | |
1 | 0 |
1 | 0 |
0 |
1 | 0 |
1 |
1 | 0 |
0 | 1 |
1 | 1 |
- Begin met leeg rooster
- Vul eerste vakje met 1
- Vul tweede vakje met 1
- Tegen de regels, keer terug: backtrack
- Vul tweede vakje met 0
- Vul derde vakje met 1
- Tegen de regels, backtrack
- Vul derde vakje met 0
- Vul vierde vakje met 1
- Oplossing gevonden!
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Algemene zoekmethode
Schrijf procedures om
-
kandidaten stap per stap uit te breiden
- moet alle mogelijke kandidaten kunnen bouwen
- te testen of een partiële kandidaat onmogelijk een oplossing kan worden
- te testen of een kandidaat compleet is
- te backtracken van een foutieve uitbreidingsstap
- "breekt" de kandidaat een stap "af"
int aantalUitbreidingen(<partiële kandidaat> k);
void maakVolgendeUitbreiding(<partiële kandidaat> k, int i);
int test(<partiële kandidaat> k);
int isCompleet(<partiële kandidaat> k);
void backtrack(<partiële kandidaat> k, int i);
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
void zoek(<partiële kandidaat> k) {
if (!test(k)) {
return; // geen uitbreiding tot oplossing
}
if (isCompleet(k)) {
printOplossing(k);
return;
}
int m = aantalUitbreidingen(k);
for (int i = 0; i < m; ++i) {
maakVolgendeUitbreiding(k,i);
zoek(k);
backtrack(k,i);
}
}
Voeg alles samen tot een recursieve zoekmethode
Algemene zoekmethode
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Mini-sudoku
1 | |
1 | 0 |
1 | 0 |
0 |
1 | 0 |
1 |
1 | 0 |
0 | 1 |
1 | 1 |
- Begin met leeg rooster
- Vul eerste vakje met 1
- Vul tweede vakje met 1
- Tegen de regels, keer terug: backtrack
- Vul tweede vakje met 0
- Vul derde vakje met 1
- Tegen de regels, backtrack
- Vul derde vakje met 0
- Vul vierde vakje met 1
- Oplossing gevonden!
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Mini-sudoku
typedef struct {
int rooster[2][2];
int ingevuld;
} Kandidaat;
int aantalUitbreidingen(Kandidaat* k){
return 2;
}
void maakVolgendeUitbreiding(Kandidaat* k, int i){
k->rooster[k->ingevuld/2][k->ingevuld%2] = i;
k->ingevuld += 1;
}
void backtrack(Kandidaat* k, int i){
k->ingevuld -= 1;
}
int isCompleet(Kandidaat* k){
return k->ingevuld==4;
}
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Mini-sudoku
int test(Kandidaat* k){
if(k->ingevuld>1 &&
k->rooster[0][0]==k->rooster[0][1]){
return 0;
} else if(k->ingevuld>2 &&
k->rooster[0][0]==k->rooster[1][0]){
return 0;
} else if(k->ingevuld>3){
if(k->rooster[0][1]==k->rooster[1][1] ||
k->rooster[1][0]==k->rooster[1][1]){
return 0;
}
}
return 1;
}
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
void zoek(<partiële kandidaat> k) {
if (!test(k)) {
return; // geen uitbreiding tot oplossing
}
if (isCompleet(k)) {
printOplossing(k);
return;
}
int m = aantalUitbreidingen(k);
for (int i = 0; i < m; ++i) {
maakVolgendeUitbreiding(k,i);
zoek(k);
backtrack(k,i);
}
}
Uitbreidingen
- Huidige zoek() drukt alle oplossingen af. Vaak willen we maar één oplossing.
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Uitbreidingen
- Huidige zoek() drukt alle oplossingen af. Vaak willen we maar één oplossing.
- Maak gebruik van terugkeerwaarde
int zoek(<partiële kandidaat> k) {
if (!test(k)) {
return 0; // geen uitbreiding tot oplossing
}
if (isCompleet(k)) {
printOplossing(k);
return 1;
}
int m = aantalUitbreidingen(k);
for (int i = 0; i < m; ++i) {
maakVolgendeUitbreiding(k,i);
if(zoek(k)) {
return 1;
}
backtrack(k,i);
}
return 0;
}
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Uitbreidingen
- Wat als een optimale oplossing gevraagd is?
- Zie presentatie 13c :)
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Samenvatting
- Algemeen algoritme voor zoekproblemen
- Bouw kandidaatoplossingen stap per stap
- Backtrack indien partiële kandidaatoplossing niet meer tot een oplossing kan leiden
13b. Backtracking
By Jo Devriendt
13b. Backtracking
- 743