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

  1. Per stap, test of het onmogelijk is de (partiële) kandidaat verder uit te bouwen tot oplossing
  2. Indien onmogelijk, keer één of meer bouwstappen terug
    • "backtrack"
    • ga verder met een nieuwe partiële kandidaat
  3. Indien test slaagt én kandidaat volledig uitgebouwd, oplossing gevonden
  4. 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
  1. Begin met leeg rooster
  2. Vul eerste vakje met 1
  3. Vul tweede vakje met 1
  4. Tegen de regels, keer terug: backtrack
  5. Vul tweede vakje met 0
  6. Vul derde vakje met 1
  7. Tegen de regels, backtrack
  8. Vul derde vakje met 0
  9. Vul vierde vakje met 1
  10. 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
  1. Begin met leeg rooster
  2. Vul eerste vakje met 1
  3. Vul tweede vakje met 1
  4. Tegen de regels, keer terug: backtrack
  5. Vul tweede vakje met 0
  6. Vul derde vakje met 1
  7. Tegen de regels, backtrack
  8. Vul derde vakje met 0
  9. Vul vierde vakje met 1
  10. 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

  • 636