Top Banner
Žilinská univerzita v Žiline Stredoeurópsky technologický inštitút 4 5 // Ri adkové ohr ani ˇ ceni a. 6 f or ( i nt i =0; i < r ows; i ++ ) { 7 di st i nct ( * thi s, mat. row(i )); 8 } 9 10 // St ´ l pcové ohr ani ˇ ceni a. 11 f or ( i nt i =0; i < col s; i ++ ) { 12 di st i nct ( * thi s, mat. col (i )); 13 } 14 15 // Št vor cové ohr ani ˇ ceni a. 16 f or ( i nt i =0; i <9; i +=3) { 17 f or ( i nt j =0; j <9; j +=3) { 18 di st i nct ( * thi s, mat. sl i ce(i , i +3, j, j +3)); 19 } 20 } 21 22 // Na ˇ cí t ame predpl nené pol í ˇ cka z pr í kl adu, ak exi st uj e. 23 if (exampl e) { 24 f or ( i nt i =0; i < r ows; i ++ ) { 25 f or ( i nt j =0; j < col s; j ++ ) { 26 i nt val = exampl e[i * col s + j]; 27 if ( val ) r el ( * thi s, mat(i , j ) == val ) ; 28 } 29 } 30 } 31 32 // Aké sa použi j e vet veni e. 33 br anch( * thi s, var s, I NT _ VAR _ SI ZE _ MI N(), I NT _ VAL _ MAX( ) ) ; 34 } Prehľadávanie Sklad ohraničení Definičobory Ohraničenia Programovanie ohraničení Štúdia CEIT-Š006-12-2014 ©2014, Žilinská univerzita, CEIT
39

Programovanie ohraničení

May 04, 2023

Download

Documents

Michal Hottmar
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Programovanie ohraničení

Žilinskaacute univerzita v Žiline Stredoeuroacutepsky technologickyacute inštituacutet

4

5

Ri adkoveacute

ohr ani ce

ni a

6

for(i nt

i = 0 i lt r ows i ++)

7

di sti nct

( thi s

mat r ow(

i ) )

8

9

10

St l pcoveacute

ohr ani ce

ni a

11

for(i nt

i = 0 i lt col s i ++)

12

di sti nct

( thi s

mat col (

i ) )

13

14

15

Št vor cov

eacute ohr ani ce

ni a

16

for(i nt

i = 0 i lt 9 i +=3)

17

for(i nt

j = 0 j lt 9 j +=3)

18

di sti nct

( thi s

mat sl i c

e( i i +3

j j +3))

19

20

21

22

Naciacutet ame

pr edpl ne

neacute pol iacutecka

z pr iacute kl adu

ak exi st uj e

23

i f ( examp

l e)

24

for(i nt

i = 0 i lt r ows i ++)

25

for(i nt

j = 0 j lt col s j ++)

26

i ntval

= exampl e[

i col s + j ]

27

i f ( val )

r el ( thi s

mat (i j )

== val )

28

29

30

31

32

Akeacutesa použ

i j evet v

eni e

33

br anch(

thi s var s

I NT_VAR

_SI ZE_MI N(

) I NT_VAL

_MAX() )

34

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Programovanie ohraničeniacute

Štuacutedia

CEIT-Š006-12-2014

copy2014 Žilinskaacute univerzita CEIT

i

Programovanie ohraničeniacuteŠtuacutedia CEIT-Š006-12-2014

Copyright copyŽilinskaacute univerzita Central European Institute of Technology ndash CEIT 2014

Všetky praacuteva vyhradeneacute Žiadna časť tejto štuacutedie nesmie byť publikovanaacute a šiacuterenaacute žiadnym spocirc-

sobom a v žiadnej podobe bez vyacuteslovneacuteho povolenia Žilinskej univerzity a Central European

Institute of Technology

Autor štuacutedie

Ing Michal Gregor PhD ndash KRIS-FEL Žilinskaacute univerzita

Obsah

1 Uacutevod 1

2 Probleacutem spĺňania ohraničeniacute 121 Formulaacutecia hry Sudoku ako CSP 2

22 Probleacutem SAT 3

3 Logickeacute programovanie ohraničeniacute 3

4 Programovanie ohraničeniacute ako riešenie Sudoku 441 Aplikaacutecia ohraničeniacute hry Sudoku 5

411 Štvorcoveacute ohraničenia 5

412 Riadkoveacute a stĺpcoveacute ohraničenia 5

42 Ohraničenia aplikujeme opakovane 6

43 Vetvenie 7

431 Naacutevrat 7

432 Strateacutegie vetvenia 9

5 Zaacutekladneacute koncepty v CP 951 Sklad ohraničeniacute 10

511 Interakcia prehľadaacutevania a skladu ohraničeniacute 10

512 Propagaacutecia ohraničeniacute 11

52 Arita ohraničeniacute 11

53 Globaacutelne ohraničenia 12

54 Ciele CP a optimalizaacutecia na baacuteze CP 12

6 Konzistenčneacute techniky 1261 Vrcholovaacute konzistentnosť 13

62 Hranovaacute konzistentnosť 13

621 Ako dosiahnuť hranovuacute konzistentnosť 14

63 Konzistentnosť po ceste 16

7 Riešenie predeterminovanyacutech CSP 1671 Maumlkkeacute ohraničenia 16

72 Max-CSP 17

73 Vaacuteženeacute CSP 17

74 Fuzzy CSP 17

middot 1 middot

75 Ďalšie priacutestupy 17

8 Reikaacutecia 1881 Využitie reikaacutecie pri modelovaniacute 18

811 Zaacutepis disjunkcie 18

812 Nerovnosť prvkov poliacute 19

813 Riešenie probleacutemu max-CSP 19

82 Polovičnaacute reikaacutecia 19

9 Obľuacutebeneacute benchmark probleacutemy 2091 Probleacutem obchodneacuteho cestujuacuteceho 20

911 Neohodnotenyacute graf 20

912 Ohodnotenyacute graf 20

913 Uacuteplnyacute graf 21

92 SEND MORE MONEY 21

93 Probleacutem magickyacutech postupnostiacute 22

10 Priacuteklad Riešenie Sudoku pomocou Gecode 22101 Direktiacutevy include a linkovanie 23

102 Trieda Sudoku 23

103 Konštrukcia triedy Sudoku 24

104 Funkcia main 26

11 Priacuteklad Riešenie Sudoku v jazyku Prolog 27111 Použiteacute moduly a vloženie Sudoku 27

112 Denovanie ohraničeniacute 27

113 Pomocneacute predikaacutety 29

114 Riešenie 29

Priacutelohy 31

A Množiny a relaacutecie IA1 Identita a kardinalita množiacuten I

A2 Karteziaacutensky suacutečin I

A21 Vlastnosti karteziaacutenskeho suacutečinu I

A3 Relaacutecie II

A4 Charakteristickaacute funkcia II

middot 2 middot

SkratkyAC hranovo konzistentnyacute (angl arc consistent) p 13

COP probleacutem optimalizaacutecie ohraničeniacute (angl constraint optimization problem) p 12

CP programovanie ohraničeniacute (angl constraint programming) pp 1 3 4 9 10 12 16 20 22

CSP probleacutem spĺňania ohraničeniacute (angl constraint satisfaction problem) pp 1ndash4 11ndash13 16

17 19 23

PC konzistentnosť po ceste (angl path consistency) p 16

SAT probleacutem spĺňania logickyacutech formuacutel (angl boolean satisability problem) p 3

TSP probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem) pp 20 21

Zoznam obraacutezkov21 Hra Sudoku 2

22 Hra Sudoku ndash riešenie 2

23 Hra Sudoku ndash rozdelenie na štvorce 3

41 Deničneacute obory premennyacutech v hracom poli Sudoku 4

42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek 5

43 Riadkoveacute a stĺpcoveacute ohraničenia 6

44 Po aplikaacutecii ohraničeniacute vieme určiť niektoreacute hodnoty 7

45 Vyacutesledok po ďalšom kroku aplikaacutecie ohraničeniacute 7

46 Stav po aplikaacutecii ohraničeniacute 8

47 Voliacuteme hodnotu 1 pre x11 8

48 Vetvenie pre x11 8

49 Vetvenie pre x14 8

410 Vetvenie pre x14 ndash naacutevrat 8

411 Voliacuteme hodnotu 3 pre x14 9

412 Stav po aplikaacutecii ohraničeniacute ndash praacutezdny deničnyacute obor 9

51 Sklad ohraničeniacute a prehľadaacutevanie scheacutema interakcie 10

52 Sklad ohraničeniacute a prehľadaacutevanie priacuteklad interakcie 10

53 Scheacutema skladu ohraničeniacute 11

61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute 13

91 TSP reprezentaacutecia neohodnotenyacutem neorientovanyacutem grafom 21

middot 3 middot

92 TSP reprezentaacutecia neohodnotenyacutem orientovanyacutem grafom 21

93 TSP reprezentaacutecia ohodnotenyacutem neorientovanyacutem grafom 21

94 TSP reprezentaacutecia ohodnotenyacutem orientovanyacutem grafom 21

middot 4 middot

1 | UacutevodV suacutečasnosti existuje veľkeacute množstvo uacuteloh v raacutemci prebiehajuacuteceho vyacuteskumu aj podnikovej praxe

ktoreacute si vyžadujuacute ryacutechle a efektiacutevne riešenie diskreacutetnych optimalizačnyacutech uacuteloh Možno sem zara-

diť napriacuteklad probleacutemy rozvrhovania plaacutenovacie uacutelohy logistickuacute optimalizaacuteciu a mnoheacute ďalšie

Značnuacute časť z tyacutechto uacuteloh možno formulovať prostredniacutectvom premennyacutech a ohraničeniacute ndash

tj podmienok ktoreacute musia hodnoty premennyacutech spĺňať aby uacutelohu bolo možneacute považovať za

vyriešenuacute Na ilustraacuteciu možno uviesť napriacuteklad dobre znaacutemy probleacutem N daacutem kde je uacutelohou

rozmiestniť N daacutem na šachovnici takyacutem spocircsobom aby sa navzaacutejom neohrozovali hru Sudoku

či probleacutem smerovania vozidiel (angl vehicle routing problem)

Jednou zo znaacutemych a naďalej perspektiacutevnych metoacuted riešiacich uacutelohy tohto typu je progra-

movanie ohraničeniacute (angl constraint programming CP) V nasledujuacutecej štuacutedii sa budeme proble-

matike programovania ohraničeniacute venovať podrobnejšie ndash najprv formaacutelne denujeme probleacutem

spĺňania ohraničeniacute Zmysel deniacutecie vzaacutepaumltiacute budeme ilustrovať na hre Sudoku na ktorej naacutesledne

ozrejmiacuteme aj zaacutekladneacute prvky a princiacutepy programovania ohraničeniacute

Naacutesledne poskytneme aj formaacutelnejšiacute vyacuteklad a podrobnejšiacute prehľad o jednotlivyacutech konceptoch

v CP ako suacute propagaacutecia ohraničeniacute sklad ohraničeniacute overenie korektnosti globaacutelne ohraničenia

konzistenčneacute techniky a pod Postupy budeme na zaacutever ilustrovať niekoľkyacutemi priacutekladmi praktic-

kej implementaacutecie na modelovyacutech uacutelohaacutech

2 | Probleacutem spĺňania ohraničeniacute

Probleacutem spĺňania ohraničeniacute (angl constraint satisfaction problem CSP) možno charakterizovať

trojicou P = 〈XDC〉 [1]

bull X je n-tica premennyacutech X = 〈x1 x2 xn〉

bull D je n-tica ich zodpovedajuacutecich deničnyacutech oborov D = 〈D1 D2 Dn〉 tj xi isin Di

bull a C je t-tica ohraničeniacute C = 〈C1 C2 Ct〉

Každeacute ohraničenieCj tvoriacute paacuter 〈RSj Sj〉 kdeRSj

je relaacutecia nad premennyacutemiSj = rozsah(Cj)[1] Inyacutemi slovami možno povedať žeRSj

je podmnožina karteziaacutenskeho suacutečinu deničnyacutech obo-

rov premennyacutech z Sj [1]1

Riešeniacutem probleacutemu P je n-tica A = 〈a1 a2 an〉 takaacute že platiacute ai isin Di a každeacute ohraničenie

Cj je splneneacute tj pre projekciu A do rozsahu Sj platiacute relaacutecia RSj

1Ku relaacuteciaacutem a karteziaacutenskemu suacutečinu možno pozrieť viac v priacutelohe A

middot 1 middot

Obr 21 Hra Sudoku Obr 22 Hra Sudoku ndash riešenie

21 Formulaacutecia hry Sudoku ako CSP

Hra Sudoku je dobryacutem priacutekladom probleacutemu spĺňania ohraničeniacute Pozostaacuteva z hracieho poľa ur-

čityacutech rozmerov ndash najčastejšie 9times 9 Pole je navyše rozdeleneacute na 9 štvorcov rozmerov 3times 3 (viď

Obr 23) Každeacute poliacutečko mocircže obsahovať čiacuteslo od 1 po 9 Na začiatku hry suacute niektoreacute poliacutečka už

vyplneneacute ndash ostatneacute treba doplniť tak aby boli splneneacute predpiacutesaneacute podmienky

bull Dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9

bull Žiadne čiacuteslo v raacutemci toho isteacuteho stĺpca sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho riadku sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho štvorca sa nesmie opakovať viackraacutet

Ilustraacutecia hracieho poľa je na Obr 21 Vyplneneacute hracie pole je na Obr 22

Ak maacuteme Sudoku opiacutesať ako probleacutem spĺňania ohraničeniacute premenneacute X buduacute tvoriť hodnoty

jednotlivyacutech poliacutečok (dokopy ich bude 9times 9) Deničnyacute obor každej z nich je D = 1 2 9Ak jednotliveacute premenneacute usporiadame do matice mocircžeme ich preindexovať ako xmk kde m

je čiacuteslo riadku a k je čiacuteslo stĺpca Ak potom uvažujeme napriacuteklad ohraničenie pre prvyacute riadok

vieme že pre jeho rozsah platiacute Sr1 = x11 x12 x19 tj ohraničenie zahŕňa praacuteve premenneacute

z prveacuteho riadku

Relaacuteciu pre prvyacute riadok mocircžeme denovať nasledovne

RSr1 = x isin D9|x1i 6= x1j forall 1 le i j 6= 9 i 6= j (21)

middot 2 middot

Obr 23 Hra Sudoku ndash rozdelenie na štvorce

Zo všetkyacutech kombinaacuteciiacute hodnocirct premennyacutech (D9) vyberaacuteme teda len takeacute dosadenia x pri ktoryacutech

platiacute že z hodnocirct v riadku 1 ani dve nie suacute rovnakeacute

Obmedzenie (21) možno zovšeobecniť pre ľubovoľnyacute riadok a obdobne možno denovať os-

tatneacute obmedzenia Keďže tento typ obmedzeniacute sa vyskytuje často existuje preň osobitneacute kľuacutečoveacute

slovo alldierent ndash tj všetky uvedeneacute premenneacute sa musia odlišovať Ako možno toto kľuacutečoveacute

slovo a ineacute kľuacutečoveacute slovaacute použiť v praxi uvidiacuteme na priacutekladoch neskocircr

22 Probleacutem SAT

Za špeciaacutelny priacutepad CSP možno považovať probleacutem spĺňania logickyacutech formuacutel (angl boolean satis-

ability problem SAT) V jeho priacutepade sa deničneacute oboryDi jednotlivyacutech premennyacutech redukujuacute

na Di = true false [1]

3 | Logickeacute programovanie ohraničeniacuteSysteacutemy na programovanie ohraničeniacute typicky integrujuacute koncepty z CP do nejakeacuteho už existu-

juacuteceho programovacieho jazyka Existuje veľkyacute počet implementaacuteciiacute pre mnoho rocircznych jazy-

kov Ako priacuteklady implementaacutecie v klasickyacutech imperatiacutevnych jazykoch možno uviesť knižnicu

Gecode pre C++ knižnicu or-tools ktoruacute možno použiacutevať z C++ Python-u Javy a NET alebo

javoveacute knižnice CHOCO a JaCoP

Osobitnuacute vetvu však tvoria logickeacute deklaratiacutevne jazyky ndash napriacuteklad Prolog ndash ktoreacute sa osobitne

hodia na integraacuteciu CP keďže s niacutem už mnoheacute koncepty zdieľajuacute Prolog napriacuteklad už obsahuje

koncept prehľadaacutevania s naacutevratom ktoryacute (ako uvidiacuteme) sa využiacuteva aj v CP [2]

middot 3 middot

Obr 41 Deničneacute obory premennyacutech v hracom poli Sudoku

Preto aj vyacutevoj v oblasti CP bol historicky do značnej miery spojenyacute praacuteve s jazykom Prolog

a s jeho rocircznymi nadstavbami ndash napr s jazykom CHIP ktoryacute zaviedol programovanie ohraničeniacute

na konečnyacutech deničnyacutech oboroch resp CLP(R) ktoreacute zaviedlo podporu pre ohraničenia na

reaacutelnych čiacuteslach [2] Ďalej ide o rocirczne prologoveacute systeacutemy ako napr ECLiPS

ea SICStus Prolog

[2] Knižnice pre programovanie ohraničeniacute existujuacute aj v inyacutech prologoch (napr clpfd pre SWI-

Prolog) V suacutevislosti s tyacutem sa hovoriacute o tzv logickom programovaniacute ohraničeniacute čiacutem sa mysliacute praacuteve

programovanie ohraničeniacute v raacutemci logickyacutech jazykov ako je Prolog

4 | Programovanie ohraničeniacute ako riešenie SudokuV tejto časti ilustrujeme zaacutekladneacute koncepty programovania ohraničeniacute na hre Sudoku čiacutem si

vybudujeme intuiacuteciu potrebnuacute pre nasledujuacuteci formaacutelnejšiacute vyacuteklad Vyššie sme ukaacutezali že hru

Sudoku možno veľmi prirodzenyacutem spocircsobom reprezentovať ako probleacutem spĺňania ohraničeniacute

(CSP)

Ak maacuteme Sudoku rozmeru 9 times 9 a F poliacutečok už maacute stanoveneacute hodnoty maacuteme 9 times 9 minusF premennyacutech ktoryacutech hodnoty musiacuteme stanoviť Deničnyacute obor každej z nich bude Di =1 2 9 Počiatočnyacute stav mocircžeme ilustrovať tak že do každeacuteho praacutezdneho poliacutečka vpiacutešeme

všetky hodnoty ktoreacute daneacute premennaacute mocircže nadobuacutedať Priacuteklad je na Obr 41

Ako vidno v hracom poli Obr 41 je preddenovanyacutech 31 poliacutečok Doplniť teda treba zvyš-

nyacutech 50 poliacutečok z ktoryacutech každeacute mocircže obsahovať hodnoty od 1 po 9 tak aby boli splneneacute všetky

ohraničenia

middot 4 middot

(a) (b) (c)

Obr 42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek

41 Aplikaacutecia ohraničeniacute hry Sudoku

O ohraničeniach hry Sudoku sme hovorili vyššie teraz ich budeme ilustrovať na priacuteklade Ako

prveacute ohraničenie sme uviedli že dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9 Toto ohraničenie

sme už zahrnuli pri určeniacute deničneacuteho oboru premennyacutech ďalej ho teda uvažovať nemusiacuteme

Prejdeme teda postupne len ostatneacute ohraničenia

411 Štvorcoveacute ohraničenia

Začnime štvorcovyacutemi ohraničeniami Princiacutep budeme ilustrovať na štvorcovom vyacuteseku z ľaveacuteho

horneacuteho rohu ktoryacute je na Obr 42a Ako vidno tri poliacutečka už majuacute preddenovaneacute hodnoty

x22 = 5 x31 = 3 a x33 = 4 Keďže tie isteacute hodnoty sa v raacutemci štvorca nesmuacute opakovať viackraacutet

je jasneacute že z deničnyacutech oborov ostatnyacutech premennyacutech mocircžeme čiacutesla 3 4 a 5 vyluacutečiť ako to

ilustrujuacute Obr 42b a 42c

Aplikujme teda obdobnyacutem spocircsobom štvorcoveacute ohraničenia na všetky štvorce a pokračujme

ďalej riadkovyacutemi a stĺpcovyacutemi ohraničeniami

412 Riadkoveacute a stĺpcoveacute ohraničenia

Priacuteklad aplikaacutecie riadkoveacuteho ohraničenia pre prvyacute riadok je na Obr 43a Ako vidno v riadku sa

vyskytuje jedna preddenovanaacute hodnota ndash čiacuteslo 9 ktoruacute je potrebneacute vyluacutečiť z deničnyacutech oborov

všetkyacutech ostatnyacutech premennyacutech v danom riadku

Ak naacutesledne budeme ilustrovať priacuteklad stĺpcoveacuteho ohraničenia na ocircsmom stĺpci ziacuteskame

Obr 43b Ako vidno vylučujeme hodnoty 9 6 7 a 1

middot 5 middot

(a) Priacuteklad riadkoveacuteho ohraničenia (b) Priacuteklad stĺpcoveacuteho ohraničenia

Obr 43 Riadkoveacute a stĺpcoveacute ohraničenia

42 Ohraničenia aplikujeme opakovane

Ak aplikujeme ohraničenia pre všetky štvorce riadky a stĺpce ziacuteskame Obr 44 Ako vidno de-

ničneacute obory niektoryacutech premennyacutech sa po aplikaacutecii ohraničeniacute zuacutežili na jedno konkreacutetne čiacuteslo

(čiacutesla zvyacuterazneneacute oranžovou farbou)

Je zrejmeacute že ak teraz ohraničenia aplikujeme znovu budeme z deničnyacutech oborov niektoryacutech

premennyacutech vedieť vyluacutečiť ďalšie čiacutesla napr v druhom riadku a deviatom stĺpci sa už nesmie

nachaacutedzať čiacuteslo 8 Takisto ho je potrebneacute vyluacutečiť aj zo štvorca č 3 Obdobne pre ďalšie čiacutesla ndash

vyacutesledok je na Obr 45

Vidno teda že ohraničenia nestačiacute aplikovať len raz ndash treba ich aplikovať opakovane až do-

vtedy keď už pomocou nich nevieme vyluacutečiť ďalšie prvky z deničneacuteho oboru žiadnej premennej

Za zmienku stojiacute aj to že (ako by sme si pri ručnej aplikaacutecii postupu ryacutechlo všimli) netreba

zakaždyacutem uvažovať uacuteplne všetky ohraničenia ndash stačiacute znovu aplikovať ohraničenia tyacutekajuacutece sa

tyacutech premennyacutech ktoryacutech deničnyacute obor sa v poslednom kroku zmenil Inyacutemi slovami ndash ak

sa zmeniacute deničnyacute obor premennej xij maacute zmysel znovu aplikovať len ohraničenia pre riadok

stĺpec a štvorec v ktorom sa xij nachaacutedza Ak aplikaacutecia tyacutechto ohraničeniacute vedie k zmene pre

ďalšie premenneacute prirodzene sa pokračuje obdobne aj pre ne

middot 6 middot

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 2: Programovanie ohraničení

i

Programovanie ohraničeniacuteŠtuacutedia CEIT-Š006-12-2014

Copyright copyŽilinskaacute univerzita Central European Institute of Technology ndash CEIT 2014

Všetky praacuteva vyhradeneacute Žiadna časť tejto štuacutedie nesmie byť publikovanaacute a šiacuterenaacute žiadnym spocirc-

sobom a v žiadnej podobe bez vyacuteslovneacuteho povolenia Žilinskej univerzity a Central European

Institute of Technology

Autor štuacutedie

Ing Michal Gregor PhD ndash KRIS-FEL Žilinskaacute univerzita

Obsah

1 Uacutevod 1

2 Probleacutem spĺňania ohraničeniacute 121 Formulaacutecia hry Sudoku ako CSP 2

22 Probleacutem SAT 3

3 Logickeacute programovanie ohraničeniacute 3

4 Programovanie ohraničeniacute ako riešenie Sudoku 441 Aplikaacutecia ohraničeniacute hry Sudoku 5

411 Štvorcoveacute ohraničenia 5

412 Riadkoveacute a stĺpcoveacute ohraničenia 5

42 Ohraničenia aplikujeme opakovane 6

43 Vetvenie 7

431 Naacutevrat 7

432 Strateacutegie vetvenia 9

5 Zaacutekladneacute koncepty v CP 951 Sklad ohraničeniacute 10

511 Interakcia prehľadaacutevania a skladu ohraničeniacute 10

512 Propagaacutecia ohraničeniacute 11

52 Arita ohraničeniacute 11

53 Globaacutelne ohraničenia 12

54 Ciele CP a optimalizaacutecia na baacuteze CP 12

6 Konzistenčneacute techniky 1261 Vrcholovaacute konzistentnosť 13

62 Hranovaacute konzistentnosť 13

621 Ako dosiahnuť hranovuacute konzistentnosť 14

63 Konzistentnosť po ceste 16

7 Riešenie predeterminovanyacutech CSP 1671 Maumlkkeacute ohraničenia 16

72 Max-CSP 17

73 Vaacuteženeacute CSP 17

74 Fuzzy CSP 17

middot 1 middot

75 Ďalšie priacutestupy 17

8 Reikaacutecia 1881 Využitie reikaacutecie pri modelovaniacute 18

811 Zaacutepis disjunkcie 18

812 Nerovnosť prvkov poliacute 19

813 Riešenie probleacutemu max-CSP 19

82 Polovičnaacute reikaacutecia 19

9 Obľuacutebeneacute benchmark probleacutemy 2091 Probleacutem obchodneacuteho cestujuacuteceho 20

911 Neohodnotenyacute graf 20

912 Ohodnotenyacute graf 20

913 Uacuteplnyacute graf 21

92 SEND MORE MONEY 21

93 Probleacutem magickyacutech postupnostiacute 22

10 Priacuteklad Riešenie Sudoku pomocou Gecode 22101 Direktiacutevy include a linkovanie 23

102 Trieda Sudoku 23

103 Konštrukcia triedy Sudoku 24

104 Funkcia main 26

11 Priacuteklad Riešenie Sudoku v jazyku Prolog 27111 Použiteacute moduly a vloženie Sudoku 27

112 Denovanie ohraničeniacute 27

113 Pomocneacute predikaacutety 29

114 Riešenie 29

Priacutelohy 31

A Množiny a relaacutecie IA1 Identita a kardinalita množiacuten I

A2 Karteziaacutensky suacutečin I

A21 Vlastnosti karteziaacutenskeho suacutečinu I

A3 Relaacutecie II

A4 Charakteristickaacute funkcia II

middot 2 middot

SkratkyAC hranovo konzistentnyacute (angl arc consistent) p 13

COP probleacutem optimalizaacutecie ohraničeniacute (angl constraint optimization problem) p 12

CP programovanie ohraničeniacute (angl constraint programming) pp 1 3 4 9 10 12 16 20 22

CSP probleacutem spĺňania ohraničeniacute (angl constraint satisfaction problem) pp 1ndash4 11ndash13 16

17 19 23

PC konzistentnosť po ceste (angl path consistency) p 16

SAT probleacutem spĺňania logickyacutech formuacutel (angl boolean satisability problem) p 3

TSP probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem) pp 20 21

Zoznam obraacutezkov21 Hra Sudoku 2

22 Hra Sudoku ndash riešenie 2

23 Hra Sudoku ndash rozdelenie na štvorce 3

41 Deničneacute obory premennyacutech v hracom poli Sudoku 4

42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek 5

43 Riadkoveacute a stĺpcoveacute ohraničenia 6

44 Po aplikaacutecii ohraničeniacute vieme určiť niektoreacute hodnoty 7

45 Vyacutesledok po ďalšom kroku aplikaacutecie ohraničeniacute 7

46 Stav po aplikaacutecii ohraničeniacute 8

47 Voliacuteme hodnotu 1 pre x11 8

48 Vetvenie pre x11 8

49 Vetvenie pre x14 8

410 Vetvenie pre x14 ndash naacutevrat 8

411 Voliacuteme hodnotu 3 pre x14 9

412 Stav po aplikaacutecii ohraničeniacute ndash praacutezdny deničnyacute obor 9

51 Sklad ohraničeniacute a prehľadaacutevanie scheacutema interakcie 10

52 Sklad ohraničeniacute a prehľadaacutevanie priacuteklad interakcie 10

53 Scheacutema skladu ohraničeniacute 11

61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute 13

91 TSP reprezentaacutecia neohodnotenyacutem neorientovanyacutem grafom 21

middot 3 middot

92 TSP reprezentaacutecia neohodnotenyacutem orientovanyacutem grafom 21

93 TSP reprezentaacutecia ohodnotenyacutem neorientovanyacutem grafom 21

94 TSP reprezentaacutecia ohodnotenyacutem orientovanyacutem grafom 21

middot 4 middot

1 | UacutevodV suacutečasnosti existuje veľkeacute množstvo uacuteloh v raacutemci prebiehajuacuteceho vyacuteskumu aj podnikovej praxe

ktoreacute si vyžadujuacute ryacutechle a efektiacutevne riešenie diskreacutetnych optimalizačnyacutech uacuteloh Možno sem zara-

diť napriacuteklad probleacutemy rozvrhovania plaacutenovacie uacutelohy logistickuacute optimalizaacuteciu a mnoheacute ďalšie

Značnuacute časť z tyacutechto uacuteloh možno formulovať prostredniacutectvom premennyacutech a ohraničeniacute ndash

tj podmienok ktoreacute musia hodnoty premennyacutech spĺňať aby uacutelohu bolo možneacute považovať za

vyriešenuacute Na ilustraacuteciu možno uviesť napriacuteklad dobre znaacutemy probleacutem N daacutem kde je uacutelohou

rozmiestniť N daacutem na šachovnici takyacutem spocircsobom aby sa navzaacutejom neohrozovali hru Sudoku

či probleacutem smerovania vozidiel (angl vehicle routing problem)

Jednou zo znaacutemych a naďalej perspektiacutevnych metoacuted riešiacich uacutelohy tohto typu je progra-

movanie ohraničeniacute (angl constraint programming CP) V nasledujuacutecej štuacutedii sa budeme proble-

matike programovania ohraničeniacute venovať podrobnejšie ndash najprv formaacutelne denujeme probleacutem

spĺňania ohraničeniacute Zmysel deniacutecie vzaacutepaumltiacute budeme ilustrovať na hre Sudoku na ktorej naacutesledne

ozrejmiacuteme aj zaacutekladneacute prvky a princiacutepy programovania ohraničeniacute

Naacutesledne poskytneme aj formaacutelnejšiacute vyacuteklad a podrobnejšiacute prehľad o jednotlivyacutech konceptoch

v CP ako suacute propagaacutecia ohraničeniacute sklad ohraničeniacute overenie korektnosti globaacutelne ohraničenia

konzistenčneacute techniky a pod Postupy budeme na zaacutever ilustrovať niekoľkyacutemi priacutekladmi praktic-

kej implementaacutecie na modelovyacutech uacutelohaacutech

2 | Probleacutem spĺňania ohraničeniacute

Probleacutem spĺňania ohraničeniacute (angl constraint satisfaction problem CSP) možno charakterizovať

trojicou P = 〈XDC〉 [1]

bull X je n-tica premennyacutech X = 〈x1 x2 xn〉

bull D je n-tica ich zodpovedajuacutecich deničnyacutech oborov D = 〈D1 D2 Dn〉 tj xi isin Di

bull a C je t-tica ohraničeniacute C = 〈C1 C2 Ct〉

Každeacute ohraničenieCj tvoriacute paacuter 〈RSj Sj〉 kdeRSj

je relaacutecia nad premennyacutemiSj = rozsah(Cj)[1] Inyacutemi slovami možno povedať žeRSj

je podmnožina karteziaacutenskeho suacutečinu deničnyacutech obo-

rov premennyacutech z Sj [1]1

Riešeniacutem probleacutemu P je n-tica A = 〈a1 a2 an〉 takaacute že platiacute ai isin Di a každeacute ohraničenie

Cj je splneneacute tj pre projekciu A do rozsahu Sj platiacute relaacutecia RSj

1Ku relaacuteciaacutem a karteziaacutenskemu suacutečinu možno pozrieť viac v priacutelohe A

middot 1 middot

Obr 21 Hra Sudoku Obr 22 Hra Sudoku ndash riešenie

21 Formulaacutecia hry Sudoku ako CSP

Hra Sudoku je dobryacutem priacutekladom probleacutemu spĺňania ohraničeniacute Pozostaacuteva z hracieho poľa ur-

čityacutech rozmerov ndash najčastejšie 9times 9 Pole je navyše rozdeleneacute na 9 štvorcov rozmerov 3times 3 (viď

Obr 23) Každeacute poliacutečko mocircže obsahovať čiacuteslo od 1 po 9 Na začiatku hry suacute niektoreacute poliacutečka už

vyplneneacute ndash ostatneacute treba doplniť tak aby boli splneneacute predpiacutesaneacute podmienky

bull Dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9

bull Žiadne čiacuteslo v raacutemci toho isteacuteho stĺpca sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho riadku sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho štvorca sa nesmie opakovať viackraacutet

Ilustraacutecia hracieho poľa je na Obr 21 Vyplneneacute hracie pole je na Obr 22

Ak maacuteme Sudoku opiacutesať ako probleacutem spĺňania ohraničeniacute premenneacute X buduacute tvoriť hodnoty

jednotlivyacutech poliacutečok (dokopy ich bude 9times 9) Deničnyacute obor každej z nich je D = 1 2 9Ak jednotliveacute premenneacute usporiadame do matice mocircžeme ich preindexovať ako xmk kde m

je čiacuteslo riadku a k je čiacuteslo stĺpca Ak potom uvažujeme napriacuteklad ohraničenie pre prvyacute riadok

vieme že pre jeho rozsah platiacute Sr1 = x11 x12 x19 tj ohraničenie zahŕňa praacuteve premenneacute

z prveacuteho riadku

Relaacuteciu pre prvyacute riadok mocircžeme denovať nasledovne

RSr1 = x isin D9|x1i 6= x1j forall 1 le i j 6= 9 i 6= j (21)

middot 2 middot

Obr 23 Hra Sudoku ndash rozdelenie na štvorce

Zo všetkyacutech kombinaacuteciiacute hodnocirct premennyacutech (D9) vyberaacuteme teda len takeacute dosadenia x pri ktoryacutech

platiacute že z hodnocirct v riadku 1 ani dve nie suacute rovnakeacute

Obmedzenie (21) možno zovšeobecniť pre ľubovoľnyacute riadok a obdobne možno denovať os-

tatneacute obmedzenia Keďže tento typ obmedzeniacute sa vyskytuje často existuje preň osobitneacute kľuacutečoveacute

slovo alldierent ndash tj všetky uvedeneacute premenneacute sa musia odlišovať Ako možno toto kľuacutečoveacute

slovo a ineacute kľuacutečoveacute slovaacute použiť v praxi uvidiacuteme na priacutekladoch neskocircr

22 Probleacutem SAT

Za špeciaacutelny priacutepad CSP možno považovať probleacutem spĺňania logickyacutech formuacutel (angl boolean satis-

ability problem SAT) V jeho priacutepade sa deničneacute oboryDi jednotlivyacutech premennyacutech redukujuacute

na Di = true false [1]

3 | Logickeacute programovanie ohraničeniacuteSysteacutemy na programovanie ohraničeniacute typicky integrujuacute koncepty z CP do nejakeacuteho už existu-

juacuteceho programovacieho jazyka Existuje veľkyacute počet implementaacuteciiacute pre mnoho rocircznych jazy-

kov Ako priacuteklady implementaacutecie v klasickyacutech imperatiacutevnych jazykoch možno uviesť knižnicu

Gecode pre C++ knižnicu or-tools ktoruacute možno použiacutevať z C++ Python-u Javy a NET alebo

javoveacute knižnice CHOCO a JaCoP

Osobitnuacute vetvu však tvoria logickeacute deklaratiacutevne jazyky ndash napriacuteklad Prolog ndash ktoreacute sa osobitne

hodia na integraacuteciu CP keďže s niacutem už mnoheacute koncepty zdieľajuacute Prolog napriacuteklad už obsahuje

koncept prehľadaacutevania s naacutevratom ktoryacute (ako uvidiacuteme) sa využiacuteva aj v CP [2]

middot 3 middot

Obr 41 Deničneacute obory premennyacutech v hracom poli Sudoku

Preto aj vyacutevoj v oblasti CP bol historicky do značnej miery spojenyacute praacuteve s jazykom Prolog

a s jeho rocircznymi nadstavbami ndash napr s jazykom CHIP ktoryacute zaviedol programovanie ohraničeniacute

na konečnyacutech deničnyacutech oboroch resp CLP(R) ktoreacute zaviedlo podporu pre ohraničenia na

reaacutelnych čiacuteslach [2] Ďalej ide o rocirczne prologoveacute systeacutemy ako napr ECLiPS

ea SICStus Prolog

[2] Knižnice pre programovanie ohraničeniacute existujuacute aj v inyacutech prologoch (napr clpfd pre SWI-

Prolog) V suacutevislosti s tyacutem sa hovoriacute o tzv logickom programovaniacute ohraničeniacute čiacutem sa mysliacute praacuteve

programovanie ohraničeniacute v raacutemci logickyacutech jazykov ako je Prolog

4 | Programovanie ohraničeniacute ako riešenie SudokuV tejto časti ilustrujeme zaacutekladneacute koncepty programovania ohraničeniacute na hre Sudoku čiacutem si

vybudujeme intuiacuteciu potrebnuacute pre nasledujuacuteci formaacutelnejšiacute vyacuteklad Vyššie sme ukaacutezali že hru

Sudoku možno veľmi prirodzenyacutem spocircsobom reprezentovať ako probleacutem spĺňania ohraničeniacute

(CSP)

Ak maacuteme Sudoku rozmeru 9 times 9 a F poliacutečok už maacute stanoveneacute hodnoty maacuteme 9 times 9 minusF premennyacutech ktoryacutech hodnoty musiacuteme stanoviť Deničnyacute obor každej z nich bude Di =1 2 9 Počiatočnyacute stav mocircžeme ilustrovať tak že do každeacuteho praacutezdneho poliacutečka vpiacutešeme

všetky hodnoty ktoreacute daneacute premennaacute mocircže nadobuacutedať Priacuteklad je na Obr 41

Ako vidno v hracom poli Obr 41 je preddenovanyacutech 31 poliacutečok Doplniť teda treba zvyš-

nyacutech 50 poliacutečok z ktoryacutech každeacute mocircže obsahovať hodnoty od 1 po 9 tak aby boli splneneacute všetky

ohraničenia

middot 4 middot

(a) (b) (c)

Obr 42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek

41 Aplikaacutecia ohraničeniacute hry Sudoku

O ohraničeniach hry Sudoku sme hovorili vyššie teraz ich budeme ilustrovať na priacuteklade Ako

prveacute ohraničenie sme uviedli že dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9 Toto ohraničenie

sme už zahrnuli pri určeniacute deničneacuteho oboru premennyacutech ďalej ho teda uvažovať nemusiacuteme

Prejdeme teda postupne len ostatneacute ohraničenia

411 Štvorcoveacute ohraničenia

Začnime štvorcovyacutemi ohraničeniami Princiacutep budeme ilustrovať na štvorcovom vyacuteseku z ľaveacuteho

horneacuteho rohu ktoryacute je na Obr 42a Ako vidno tri poliacutečka už majuacute preddenovaneacute hodnoty

x22 = 5 x31 = 3 a x33 = 4 Keďže tie isteacute hodnoty sa v raacutemci štvorca nesmuacute opakovať viackraacutet

je jasneacute že z deničnyacutech oborov ostatnyacutech premennyacutech mocircžeme čiacutesla 3 4 a 5 vyluacutečiť ako to

ilustrujuacute Obr 42b a 42c

Aplikujme teda obdobnyacutem spocircsobom štvorcoveacute ohraničenia na všetky štvorce a pokračujme

ďalej riadkovyacutemi a stĺpcovyacutemi ohraničeniami

412 Riadkoveacute a stĺpcoveacute ohraničenia

Priacuteklad aplikaacutecie riadkoveacuteho ohraničenia pre prvyacute riadok je na Obr 43a Ako vidno v riadku sa

vyskytuje jedna preddenovanaacute hodnota ndash čiacuteslo 9 ktoruacute je potrebneacute vyluacutečiť z deničnyacutech oborov

všetkyacutech ostatnyacutech premennyacutech v danom riadku

Ak naacutesledne budeme ilustrovať priacuteklad stĺpcoveacuteho ohraničenia na ocircsmom stĺpci ziacuteskame

Obr 43b Ako vidno vylučujeme hodnoty 9 6 7 a 1

middot 5 middot

(a) Priacuteklad riadkoveacuteho ohraničenia (b) Priacuteklad stĺpcoveacuteho ohraničenia

Obr 43 Riadkoveacute a stĺpcoveacute ohraničenia

42 Ohraničenia aplikujeme opakovane

Ak aplikujeme ohraničenia pre všetky štvorce riadky a stĺpce ziacuteskame Obr 44 Ako vidno de-

ničneacute obory niektoryacutech premennyacutech sa po aplikaacutecii ohraničeniacute zuacutežili na jedno konkreacutetne čiacuteslo

(čiacutesla zvyacuterazneneacute oranžovou farbou)

Je zrejmeacute že ak teraz ohraničenia aplikujeme znovu budeme z deničnyacutech oborov niektoryacutech

premennyacutech vedieť vyluacutečiť ďalšie čiacutesla napr v druhom riadku a deviatom stĺpci sa už nesmie

nachaacutedzať čiacuteslo 8 Takisto ho je potrebneacute vyluacutečiť aj zo štvorca č 3 Obdobne pre ďalšie čiacutesla ndash

vyacutesledok je na Obr 45

Vidno teda že ohraničenia nestačiacute aplikovať len raz ndash treba ich aplikovať opakovane až do-

vtedy keď už pomocou nich nevieme vyluacutečiť ďalšie prvky z deničneacuteho oboru žiadnej premennej

Za zmienku stojiacute aj to že (ako by sme si pri ručnej aplikaacutecii postupu ryacutechlo všimli) netreba

zakaždyacutem uvažovať uacuteplne všetky ohraničenia ndash stačiacute znovu aplikovať ohraničenia tyacutekajuacutece sa

tyacutech premennyacutech ktoryacutech deničnyacute obor sa v poslednom kroku zmenil Inyacutemi slovami ndash ak

sa zmeniacute deničnyacute obor premennej xij maacute zmysel znovu aplikovať len ohraničenia pre riadok

stĺpec a štvorec v ktorom sa xij nachaacutedza Ak aplikaacutecia tyacutechto ohraničeniacute vedie k zmene pre

ďalšie premenneacute prirodzene sa pokračuje obdobne aj pre ne

middot 6 middot

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 3: Programovanie ohraničení

Obsah

1 Uacutevod 1

2 Probleacutem spĺňania ohraničeniacute 121 Formulaacutecia hry Sudoku ako CSP 2

22 Probleacutem SAT 3

3 Logickeacute programovanie ohraničeniacute 3

4 Programovanie ohraničeniacute ako riešenie Sudoku 441 Aplikaacutecia ohraničeniacute hry Sudoku 5

411 Štvorcoveacute ohraničenia 5

412 Riadkoveacute a stĺpcoveacute ohraničenia 5

42 Ohraničenia aplikujeme opakovane 6

43 Vetvenie 7

431 Naacutevrat 7

432 Strateacutegie vetvenia 9

5 Zaacutekladneacute koncepty v CP 951 Sklad ohraničeniacute 10

511 Interakcia prehľadaacutevania a skladu ohraničeniacute 10

512 Propagaacutecia ohraničeniacute 11

52 Arita ohraničeniacute 11

53 Globaacutelne ohraničenia 12

54 Ciele CP a optimalizaacutecia na baacuteze CP 12

6 Konzistenčneacute techniky 1261 Vrcholovaacute konzistentnosť 13

62 Hranovaacute konzistentnosť 13

621 Ako dosiahnuť hranovuacute konzistentnosť 14

63 Konzistentnosť po ceste 16

7 Riešenie predeterminovanyacutech CSP 1671 Maumlkkeacute ohraničenia 16

72 Max-CSP 17

73 Vaacuteženeacute CSP 17

74 Fuzzy CSP 17

middot 1 middot

75 Ďalšie priacutestupy 17

8 Reikaacutecia 1881 Využitie reikaacutecie pri modelovaniacute 18

811 Zaacutepis disjunkcie 18

812 Nerovnosť prvkov poliacute 19

813 Riešenie probleacutemu max-CSP 19

82 Polovičnaacute reikaacutecia 19

9 Obľuacutebeneacute benchmark probleacutemy 2091 Probleacutem obchodneacuteho cestujuacuteceho 20

911 Neohodnotenyacute graf 20

912 Ohodnotenyacute graf 20

913 Uacuteplnyacute graf 21

92 SEND MORE MONEY 21

93 Probleacutem magickyacutech postupnostiacute 22

10 Priacuteklad Riešenie Sudoku pomocou Gecode 22101 Direktiacutevy include a linkovanie 23

102 Trieda Sudoku 23

103 Konštrukcia triedy Sudoku 24

104 Funkcia main 26

11 Priacuteklad Riešenie Sudoku v jazyku Prolog 27111 Použiteacute moduly a vloženie Sudoku 27

112 Denovanie ohraničeniacute 27

113 Pomocneacute predikaacutety 29

114 Riešenie 29

Priacutelohy 31

A Množiny a relaacutecie IA1 Identita a kardinalita množiacuten I

A2 Karteziaacutensky suacutečin I

A21 Vlastnosti karteziaacutenskeho suacutečinu I

A3 Relaacutecie II

A4 Charakteristickaacute funkcia II

middot 2 middot

SkratkyAC hranovo konzistentnyacute (angl arc consistent) p 13

COP probleacutem optimalizaacutecie ohraničeniacute (angl constraint optimization problem) p 12

CP programovanie ohraničeniacute (angl constraint programming) pp 1 3 4 9 10 12 16 20 22

CSP probleacutem spĺňania ohraničeniacute (angl constraint satisfaction problem) pp 1ndash4 11ndash13 16

17 19 23

PC konzistentnosť po ceste (angl path consistency) p 16

SAT probleacutem spĺňania logickyacutech formuacutel (angl boolean satisability problem) p 3

TSP probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem) pp 20 21

Zoznam obraacutezkov21 Hra Sudoku 2

22 Hra Sudoku ndash riešenie 2

23 Hra Sudoku ndash rozdelenie na štvorce 3

41 Deničneacute obory premennyacutech v hracom poli Sudoku 4

42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek 5

43 Riadkoveacute a stĺpcoveacute ohraničenia 6

44 Po aplikaacutecii ohraničeniacute vieme určiť niektoreacute hodnoty 7

45 Vyacutesledok po ďalšom kroku aplikaacutecie ohraničeniacute 7

46 Stav po aplikaacutecii ohraničeniacute 8

47 Voliacuteme hodnotu 1 pre x11 8

48 Vetvenie pre x11 8

49 Vetvenie pre x14 8

410 Vetvenie pre x14 ndash naacutevrat 8

411 Voliacuteme hodnotu 3 pre x14 9

412 Stav po aplikaacutecii ohraničeniacute ndash praacutezdny deničnyacute obor 9

51 Sklad ohraničeniacute a prehľadaacutevanie scheacutema interakcie 10

52 Sklad ohraničeniacute a prehľadaacutevanie priacuteklad interakcie 10

53 Scheacutema skladu ohraničeniacute 11

61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute 13

91 TSP reprezentaacutecia neohodnotenyacutem neorientovanyacutem grafom 21

middot 3 middot

92 TSP reprezentaacutecia neohodnotenyacutem orientovanyacutem grafom 21

93 TSP reprezentaacutecia ohodnotenyacutem neorientovanyacutem grafom 21

94 TSP reprezentaacutecia ohodnotenyacutem orientovanyacutem grafom 21

middot 4 middot

1 | UacutevodV suacutečasnosti existuje veľkeacute množstvo uacuteloh v raacutemci prebiehajuacuteceho vyacuteskumu aj podnikovej praxe

ktoreacute si vyžadujuacute ryacutechle a efektiacutevne riešenie diskreacutetnych optimalizačnyacutech uacuteloh Možno sem zara-

diť napriacuteklad probleacutemy rozvrhovania plaacutenovacie uacutelohy logistickuacute optimalizaacuteciu a mnoheacute ďalšie

Značnuacute časť z tyacutechto uacuteloh možno formulovať prostredniacutectvom premennyacutech a ohraničeniacute ndash

tj podmienok ktoreacute musia hodnoty premennyacutech spĺňať aby uacutelohu bolo možneacute považovať za

vyriešenuacute Na ilustraacuteciu možno uviesť napriacuteklad dobre znaacutemy probleacutem N daacutem kde je uacutelohou

rozmiestniť N daacutem na šachovnici takyacutem spocircsobom aby sa navzaacutejom neohrozovali hru Sudoku

či probleacutem smerovania vozidiel (angl vehicle routing problem)

Jednou zo znaacutemych a naďalej perspektiacutevnych metoacuted riešiacich uacutelohy tohto typu je progra-

movanie ohraničeniacute (angl constraint programming CP) V nasledujuacutecej štuacutedii sa budeme proble-

matike programovania ohraničeniacute venovať podrobnejšie ndash najprv formaacutelne denujeme probleacutem

spĺňania ohraničeniacute Zmysel deniacutecie vzaacutepaumltiacute budeme ilustrovať na hre Sudoku na ktorej naacutesledne

ozrejmiacuteme aj zaacutekladneacute prvky a princiacutepy programovania ohraničeniacute

Naacutesledne poskytneme aj formaacutelnejšiacute vyacuteklad a podrobnejšiacute prehľad o jednotlivyacutech konceptoch

v CP ako suacute propagaacutecia ohraničeniacute sklad ohraničeniacute overenie korektnosti globaacutelne ohraničenia

konzistenčneacute techniky a pod Postupy budeme na zaacutever ilustrovať niekoľkyacutemi priacutekladmi praktic-

kej implementaacutecie na modelovyacutech uacutelohaacutech

2 | Probleacutem spĺňania ohraničeniacute

Probleacutem spĺňania ohraničeniacute (angl constraint satisfaction problem CSP) možno charakterizovať

trojicou P = 〈XDC〉 [1]

bull X je n-tica premennyacutech X = 〈x1 x2 xn〉

bull D je n-tica ich zodpovedajuacutecich deničnyacutech oborov D = 〈D1 D2 Dn〉 tj xi isin Di

bull a C je t-tica ohraničeniacute C = 〈C1 C2 Ct〉

Každeacute ohraničenieCj tvoriacute paacuter 〈RSj Sj〉 kdeRSj

je relaacutecia nad premennyacutemiSj = rozsah(Cj)[1] Inyacutemi slovami možno povedať žeRSj

je podmnožina karteziaacutenskeho suacutečinu deničnyacutech obo-

rov premennyacutech z Sj [1]1

Riešeniacutem probleacutemu P je n-tica A = 〈a1 a2 an〉 takaacute že platiacute ai isin Di a každeacute ohraničenie

Cj je splneneacute tj pre projekciu A do rozsahu Sj platiacute relaacutecia RSj

1Ku relaacuteciaacutem a karteziaacutenskemu suacutečinu možno pozrieť viac v priacutelohe A

middot 1 middot

Obr 21 Hra Sudoku Obr 22 Hra Sudoku ndash riešenie

21 Formulaacutecia hry Sudoku ako CSP

Hra Sudoku je dobryacutem priacutekladom probleacutemu spĺňania ohraničeniacute Pozostaacuteva z hracieho poľa ur-

čityacutech rozmerov ndash najčastejšie 9times 9 Pole je navyše rozdeleneacute na 9 štvorcov rozmerov 3times 3 (viď

Obr 23) Každeacute poliacutečko mocircže obsahovať čiacuteslo od 1 po 9 Na začiatku hry suacute niektoreacute poliacutečka už

vyplneneacute ndash ostatneacute treba doplniť tak aby boli splneneacute predpiacutesaneacute podmienky

bull Dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9

bull Žiadne čiacuteslo v raacutemci toho isteacuteho stĺpca sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho riadku sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho štvorca sa nesmie opakovať viackraacutet

Ilustraacutecia hracieho poľa je na Obr 21 Vyplneneacute hracie pole je na Obr 22

Ak maacuteme Sudoku opiacutesať ako probleacutem spĺňania ohraničeniacute premenneacute X buduacute tvoriť hodnoty

jednotlivyacutech poliacutečok (dokopy ich bude 9times 9) Deničnyacute obor každej z nich je D = 1 2 9Ak jednotliveacute premenneacute usporiadame do matice mocircžeme ich preindexovať ako xmk kde m

je čiacuteslo riadku a k je čiacuteslo stĺpca Ak potom uvažujeme napriacuteklad ohraničenie pre prvyacute riadok

vieme že pre jeho rozsah platiacute Sr1 = x11 x12 x19 tj ohraničenie zahŕňa praacuteve premenneacute

z prveacuteho riadku

Relaacuteciu pre prvyacute riadok mocircžeme denovať nasledovne

RSr1 = x isin D9|x1i 6= x1j forall 1 le i j 6= 9 i 6= j (21)

middot 2 middot

Obr 23 Hra Sudoku ndash rozdelenie na štvorce

Zo všetkyacutech kombinaacuteciiacute hodnocirct premennyacutech (D9) vyberaacuteme teda len takeacute dosadenia x pri ktoryacutech

platiacute že z hodnocirct v riadku 1 ani dve nie suacute rovnakeacute

Obmedzenie (21) možno zovšeobecniť pre ľubovoľnyacute riadok a obdobne možno denovať os-

tatneacute obmedzenia Keďže tento typ obmedzeniacute sa vyskytuje často existuje preň osobitneacute kľuacutečoveacute

slovo alldierent ndash tj všetky uvedeneacute premenneacute sa musia odlišovať Ako možno toto kľuacutečoveacute

slovo a ineacute kľuacutečoveacute slovaacute použiť v praxi uvidiacuteme na priacutekladoch neskocircr

22 Probleacutem SAT

Za špeciaacutelny priacutepad CSP možno považovať probleacutem spĺňania logickyacutech formuacutel (angl boolean satis-

ability problem SAT) V jeho priacutepade sa deničneacute oboryDi jednotlivyacutech premennyacutech redukujuacute

na Di = true false [1]

3 | Logickeacute programovanie ohraničeniacuteSysteacutemy na programovanie ohraničeniacute typicky integrujuacute koncepty z CP do nejakeacuteho už existu-

juacuteceho programovacieho jazyka Existuje veľkyacute počet implementaacuteciiacute pre mnoho rocircznych jazy-

kov Ako priacuteklady implementaacutecie v klasickyacutech imperatiacutevnych jazykoch možno uviesť knižnicu

Gecode pre C++ knižnicu or-tools ktoruacute možno použiacutevať z C++ Python-u Javy a NET alebo

javoveacute knižnice CHOCO a JaCoP

Osobitnuacute vetvu však tvoria logickeacute deklaratiacutevne jazyky ndash napriacuteklad Prolog ndash ktoreacute sa osobitne

hodia na integraacuteciu CP keďže s niacutem už mnoheacute koncepty zdieľajuacute Prolog napriacuteklad už obsahuje

koncept prehľadaacutevania s naacutevratom ktoryacute (ako uvidiacuteme) sa využiacuteva aj v CP [2]

middot 3 middot

Obr 41 Deničneacute obory premennyacutech v hracom poli Sudoku

Preto aj vyacutevoj v oblasti CP bol historicky do značnej miery spojenyacute praacuteve s jazykom Prolog

a s jeho rocircznymi nadstavbami ndash napr s jazykom CHIP ktoryacute zaviedol programovanie ohraničeniacute

na konečnyacutech deničnyacutech oboroch resp CLP(R) ktoreacute zaviedlo podporu pre ohraničenia na

reaacutelnych čiacuteslach [2] Ďalej ide o rocirczne prologoveacute systeacutemy ako napr ECLiPS

ea SICStus Prolog

[2] Knižnice pre programovanie ohraničeniacute existujuacute aj v inyacutech prologoch (napr clpfd pre SWI-

Prolog) V suacutevislosti s tyacutem sa hovoriacute o tzv logickom programovaniacute ohraničeniacute čiacutem sa mysliacute praacuteve

programovanie ohraničeniacute v raacutemci logickyacutech jazykov ako je Prolog

4 | Programovanie ohraničeniacute ako riešenie SudokuV tejto časti ilustrujeme zaacutekladneacute koncepty programovania ohraničeniacute na hre Sudoku čiacutem si

vybudujeme intuiacuteciu potrebnuacute pre nasledujuacuteci formaacutelnejšiacute vyacuteklad Vyššie sme ukaacutezali že hru

Sudoku možno veľmi prirodzenyacutem spocircsobom reprezentovať ako probleacutem spĺňania ohraničeniacute

(CSP)

Ak maacuteme Sudoku rozmeru 9 times 9 a F poliacutečok už maacute stanoveneacute hodnoty maacuteme 9 times 9 minusF premennyacutech ktoryacutech hodnoty musiacuteme stanoviť Deničnyacute obor každej z nich bude Di =1 2 9 Počiatočnyacute stav mocircžeme ilustrovať tak že do každeacuteho praacutezdneho poliacutečka vpiacutešeme

všetky hodnoty ktoreacute daneacute premennaacute mocircže nadobuacutedať Priacuteklad je na Obr 41

Ako vidno v hracom poli Obr 41 je preddenovanyacutech 31 poliacutečok Doplniť teda treba zvyš-

nyacutech 50 poliacutečok z ktoryacutech každeacute mocircže obsahovať hodnoty od 1 po 9 tak aby boli splneneacute všetky

ohraničenia

middot 4 middot

(a) (b) (c)

Obr 42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek

41 Aplikaacutecia ohraničeniacute hry Sudoku

O ohraničeniach hry Sudoku sme hovorili vyššie teraz ich budeme ilustrovať na priacuteklade Ako

prveacute ohraničenie sme uviedli že dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9 Toto ohraničenie

sme už zahrnuli pri určeniacute deničneacuteho oboru premennyacutech ďalej ho teda uvažovať nemusiacuteme

Prejdeme teda postupne len ostatneacute ohraničenia

411 Štvorcoveacute ohraničenia

Začnime štvorcovyacutemi ohraničeniami Princiacutep budeme ilustrovať na štvorcovom vyacuteseku z ľaveacuteho

horneacuteho rohu ktoryacute je na Obr 42a Ako vidno tri poliacutečka už majuacute preddenovaneacute hodnoty

x22 = 5 x31 = 3 a x33 = 4 Keďže tie isteacute hodnoty sa v raacutemci štvorca nesmuacute opakovať viackraacutet

je jasneacute že z deničnyacutech oborov ostatnyacutech premennyacutech mocircžeme čiacutesla 3 4 a 5 vyluacutečiť ako to

ilustrujuacute Obr 42b a 42c

Aplikujme teda obdobnyacutem spocircsobom štvorcoveacute ohraničenia na všetky štvorce a pokračujme

ďalej riadkovyacutemi a stĺpcovyacutemi ohraničeniami

412 Riadkoveacute a stĺpcoveacute ohraničenia

Priacuteklad aplikaacutecie riadkoveacuteho ohraničenia pre prvyacute riadok je na Obr 43a Ako vidno v riadku sa

vyskytuje jedna preddenovanaacute hodnota ndash čiacuteslo 9 ktoruacute je potrebneacute vyluacutečiť z deničnyacutech oborov

všetkyacutech ostatnyacutech premennyacutech v danom riadku

Ak naacutesledne budeme ilustrovať priacuteklad stĺpcoveacuteho ohraničenia na ocircsmom stĺpci ziacuteskame

Obr 43b Ako vidno vylučujeme hodnoty 9 6 7 a 1

middot 5 middot

(a) Priacuteklad riadkoveacuteho ohraničenia (b) Priacuteklad stĺpcoveacuteho ohraničenia

Obr 43 Riadkoveacute a stĺpcoveacute ohraničenia

42 Ohraničenia aplikujeme opakovane

Ak aplikujeme ohraničenia pre všetky štvorce riadky a stĺpce ziacuteskame Obr 44 Ako vidno de-

ničneacute obory niektoryacutech premennyacutech sa po aplikaacutecii ohraničeniacute zuacutežili na jedno konkreacutetne čiacuteslo

(čiacutesla zvyacuterazneneacute oranžovou farbou)

Je zrejmeacute že ak teraz ohraničenia aplikujeme znovu budeme z deničnyacutech oborov niektoryacutech

premennyacutech vedieť vyluacutečiť ďalšie čiacutesla napr v druhom riadku a deviatom stĺpci sa už nesmie

nachaacutedzať čiacuteslo 8 Takisto ho je potrebneacute vyluacutečiť aj zo štvorca č 3 Obdobne pre ďalšie čiacutesla ndash

vyacutesledok je na Obr 45

Vidno teda že ohraničenia nestačiacute aplikovať len raz ndash treba ich aplikovať opakovane až do-

vtedy keď už pomocou nich nevieme vyluacutečiť ďalšie prvky z deničneacuteho oboru žiadnej premennej

Za zmienku stojiacute aj to že (ako by sme si pri ručnej aplikaacutecii postupu ryacutechlo všimli) netreba

zakaždyacutem uvažovať uacuteplne všetky ohraničenia ndash stačiacute znovu aplikovať ohraničenia tyacutekajuacutece sa

tyacutech premennyacutech ktoryacutech deničnyacute obor sa v poslednom kroku zmenil Inyacutemi slovami ndash ak

sa zmeniacute deničnyacute obor premennej xij maacute zmysel znovu aplikovať len ohraničenia pre riadok

stĺpec a štvorec v ktorom sa xij nachaacutedza Ak aplikaacutecia tyacutechto ohraničeniacute vedie k zmene pre

ďalšie premenneacute prirodzene sa pokračuje obdobne aj pre ne

middot 6 middot

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 4: Programovanie ohraničení

75 Ďalšie priacutestupy 17

8 Reikaacutecia 1881 Využitie reikaacutecie pri modelovaniacute 18

811 Zaacutepis disjunkcie 18

812 Nerovnosť prvkov poliacute 19

813 Riešenie probleacutemu max-CSP 19

82 Polovičnaacute reikaacutecia 19

9 Obľuacutebeneacute benchmark probleacutemy 2091 Probleacutem obchodneacuteho cestujuacuteceho 20

911 Neohodnotenyacute graf 20

912 Ohodnotenyacute graf 20

913 Uacuteplnyacute graf 21

92 SEND MORE MONEY 21

93 Probleacutem magickyacutech postupnostiacute 22

10 Priacuteklad Riešenie Sudoku pomocou Gecode 22101 Direktiacutevy include a linkovanie 23

102 Trieda Sudoku 23

103 Konštrukcia triedy Sudoku 24

104 Funkcia main 26

11 Priacuteklad Riešenie Sudoku v jazyku Prolog 27111 Použiteacute moduly a vloženie Sudoku 27

112 Denovanie ohraničeniacute 27

113 Pomocneacute predikaacutety 29

114 Riešenie 29

Priacutelohy 31

A Množiny a relaacutecie IA1 Identita a kardinalita množiacuten I

A2 Karteziaacutensky suacutečin I

A21 Vlastnosti karteziaacutenskeho suacutečinu I

A3 Relaacutecie II

A4 Charakteristickaacute funkcia II

middot 2 middot

SkratkyAC hranovo konzistentnyacute (angl arc consistent) p 13

COP probleacutem optimalizaacutecie ohraničeniacute (angl constraint optimization problem) p 12

CP programovanie ohraničeniacute (angl constraint programming) pp 1 3 4 9 10 12 16 20 22

CSP probleacutem spĺňania ohraničeniacute (angl constraint satisfaction problem) pp 1ndash4 11ndash13 16

17 19 23

PC konzistentnosť po ceste (angl path consistency) p 16

SAT probleacutem spĺňania logickyacutech formuacutel (angl boolean satisability problem) p 3

TSP probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem) pp 20 21

Zoznam obraacutezkov21 Hra Sudoku 2

22 Hra Sudoku ndash riešenie 2

23 Hra Sudoku ndash rozdelenie na štvorce 3

41 Deničneacute obory premennyacutech v hracom poli Sudoku 4

42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek 5

43 Riadkoveacute a stĺpcoveacute ohraničenia 6

44 Po aplikaacutecii ohraničeniacute vieme určiť niektoreacute hodnoty 7

45 Vyacutesledok po ďalšom kroku aplikaacutecie ohraničeniacute 7

46 Stav po aplikaacutecii ohraničeniacute 8

47 Voliacuteme hodnotu 1 pre x11 8

48 Vetvenie pre x11 8

49 Vetvenie pre x14 8

410 Vetvenie pre x14 ndash naacutevrat 8

411 Voliacuteme hodnotu 3 pre x14 9

412 Stav po aplikaacutecii ohraničeniacute ndash praacutezdny deničnyacute obor 9

51 Sklad ohraničeniacute a prehľadaacutevanie scheacutema interakcie 10

52 Sklad ohraničeniacute a prehľadaacutevanie priacuteklad interakcie 10

53 Scheacutema skladu ohraničeniacute 11

61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute 13

91 TSP reprezentaacutecia neohodnotenyacutem neorientovanyacutem grafom 21

middot 3 middot

92 TSP reprezentaacutecia neohodnotenyacutem orientovanyacutem grafom 21

93 TSP reprezentaacutecia ohodnotenyacutem neorientovanyacutem grafom 21

94 TSP reprezentaacutecia ohodnotenyacutem orientovanyacutem grafom 21

middot 4 middot

1 | UacutevodV suacutečasnosti existuje veľkeacute množstvo uacuteloh v raacutemci prebiehajuacuteceho vyacuteskumu aj podnikovej praxe

ktoreacute si vyžadujuacute ryacutechle a efektiacutevne riešenie diskreacutetnych optimalizačnyacutech uacuteloh Možno sem zara-

diť napriacuteklad probleacutemy rozvrhovania plaacutenovacie uacutelohy logistickuacute optimalizaacuteciu a mnoheacute ďalšie

Značnuacute časť z tyacutechto uacuteloh možno formulovať prostredniacutectvom premennyacutech a ohraničeniacute ndash

tj podmienok ktoreacute musia hodnoty premennyacutech spĺňať aby uacutelohu bolo možneacute považovať za

vyriešenuacute Na ilustraacuteciu možno uviesť napriacuteklad dobre znaacutemy probleacutem N daacutem kde je uacutelohou

rozmiestniť N daacutem na šachovnici takyacutem spocircsobom aby sa navzaacutejom neohrozovali hru Sudoku

či probleacutem smerovania vozidiel (angl vehicle routing problem)

Jednou zo znaacutemych a naďalej perspektiacutevnych metoacuted riešiacich uacutelohy tohto typu je progra-

movanie ohraničeniacute (angl constraint programming CP) V nasledujuacutecej štuacutedii sa budeme proble-

matike programovania ohraničeniacute venovať podrobnejšie ndash najprv formaacutelne denujeme probleacutem

spĺňania ohraničeniacute Zmysel deniacutecie vzaacutepaumltiacute budeme ilustrovať na hre Sudoku na ktorej naacutesledne

ozrejmiacuteme aj zaacutekladneacute prvky a princiacutepy programovania ohraničeniacute

Naacutesledne poskytneme aj formaacutelnejšiacute vyacuteklad a podrobnejšiacute prehľad o jednotlivyacutech konceptoch

v CP ako suacute propagaacutecia ohraničeniacute sklad ohraničeniacute overenie korektnosti globaacutelne ohraničenia

konzistenčneacute techniky a pod Postupy budeme na zaacutever ilustrovať niekoľkyacutemi priacutekladmi praktic-

kej implementaacutecie na modelovyacutech uacutelohaacutech

2 | Probleacutem spĺňania ohraničeniacute

Probleacutem spĺňania ohraničeniacute (angl constraint satisfaction problem CSP) možno charakterizovať

trojicou P = 〈XDC〉 [1]

bull X je n-tica premennyacutech X = 〈x1 x2 xn〉

bull D je n-tica ich zodpovedajuacutecich deničnyacutech oborov D = 〈D1 D2 Dn〉 tj xi isin Di

bull a C je t-tica ohraničeniacute C = 〈C1 C2 Ct〉

Každeacute ohraničenieCj tvoriacute paacuter 〈RSj Sj〉 kdeRSj

je relaacutecia nad premennyacutemiSj = rozsah(Cj)[1] Inyacutemi slovami možno povedať žeRSj

je podmnožina karteziaacutenskeho suacutečinu deničnyacutech obo-

rov premennyacutech z Sj [1]1

Riešeniacutem probleacutemu P je n-tica A = 〈a1 a2 an〉 takaacute že platiacute ai isin Di a každeacute ohraničenie

Cj je splneneacute tj pre projekciu A do rozsahu Sj platiacute relaacutecia RSj

1Ku relaacuteciaacutem a karteziaacutenskemu suacutečinu možno pozrieť viac v priacutelohe A

middot 1 middot

Obr 21 Hra Sudoku Obr 22 Hra Sudoku ndash riešenie

21 Formulaacutecia hry Sudoku ako CSP

Hra Sudoku je dobryacutem priacutekladom probleacutemu spĺňania ohraničeniacute Pozostaacuteva z hracieho poľa ur-

čityacutech rozmerov ndash najčastejšie 9times 9 Pole je navyše rozdeleneacute na 9 štvorcov rozmerov 3times 3 (viď

Obr 23) Každeacute poliacutečko mocircže obsahovať čiacuteslo od 1 po 9 Na začiatku hry suacute niektoreacute poliacutečka už

vyplneneacute ndash ostatneacute treba doplniť tak aby boli splneneacute predpiacutesaneacute podmienky

bull Dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9

bull Žiadne čiacuteslo v raacutemci toho isteacuteho stĺpca sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho riadku sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho štvorca sa nesmie opakovať viackraacutet

Ilustraacutecia hracieho poľa je na Obr 21 Vyplneneacute hracie pole je na Obr 22

Ak maacuteme Sudoku opiacutesať ako probleacutem spĺňania ohraničeniacute premenneacute X buduacute tvoriť hodnoty

jednotlivyacutech poliacutečok (dokopy ich bude 9times 9) Deničnyacute obor každej z nich je D = 1 2 9Ak jednotliveacute premenneacute usporiadame do matice mocircžeme ich preindexovať ako xmk kde m

je čiacuteslo riadku a k je čiacuteslo stĺpca Ak potom uvažujeme napriacuteklad ohraničenie pre prvyacute riadok

vieme že pre jeho rozsah platiacute Sr1 = x11 x12 x19 tj ohraničenie zahŕňa praacuteve premenneacute

z prveacuteho riadku

Relaacuteciu pre prvyacute riadok mocircžeme denovať nasledovne

RSr1 = x isin D9|x1i 6= x1j forall 1 le i j 6= 9 i 6= j (21)

middot 2 middot

Obr 23 Hra Sudoku ndash rozdelenie na štvorce

Zo všetkyacutech kombinaacuteciiacute hodnocirct premennyacutech (D9) vyberaacuteme teda len takeacute dosadenia x pri ktoryacutech

platiacute že z hodnocirct v riadku 1 ani dve nie suacute rovnakeacute

Obmedzenie (21) možno zovšeobecniť pre ľubovoľnyacute riadok a obdobne možno denovať os-

tatneacute obmedzenia Keďže tento typ obmedzeniacute sa vyskytuje často existuje preň osobitneacute kľuacutečoveacute

slovo alldierent ndash tj všetky uvedeneacute premenneacute sa musia odlišovať Ako možno toto kľuacutečoveacute

slovo a ineacute kľuacutečoveacute slovaacute použiť v praxi uvidiacuteme na priacutekladoch neskocircr

22 Probleacutem SAT

Za špeciaacutelny priacutepad CSP možno považovať probleacutem spĺňania logickyacutech formuacutel (angl boolean satis-

ability problem SAT) V jeho priacutepade sa deničneacute oboryDi jednotlivyacutech premennyacutech redukujuacute

na Di = true false [1]

3 | Logickeacute programovanie ohraničeniacuteSysteacutemy na programovanie ohraničeniacute typicky integrujuacute koncepty z CP do nejakeacuteho už existu-

juacuteceho programovacieho jazyka Existuje veľkyacute počet implementaacuteciiacute pre mnoho rocircznych jazy-

kov Ako priacuteklady implementaacutecie v klasickyacutech imperatiacutevnych jazykoch možno uviesť knižnicu

Gecode pre C++ knižnicu or-tools ktoruacute možno použiacutevať z C++ Python-u Javy a NET alebo

javoveacute knižnice CHOCO a JaCoP

Osobitnuacute vetvu však tvoria logickeacute deklaratiacutevne jazyky ndash napriacuteklad Prolog ndash ktoreacute sa osobitne

hodia na integraacuteciu CP keďže s niacutem už mnoheacute koncepty zdieľajuacute Prolog napriacuteklad už obsahuje

koncept prehľadaacutevania s naacutevratom ktoryacute (ako uvidiacuteme) sa využiacuteva aj v CP [2]

middot 3 middot

Obr 41 Deničneacute obory premennyacutech v hracom poli Sudoku

Preto aj vyacutevoj v oblasti CP bol historicky do značnej miery spojenyacute praacuteve s jazykom Prolog

a s jeho rocircznymi nadstavbami ndash napr s jazykom CHIP ktoryacute zaviedol programovanie ohraničeniacute

na konečnyacutech deničnyacutech oboroch resp CLP(R) ktoreacute zaviedlo podporu pre ohraničenia na

reaacutelnych čiacuteslach [2] Ďalej ide o rocirczne prologoveacute systeacutemy ako napr ECLiPS

ea SICStus Prolog

[2] Knižnice pre programovanie ohraničeniacute existujuacute aj v inyacutech prologoch (napr clpfd pre SWI-

Prolog) V suacutevislosti s tyacutem sa hovoriacute o tzv logickom programovaniacute ohraničeniacute čiacutem sa mysliacute praacuteve

programovanie ohraničeniacute v raacutemci logickyacutech jazykov ako je Prolog

4 | Programovanie ohraničeniacute ako riešenie SudokuV tejto časti ilustrujeme zaacutekladneacute koncepty programovania ohraničeniacute na hre Sudoku čiacutem si

vybudujeme intuiacuteciu potrebnuacute pre nasledujuacuteci formaacutelnejšiacute vyacuteklad Vyššie sme ukaacutezali že hru

Sudoku možno veľmi prirodzenyacutem spocircsobom reprezentovať ako probleacutem spĺňania ohraničeniacute

(CSP)

Ak maacuteme Sudoku rozmeru 9 times 9 a F poliacutečok už maacute stanoveneacute hodnoty maacuteme 9 times 9 minusF premennyacutech ktoryacutech hodnoty musiacuteme stanoviť Deničnyacute obor každej z nich bude Di =1 2 9 Počiatočnyacute stav mocircžeme ilustrovať tak že do každeacuteho praacutezdneho poliacutečka vpiacutešeme

všetky hodnoty ktoreacute daneacute premennaacute mocircže nadobuacutedať Priacuteklad je na Obr 41

Ako vidno v hracom poli Obr 41 je preddenovanyacutech 31 poliacutečok Doplniť teda treba zvyš-

nyacutech 50 poliacutečok z ktoryacutech každeacute mocircže obsahovať hodnoty od 1 po 9 tak aby boli splneneacute všetky

ohraničenia

middot 4 middot

(a) (b) (c)

Obr 42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek

41 Aplikaacutecia ohraničeniacute hry Sudoku

O ohraničeniach hry Sudoku sme hovorili vyššie teraz ich budeme ilustrovať na priacuteklade Ako

prveacute ohraničenie sme uviedli že dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9 Toto ohraničenie

sme už zahrnuli pri určeniacute deničneacuteho oboru premennyacutech ďalej ho teda uvažovať nemusiacuteme

Prejdeme teda postupne len ostatneacute ohraničenia

411 Štvorcoveacute ohraničenia

Začnime štvorcovyacutemi ohraničeniami Princiacutep budeme ilustrovať na štvorcovom vyacuteseku z ľaveacuteho

horneacuteho rohu ktoryacute je na Obr 42a Ako vidno tri poliacutečka už majuacute preddenovaneacute hodnoty

x22 = 5 x31 = 3 a x33 = 4 Keďže tie isteacute hodnoty sa v raacutemci štvorca nesmuacute opakovať viackraacutet

je jasneacute že z deničnyacutech oborov ostatnyacutech premennyacutech mocircžeme čiacutesla 3 4 a 5 vyluacutečiť ako to

ilustrujuacute Obr 42b a 42c

Aplikujme teda obdobnyacutem spocircsobom štvorcoveacute ohraničenia na všetky štvorce a pokračujme

ďalej riadkovyacutemi a stĺpcovyacutemi ohraničeniami

412 Riadkoveacute a stĺpcoveacute ohraničenia

Priacuteklad aplikaacutecie riadkoveacuteho ohraničenia pre prvyacute riadok je na Obr 43a Ako vidno v riadku sa

vyskytuje jedna preddenovanaacute hodnota ndash čiacuteslo 9 ktoruacute je potrebneacute vyluacutečiť z deničnyacutech oborov

všetkyacutech ostatnyacutech premennyacutech v danom riadku

Ak naacutesledne budeme ilustrovať priacuteklad stĺpcoveacuteho ohraničenia na ocircsmom stĺpci ziacuteskame

Obr 43b Ako vidno vylučujeme hodnoty 9 6 7 a 1

middot 5 middot

(a) Priacuteklad riadkoveacuteho ohraničenia (b) Priacuteklad stĺpcoveacuteho ohraničenia

Obr 43 Riadkoveacute a stĺpcoveacute ohraničenia

42 Ohraničenia aplikujeme opakovane

Ak aplikujeme ohraničenia pre všetky štvorce riadky a stĺpce ziacuteskame Obr 44 Ako vidno de-

ničneacute obory niektoryacutech premennyacutech sa po aplikaacutecii ohraničeniacute zuacutežili na jedno konkreacutetne čiacuteslo

(čiacutesla zvyacuterazneneacute oranžovou farbou)

Je zrejmeacute že ak teraz ohraničenia aplikujeme znovu budeme z deničnyacutech oborov niektoryacutech

premennyacutech vedieť vyluacutečiť ďalšie čiacutesla napr v druhom riadku a deviatom stĺpci sa už nesmie

nachaacutedzať čiacuteslo 8 Takisto ho je potrebneacute vyluacutečiť aj zo štvorca č 3 Obdobne pre ďalšie čiacutesla ndash

vyacutesledok je na Obr 45

Vidno teda že ohraničenia nestačiacute aplikovať len raz ndash treba ich aplikovať opakovane až do-

vtedy keď už pomocou nich nevieme vyluacutečiť ďalšie prvky z deničneacuteho oboru žiadnej premennej

Za zmienku stojiacute aj to že (ako by sme si pri ručnej aplikaacutecii postupu ryacutechlo všimli) netreba

zakaždyacutem uvažovať uacuteplne všetky ohraničenia ndash stačiacute znovu aplikovať ohraničenia tyacutekajuacutece sa

tyacutech premennyacutech ktoryacutech deničnyacute obor sa v poslednom kroku zmenil Inyacutemi slovami ndash ak

sa zmeniacute deničnyacute obor premennej xij maacute zmysel znovu aplikovať len ohraničenia pre riadok

stĺpec a štvorec v ktorom sa xij nachaacutedza Ak aplikaacutecia tyacutechto ohraničeniacute vedie k zmene pre

ďalšie premenneacute prirodzene sa pokračuje obdobne aj pre ne

middot 6 middot

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 5: Programovanie ohraničení

SkratkyAC hranovo konzistentnyacute (angl arc consistent) p 13

COP probleacutem optimalizaacutecie ohraničeniacute (angl constraint optimization problem) p 12

CP programovanie ohraničeniacute (angl constraint programming) pp 1 3 4 9 10 12 16 20 22

CSP probleacutem spĺňania ohraničeniacute (angl constraint satisfaction problem) pp 1ndash4 11ndash13 16

17 19 23

PC konzistentnosť po ceste (angl path consistency) p 16

SAT probleacutem spĺňania logickyacutech formuacutel (angl boolean satisability problem) p 3

TSP probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem) pp 20 21

Zoznam obraacutezkov21 Hra Sudoku 2

22 Hra Sudoku ndash riešenie 2

23 Hra Sudoku ndash rozdelenie na štvorce 3

41 Deničneacute obory premennyacutech v hracom poli Sudoku 4

42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek 5

43 Riadkoveacute a stĺpcoveacute ohraničenia 6

44 Po aplikaacutecii ohraničeniacute vieme určiť niektoreacute hodnoty 7

45 Vyacutesledok po ďalšom kroku aplikaacutecie ohraničeniacute 7

46 Stav po aplikaacutecii ohraničeniacute 8

47 Voliacuteme hodnotu 1 pre x11 8

48 Vetvenie pre x11 8

49 Vetvenie pre x14 8

410 Vetvenie pre x14 ndash naacutevrat 8

411 Voliacuteme hodnotu 3 pre x14 9

412 Stav po aplikaacutecii ohraničeniacute ndash praacutezdny deničnyacute obor 9

51 Sklad ohraničeniacute a prehľadaacutevanie scheacutema interakcie 10

52 Sklad ohraničeniacute a prehľadaacutevanie priacuteklad interakcie 10

53 Scheacutema skladu ohraničeniacute 11

61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute 13

91 TSP reprezentaacutecia neohodnotenyacutem neorientovanyacutem grafom 21

middot 3 middot

92 TSP reprezentaacutecia neohodnotenyacutem orientovanyacutem grafom 21

93 TSP reprezentaacutecia ohodnotenyacutem neorientovanyacutem grafom 21

94 TSP reprezentaacutecia ohodnotenyacutem orientovanyacutem grafom 21

middot 4 middot

1 | UacutevodV suacutečasnosti existuje veľkeacute množstvo uacuteloh v raacutemci prebiehajuacuteceho vyacuteskumu aj podnikovej praxe

ktoreacute si vyžadujuacute ryacutechle a efektiacutevne riešenie diskreacutetnych optimalizačnyacutech uacuteloh Možno sem zara-

diť napriacuteklad probleacutemy rozvrhovania plaacutenovacie uacutelohy logistickuacute optimalizaacuteciu a mnoheacute ďalšie

Značnuacute časť z tyacutechto uacuteloh možno formulovať prostredniacutectvom premennyacutech a ohraničeniacute ndash

tj podmienok ktoreacute musia hodnoty premennyacutech spĺňať aby uacutelohu bolo možneacute považovať za

vyriešenuacute Na ilustraacuteciu možno uviesť napriacuteklad dobre znaacutemy probleacutem N daacutem kde je uacutelohou

rozmiestniť N daacutem na šachovnici takyacutem spocircsobom aby sa navzaacutejom neohrozovali hru Sudoku

či probleacutem smerovania vozidiel (angl vehicle routing problem)

Jednou zo znaacutemych a naďalej perspektiacutevnych metoacuted riešiacich uacutelohy tohto typu je progra-

movanie ohraničeniacute (angl constraint programming CP) V nasledujuacutecej štuacutedii sa budeme proble-

matike programovania ohraničeniacute venovať podrobnejšie ndash najprv formaacutelne denujeme probleacutem

spĺňania ohraničeniacute Zmysel deniacutecie vzaacutepaumltiacute budeme ilustrovať na hre Sudoku na ktorej naacutesledne

ozrejmiacuteme aj zaacutekladneacute prvky a princiacutepy programovania ohraničeniacute

Naacutesledne poskytneme aj formaacutelnejšiacute vyacuteklad a podrobnejšiacute prehľad o jednotlivyacutech konceptoch

v CP ako suacute propagaacutecia ohraničeniacute sklad ohraničeniacute overenie korektnosti globaacutelne ohraničenia

konzistenčneacute techniky a pod Postupy budeme na zaacutever ilustrovať niekoľkyacutemi priacutekladmi praktic-

kej implementaacutecie na modelovyacutech uacutelohaacutech

2 | Probleacutem spĺňania ohraničeniacute

Probleacutem spĺňania ohraničeniacute (angl constraint satisfaction problem CSP) možno charakterizovať

trojicou P = 〈XDC〉 [1]

bull X je n-tica premennyacutech X = 〈x1 x2 xn〉

bull D je n-tica ich zodpovedajuacutecich deničnyacutech oborov D = 〈D1 D2 Dn〉 tj xi isin Di

bull a C je t-tica ohraničeniacute C = 〈C1 C2 Ct〉

Každeacute ohraničenieCj tvoriacute paacuter 〈RSj Sj〉 kdeRSj

je relaacutecia nad premennyacutemiSj = rozsah(Cj)[1] Inyacutemi slovami možno povedať žeRSj

je podmnožina karteziaacutenskeho suacutečinu deničnyacutech obo-

rov premennyacutech z Sj [1]1

Riešeniacutem probleacutemu P je n-tica A = 〈a1 a2 an〉 takaacute že platiacute ai isin Di a každeacute ohraničenie

Cj je splneneacute tj pre projekciu A do rozsahu Sj platiacute relaacutecia RSj

1Ku relaacuteciaacutem a karteziaacutenskemu suacutečinu možno pozrieť viac v priacutelohe A

middot 1 middot

Obr 21 Hra Sudoku Obr 22 Hra Sudoku ndash riešenie

21 Formulaacutecia hry Sudoku ako CSP

Hra Sudoku je dobryacutem priacutekladom probleacutemu spĺňania ohraničeniacute Pozostaacuteva z hracieho poľa ur-

čityacutech rozmerov ndash najčastejšie 9times 9 Pole je navyše rozdeleneacute na 9 štvorcov rozmerov 3times 3 (viď

Obr 23) Každeacute poliacutečko mocircže obsahovať čiacuteslo od 1 po 9 Na začiatku hry suacute niektoreacute poliacutečka už

vyplneneacute ndash ostatneacute treba doplniť tak aby boli splneneacute predpiacutesaneacute podmienky

bull Dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9

bull Žiadne čiacuteslo v raacutemci toho isteacuteho stĺpca sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho riadku sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho štvorca sa nesmie opakovať viackraacutet

Ilustraacutecia hracieho poľa je na Obr 21 Vyplneneacute hracie pole je na Obr 22

Ak maacuteme Sudoku opiacutesať ako probleacutem spĺňania ohraničeniacute premenneacute X buduacute tvoriť hodnoty

jednotlivyacutech poliacutečok (dokopy ich bude 9times 9) Deničnyacute obor každej z nich je D = 1 2 9Ak jednotliveacute premenneacute usporiadame do matice mocircžeme ich preindexovať ako xmk kde m

je čiacuteslo riadku a k je čiacuteslo stĺpca Ak potom uvažujeme napriacuteklad ohraničenie pre prvyacute riadok

vieme že pre jeho rozsah platiacute Sr1 = x11 x12 x19 tj ohraničenie zahŕňa praacuteve premenneacute

z prveacuteho riadku

Relaacuteciu pre prvyacute riadok mocircžeme denovať nasledovne

RSr1 = x isin D9|x1i 6= x1j forall 1 le i j 6= 9 i 6= j (21)

middot 2 middot

Obr 23 Hra Sudoku ndash rozdelenie na štvorce

Zo všetkyacutech kombinaacuteciiacute hodnocirct premennyacutech (D9) vyberaacuteme teda len takeacute dosadenia x pri ktoryacutech

platiacute že z hodnocirct v riadku 1 ani dve nie suacute rovnakeacute

Obmedzenie (21) možno zovšeobecniť pre ľubovoľnyacute riadok a obdobne možno denovať os-

tatneacute obmedzenia Keďže tento typ obmedzeniacute sa vyskytuje často existuje preň osobitneacute kľuacutečoveacute

slovo alldierent ndash tj všetky uvedeneacute premenneacute sa musia odlišovať Ako možno toto kľuacutečoveacute

slovo a ineacute kľuacutečoveacute slovaacute použiť v praxi uvidiacuteme na priacutekladoch neskocircr

22 Probleacutem SAT

Za špeciaacutelny priacutepad CSP možno považovať probleacutem spĺňania logickyacutech formuacutel (angl boolean satis-

ability problem SAT) V jeho priacutepade sa deničneacute oboryDi jednotlivyacutech premennyacutech redukujuacute

na Di = true false [1]

3 | Logickeacute programovanie ohraničeniacuteSysteacutemy na programovanie ohraničeniacute typicky integrujuacute koncepty z CP do nejakeacuteho už existu-

juacuteceho programovacieho jazyka Existuje veľkyacute počet implementaacuteciiacute pre mnoho rocircznych jazy-

kov Ako priacuteklady implementaacutecie v klasickyacutech imperatiacutevnych jazykoch možno uviesť knižnicu

Gecode pre C++ knižnicu or-tools ktoruacute možno použiacutevať z C++ Python-u Javy a NET alebo

javoveacute knižnice CHOCO a JaCoP

Osobitnuacute vetvu však tvoria logickeacute deklaratiacutevne jazyky ndash napriacuteklad Prolog ndash ktoreacute sa osobitne

hodia na integraacuteciu CP keďže s niacutem už mnoheacute koncepty zdieľajuacute Prolog napriacuteklad už obsahuje

koncept prehľadaacutevania s naacutevratom ktoryacute (ako uvidiacuteme) sa využiacuteva aj v CP [2]

middot 3 middot

Obr 41 Deničneacute obory premennyacutech v hracom poli Sudoku

Preto aj vyacutevoj v oblasti CP bol historicky do značnej miery spojenyacute praacuteve s jazykom Prolog

a s jeho rocircznymi nadstavbami ndash napr s jazykom CHIP ktoryacute zaviedol programovanie ohraničeniacute

na konečnyacutech deničnyacutech oboroch resp CLP(R) ktoreacute zaviedlo podporu pre ohraničenia na

reaacutelnych čiacuteslach [2] Ďalej ide o rocirczne prologoveacute systeacutemy ako napr ECLiPS

ea SICStus Prolog

[2] Knižnice pre programovanie ohraničeniacute existujuacute aj v inyacutech prologoch (napr clpfd pre SWI-

Prolog) V suacutevislosti s tyacutem sa hovoriacute o tzv logickom programovaniacute ohraničeniacute čiacutem sa mysliacute praacuteve

programovanie ohraničeniacute v raacutemci logickyacutech jazykov ako je Prolog

4 | Programovanie ohraničeniacute ako riešenie SudokuV tejto časti ilustrujeme zaacutekladneacute koncepty programovania ohraničeniacute na hre Sudoku čiacutem si

vybudujeme intuiacuteciu potrebnuacute pre nasledujuacuteci formaacutelnejšiacute vyacuteklad Vyššie sme ukaacutezali že hru

Sudoku možno veľmi prirodzenyacutem spocircsobom reprezentovať ako probleacutem spĺňania ohraničeniacute

(CSP)

Ak maacuteme Sudoku rozmeru 9 times 9 a F poliacutečok už maacute stanoveneacute hodnoty maacuteme 9 times 9 minusF premennyacutech ktoryacutech hodnoty musiacuteme stanoviť Deničnyacute obor každej z nich bude Di =1 2 9 Počiatočnyacute stav mocircžeme ilustrovať tak že do každeacuteho praacutezdneho poliacutečka vpiacutešeme

všetky hodnoty ktoreacute daneacute premennaacute mocircže nadobuacutedať Priacuteklad je na Obr 41

Ako vidno v hracom poli Obr 41 je preddenovanyacutech 31 poliacutečok Doplniť teda treba zvyš-

nyacutech 50 poliacutečok z ktoryacutech každeacute mocircže obsahovať hodnoty od 1 po 9 tak aby boli splneneacute všetky

ohraničenia

middot 4 middot

(a) (b) (c)

Obr 42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek

41 Aplikaacutecia ohraničeniacute hry Sudoku

O ohraničeniach hry Sudoku sme hovorili vyššie teraz ich budeme ilustrovať na priacuteklade Ako

prveacute ohraničenie sme uviedli že dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9 Toto ohraničenie

sme už zahrnuli pri určeniacute deničneacuteho oboru premennyacutech ďalej ho teda uvažovať nemusiacuteme

Prejdeme teda postupne len ostatneacute ohraničenia

411 Štvorcoveacute ohraničenia

Začnime štvorcovyacutemi ohraničeniami Princiacutep budeme ilustrovať na štvorcovom vyacuteseku z ľaveacuteho

horneacuteho rohu ktoryacute je na Obr 42a Ako vidno tri poliacutečka už majuacute preddenovaneacute hodnoty

x22 = 5 x31 = 3 a x33 = 4 Keďže tie isteacute hodnoty sa v raacutemci štvorca nesmuacute opakovať viackraacutet

je jasneacute že z deničnyacutech oborov ostatnyacutech premennyacutech mocircžeme čiacutesla 3 4 a 5 vyluacutečiť ako to

ilustrujuacute Obr 42b a 42c

Aplikujme teda obdobnyacutem spocircsobom štvorcoveacute ohraničenia na všetky štvorce a pokračujme

ďalej riadkovyacutemi a stĺpcovyacutemi ohraničeniami

412 Riadkoveacute a stĺpcoveacute ohraničenia

Priacuteklad aplikaacutecie riadkoveacuteho ohraničenia pre prvyacute riadok je na Obr 43a Ako vidno v riadku sa

vyskytuje jedna preddenovanaacute hodnota ndash čiacuteslo 9 ktoruacute je potrebneacute vyluacutečiť z deničnyacutech oborov

všetkyacutech ostatnyacutech premennyacutech v danom riadku

Ak naacutesledne budeme ilustrovať priacuteklad stĺpcoveacuteho ohraničenia na ocircsmom stĺpci ziacuteskame

Obr 43b Ako vidno vylučujeme hodnoty 9 6 7 a 1

middot 5 middot

(a) Priacuteklad riadkoveacuteho ohraničenia (b) Priacuteklad stĺpcoveacuteho ohraničenia

Obr 43 Riadkoveacute a stĺpcoveacute ohraničenia

42 Ohraničenia aplikujeme opakovane

Ak aplikujeme ohraničenia pre všetky štvorce riadky a stĺpce ziacuteskame Obr 44 Ako vidno de-

ničneacute obory niektoryacutech premennyacutech sa po aplikaacutecii ohraničeniacute zuacutežili na jedno konkreacutetne čiacuteslo

(čiacutesla zvyacuterazneneacute oranžovou farbou)

Je zrejmeacute že ak teraz ohraničenia aplikujeme znovu budeme z deničnyacutech oborov niektoryacutech

premennyacutech vedieť vyluacutečiť ďalšie čiacutesla napr v druhom riadku a deviatom stĺpci sa už nesmie

nachaacutedzať čiacuteslo 8 Takisto ho je potrebneacute vyluacutečiť aj zo štvorca č 3 Obdobne pre ďalšie čiacutesla ndash

vyacutesledok je na Obr 45

Vidno teda že ohraničenia nestačiacute aplikovať len raz ndash treba ich aplikovať opakovane až do-

vtedy keď už pomocou nich nevieme vyluacutečiť ďalšie prvky z deničneacuteho oboru žiadnej premennej

Za zmienku stojiacute aj to že (ako by sme si pri ručnej aplikaacutecii postupu ryacutechlo všimli) netreba

zakaždyacutem uvažovať uacuteplne všetky ohraničenia ndash stačiacute znovu aplikovať ohraničenia tyacutekajuacutece sa

tyacutech premennyacutech ktoryacutech deničnyacute obor sa v poslednom kroku zmenil Inyacutemi slovami ndash ak

sa zmeniacute deničnyacute obor premennej xij maacute zmysel znovu aplikovať len ohraničenia pre riadok

stĺpec a štvorec v ktorom sa xij nachaacutedza Ak aplikaacutecia tyacutechto ohraničeniacute vedie k zmene pre

ďalšie premenneacute prirodzene sa pokračuje obdobne aj pre ne

middot 6 middot

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 6: Programovanie ohraničení

92 TSP reprezentaacutecia neohodnotenyacutem orientovanyacutem grafom 21

93 TSP reprezentaacutecia ohodnotenyacutem neorientovanyacutem grafom 21

94 TSP reprezentaacutecia ohodnotenyacutem orientovanyacutem grafom 21

middot 4 middot

1 | UacutevodV suacutečasnosti existuje veľkeacute množstvo uacuteloh v raacutemci prebiehajuacuteceho vyacuteskumu aj podnikovej praxe

ktoreacute si vyžadujuacute ryacutechle a efektiacutevne riešenie diskreacutetnych optimalizačnyacutech uacuteloh Možno sem zara-

diť napriacuteklad probleacutemy rozvrhovania plaacutenovacie uacutelohy logistickuacute optimalizaacuteciu a mnoheacute ďalšie

Značnuacute časť z tyacutechto uacuteloh možno formulovať prostredniacutectvom premennyacutech a ohraničeniacute ndash

tj podmienok ktoreacute musia hodnoty premennyacutech spĺňať aby uacutelohu bolo možneacute považovať za

vyriešenuacute Na ilustraacuteciu možno uviesť napriacuteklad dobre znaacutemy probleacutem N daacutem kde je uacutelohou

rozmiestniť N daacutem na šachovnici takyacutem spocircsobom aby sa navzaacutejom neohrozovali hru Sudoku

či probleacutem smerovania vozidiel (angl vehicle routing problem)

Jednou zo znaacutemych a naďalej perspektiacutevnych metoacuted riešiacich uacutelohy tohto typu je progra-

movanie ohraničeniacute (angl constraint programming CP) V nasledujuacutecej štuacutedii sa budeme proble-

matike programovania ohraničeniacute venovať podrobnejšie ndash najprv formaacutelne denujeme probleacutem

spĺňania ohraničeniacute Zmysel deniacutecie vzaacutepaumltiacute budeme ilustrovať na hre Sudoku na ktorej naacutesledne

ozrejmiacuteme aj zaacutekladneacute prvky a princiacutepy programovania ohraničeniacute

Naacutesledne poskytneme aj formaacutelnejšiacute vyacuteklad a podrobnejšiacute prehľad o jednotlivyacutech konceptoch

v CP ako suacute propagaacutecia ohraničeniacute sklad ohraničeniacute overenie korektnosti globaacutelne ohraničenia

konzistenčneacute techniky a pod Postupy budeme na zaacutever ilustrovať niekoľkyacutemi priacutekladmi praktic-

kej implementaacutecie na modelovyacutech uacutelohaacutech

2 | Probleacutem spĺňania ohraničeniacute

Probleacutem spĺňania ohraničeniacute (angl constraint satisfaction problem CSP) možno charakterizovať

trojicou P = 〈XDC〉 [1]

bull X je n-tica premennyacutech X = 〈x1 x2 xn〉

bull D je n-tica ich zodpovedajuacutecich deničnyacutech oborov D = 〈D1 D2 Dn〉 tj xi isin Di

bull a C je t-tica ohraničeniacute C = 〈C1 C2 Ct〉

Každeacute ohraničenieCj tvoriacute paacuter 〈RSj Sj〉 kdeRSj

je relaacutecia nad premennyacutemiSj = rozsah(Cj)[1] Inyacutemi slovami možno povedať žeRSj

je podmnožina karteziaacutenskeho suacutečinu deničnyacutech obo-

rov premennyacutech z Sj [1]1

Riešeniacutem probleacutemu P je n-tica A = 〈a1 a2 an〉 takaacute že platiacute ai isin Di a každeacute ohraničenie

Cj je splneneacute tj pre projekciu A do rozsahu Sj platiacute relaacutecia RSj

1Ku relaacuteciaacutem a karteziaacutenskemu suacutečinu možno pozrieť viac v priacutelohe A

middot 1 middot

Obr 21 Hra Sudoku Obr 22 Hra Sudoku ndash riešenie

21 Formulaacutecia hry Sudoku ako CSP

Hra Sudoku je dobryacutem priacutekladom probleacutemu spĺňania ohraničeniacute Pozostaacuteva z hracieho poľa ur-

čityacutech rozmerov ndash najčastejšie 9times 9 Pole je navyše rozdeleneacute na 9 štvorcov rozmerov 3times 3 (viď

Obr 23) Každeacute poliacutečko mocircže obsahovať čiacuteslo od 1 po 9 Na začiatku hry suacute niektoreacute poliacutečka už

vyplneneacute ndash ostatneacute treba doplniť tak aby boli splneneacute predpiacutesaneacute podmienky

bull Dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9

bull Žiadne čiacuteslo v raacutemci toho isteacuteho stĺpca sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho riadku sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho štvorca sa nesmie opakovať viackraacutet

Ilustraacutecia hracieho poľa je na Obr 21 Vyplneneacute hracie pole je na Obr 22

Ak maacuteme Sudoku opiacutesať ako probleacutem spĺňania ohraničeniacute premenneacute X buduacute tvoriť hodnoty

jednotlivyacutech poliacutečok (dokopy ich bude 9times 9) Deničnyacute obor každej z nich je D = 1 2 9Ak jednotliveacute premenneacute usporiadame do matice mocircžeme ich preindexovať ako xmk kde m

je čiacuteslo riadku a k je čiacuteslo stĺpca Ak potom uvažujeme napriacuteklad ohraničenie pre prvyacute riadok

vieme že pre jeho rozsah platiacute Sr1 = x11 x12 x19 tj ohraničenie zahŕňa praacuteve premenneacute

z prveacuteho riadku

Relaacuteciu pre prvyacute riadok mocircžeme denovať nasledovne

RSr1 = x isin D9|x1i 6= x1j forall 1 le i j 6= 9 i 6= j (21)

middot 2 middot

Obr 23 Hra Sudoku ndash rozdelenie na štvorce

Zo všetkyacutech kombinaacuteciiacute hodnocirct premennyacutech (D9) vyberaacuteme teda len takeacute dosadenia x pri ktoryacutech

platiacute že z hodnocirct v riadku 1 ani dve nie suacute rovnakeacute

Obmedzenie (21) možno zovšeobecniť pre ľubovoľnyacute riadok a obdobne možno denovať os-

tatneacute obmedzenia Keďže tento typ obmedzeniacute sa vyskytuje často existuje preň osobitneacute kľuacutečoveacute

slovo alldierent ndash tj všetky uvedeneacute premenneacute sa musia odlišovať Ako možno toto kľuacutečoveacute

slovo a ineacute kľuacutečoveacute slovaacute použiť v praxi uvidiacuteme na priacutekladoch neskocircr

22 Probleacutem SAT

Za špeciaacutelny priacutepad CSP možno považovať probleacutem spĺňania logickyacutech formuacutel (angl boolean satis-

ability problem SAT) V jeho priacutepade sa deničneacute oboryDi jednotlivyacutech premennyacutech redukujuacute

na Di = true false [1]

3 | Logickeacute programovanie ohraničeniacuteSysteacutemy na programovanie ohraničeniacute typicky integrujuacute koncepty z CP do nejakeacuteho už existu-

juacuteceho programovacieho jazyka Existuje veľkyacute počet implementaacuteciiacute pre mnoho rocircznych jazy-

kov Ako priacuteklady implementaacutecie v klasickyacutech imperatiacutevnych jazykoch možno uviesť knižnicu

Gecode pre C++ knižnicu or-tools ktoruacute možno použiacutevať z C++ Python-u Javy a NET alebo

javoveacute knižnice CHOCO a JaCoP

Osobitnuacute vetvu však tvoria logickeacute deklaratiacutevne jazyky ndash napriacuteklad Prolog ndash ktoreacute sa osobitne

hodia na integraacuteciu CP keďže s niacutem už mnoheacute koncepty zdieľajuacute Prolog napriacuteklad už obsahuje

koncept prehľadaacutevania s naacutevratom ktoryacute (ako uvidiacuteme) sa využiacuteva aj v CP [2]

middot 3 middot

Obr 41 Deničneacute obory premennyacutech v hracom poli Sudoku

Preto aj vyacutevoj v oblasti CP bol historicky do značnej miery spojenyacute praacuteve s jazykom Prolog

a s jeho rocircznymi nadstavbami ndash napr s jazykom CHIP ktoryacute zaviedol programovanie ohraničeniacute

na konečnyacutech deničnyacutech oboroch resp CLP(R) ktoreacute zaviedlo podporu pre ohraničenia na

reaacutelnych čiacuteslach [2] Ďalej ide o rocirczne prologoveacute systeacutemy ako napr ECLiPS

ea SICStus Prolog

[2] Knižnice pre programovanie ohraničeniacute existujuacute aj v inyacutech prologoch (napr clpfd pre SWI-

Prolog) V suacutevislosti s tyacutem sa hovoriacute o tzv logickom programovaniacute ohraničeniacute čiacutem sa mysliacute praacuteve

programovanie ohraničeniacute v raacutemci logickyacutech jazykov ako je Prolog

4 | Programovanie ohraničeniacute ako riešenie SudokuV tejto časti ilustrujeme zaacutekladneacute koncepty programovania ohraničeniacute na hre Sudoku čiacutem si

vybudujeme intuiacuteciu potrebnuacute pre nasledujuacuteci formaacutelnejšiacute vyacuteklad Vyššie sme ukaacutezali že hru

Sudoku možno veľmi prirodzenyacutem spocircsobom reprezentovať ako probleacutem spĺňania ohraničeniacute

(CSP)

Ak maacuteme Sudoku rozmeru 9 times 9 a F poliacutečok už maacute stanoveneacute hodnoty maacuteme 9 times 9 minusF premennyacutech ktoryacutech hodnoty musiacuteme stanoviť Deničnyacute obor každej z nich bude Di =1 2 9 Počiatočnyacute stav mocircžeme ilustrovať tak že do každeacuteho praacutezdneho poliacutečka vpiacutešeme

všetky hodnoty ktoreacute daneacute premennaacute mocircže nadobuacutedať Priacuteklad je na Obr 41

Ako vidno v hracom poli Obr 41 je preddenovanyacutech 31 poliacutečok Doplniť teda treba zvyš-

nyacutech 50 poliacutečok z ktoryacutech každeacute mocircže obsahovať hodnoty od 1 po 9 tak aby boli splneneacute všetky

ohraničenia

middot 4 middot

(a) (b) (c)

Obr 42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek

41 Aplikaacutecia ohraničeniacute hry Sudoku

O ohraničeniach hry Sudoku sme hovorili vyššie teraz ich budeme ilustrovať na priacuteklade Ako

prveacute ohraničenie sme uviedli že dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9 Toto ohraničenie

sme už zahrnuli pri určeniacute deničneacuteho oboru premennyacutech ďalej ho teda uvažovať nemusiacuteme

Prejdeme teda postupne len ostatneacute ohraničenia

411 Štvorcoveacute ohraničenia

Začnime štvorcovyacutemi ohraničeniami Princiacutep budeme ilustrovať na štvorcovom vyacuteseku z ľaveacuteho

horneacuteho rohu ktoryacute je na Obr 42a Ako vidno tri poliacutečka už majuacute preddenovaneacute hodnoty

x22 = 5 x31 = 3 a x33 = 4 Keďže tie isteacute hodnoty sa v raacutemci štvorca nesmuacute opakovať viackraacutet

je jasneacute že z deničnyacutech oborov ostatnyacutech premennyacutech mocircžeme čiacutesla 3 4 a 5 vyluacutečiť ako to

ilustrujuacute Obr 42b a 42c

Aplikujme teda obdobnyacutem spocircsobom štvorcoveacute ohraničenia na všetky štvorce a pokračujme

ďalej riadkovyacutemi a stĺpcovyacutemi ohraničeniami

412 Riadkoveacute a stĺpcoveacute ohraničenia

Priacuteklad aplikaacutecie riadkoveacuteho ohraničenia pre prvyacute riadok je na Obr 43a Ako vidno v riadku sa

vyskytuje jedna preddenovanaacute hodnota ndash čiacuteslo 9 ktoruacute je potrebneacute vyluacutečiť z deničnyacutech oborov

všetkyacutech ostatnyacutech premennyacutech v danom riadku

Ak naacutesledne budeme ilustrovať priacuteklad stĺpcoveacuteho ohraničenia na ocircsmom stĺpci ziacuteskame

Obr 43b Ako vidno vylučujeme hodnoty 9 6 7 a 1

middot 5 middot

(a) Priacuteklad riadkoveacuteho ohraničenia (b) Priacuteklad stĺpcoveacuteho ohraničenia

Obr 43 Riadkoveacute a stĺpcoveacute ohraničenia

42 Ohraničenia aplikujeme opakovane

Ak aplikujeme ohraničenia pre všetky štvorce riadky a stĺpce ziacuteskame Obr 44 Ako vidno de-

ničneacute obory niektoryacutech premennyacutech sa po aplikaacutecii ohraničeniacute zuacutežili na jedno konkreacutetne čiacuteslo

(čiacutesla zvyacuterazneneacute oranžovou farbou)

Je zrejmeacute že ak teraz ohraničenia aplikujeme znovu budeme z deničnyacutech oborov niektoryacutech

premennyacutech vedieť vyluacutečiť ďalšie čiacutesla napr v druhom riadku a deviatom stĺpci sa už nesmie

nachaacutedzať čiacuteslo 8 Takisto ho je potrebneacute vyluacutečiť aj zo štvorca č 3 Obdobne pre ďalšie čiacutesla ndash

vyacutesledok je na Obr 45

Vidno teda že ohraničenia nestačiacute aplikovať len raz ndash treba ich aplikovať opakovane až do-

vtedy keď už pomocou nich nevieme vyluacutečiť ďalšie prvky z deničneacuteho oboru žiadnej premennej

Za zmienku stojiacute aj to že (ako by sme si pri ručnej aplikaacutecii postupu ryacutechlo všimli) netreba

zakaždyacutem uvažovať uacuteplne všetky ohraničenia ndash stačiacute znovu aplikovať ohraničenia tyacutekajuacutece sa

tyacutech premennyacutech ktoryacutech deničnyacute obor sa v poslednom kroku zmenil Inyacutemi slovami ndash ak

sa zmeniacute deničnyacute obor premennej xij maacute zmysel znovu aplikovať len ohraničenia pre riadok

stĺpec a štvorec v ktorom sa xij nachaacutedza Ak aplikaacutecia tyacutechto ohraničeniacute vedie k zmene pre

ďalšie premenneacute prirodzene sa pokračuje obdobne aj pre ne

middot 6 middot

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 7: Programovanie ohraničení

1 | UacutevodV suacutečasnosti existuje veľkeacute množstvo uacuteloh v raacutemci prebiehajuacuteceho vyacuteskumu aj podnikovej praxe

ktoreacute si vyžadujuacute ryacutechle a efektiacutevne riešenie diskreacutetnych optimalizačnyacutech uacuteloh Možno sem zara-

diť napriacuteklad probleacutemy rozvrhovania plaacutenovacie uacutelohy logistickuacute optimalizaacuteciu a mnoheacute ďalšie

Značnuacute časť z tyacutechto uacuteloh možno formulovať prostredniacutectvom premennyacutech a ohraničeniacute ndash

tj podmienok ktoreacute musia hodnoty premennyacutech spĺňať aby uacutelohu bolo možneacute považovať za

vyriešenuacute Na ilustraacuteciu možno uviesť napriacuteklad dobre znaacutemy probleacutem N daacutem kde je uacutelohou

rozmiestniť N daacutem na šachovnici takyacutem spocircsobom aby sa navzaacutejom neohrozovali hru Sudoku

či probleacutem smerovania vozidiel (angl vehicle routing problem)

Jednou zo znaacutemych a naďalej perspektiacutevnych metoacuted riešiacich uacutelohy tohto typu je progra-

movanie ohraničeniacute (angl constraint programming CP) V nasledujuacutecej štuacutedii sa budeme proble-

matike programovania ohraničeniacute venovať podrobnejšie ndash najprv formaacutelne denujeme probleacutem

spĺňania ohraničeniacute Zmysel deniacutecie vzaacutepaumltiacute budeme ilustrovať na hre Sudoku na ktorej naacutesledne

ozrejmiacuteme aj zaacutekladneacute prvky a princiacutepy programovania ohraničeniacute

Naacutesledne poskytneme aj formaacutelnejšiacute vyacuteklad a podrobnejšiacute prehľad o jednotlivyacutech konceptoch

v CP ako suacute propagaacutecia ohraničeniacute sklad ohraničeniacute overenie korektnosti globaacutelne ohraničenia

konzistenčneacute techniky a pod Postupy budeme na zaacutever ilustrovať niekoľkyacutemi priacutekladmi praktic-

kej implementaacutecie na modelovyacutech uacutelohaacutech

2 | Probleacutem spĺňania ohraničeniacute

Probleacutem spĺňania ohraničeniacute (angl constraint satisfaction problem CSP) možno charakterizovať

trojicou P = 〈XDC〉 [1]

bull X je n-tica premennyacutech X = 〈x1 x2 xn〉

bull D je n-tica ich zodpovedajuacutecich deničnyacutech oborov D = 〈D1 D2 Dn〉 tj xi isin Di

bull a C je t-tica ohraničeniacute C = 〈C1 C2 Ct〉

Každeacute ohraničenieCj tvoriacute paacuter 〈RSj Sj〉 kdeRSj

je relaacutecia nad premennyacutemiSj = rozsah(Cj)[1] Inyacutemi slovami možno povedať žeRSj

je podmnožina karteziaacutenskeho suacutečinu deničnyacutech obo-

rov premennyacutech z Sj [1]1

Riešeniacutem probleacutemu P je n-tica A = 〈a1 a2 an〉 takaacute že platiacute ai isin Di a každeacute ohraničenie

Cj je splneneacute tj pre projekciu A do rozsahu Sj platiacute relaacutecia RSj

1Ku relaacuteciaacutem a karteziaacutenskemu suacutečinu možno pozrieť viac v priacutelohe A

middot 1 middot

Obr 21 Hra Sudoku Obr 22 Hra Sudoku ndash riešenie

21 Formulaacutecia hry Sudoku ako CSP

Hra Sudoku je dobryacutem priacutekladom probleacutemu spĺňania ohraničeniacute Pozostaacuteva z hracieho poľa ur-

čityacutech rozmerov ndash najčastejšie 9times 9 Pole je navyše rozdeleneacute na 9 štvorcov rozmerov 3times 3 (viď

Obr 23) Každeacute poliacutečko mocircže obsahovať čiacuteslo od 1 po 9 Na začiatku hry suacute niektoreacute poliacutečka už

vyplneneacute ndash ostatneacute treba doplniť tak aby boli splneneacute predpiacutesaneacute podmienky

bull Dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9

bull Žiadne čiacuteslo v raacutemci toho isteacuteho stĺpca sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho riadku sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho štvorca sa nesmie opakovať viackraacutet

Ilustraacutecia hracieho poľa je na Obr 21 Vyplneneacute hracie pole je na Obr 22

Ak maacuteme Sudoku opiacutesať ako probleacutem spĺňania ohraničeniacute premenneacute X buduacute tvoriť hodnoty

jednotlivyacutech poliacutečok (dokopy ich bude 9times 9) Deničnyacute obor každej z nich je D = 1 2 9Ak jednotliveacute premenneacute usporiadame do matice mocircžeme ich preindexovať ako xmk kde m

je čiacuteslo riadku a k je čiacuteslo stĺpca Ak potom uvažujeme napriacuteklad ohraničenie pre prvyacute riadok

vieme že pre jeho rozsah platiacute Sr1 = x11 x12 x19 tj ohraničenie zahŕňa praacuteve premenneacute

z prveacuteho riadku

Relaacuteciu pre prvyacute riadok mocircžeme denovať nasledovne

RSr1 = x isin D9|x1i 6= x1j forall 1 le i j 6= 9 i 6= j (21)

middot 2 middot

Obr 23 Hra Sudoku ndash rozdelenie na štvorce

Zo všetkyacutech kombinaacuteciiacute hodnocirct premennyacutech (D9) vyberaacuteme teda len takeacute dosadenia x pri ktoryacutech

platiacute že z hodnocirct v riadku 1 ani dve nie suacute rovnakeacute

Obmedzenie (21) možno zovšeobecniť pre ľubovoľnyacute riadok a obdobne možno denovať os-

tatneacute obmedzenia Keďže tento typ obmedzeniacute sa vyskytuje často existuje preň osobitneacute kľuacutečoveacute

slovo alldierent ndash tj všetky uvedeneacute premenneacute sa musia odlišovať Ako možno toto kľuacutečoveacute

slovo a ineacute kľuacutečoveacute slovaacute použiť v praxi uvidiacuteme na priacutekladoch neskocircr

22 Probleacutem SAT

Za špeciaacutelny priacutepad CSP možno považovať probleacutem spĺňania logickyacutech formuacutel (angl boolean satis-

ability problem SAT) V jeho priacutepade sa deničneacute oboryDi jednotlivyacutech premennyacutech redukujuacute

na Di = true false [1]

3 | Logickeacute programovanie ohraničeniacuteSysteacutemy na programovanie ohraničeniacute typicky integrujuacute koncepty z CP do nejakeacuteho už existu-

juacuteceho programovacieho jazyka Existuje veľkyacute počet implementaacuteciiacute pre mnoho rocircznych jazy-

kov Ako priacuteklady implementaacutecie v klasickyacutech imperatiacutevnych jazykoch možno uviesť knižnicu

Gecode pre C++ knižnicu or-tools ktoruacute možno použiacutevať z C++ Python-u Javy a NET alebo

javoveacute knižnice CHOCO a JaCoP

Osobitnuacute vetvu však tvoria logickeacute deklaratiacutevne jazyky ndash napriacuteklad Prolog ndash ktoreacute sa osobitne

hodia na integraacuteciu CP keďže s niacutem už mnoheacute koncepty zdieľajuacute Prolog napriacuteklad už obsahuje

koncept prehľadaacutevania s naacutevratom ktoryacute (ako uvidiacuteme) sa využiacuteva aj v CP [2]

middot 3 middot

Obr 41 Deničneacute obory premennyacutech v hracom poli Sudoku

Preto aj vyacutevoj v oblasti CP bol historicky do značnej miery spojenyacute praacuteve s jazykom Prolog

a s jeho rocircznymi nadstavbami ndash napr s jazykom CHIP ktoryacute zaviedol programovanie ohraničeniacute

na konečnyacutech deničnyacutech oboroch resp CLP(R) ktoreacute zaviedlo podporu pre ohraničenia na

reaacutelnych čiacuteslach [2] Ďalej ide o rocirczne prologoveacute systeacutemy ako napr ECLiPS

ea SICStus Prolog

[2] Knižnice pre programovanie ohraničeniacute existujuacute aj v inyacutech prologoch (napr clpfd pre SWI-

Prolog) V suacutevislosti s tyacutem sa hovoriacute o tzv logickom programovaniacute ohraničeniacute čiacutem sa mysliacute praacuteve

programovanie ohraničeniacute v raacutemci logickyacutech jazykov ako je Prolog

4 | Programovanie ohraničeniacute ako riešenie SudokuV tejto časti ilustrujeme zaacutekladneacute koncepty programovania ohraničeniacute na hre Sudoku čiacutem si

vybudujeme intuiacuteciu potrebnuacute pre nasledujuacuteci formaacutelnejšiacute vyacuteklad Vyššie sme ukaacutezali že hru

Sudoku možno veľmi prirodzenyacutem spocircsobom reprezentovať ako probleacutem spĺňania ohraničeniacute

(CSP)

Ak maacuteme Sudoku rozmeru 9 times 9 a F poliacutečok už maacute stanoveneacute hodnoty maacuteme 9 times 9 minusF premennyacutech ktoryacutech hodnoty musiacuteme stanoviť Deničnyacute obor každej z nich bude Di =1 2 9 Počiatočnyacute stav mocircžeme ilustrovať tak že do každeacuteho praacutezdneho poliacutečka vpiacutešeme

všetky hodnoty ktoreacute daneacute premennaacute mocircže nadobuacutedať Priacuteklad je na Obr 41

Ako vidno v hracom poli Obr 41 je preddenovanyacutech 31 poliacutečok Doplniť teda treba zvyš-

nyacutech 50 poliacutečok z ktoryacutech každeacute mocircže obsahovať hodnoty od 1 po 9 tak aby boli splneneacute všetky

ohraničenia

middot 4 middot

(a) (b) (c)

Obr 42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek

41 Aplikaacutecia ohraničeniacute hry Sudoku

O ohraničeniach hry Sudoku sme hovorili vyššie teraz ich budeme ilustrovať na priacuteklade Ako

prveacute ohraničenie sme uviedli že dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9 Toto ohraničenie

sme už zahrnuli pri určeniacute deničneacuteho oboru premennyacutech ďalej ho teda uvažovať nemusiacuteme

Prejdeme teda postupne len ostatneacute ohraničenia

411 Štvorcoveacute ohraničenia

Začnime štvorcovyacutemi ohraničeniami Princiacutep budeme ilustrovať na štvorcovom vyacuteseku z ľaveacuteho

horneacuteho rohu ktoryacute je na Obr 42a Ako vidno tri poliacutečka už majuacute preddenovaneacute hodnoty

x22 = 5 x31 = 3 a x33 = 4 Keďže tie isteacute hodnoty sa v raacutemci štvorca nesmuacute opakovať viackraacutet

je jasneacute že z deničnyacutech oborov ostatnyacutech premennyacutech mocircžeme čiacutesla 3 4 a 5 vyluacutečiť ako to

ilustrujuacute Obr 42b a 42c

Aplikujme teda obdobnyacutem spocircsobom štvorcoveacute ohraničenia na všetky štvorce a pokračujme

ďalej riadkovyacutemi a stĺpcovyacutemi ohraničeniami

412 Riadkoveacute a stĺpcoveacute ohraničenia

Priacuteklad aplikaacutecie riadkoveacuteho ohraničenia pre prvyacute riadok je na Obr 43a Ako vidno v riadku sa

vyskytuje jedna preddenovanaacute hodnota ndash čiacuteslo 9 ktoruacute je potrebneacute vyluacutečiť z deničnyacutech oborov

všetkyacutech ostatnyacutech premennyacutech v danom riadku

Ak naacutesledne budeme ilustrovať priacuteklad stĺpcoveacuteho ohraničenia na ocircsmom stĺpci ziacuteskame

Obr 43b Ako vidno vylučujeme hodnoty 9 6 7 a 1

middot 5 middot

(a) Priacuteklad riadkoveacuteho ohraničenia (b) Priacuteklad stĺpcoveacuteho ohraničenia

Obr 43 Riadkoveacute a stĺpcoveacute ohraničenia

42 Ohraničenia aplikujeme opakovane

Ak aplikujeme ohraničenia pre všetky štvorce riadky a stĺpce ziacuteskame Obr 44 Ako vidno de-

ničneacute obory niektoryacutech premennyacutech sa po aplikaacutecii ohraničeniacute zuacutežili na jedno konkreacutetne čiacuteslo

(čiacutesla zvyacuterazneneacute oranžovou farbou)

Je zrejmeacute že ak teraz ohraničenia aplikujeme znovu budeme z deničnyacutech oborov niektoryacutech

premennyacutech vedieť vyluacutečiť ďalšie čiacutesla napr v druhom riadku a deviatom stĺpci sa už nesmie

nachaacutedzať čiacuteslo 8 Takisto ho je potrebneacute vyluacutečiť aj zo štvorca č 3 Obdobne pre ďalšie čiacutesla ndash

vyacutesledok je na Obr 45

Vidno teda že ohraničenia nestačiacute aplikovať len raz ndash treba ich aplikovať opakovane až do-

vtedy keď už pomocou nich nevieme vyluacutečiť ďalšie prvky z deničneacuteho oboru žiadnej premennej

Za zmienku stojiacute aj to že (ako by sme si pri ručnej aplikaacutecii postupu ryacutechlo všimli) netreba

zakaždyacutem uvažovať uacuteplne všetky ohraničenia ndash stačiacute znovu aplikovať ohraničenia tyacutekajuacutece sa

tyacutech premennyacutech ktoryacutech deničnyacute obor sa v poslednom kroku zmenil Inyacutemi slovami ndash ak

sa zmeniacute deničnyacute obor premennej xij maacute zmysel znovu aplikovať len ohraničenia pre riadok

stĺpec a štvorec v ktorom sa xij nachaacutedza Ak aplikaacutecia tyacutechto ohraničeniacute vedie k zmene pre

ďalšie premenneacute prirodzene sa pokračuje obdobne aj pre ne

middot 6 middot

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 8: Programovanie ohraničení

Obr 21 Hra Sudoku Obr 22 Hra Sudoku ndash riešenie

21 Formulaacutecia hry Sudoku ako CSP

Hra Sudoku je dobryacutem priacutekladom probleacutemu spĺňania ohraničeniacute Pozostaacuteva z hracieho poľa ur-

čityacutech rozmerov ndash najčastejšie 9times 9 Pole je navyše rozdeleneacute na 9 štvorcov rozmerov 3times 3 (viď

Obr 23) Každeacute poliacutečko mocircže obsahovať čiacuteslo od 1 po 9 Na začiatku hry suacute niektoreacute poliacutečka už

vyplneneacute ndash ostatneacute treba doplniť tak aby boli splneneacute predpiacutesaneacute podmienky

bull Dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9

bull Žiadne čiacuteslo v raacutemci toho isteacuteho stĺpca sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho riadku sa nesmie opakovať viackraacutet

bull Žiadne čiacuteslo v raacutemci toho isteacuteho štvorca sa nesmie opakovať viackraacutet

Ilustraacutecia hracieho poľa je na Obr 21 Vyplneneacute hracie pole je na Obr 22

Ak maacuteme Sudoku opiacutesať ako probleacutem spĺňania ohraničeniacute premenneacute X buduacute tvoriť hodnoty

jednotlivyacutech poliacutečok (dokopy ich bude 9times 9) Deničnyacute obor každej z nich je D = 1 2 9Ak jednotliveacute premenneacute usporiadame do matice mocircžeme ich preindexovať ako xmk kde m

je čiacuteslo riadku a k je čiacuteslo stĺpca Ak potom uvažujeme napriacuteklad ohraničenie pre prvyacute riadok

vieme že pre jeho rozsah platiacute Sr1 = x11 x12 x19 tj ohraničenie zahŕňa praacuteve premenneacute

z prveacuteho riadku

Relaacuteciu pre prvyacute riadok mocircžeme denovať nasledovne

RSr1 = x isin D9|x1i 6= x1j forall 1 le i j 6= 9 i 6= j (21)

middot 2 middot

Obr 23 Hra Sudoku ndash rozdelenie na štvorce

Zo všetkyacutech kombinaacuteciiacute hodnocirct premennyacutech (D9) vyberaacuteme teda len takeacute dosadenia x pri ktoryacutech

platiacute že z hodnocirct v riadku 1 ani dve nie suacute rovnakeacute

Obmedzenie (21) možno zovšeobecniť pre ľubovoľnyacute riadok a obdobne možno denovať os-

tatneacute obmedzenia Keďže tento typ obmedzeniacute sa vyskytuje často existuje preň osobitneacute kľuacutečoveacute

slovo alldierent ndash tj všetky uvedeneacute premenneacute sa musia odlišovať Ako možno toto kľuacutečoveacute

slovo a ineacute kľuacutečoveacute slovaacute použiť v praxi uvidiacuteme na priacutekladoch neskocircr

22 Probleacutem SAT

Za špeciaacutelny priacutepad CSP možno považovať probleacutem spĺňania logickyacutech formuacutel (angl boolean satis-

ability problem SAT) V jeho priacutepade sa deničneacute oboryDi jednotlivyacutech premennyacutech redukujuacute

na Di = true false [1]

3 | Logickeacute programovanie ohraničeniacuteSysteacutemy na programovanie ohraničeniacute typicky integrujuacute koncepty z CP do nejakeacuteho už existu-

juacuteceho programovacieho jazyka Existuje veľkyacute počet implementaacuteciiacute pre mnoho rocircznych jazy-

kov Ako priacuteklady implementaacutecie v klasickyacutech imperatiacutevnych jazykoch možno uviesť knižnicu

Gecode pre C++ knižnicu or-tools ktoruacute možno použiacutevať z C++ Python-u Javy a NET alebo

javoveacute knižnice CHOCO a JaCoP

Osobitnuacute vetvu však tvoria logickeacute deklaratiacutevne jazyky ndash napriacuteklad Prolog ndash ktoreacute sa osobitne

hodia na integraacuteciu CP keďže s niacutem už mnoheacute koncepty zdieľajuacute Prolog napriacuteklad už obsahuje

koncept prehľadaacutevania s naacutevratom ktoryacute (ako uvidiacuteme) sa využiacuteva aj v CP [2]

middot 3 middot

Obr 41 Deničneacute obory premennyacutech v hracom poli Sudoku

Preto aj vyacutevoj v oblasti CP bol historicky do značnej miery spojenyacute praacuteve s jazykom Prolog

a s jeho rocircznymi nadstavbami ndash napr s jazykom CHIP ktoryacute zaviedol programovanie ohraničeniacute

na konečnyacutech deničnyacutech oboroch resp CLP(R) ktoreacute zaviedlo podporu pre ohraničenia na

reaacutelnych čiacuteslach [2] Ďalej ide o rocirczne prologoveacute systeacutemy ako napr ECLiPS

ea SICStus Prolog

[2] Knižnice pre programovanie ohraničeniacute existujuacute aj v inyacutech prologoch (napr clpfd pre SWI-

Prolog) V suacutevislosti s tyacutem sa hovoriacute o tzv logickom programovaniacute ohraničeniacute čiacutem sa mysliacute praacuteve

programovanie ohraničeniacute v raacutemci logickyacutech jazykov ako je Prolog

4 | Programovanie ohraničeniacute ako riešenie SudokuV tejto časti ilustrujeme zaacutekladneacute koncepty programovania ohraničeniacute na hre Sudoku čiacutem si

vybudujeme intuiacuteciu potrebnuacute pre nasledujuacuteci formaacutelnejšiacute vyacuteklad Vyššie sme ukaacutezali že hru

Sudoku možno veľmi prirodzenyacutem spocircsobom reprezentovať ako probleacutem spĺňania ohraničeniacute

(CSP)

Ak maacuteme Sudoku rozmeru 9 times 9 a F poliacutečok už maacute stanoveneacute hodnoty maacuteme 9 times 9 minusF premennyacutech ktoryacutech hodnoty musiacuteme stanoviť Deničnyacute obor každej z nich bude Di =1 2 9 Počiatočnyacute stav mocircžeme ilustrovať tak že do každeacuteho praacutezdneho poliacutečka vpiacutešeme

všetky hodnoty ktoreacute daneacute premennaacute mocircže nadobuacutedať Priacuteklad je na Obr 41

Ako vidno v hracom poli Obr 41 je preddenovanyacutech 31 poliacutečok Doplniť teda treba zvyš-

nyacutech 50 poliacutečok z ktoryacutech každeacute mocircže obsahovať hodnoty od 1 po 9 tak aby boli splneneacute všetky

ohraničenia

middot 4 middot

(a) (b) (c)

Obr 42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek

41 Aplikaacutecia ohraničeniacute hry Sudoku

O ohraničeniach hry Sudoku sme hovorili vyššie teraz ich budeme ilustrovať na priacuteklade Ako

prveacute ohraničenie sme uviedli že dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9 Toto ohraničenie

sme už zahrnuli pri určeniacute deničneacuteho oboru premennyacutech ďalej ho teda uvažovať nemusiacuteme

Prejdeme teda postupne len ostatneacute ohraničenia

411 Štvorcoveacute ohraničenia

Začnime štvorcovyacutemi ohraničeniami Princiacutep budeme ilustrovať na štvorcovom vyacuteseku z ľaveacuteho

horneacuteho rohu ktoryacute je na Obr 42a Ako vidno tri poliacutečka už majuacute preddenovaneacute hodnoty

x22 = 5 x31 = 3 a x33 = 4 Keďže tie isteacute hodnoty sa v raacutemci štvorca nesmuacute opakovať viackraacutet

je jasneacute že z deničnyacutech oborov ostatnyacutech premennyacutech mocircžeme čiacutesla 3 4 a 5 vyluacutečiť ako to

ilustrujuacute Obr 42b a 42c

Aplikujme teda obdobnyacutem spocircsobom štvorcoveacute ohraničenia na všetky štvorce a pokračujme

ďalej riadkovyacutemi a stĺpcovyacutemi ohraničeniami

412 Riadkoveacute a stĺpcoveacute ohraničenia

Priacuteklad aplikaacutecie riadkoveacuteho ohraničenia pre prvyacute riadok je na Obr 43a Ako vidno v riadku sa

vyskytuje jedna preddenovanaacute hodnota ndash čiacuteslo 9 ktoruacute je potrebneacute vyluacutečiť z deničnyacutech oborov

všetkyacutech ostatnyacutech premennyacutech v danom riadku

Ak naacutesledne budeme ilustrovať priacuteklad stĺpcoveacuteho ohraničenia na ocircsmom stĺpci ziacuteskame

Obr 43b Ako vidno vylučujeme hodnoty 9 6 7 a 1

middot 5 middot

(a) Priacuteklad riadkoveacuteho ohraničenia (b) Priacuteklad stĺpcoveacuteho ohraničenia

Obr 43 Riadkoveacute a stĺpcoveacute ohraničenia

42 Ohraničenia aplikujeme opakovane

Ak aplikujeme ohraničenia pre všetky štvorce riadky a stĺpce ziacuteskame Obr 44 Ako vidno de-

ničneacute obory niektoryacutech premennyacutech sa po aplikaacutecii ohraničeniacute zuacutežili na jedno konkreacutetne čiacuteslo

(čiacutesla zvyacuterazneneacute oranžovou farbou)

Je zrejmeacute že ak teraz ohraničenia aplikujeme znovu budeme z deničnyacutech oborov niektoryacutech

premennyacutech vedieť vyluacutečiť ďalšie čiacutesla napr v druhom riadku a deviatom stĺpci sa už nesmie

nachaacutedzať čiacuteslo 8 Takisto ho je potrebneacute vyluacutečiť aj zo štvorca č 3 Obdobne pre ďalšie čiacutesla ndash

vyacutesledok je na Obr 45

Vidno teda že ohraničenia nestačiacute aplikovať len raz ndash treba ich aplikovať opakovane až do-

vtedy keď už pomocou nich nevieme vyluacutečiť ďalšie prvky z deničneacuteho oboru žiadnej premennej

Za zmienku stojiacute aj to že (ako by sme si pri ručnej aplikaacutecii postupu ryacutechlo všimli) netreba

zakaždyacutem uvažovať uacuteplne všetky ohraničenia ndash stačiacute znovu aplikovať ohraničenia tyacutekajuacutece sa

tyacutech premennyacutech ktoryacutech deničnyacute obor sa v poslednom kroku zmenil Inyacutemi slovami ndash ak

sa zmeniacute deničnyacute obor premennej xij maacute zmysel znovu aplikovať len ohraničenia pre riadok

stĺpec a štvorec v ktorom sa xij nachaacutedza Ak aplikaacutecia tyacutechto ohraničeniacute vedie k zmene pre

ďalšie premenneacute prirodzene sa pokračuje obdobne aj pre ne

middot 6 middot

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 9: Programovanie ohraničení

Obr 23 Hra Sudoku ndash rozdelenie na štvorce

Zo všetkyacutech kombinaacuteciiacute hodnocirct premennyacutech (D9) vyberaacuteme teda len takeacute dosadenia x pri ktoryacutech

platiacute že z hodnocirct v riadku 1 ani dve nie suacute rovnakeacute

Obmedzenie (21) možno zovšeobecniť pre ľubovoľnyacute riadok a obdobne možno denovať os-

tatneacute obmedzenia Keďže tento typ obmedzeniacute sa vyskytuje často existuje preň osobitneacute kľuacutečoveacute

slovo alldierent ndash tj všetky uvedeneacute premenneacute sa musia odlišovať Ako možno toto kľuacutečoveacute

slovo a ineacute kľuacutečoveacute slovaacute použiť v praxi uvidiacuteme na priacutekladoch neskocircr

22 Probleacutem SAT

Za špeciaacutelny priacutepad CSP možno považovať probleacutem spĺňania logickyacutech formuacutel (angl boolean satis-

ability problem SAT) V jeho priacutepade sa deničneacute oboryDi jednotlivyacutech premennyacutech redukujuacute

na Di = true false [1]

3 | Logickeacute programovanie ohraničeniacuteSysteacutemy na programovanie ohraničeniacute typicky integrujuacute koncepty z CP do nejakeacuteho už existu-

juacuteceho programovacieho jazyka Existuje veľkyacute počet implementaacuteciiacute pre mnoho rocircznych jazy-

kov Ako priacuteklady implementaacutecie v klasickyacutech imperatiacutevnych jazykoch možno uviesť knižnicu

Gecode pre C++ knižnicu or-tools ktoruacute možno použiacutevať z C++ Python-u Javy a NET alebo

javoveacute knižnice CHOCO a JaCoP

Osobitnuacute vetvu však tvoria logickeacute deklaratiacutevne jazyky ndash napriacuteklad Prolog ndash ktoreacute sa osobitne

hodia na integraacuteciu CP keďže s niacutem už mnoheacute koncepty zdieľajuacute Prolog napriacuteklad už obsahuje

koncept prehľadaacutevania s naacutevratom ktoryacute (ako uvidiacuteme) sa využiacuteva aj v CP [2]

middot 3 middot

Obr 41 Deničneacute obory premennyacutech v hracom poli Sudoku

Preto aj vyacutevoj v oblasti CP bol historicky do značnej miery spojenyacute praacuteve s jazykom Prolog

a s jeho rocircznymi nadstavbami ndash napr s jazykom CHIP ktoryacute zaviedol programovanie ohraničeniacute

na konečnyacutech deničnyacutech oboroch resp CLP(R) ktoreacute zaviedlo podporu pre ohraničenia na

reaacutelnych čiacuteslach [2] Ďalej ide o rocirczne prologoveacute systeacutemy ako napr ECLiPS

ea SICStus Prolog

[2] Knižnice pre programovanie ohraničeniacute existujuacute aj v inyacutech prologoch (napr clpfd pre SWI-

Prolog) V suacutevislosti s tyacutem sa hovoriacute o tzv logickom programovaniacute ohraničeniacute čiacutem sa mysliacute praacuteve

programovanie ohraničeniacute v raacutemci logickyacutech jazykov ako je Prolog

4 | Programovanie ohraničeniacute ako riešenie SudokuV tejto časti ilustrujeme zaacutekladneacute koncepty programovania ohraničeniacute na hre Sudoku čiacutem si

vybudujeme intuiacuteciu potrebnuacute pre nasledujuacuteci formaacutelnejšiacute vyacuteklad Vyššie sme ukaacutezali že hru

Sudoku možno veľmi prirodzenyacutem spocircsobom reprezentovať ako probleacutem spĺňania ohraničeniacute

(CSP)

Ak maacuteme Sudoku rozmeru 9 times 9 a F poliacutečok už maacute stanoveneacute hodnoty maacuteme 9 times 9 minusF premennyacutech ktoryacutech hodnoty musiacuteme stanoviť Deničnyacute obor každej z nich bude Di =1 2 9 Počiatočnyacute stav mocircžeme ilustrovať tak že do každeacuteho praacutezdneho poliacutečka vpiacutešeme

všetky hodnoty ktoreacute daneacute premennaacute mocircže nadobuacutedať Priacuteklad je na Obr 41

Ako vidno v hracom poli Obr 41 je preddenovanyacutech 31 poliacutečok Doplniť teda treba zvyš-

nyacutech 50 poliacutečok z ktoryacutech každeacute mocircže obsahovať hodnoty od 1 po 9 tak aby boli splneneacute všetky

ohraničenia

middot 4 middot

(a) (b) (c)

Obr 42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek

41 Aplikaacutecia ohraničeniacute hry Sudoku

O ohraničeniach hry Sudoku sme hovorili vyššie teraz ich budeme ilustrovať na priacuteklade Ako

prveacute ohraničenie sme uviedli že dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9 Toto ohraničenie

sme už zahrnuli pri určeniacute deničneacuteho oboru premennyacutech ďalej ho teda uvažovať nemusiacuteme

Prejdeme teda postupne len ostatneacute ohraničenia

411 Štvorcoveacute ohraničenia

Začnime štvorcovyacutemi ohraničeniami Princiacutep budeme ilustrovať na štvorcovom vyacuteseku z ľaveacuteho

horneacuteho rohu ktoryacute je na Obr 42a Ako vidno tri poliacutečka už majuacute preddenovaneacute hodnoty

x22 = 5 x31 = 3 a x33 = 4 Keďže tie isteacute hodnoty sa v raacutemci štvorca nesmuacute opakovať viackraacutet

je jasneacute že z deničnyacutech oborov ostatnyacutech premennyacutech mocircžeme čiacutesla 3 4 a 5 vyluacutečiť ako to

ilustrujuacute Obr 42b a 42c

Aplikujme teda obdobnyacutem spocircsobom štvorcoveacute ohraničenia na všetky štvorce a pokračujme

ďalej riadkovyacutemi a stĺpcovyacutemi ohraničeniami

412 Riadkoveacute a stĺpcoveacute ohraničenia

Priacuteklad aplikaacutecie riadkoveacuteho ohraničenia pre prvyacute riadok je na Obr 43a Ako vidno v riadku sa

vyskytuje jedna preddenovanaacute hodnota ndash čiacuteslo 9 ktoruacute je potrebneacute vyluacutečiť z deničnyacutech oborov

všetkyacutech ostatnyacutech premennyacutech v danom riadku

Ak naacutesledne budeme ilustrovať priacuteklad stĺpcoveacuteho ohraničenia na ocircsmom stĺpci ziacuteskame

Obr 43b Ako vidno vylučujeme hodnoty 9 6 7 a 1

middot 5 middot

(a) Priacuteklad riadkoveacuteho ohraničenia (b) Priacuteklad stĺpcoveacuteho ohraničenia

Obr 43 Riadkoveacute a stĺpcoveacute ohraničenia

42 Ohraničenia aplikujeme opakovane

Ak aplikujeme ohraničenia pre všetky štvorce riadky a stĺpce ziacuteskame Obr 44 Ako vidno de-

ničneacute obory niektoryacutech premennyacutech sa po aplikaacutecii ohraničeniacute zuacutežili na jedno konkreacutetne čiacuteslo

(čiacutesla zvyacuterazneneacute oranžovou farbou)

Je zrejmeacute že ak teraz ohraničenia aplikujeme znovu budeme z deničnyacutech oborov niektoryacutech

premennyacutech vedieť vyluacutečiť ďalšie čiacutesla napr v druhom riadku a deviatom stĺpci sa už nesmie

nachaacutedzať čiacuteslo 8 Takisto ho je potrebneacute vyluacutečiť aj zo štvorca č 3 Obdobne pre ďalšie čiacutesla ndash

vyacutesledok je na Obr 45

Vidno teda že ohraničenia nestačiacute aplikovať len raz ndash treba ich aplikovať opakovane až do-

vtedy keď už pomocou nich nevieme vyluacutečiť ďalšie prvky z deničneacuteho oboru žiadnej premennej

Za zmienku stojiacute aj to že (ako by sme si pri ručnej aplikaacutecii postupu ryacutechlo všimli) netreba

zakaždyacutem uvažovať uacuteplne všetky ohraničenia ndash stačiacute znovu aplikovať ohraničenia tyacutekajuacutece sa

tyacutech premennyacutech ktoryacutech deničnyacute obor sa v poslednom kroku zmenil Inyacutemi slovami ndash ak

sa zmeniacute deničnyacute obor premennej xij maacute zmysel znovu aplikovať len ohraničenia pre riadok

stĺpec a štvorec v ktorom sa xij nachaacutedza Ak aplikaacutecia tyacutechto ohraničeniacute vedie k zmene pre

ďalšie premenneacute prirodzene sa pokračuje obdobne aj pre ne

middot 6 middot

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 10: Programovanie ohraničení

Obr 41 Deničneacute obory premennyacutech v hracom poli Sudoku

Preto aj vyacutevoj v oblasti CP bol historicky do značnej miery spojenyacute praacuteve s jazykom Prolog

a s jeho rocircznymi nadstavbami ndash napr s jazykom CHIP ktoryacute zaviedol programovanie ohraničeniacute

na konečnyacutech deničnyacutech oboroch resp CLP(R) ktoreacute zaviedlo podporu pre ohraničenia na

reaacutelnych čiacuteslach [2] Ďalej ide o rocirczne prologoveacute systeacutemy ako napr ECLiPS

ea SICStus Prolog

[2] Knižnice pre programovanie ohraničeniacute existujuacute aj v inyacutech prologoch (napr clpfd pre SWI-

Prolog) V suacutevislosti s tyacutem sa hovoriacute o tzv logickom programovaniacute ohraničeniacute čiacutem sa mysliacute praacuteve

programovanie ohraničeniacute v raacutemci logickyacutech jazykov ako je Prolog

4 | Programovanie ohraničeniacute ako riešenie SudokuV tejto časti ilustrujeme zaacutekladneacute koncepty programovania ohraničeniacute na hre Sudoku čiacutem si

vybudujeme intuiacuteciu potrebnuacute pre nasledujuacuteci formaacutelnejšiacute vyacuteklad Vyššie sme ukaacutezali že hru

Sudoku možno veľmi prirodzenyacutem spocircsobom reprezentovať ako probleacutem spĺňania ohraničeniacute

(CSP)

Ak maacuteme Sudoku rozmeru 9 times 9 a F poliacutečok už maacute stanoveneacute hodnoty maacuteme 9 times 9 minusF premennyacutech ktoryacutech hodnoty musiacuteme stanoviť Deničnyacute obor každej z nich bude Di =1 2 9 Počiatočnyacute stav mocircžeme ilustrovať tak že do každeacuteho praacutezdneho poliacutečka vpiacutešeme

všetky hodnoty ktoreacute daneacute premennaacute mocircže nadobuacutedať Priacuteklad je na Obr 41

Ako vidno v hracom poli Obr 41 je preddenovanyacutech 31 poliacutečok Doplniť teda treba zvyš-

nyacutech 50 poliacutečok z ktoryacutech každeacute mocircže obsahovať hodnoty od 1 po 9 tak aby boli splneneacute všetky

ohraničenia

middot 4 middot

(a) (b) (c)

Obr 42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek

41 Aplikaacutecia ohraničeniacute hry Sudoku

O ohraničeniach hry Sudoku sme hovorili vyššie teraz ich budeme ilustrovať na priacuteklade Ako

prveacute ohraničenie sme uviedli že dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9 Toto ohraničenie

sme už zahrnuli pri určeniacute deničneacuteho oboru premennyacutech ďalej ho teda uvažovať nemusiacuteme

Prejdeme teda postupne len ostatneacute ohraničenia

411 Štvorcoveacute ohraničenia

Začnime štvorcovyacutemi ohraničeniami Princiacutep budeme ilustrovať na štvorcovom vyacuteseku z ľaveacuteho

horneacuteho rohu ktoryacute je na Obr 42a Ako vidno tri poliacutečka už majuacute preddenovaneacute hodnoty

x22 = 5 x31 = 3 a x33 = 4 Keďže tie isteacute hodnoty sa v raacutemci štvorca nesmuacute opakovať viackraacutet

je jasneacute že z deničnyacutech oborov ostatnyacutech premennyacutech mocircžeme čiacutesla 3 4 a 5 vyluacutečiť ako to

ilustrujuacute Obr 42b a 42c

Aplikujme teda obdobnyacutem spocircsobom štvorcoveacute ohraničenia na všetky štvorce a pokračujme

ďalej riadkovyacutemi a stĺpcovyacutemi ohraničeniami

412 Riadkoveacute a stĺpcoveacute ohraničenia

Priacuteklad aplikaacutecie riadkoveacuteho ohraničenia pre prvyacute riadok je na Obr 43a Ako vidno v riadku sa

vyskytuje jedna preddenovanaacute hodnota ndash čiacuteslo 9 ktoruacute je potrebneacute vyluacutečiť z deničnyacutech oborov

všetkyacutech ostatnyacutech premennyacutech v danom riadku

Ak naacutesledne budeme ilustrovať priacuteklad stĺpcoveacuteho ohraničenia na ocircsmom stĺpci ziacuteskame

Obr 43b Ako vidno vylučujeme hodnoty 9 6 7 a 1

middot 5 middot

(a) Priacuteklad riadkoveacuteho ohraničenia (b) Priacuteklad stĺpcoveacuteho ohraničenia

Obr 43 Riadkoveacute a stĺpcoveacute ohraničenia

42 Ohraničenia aplikujeme opakovane

Ak aplikujeme ohraničenia pre všetky štvorce riadky a stĺpce ziacuteskame Obr 44 Ako vidno de-

ničneacute obory niektoryacutech premennyacutech sa po aplikaacutecii ohraničeniacute zuacutežili na jedno konkreacutetne čiacuteslo

(čiacutesla zvyacuterazneneacute oranžovou farbou)

Je zrejmeacute že ak teraz ohraničenia aplikujeme znovu budeme z deničnyacutech oborov niektoryacutech

premennyacutech vedieť vyluacutečiť ďalšie čiacutesla napr v druhom riadku a deviatom stĺpci sa už nesmie

nachaacutedzať čiacuteslo 8 Takisto ho je potrebneacute vyluacutečiť aj zo štvorca č 3 Obdobne pre ďalšie čiacutesla ndash

vyacutesledok je na Obr 45

Vidno teda že ohraničenia nestačiacute aplikovať len raz ndash treba ich aplikovať opakovane až do-

vtedy keď už pomocou nich nevieme vyluacutečiť ďalšie prvky z deničneacuteho oboru žiadnej premennej

Za zmienku stojiacute aj to že (ako by sme si pri ručnej aplikaacutecii postupu ryacutechlo všimli) netreba

zakaždyacutem uvažovať uacuteplne všetky ohraničenia ndash stačiacute znovu aplikovať ohraničenia tyacutekajuacutece sa

tyacutech premennyacutech ktoryacutech deničnyacute obor sa v poslednom kroku zmenil Inyacutemi slovami ndash ak

sa zmeniacute deničnyacute obor premennej xij maacute zmysel znovu aplikovať len ohraničenia pre riadok

stĺpec a štvorec v ktorom sa xij nachaacutedza Ak aplikaacutecia tyacutechto ohraničeniacute vedie k zmene pre

ďalšie premenneacute prirodzene sa pokračuje obdobne aj pre ne

middot 6 middot

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 11: Programovanie ohraničení

(a) (b) (c)

Obr 42 Postup pre ľavyacute hornyacute štvorcovyacute vyacutesek

41 Aplikaacutecia ohraničeniacute hry Sudoku

O ohraničeniach hry Sudoku sme hovorili vyššie teraz ich budeme ilustrovať na priacuteklade Ako

prveacute ohraničenie sme uviedli že dopĺňaneacute čiacutesla musia byť z rozsahu 1 až 9 Toto ohraničenie

sme už zahrnuli pri určeniacute deničneacuteho oboru premennyacutech ďalej ho teda uvažovať nemusiacuteme

Prejdeme teda postupne len ostatneacute ohraničenia

411 Štvorcoveacute ohraničenia

Začnime štvorcovyacutemi ohraničeniami Princiacutep budeme ilustrovať na štvorcovom vyacuteseku z ľaveacuteho

horneacuteho rohu ktoryacute je na Obr 42a Ako vidno tri poliacutečka už majuacute preddenovaneacute hodnoty

x22 = 5 x31 = 3 a x33 = 4 Keďže tie isteacute hodnoty sa v raacutemci štvorca nesmuacute opakovať viackraacutet

je jasneacute že z deničnyacutech oborov ostatnyacutech premennyacutech mocircžeme čiacutesla 3 4 a 5 vyluacutečiť ako to

ilustrujuacute Obr 42b a 42c

Aplikujme teda obdobnyacutem spocircsobom štvorcoveacute ohraničenia na všetky štvorce a pokračujme

ďalej riadkovyacutemi a stĺpcovyacutemi ohraničeniami

412 Riadkoveacute a stĺpcoveacute ohraničenia

Priacuteklad aplikaacutecie riadkoveacuteho ohraničenia pre prvyacute riadok je na Obr 43a Ako vidno v riadku sa

vyskytuje jedna preddenovanaacute hodnota ndash čiacuteslo 9 ktoruacute je potrebneacute vyluacutečiť z deničnyacutech oborov

všetkyacutech ostatnyacutech premennyacutech v danom riadku

Ak naacutesledne budeme ilustrovať priacuteklad stĺpcoveacuteho ohraničenia na ocircsmom stĺpci ziacuteskame

Obr 43b Ako vidno vylučujeme hodnoty 9 6 7 a 1

middot 5 middot

(a) Priacuteklad riadkoveacuteho ohraničenia (b) Priacuteklad stĺpcoveacuteho ohraničenia

Obr 43 Riadkoveacute a stĺpcoveacute ohraničenia

42 Ohraničenia aplikujeme opakovane

Ak aplikujeme ohraničenia pre všetky štvorce riadky a stĺpce ziacuteskame Obr 44 Ako vidno de-

ničneacute obory niektoryacutech premennyacutech sa po aplikaacutecii ohraničeniacute zuacutežili na jedno konkreacutetne čiacuteslo

(čiacutesla zvyacuterazneneacute oranžovou farbou)

Je zrejmeacute že ak teraz ohraničenia aplikujeme znovu budeme z deničnyacutech oborov niektoryacutech

premennyacutech vedieť vyluacutečiť ďalšie čiacutesla napr v druhom riadku a deviatom stĺpci sa už nesmie

nachaacutedzať čiacuteslo 8 Takisto ho je potrebneacute vyluacutečiť aj zo štvorca č 3 Obdobne pre ďalšie čiacutesla ndash

vyacutesledok je na Obr 45

Vidno teda že ohraničenia nestačiacute aplikovať len raz ndash treba ich aplikovať opakovane až do-

vtedy keď už pomocou nich nevieme vyluacutečiť ďalšie prvky z deničneacuteho oboru žiadnej premennej

Za zmienku stojiacute aj to že (ako by sme si pri ručnej aplikaacutecii postupu ryacutechlo všimli) netreba

zakaždyacutem uvažovať uacuteplne všetky ohraničenia ndash stačiacute znovu aplikovať ohraničenia tyacutekajuacutece sa

tyacutech premennyacutech ktoryacutech deničnyacute obor sa v poslednom kroku zmenil Inyacutemi slovami ndash ak

sa zmeniacute deničnyacute obor premennej xij maacute zmysel znovu aplikovať len ohraničenia pre riadok

stĺpec a štvorec v ktorom sa xij nachaacutedza Ak aplikaacutecia tyacutechto ohraničeniacute vedie k zmene pre

ďalšie premenneacute prirodzene sa pokračuje obdobne aj pre ne

middot 6 middot

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 12: Programovanie ohraničení

(a) Priacuteklad riadkoveacuteho ohraničenia (b) Priacuteklad stĺpcoveacuteho ohraničenia

Obr 43 Riadkoveacute a stĺpcoveacute ohraničenia

42 Ohraničenia aplikujeme opakovane

Ak aplikujeme ohraničenia pre všetky štvorce riadky a stĺpce ziacuteskame Obr 44 Ako vidno de-

ničneacute obory niektoryacutech premennyacutech sa po aplikaacutecii ohraničeniacute zuacutežili na jedno konkreacutetne čiacuteslo

(čiacutesla zvyacuterazneneacute oranžovou farbou)

Je zrejmeacute že ak teraz ohraničenia aplikujeme znovu budeme z deničnyacutech oborov niektoryacutech

premennyacutech vedieť vyluacutečiť ďalšie čiacutesla napr v druhom riadku a deviatom stĺpci sa už nesmie

nachaacutedzať čiacuteslo 8 Takisto ho je potrebneacute vyluacutečiť aj zo štvorca č 3 Obdobne pre ďalšie čiacutesla ndash

vyacutesledok je na Obr 45

Vidno teda že ohraničenia nestačiacute aplikovať len raz ndash treba ich aplikovať opakovane až do-

vtedy keď už pomocou nich nevieme vyluacutečiť ďalšie prvky z deničneacuteho oboru žiadnej premennej

Za zmienku stojiacute aj to že (ako by sme si pri ručnej aplikaacutecii postupu ryacutechlo všimli) netreba

zakaždyacutem uvažovať uacuteplne všetky ohraničenia ndash stačiacute znovu aplikovať ohraničenia tyacutekajuacutece sa

tyacutech premennyacutech ktoryacutech deničnyacute obor sa v poslednom kroku zmenil Inyacutemi slovami ndash ak

sa zmeniacute deničnyacute obor premennej xij maacute zmysel znovu aplikovať len ohraničenia pre riadok

stĺpec a štvorec v ktorom sa xij nachaacutedza Ak aplikaacutecia tyacutechto ohraničeniacute vedie k zmene pre

ďalšie premenneacute prirodzene sa pokračuje obdobne aj pre ne

middot 6 middot

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 13: Programovanie ohraničení

Obr 44 Po aplikaacutecii ohraničeniacute vieme určiť

niektoreacute hodnoty

Obr 45 Vyacutesledok po ďalšom kroku aplikaacutecie

ohraničeniacute

43 Vetvenie

Ak ďalej opakovane aplikujeme ohraničenia ziacuteskame napokon konguraacuteciu na Obr 46 z kto-

rej už nemožno vyluacutečiť ďalšie hodnoty Musiacuteme preto hodnotu niektorej premennej zvoliť Na

tomto mieste dochaacutedza k vetveniu keďže voliacuteme z viaceryacutech možnostiacute Postup je analogickyacute kla-

sickyacutem metoacutedam prehľadaacutevania stavoveacuteho priestoru s naacutevratom (angl backtracking) ndash naacutevrat sa

uskutočniacute ak zistiacuteme že pre zvoleneacute hodnoty probleacutem nemaacute riešenie Ak je uacutelohou naacutejsť všetky

riešenia preskuacutemajuacute sa alternatiacutevne možnosti v každej vetve aj vtedy ak sa už riešenie našlo

Pre premennuacute x11 sme zatiaľ nevyluacutečili hodnoty 1 a 6 Pokuacutesme sa teda zvoliť x11 = 1 a od

toho bodu znovu aplikovať ohraničenia Postup ilustruje Obr 47

Vetvenie ku ktoreacutemu tu dochaacutedza schmematicky zobrazuje Obr 48 Ako vidno voliacuteme hod-

notu 1 pre ktoruacute Ďalej pokračuje postup hľadania riešenia Hodnota 6 zostaacuteva zatiaľ bokom ndash

otvoriacute sa v priacutepade že docircjde k naacutevratu

431 Naacutevrat

Voľbou x11 = 1 sa naacutem opaumlť otvorila možnosť vyluacutečiť aplikaacuteciou ohraničeniacute niektoreacute hodnoty

z deničnyacutech oborov premennyacutech Takto ziacuteskame konguraacuteciu na Obr 411 Tu sa opaumlť dosta-

neme do situaacutecie kedy docircjde k vetveniu Tento raz voliacuteme hodnotu premennej x14 = 3 (vetvenie

na Obr 49)

Pri ďalšom riešeniacute vznikne novaacute situaacutecia ndash ako vidno na Obr 412 deničnyacute obor premennej

x46 sa celkom vypraacutezdnil ndash neviem teda pre tuacuteto premennuacute zvoliť takuacute hodnotu ktoraacute by bola

middot 7 middot

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 14: Programovanie ohraničení

Obr 46 Stav po aplikaacutecii ohraničeniacute Obr 47 Voliacuteme hodnotu 1 pre x11

Obr 48 Vetvenie pre x11

Obr 49 Vetvenie pre x14 Obr 410 Vetvenie pre x14 ndash naacutevrat

middot 8 middot

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 15: Programovanie ohraničení

Obr 411 Voliacuteme hodnotu 3 pre x14 Obr 412 Stav po aplikaacutecii ohraničeniacute ndash

praacutezdny deničnyacute obor

schopnaacute splniť obmedzenia Ako sme povedali v takomto priacutepade musiacuteme uskutočniť naacutevrat

k posledneacutemu vetveniu ndash hodnotu x14 = 3 teda zamietneme a namiesto nej voliacuteme x14 = 7 ako

to ilustruje Obr 410

Ďalej by sme postupovali obdobne v našom priacutepade už opakovanou aplikaacuteciou ohraničeniacute

dospejeme k riešeniu bez ďalšieho vetvenia

432 Strateacutegie vetvenia

Keďže pri vetveniacute maacuteme možnosť vybrať si premennuacute ktorej hodnotu budeme voliť vyvstaacuteva

otaacutezka ktoruacute premennuacute je najlepšie vybrať resp ktoruacute jej hodnotu zvoliť V tejto suacutevislosti je

priacutepustnyacutech viacero spocircsobov ndash existujuacute viacereacute strateacutegie vetvenia ndash mocircžeme sa napriacuteklad po-

kuacutešať voliť premenneacute s čo najmenšiacutem počtom zostaacutevajuacutecich hodnocirct aplikovať určituacute heuristiku

alebo jednoducho zvoliť povedzme prehľadaacutevanie do hĺbky

5 | Zaacutekladneacute koncepty v CPV tejto časti prejdeme zaacutekladneacute koncepty v programovaniacute ohraničeniacute Vaumlčšinu z nich sme už

ilustrovali na priacuteklade hry Sudoku vyššie Na tomto mieste teda budeme stavať na ziacuteskanej intuiacutecii

a poznatky len zovšeobecniacuteme a doplniacuteme

middot 9 middot

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 16: Programovanie ohraničení

Prehľadaacutevanie Sklad ohraničeniacute

Obr 51 Sklad ohraničeniacute a prehľadaacutevanie

scheacutema interakcie [3]

Nesplniteľneacute

Prehľadaacutevanie Sklad ohraničeniacute

Splniteľneacute

1

2

Obr 52 Sklad ohraničeniacute a prehľadaacutevanie priacute-

klad interakcie [3]

51 Sklad ohraničeniacute

Blok CP systeacutemu ktoryacute spravuje ohraničenia a zabezpečuje ich aplikaacuteciu nazyacutevame sklad ohrani-

čeniacute (angl constraint store) Ako sme už videli vyššie v priacuteklade s hrou Sudoku v CP interagujuacute

spolu dva procesy ndash proces prehľadaacutevania (vetvenie) a proces aplikaacutecie ohraničeniacute

511 Interakcia prehľadaacutevania a skladu ohraničeniacute

Schematickeacute znaacutezornenie je na Obr 51 Ako vidno medzi blokom bdquoprehľadaacutevanieldquo a blokom

bdquosklad ohraničeniacuteldquo prebieha obojsmernaacute komunikaacutecia Sklad ohraničeniacute dostane na začiatku pre-

menneacute spolu s ich deničnyacutemi obormi a ohraničenia Naacutesledne ohraničenia aplikuje čo vedie

k dvom cieľom

1 Vyhodnotiť splniteľnosť (overenie korektnosti) či vocircbec existujuacute takeacute hodnoty pre-

mennyacutech pri ktoryacutech suacute splneneacute všetky ohraničenia

2 Vyluacutečiť niektoreacute hodnoty (propagaacutecia ohraničeniacute) z deničnyacutech oborov premennyacutech

sa odstraacutenia tie hodnoty pri ktoryacutech nemožno splniť niektoreacute ohraničenie

Po tejto prvej aplikaacutecii ohraničeniacute ndash keď sklad ohraničeniacute vyluacuteči čo najviac hodnocirct povie

bloku prehľadaacutevanie že uacuteloha je splniteľnaacute Blok prehľadaacutevanie naacutesledne zvoliacute pre niektoruacute pre-

mennuacute hodnotu (vetvenie) a navrhne skladu ohraničeniacute pridať ju ako ďalšie ohraničenie

Priacuteklad je na Obr 52 ndash prehľadaacutevanie navrhuje priradiť X = 5 Sklad ohraničeniacute znovu

s použitiacutem tohto noveacuteho ohraničenia vyluacuteči čo najviac hodnocirct a vyhodnotiacute splniteľnosť Odpovie

že uacuteloha je splniteľnaacute

Blok prehľadaacutevanie teda znovu navrhne hodnotu ndash v našom priacuteklade hodnotu Y 6= 2 (ako

vidno je priacutepustneacute voliť nielen konkreacutetne hodnoty ale sa dajuacute pridať aj ineacute typy ohraničeniacute) Sklad

ohraničeniacute aplikuje rovnakyacute postup Tento raz však zistiacute že ohraničenia už nie suacute splniteľneacute Tuacuteto

informaacuteciu komunikuje naspaumlť bloku prehľadaacutevanie ktoryacute sa navraacuteti k posledneacutemu vetveniu

a navrhne inuacute hodnotu

middot 10 middot

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 17: Programovanie ohraničení

Prehľadaacutevanie

Sklad ohraničeniacute

Definičneacute obory

hellip

Ohraničenia

Obr 53 Scheacutema skladu ohraničeniacute [3]

512 Propagaacutecia ohraničeniacute

Ako sme už ukaacutezali sklad aplikaacuteciou ohraničeniacute zabezpečuje dve funkcie (a) propagaacuteciu ohra-

ničeniacute (b) overenie korektnosti Propagaacuteciou (šiacutereniacutem) ohraničeniacute (angl constraint propaga-

tion) rozumieme proces kde sa aplikujuacute ohraničenia a pomocou nich sa vylučujuacute niektoreacute hod-

noty z deničnyacutech oborov jednotlivyacutech premennyacutech Ohraničenia zaacuteroveň sluacutežia na overeniekorektnosti ndash umožňujuacute určiť či danaacute konguraacutecia premennyacutech vyhovuje požiadavkaacutem tj či

mocircže alebo nemocircže byť riešeniacutem daneacuteho probleacutemu Ohraničenia mocircžu byť denovaneacute aj tak že

riešenie neexistuje ndash v tom priacutepade všetky vetvy prehľadaacutevania skončia nesplnenyacutemi ohraniče-

niami Programovanie ohraničeniacute umožňuje teda dokaacutezať aj neexistenciu riešenia

Schematickaacute ilustraacutecia toho ako sklad ohraničeniacute funguje vo vnuacutetri je na Obr 53 Ako vidno

sklad spravuje deničneacute obory premennyacutech S tyacutemito interagujuacute jednotliveacute ohraničenia Vyacutehodou

je že ohraničenia suacute vzaacutejomne nezaacutevisleacute ndash medzi sebou neinteragujuacute čo zjednodušuje manipu-

laacuteciu s nimi Ak je nejakaacute miera interakcie predsa len žiaduca mocircže sa realizovať cez pomocnuacute

premennuacute ndash samotneacute ohraničenia aj potom ostaacutevajuacute nezaacutevisleacute a prepojenie sa realizuje cez de-

ničneacute obory O tom však viac v podkapitole o reikaacutecii (časť 8)

52 Arita ohraničeniacute

Z deniacutecie ohraničeniacute ktoruacute sme uviedli pri deniacutecii CSP v časti 2 nevyplyacutevajuacute žiadne obmedze-

nia pre aritu ohraničeniacute Osobitnyacutemi priacutepadmi z hľadiska arity suacute [2 4 5]

bull Unaacuterne ohraničenia Operujuacute na jednotlivyacutech premennyacutech napr X 6= 2

bull Binaacuterne ohraničenia Operujuacute na dvojiciach premennyacutech napr X = Y

bull Nebinaacuterne ohraničenia Operujuacute na viac než dvoch premennyacutech tj majuacute aritu n gt 2

Unaacuterne ohraničenia do tejto triedy teda nepatria hoci tiež nie suacute binaacuterne

Ako hovoriacute napr [4 5] ohraničenia vyššej arity (nebinaacuterne) možno rozložiť na binaacuterne ohra-

ničenia hoci v praxi to vaumlčšinou nemaacute zmysel Možno však vďaka tomu povedať že CSP s binaacuter-

nymi ohraničeniami zastupujuacute do istej miery aj ineacute typy CSP [4]

middot 11 middot

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 18: Programovanie ohraničení

53 Globaacutelne ohraničenia

Osobitnyacutem typom ohraničeniacute suacute tzv globaacutelne ohraničenia Rozumieme nimi zložitejšie ohrani-

čenia ktoryacutech arita je často ľubovoľnaacute Propagaacutecia takyacutechto ohraničeniacute sa potom rieši osobitnyacutem

na to určenyacutem algoritmom Modelovať probleacutem pomocou globaacutelnych ohraničeniacute (tam kde to je

možneacute) je teda nielen jednoduchšie ale predovšetkyacutem to vedie k efektiacutevnejšej propagaacutecii ohra-

ničeniacute

Typickyacutem priacutekladom globaacutelneho ohraničenia je ohraničenie alldifferent (al distinct)

ktoreacute o ľubovoľnej množine premennyacutech hovoriacute že sa musia navzaacutejom liacutešiť Ako vidno ohra-

ničenie alldifferent maacute ľubovoľnuacute aritu keďže ho možno aplikovať na ľubovoľnuacute množinu

premennyacutech

54 Ciele CP a optimalizaacutecia na baacuteze CP

Pri aplikaacutecii CP na určityacute probleacutem spĺňania ohraničeniacute (CSP) naacutem ide o splnenie jedneacuteho z nasle-

dujuacutecich cieľov [6]

bull naacutejdenie jedneacuteho riešenia CSP

bull naacutejdenie všetkyacutech riešeniacute CSP

bull naacutejdenie riešenia ktoreacute je optimaacutelne (alebo aspoň dostatočne dobreacute) vzhľadom na určiteacute

kriteacuterium ndash v tomto priacutepade hovoriacuteme o tzv probleacuteme optimalizaacutecie ohraničeniacute (angl con-

straint optimization problem COP)

Pri riešeniacute probleacutemu optimalizaacutecie ohraničeniacute pomocou CP sa najčastejšie postupuje tak že

sa (rovnako ako pri bežnom CP) naacutejde prveacute riešenie spĺňajuacutece všetky ohraničenia Naacutesledne sa

pomocou zadaneacuteho kriteacuteria určiacute jeho cena Do skladu ohraničeniacute sa potom ako ďalšie ohraničenie

pridaacute že riešenie musiacute mať nižšiu cenu V priacutepade že chceme daneacute kriteacuterium maximalizovať

postupuje sa uacuteplne obdobne

6 | Konzistenčneacute technikyKonzistenčneacute techniky riadia aplikaacuteciu ohraničeniacute v raacutemci skladu ohraničeniacute ndash jednak v zmysle

šiacuterenia ohraničeniacute a jednak v zmysle overenia korektnosti resp konzistentnosti

Ak maacute CSP len binaacuterne ohraničenia (a ako sme povedali vyššie ľubovoľneacute nebinaacuterne ohra-

ničenia možno previesť na binaacuterne hoci to vaumlčšinou nemaacute praktickyacute zmysel) možno ho repre-

zentovať grafom ohraničeniacute Vrcholmi v grafe suacute jednotliveacute premenneacute a hrany existujuacute medzi

tyacutemi vrcholmi ktoryacutech premenneacute suacute previazaneacute ohraničeniacutem [4] Praacuteve z tejto grackej analoacutegie

middot 12 middot

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 19: Programovanie ohraničení

Obr 61 Priacuteklad CSP ktoreacute nie je konzistentneacute hoci je hranovo konzistentneacute [2]

čerpajuacute naacutezvy viaceryacutech zaacutekladnyacutech konzistenčnyacutech techniacutek V tejto časti sa pozrieme aspoň na

niektoreacute z nich ndash konkreacutetne na vrcholovuacute a hranovuacute konzistentnosť a na tzv konzistentnosť po

ceste Ďalšie konzistenčneacute techniky možno pozrieť napr v [5 6]

61 Vrcholovaacute konzistentnosť

Najjednoduchšou konzistenčnou technikou je tzv vrcholovaacute konzistentnosť (angl node consis-

tency) ndash taacute odstraňuje z deničneacuteho oboru jednej premennej hodnoty nevyhovujuacutece unaacuternym

ohraničeniam [5] Čo sa tyacuteka vrcholovej konzistentnosti stačiacute teda jednoducho iterovať cez jed-

notliveacute premenneacute a nad nimi denovaneacute unaacuterne ohraničenia a odstraňovať hodnoty Ak by všetky

ohraničenia boli unaacuterne stačila by dokonca na ich propagaacuteciu jedinaacute iteraacutecia

62 Hranovaacute konzistentnosť

Nech maacuteme binaacuterne ohraničenieCij na premennyacutech xi isin Di a xj isin Dj Platiacute tedaCij sube DitimesDj

Hovoriacuteme že ohraničenie Cij je hranovo konzistentneacute (AC angl arc consistent) ak platiacute [2]

bull foralla isin Di exist b isin Dj (a b) isin C

bull forallb isin Dj exist a isin Di (a b) isin C

Teda ak pre každuacute hodnotu a v deničnom obore Di existuje takyacute naacuteprotivok b v deničnom

obore Dj že priradenie xi = a xj = b spĺňa ohraničenie Cij [4]

Ak pre nejakuacute hodnotu a isin Di neexistuje hodnota b isin Dj ktoraacute toto spĺňa možno hodnotu a

z deničneacuteho oboruDi vyluacutečiť keďže už nemocircže byť suacutečasťou žiadneho konzistentneacuteho riešenia

[4]

Hovoriacuteme že CSP je hranovo konzistentneacute ak všetky jeho ohraničenia suacute hranovo konzis-

tentneacute [5] Ak je CSP hranovo konzistentneacute neznamenaacute to ešte že je konzistentneacute všeobecne

Hranovaacute konzistentnosť neimplikuje konzistentnosť ako takuacute

Priacuteklad CSP ktoreacute je nekonzistentneacute a zaacuteroveň je konzistentneacute hranovo vidno na Obr 61

Nevieme či bude xi nadobuacutedať hodnotu a alebo b preto nevieme zatiaľ vyluacutečiť ani jednu z hodnocirct

z deničneacuteho oboru pre xj Zaacuteroveň je však zrejmeacute že CSP je nekonzistentneacute keďže nie je možneacute

aby zaacuteroveň platilo xi = xj aj xi 6= xj

middot 13 middot

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 20: Programovanie ohraničení

621 Ako dosiahnuť hranovuacute konzistentnosť

Najjednoduchšiacutem spocircsobom ako dosiahnuť hranovuacute konzistentnosť je iterovať cez všetky hrany

a postupne odstraňovať z deničnyacutech oborov premennyacutech hodnoty ktoreacute hranovej konzisten-

tnosti prekaacutežajuacute Tento postup treba ako vieme aplikovať opakovane až dovtedy kyacutem sa už

deničneacute obory nemenia

Proceduacuteru ktoraacute takto odstraňuje hodnoty z deničnyacutech oborov nazyacutevame reviacuteziou (orien-

tovanej) hrany Pseudokoacuted reviacutezie ukazuje Algoritmus 1 Keďže pre tuacute istuacute hranu (i j) mocircže

existovať aj viacero ohraničeniacute označiacuteme n-teacute ohraničenie Cnij Ako vidno proceduacutera navracia

hodnotu true alebo false podľa toho či bola z deničneacuteho oboru danej premennej vyluacutečenaacute nejakaacute

hodnota alebo nie

Algoritmus 1 Algoritmus proceduacutery reviacutezia hrany (podľa [6] s upravenyacutem značeniacutem)

1 procedure revise(i j) begin2 odstraacuteneneacutelarr false

3 foreach a isin Di do4 if b isin Dj (a b) isin Cn

ij foralln then5 odstraacuteniť a z Di

6 odstraacuteneneacutelarr true

7 end

8 end9 return odstraacuteneneacute

10 end

Ak teda reviacuteziu aplikujeme pre všetky hrany a opakovane dosiahneme napokon hranovuacute

konzistentnosť Algoritmus ktoryacute takto postupuje sa nazyacuteva AC-1 [6] Jeho pseudokoacuted ukazuje

Algoritmus 2

Nevyacutehodou AC-1 je že zbytočne opakuje niektoreacute reviacutezie Ak sa zmeniacute deničnyacute obor hoci len

jednej premennej automaticky sa revidujuacute všetky hrany ndash zmena maacute však v skutočnosti vplyv

len na tie hrany ktoreacute danuacute premennuacute obsahujuacute [5] To isteacute sme už vyššie ilustrovali na priacuteklade

so Sudoku (viď časť 42) ndash tiež bolo potrebneacute uvažovať len tie riadky stĺpce a štvorce kde nastala

zmena

Odpoveďou na tuacuteto vyacutehradu je algoritmus AC-2 [5] Ešte efektiacutevnejšou verziou tohto algo-

ritmu je však algoritmus AC-3 ktoryacute pri opakovanej reviacutezii pracuje s jednou frontou hraacuten Pse-

udokoacuted ukazuje Algoritmus 3

Existujuacute aj ďalšie vylepšeneacute verzie ndash prinajmenšom po AC-7 [4] Tyacutemto sa už nebudeme pod-

robnejšie venovať ndash viac možno pozrieť napr v [5 6]

middot 14 middot

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 21: Programovanie ohraničení

Algoritmus 2 Algoritmus AC-1 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-1(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 repeat4 zmeneneacutelarr false

5 foreach hrana (i j) isin Q do6 zmeneneacutelarr revise(i j) or zmeneneacute

7 end

8 until not(zmeneneacute)

9 end

Algoritmus 3 Algoritmus AC-3 (podľa [6] s upravenyacutem značeniacutem)

1 procedure AC-3(G) begin2 Qlarr (i j) isin hrany(G) i 6= j3 while not empty Q do4 foreach hrana (km) isin Q do5 zmazať (km) z Q

6 if revise(km) then7 Qlarr Q cup (i k) isin hrany(G) i 6= k i 6= m8 end

9 end

10 end

11 end

middot 15 middot

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 22: Programovanie ohraničení

63 Konzistentnosť po ceste

Keďže ako sme vyššie ukaacutezali hranovaacute konzistentnosť neimplikuje celkovuacute konzistentnosť hľa-

dali sa pri vyacutevoji CP ešte ineacute konzistenčneacute techniky Jednou z tyacutechto je tzv konzistentnosť poceste (PC angl path consistency)

Hovoriacuteme že cesta (1 2 n) je konzistentnaacute ak pre každyacute paacuter (x1 xn) konzistentnyacutech hod-

nocirct (tj takyacutech že spĺňajuacute všetky binaacuterne ohraničenia medzi 1 a n) existujuacute hodnoty x2 xnminus1

takeacute že všetky ohraničenia i i+ 1 suacute splneneacute [5]

Stojiacute za zmienku že taacuteto deniacutecia nehovoriacute nič o ohraničeniach medzi i a j pre |i minus j| gt 1

Daacute sa však ukaacutezať že ak suacute všetky cesty dĺžky 2 konzistentneacute po ceste celyacute CSP je konzistentnyacute

po ceste Algoritmy zabezpečujuacutece konzistentnosť po ceste preto pracujuacute len s cestami dĺžky 2

a (podobne ako AC) zabezpečujuacute konzistentnosť po ceste opakovanou aplikaacuteciou reviacuteziiacute [5]

7 | Riešenie predeterminovanyacutech CSP

V praxi suacute probleacutemy spĺňania ohraničeniacute často predeterminovaneacute ndash tj ohraničeniacute je priveľa a ne-

možno ich všetky suacutečasne splniť Typickyacutem priacutekladom mocircže byť tvorba školskeacuteho rozvrhu kde

treba brať do uacutevahy kapacitneacute možnosti miestnostiacute ďalej že taacute istaacute trieda (a rovnako ten istyacute uči-

teľ) nesmie mať viacero hodiacuten suacutečasne a pod K tomu sa navyše pridaacutevajuacute ineacute požiadavky napr

mocircže byť snaha vyučovať podľa možnosti predovšetkyacutem dopoludnia priacutepade mocircžu požiadavky

denovať učitelia ktoriacute sa mocircžu dostaviť len v niektoreacute dni

71 Maumlkkeacute ohraničenia

Ak nemožno všetky požiadavky splniť suacutečasne je možneacute niektoreacute z nich relaxovať Z priacutekladu

s rozvrhom je zrejmeacute že možno relaxovať len niektoreacute ohraničenia ndash ak napr priradiacuteme tomu

isteacutemu učiteľovi v rovnakom čase dve vyučovacie hodiny nie je fyzicky možneacute aby ich obe odučil

Na druhej strane rocirczne doplňujuacutece požiadavky relaxovať možno ndash v priacutepade že to je potrebneacute

možno napriacuteklad vyučovať aj večer

Pri riešeniacute predeterminovanyacutech CSP sa teda pracuje s dvomi typmi ohraničeniacute ndash s ostryacutemi(klasickyacutemi angl crisp constraint) ohraničeniami a s tzv maumlkkyacutemi ohraničeniami (angl soft

constraints) ktoreacute možno relaxovať [2]

Pomocou maumlkkyacutech ohraničeniacute mocircžeme pocircvodnyacute predeterminovanyacute probleacutem previesť na prob-

leacutem kde sa snažiacuteme naacutejsť najlepšie riešenie spĺňajuacutece všetky ostreacute ohraničenia ndash tj na opti-

malizačnyacute probleacutem Kriteacuteriaacute možno voliť rocirczne (napr aby bolo splnenyacutech čo najviac maumlkkyacutech

ohraničeniacute aby boli splneneacute tie najdocircležitejšie maumlkkeacute ohraničenia a pod) Ak probleacutem je prob-

leacutem predeterminovanyacute a použiacutevame maumlkkeacute ohraničenia hovoriacuteme o tzv probleacuteme čiastočneacuteho

middot 16 middot

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 23: Programovanie ohraničení

splnenia ohraničeniacute (čiastočneacute CSP angl partial constraint satisfaction problem) [2]

72 Max-CSP

Probleacutem čiastočneacuteho splnenia ohraničeniacute kde hľadaacuteme riešenie ktoreacute spĺňa všetky ostreacute ohrani-

čenia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa nazyacuteva max-CSP [2] V priacuteklade s rozvrhmi

Jednou z možnostiacute ako tu postupovať je použiť tzv počet hranovyacutech konzistentostiacute V priacute-

klade s rozvrhmi by to znamenalo buď maximalizovať počet splnenyacutech pocircvodnyacutech maumlkkyacutech

ohraničeniacute (tj počet študentov ktoryacutem v rozvrhu nič nekoliduje) alebo transformovať každeacute

discjunctive ohraničenie na ohraničenia disj a snažiť sa splniť čo najviac z nich (tj minimali-

zovať počet koliacuteziiacute medzi kurzami zvolenyacutemi jednotlivyacutemi študentmi)

73 Vaacuteženeacute CSP

Ďalšou možnosťou je priradiť každeacutemu z maumlkkyacutech ohraničeniacute určituacute čiacuteselnuacute vaacutehu vyjadrujuacutecu

akuacute docircležitosť prikladaacuteme daneacutemu ohraničeniu ndash tj akou hodnotou budeme pokutovať jeho

nesplnenie Takto formulovanyacute probleacutem nazyacutevame aj vaacuteženyacute probleacutem spĺňania ohraničeniacute(angl weighted constraint satisfaction problem) [2] Cieľom je minimalizovať celkovyacute suacutečet pokuacutet

vyplyacutevajuacutecich z nesplnenyacutech ohraničeniacute Probleacutem max-CSP možno považovať za typ vaacuteženeacuteho

CSP kde všetky vaacutehy suacute nastaveneacute rovnako

74 Fuzzy CSP

Existuje aj priacutestup ktoryacute zavaacutedza mieru splnenia každeacuteho ohraničenia formalizovanuacute pomocou

fuzzy konceptov Miera splnenia ohraničenia C pri inštanciaacutecii (konguraacutecii hodnocirct premen-

nyacutech) I sa označuje sat(C I) Platiacute sat(C I) isin 〈0 1〉 kde 0 znamenaacute že ohraničenie C nie je

v inštanciaacutecii I vocircbec splneneacute a 1 znamenaacute že je splneneacute uacuteplne

Takaacuteto formulaacutecia probleacutemu sa nazyacuteva fuzzy CSP [2] Cieľom je najčastejšie naacutejsť takuacute in-

štanciaacuteciu Ilowast ktoraacute maximalizuje najmenšiu mieru splnenia [2] tj pre ňu platiacute nasledujuacutece

Ilowast = argmaxI

minC

sat(C I) (71)

75 Ďalšie priacutestupy

Okrem uvedenyacutech existujuacute ešte viacereacute ineacute priacutestupy Jeden z nich je založenyacute na reikaacutecii ndash

o tomto budeme ešte hovoriť v nasledujuacutecej kapitole Čo sa tyacuteka ostatnyacutech priacutestupov ndash napr

hierarchiiacute ohraničeniacute a zovšeobecnenyacutech priacutestupov ndash možno viac pozrieť napr v [2]

middot 17 middot

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 24: Programovanie ohraničení

8 | ReikaacuteciaReikaacutecia je proces kedy sa validita ohraničenia premieta do boolovskej premennej [7] Mohli

by sme povedať že ohraničenie sa materializuje staacuteva sa reaacutelnym (odtiaľ reikaacutecia) Ako priacuteklad

možno uviesť reikovaneacute ohraničenie b = 1 hArr x = y kde b je boolovskaacute premennaacute a x = y je

ohraničenie Takeacuteto ohraničenie sa propaguje nasledujuacutecim spocircsobom [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

bull Ak platiacute x 6= y propaguje sa b = 0

81 Využitie reikaacutecie pri modelovaniacute

Reikaacutecia maacute pri modelovaniacute viacero využitiacute Ako priacuteklad ukaacutežeme ako ju možno použiť na zaacutepis

disjunktnyacutech ohraničeniacute a ako možno pomocou nej zapiacutesať že dve polia veľkosti n sa po prv-

koch nerovnajuacute Priacuteklady suacute len ilustratiacutevne ndash nechceme povedať že ide o jedinyacute alebo o najlepšiacute

spocircsob reprezentaacutecie disjunkcie resp nerovnosti poliacute po prvkoch Osobitnyacutem priacutepadom využitia

reikaacutecie je aj riešenie max-CSP a vaacuteženeacuteho CSP o ktoryacutech bola reč vyššie ndash na tuacuteto aplikaacuteciu sa

tiež v kraacutetkosti pozrieme

811 Zaacutepis disjunkcie

Za normaacutelnych okolnostiacute suacute všetky ohraničenia v konjunkcii tj vyžaduje sa aby platili všetky

suacutečasne V praxi však často potrebujeme vyjadriť že existuje viacero alternatiacutev ktoreacute suacute priacutepustneacute

ndash tj že maacute platiť ohraničenie C1 alebo C2 Označujeme C1 or C2

Jednyacutem zo spocircsobov ako disjunkciu zapiacutesať je použiť reikaacuteciu V tom priacutepade denujeme

dve reikovaneacute ohraničenia

b1 hArr C1 a b2 hArr C2 (81)

Naacutesledne ich reikaacutecie b1 a b2 previažeme ďalšiacutem ohraničeniacutem

b1 + b2 gt= 1 (82)

Ak platiacute praacuteve jedno z ohraničeniacute suacutečet b1 + b2 bude rovnyacute 1 Ak platia obe suacutečet bude 2

tj gt 1 Ak nie je splneneacute ani jedno z ohraničeniacute suacutečet bude rovnyacute 0 tj disjunktneacute ohraničenie

C1 or C2 nie je splneneacute

middot 18 middot

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 25: Programovanie ohraničení

812 Nerovnosť prvkov poliacute

Nech maacuteme dve polia X a Y veľkosti n Chceme vyjadriť že

X[i] 6= Y [i] foralli isin 1 2 n (83)

Jednyacutem zo spocircsobov ako postupovať je denovať pre každeacute i reikovaneacute ohraničenie v tvare

bi hArr X[i] 6= Y [i] a naacutesledne povedať že suacutečet všetkyacutech bi sa musiacute rovnať n Ak ohraničenie

nebude splneneacute aspoň pre jedno i zodpovedajuacutece bi bude rovneacute 0 a suacutečet všetkyacutech bi bude menšiacute

než n

813 Riešenie probleacutemu max-CSP

Ako sme povedali vyššie pri riešeniacute predeterminovanyacutech CSP možno niektoreacute ostreacute ohraničenia

nahradiť maumlkkyacutemi ohraničeniami Probleacutem naacutejdenia riešenia ktoreacute spĺňa všetky ostreacute ohraniče-

nia a čo najvaumlčšiacute počet maumlkkyacutech ohraničeniacute sa potom označuje ako max-CSP

Ak jednotliveacute ohraničenia C1 C2 Cn reikujeme tj b1 hArr C1 bn hArr Cn mocircžeme

pocircvodnyacute max-CSP probleacutem previesť jednoducho na CSP optimalizačnyacute probleacutem kde uacutečelovaacute

funkcia budensum

i=1bi (84)

tj suacutečet reikaacuteciiacute resp počet splnenyacutech ohraničeniacute [2]

Obdobne v priacutepade vaacuteženeacuteho CSP ndash tu by uacutečelovaacute funkcia navyše operovala aj s vaacutehami wi

jednotlivyacutech ohraničeniacute tj

nsumi=1

wibi (85)

82 Polovičnaacute reikaacutecia

Typ reikaacutecie o ktorej sme hovorili vyššie sa nazyacuteva aj uacuteplnaacute reikaacutecia Okrem uacuteplnej reikaacutecie

existuje aj polovičnaacute reikaacutecia [7] ndash tu sa propagaacutecia ohraničeniacute deje len v jednom smere

Priacutekladom takeacuteho ohraničenia mocircže byť b = 1 rArr x = y V tomto priacutepade sa propaguje len

nasledovne [7]

bull Ak sa priradiacute b = 1 propaguje sa ohraničenie x = y

bull Ak platiacute x 6= y propaguje sa b = 0

Mocircže nastať aj priacutepad kedy sa propaguje v opačnom smere Napriacuteklad b = 1 lArr x = y sa

bude propagovať [7]

bull Ak sa priradiacute b = 0 propaguje sa ohraničenie x 6= y

bull Ak platiacute x = y propaguje sa b = 1

middot 19 middot

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 26: Programovanie ohraničení

9 | Obľuacutebeneacute benchmark probleacutemyNa tomto mieste uvedieme niekoľko obľuacutebenyacutech benchmark probleacutemov na ktoryacutech sa CP (ale aj

ineacute metoacutedy) často ilustrujuacute resp sa porovnaacuteva ich uacutečinnosť

91 Probleacutem obchodneacuteho cestujuacuteceho

Probleacutem obchodneacuteho cestujuacuteceho (angl travelling salesman problem TSP) je azda jednyacutem z naj-

znaacutemejšiacutech benchmark probleacutemov v oblasti strojoveacuteho učenia vocircbec ndash aplikovalo sa naň už ne-

spočetneacute množstvo rocircznych metoacuted

Podstatou probleacutemu je že obchodnyacute cestujuacuteci maacute za uacutelohu navštiacuteviť určiteacute mestaacute Cieľom

je naplaacutenovať takuacute trasu aby žiadne mesto nenavštiacutevil viackraacutet a aby bola cesta čo najkratšia

Okrem toho sa typicky požaduje aby cesta končila v tom istom bode z ktoreacuteho vychaacutedza (tj aby

bola uzavretaacute) Treba poznamenať že probleacutem obchodneacuteho cestujuacuteceho je NP-ťažkyacute

Probleacutem maacute viacero variantov niektoreacute napriacuteklad povoľujuacute navštiacuteviť to isteacute miesto aj viackraacutet

Zo všetkyacutech takyacutechto variantov vyberaacuteme na ďalšiu diskusiu tieto tri

bull Probleacutem je reprezentovanyacuteneohodnotenyacutemgrafom ktoryacute určuje z ktoreacuteho mesta možno

prejsť do ktoreacuteho

bull Probleacutem je reprezentovanyacute ohodnotenyacutem grafom tj pribuacuteda koncept dĺžky (ceny) cesty

ndash tuacuteto sa snažiacuteme minimalizovať

bull Probleacutem je reprezentovanyacute uacuteplnyacutem ohodnotenyacutem grafom (resp maticou cien) tj uvažuje

sa že možno prejsť z každeacuteho mesta do každeacuteho

911 Neohodnotenyacute graf

Priacuteklad TSP reprezentovaneacuteho neohodnotenyacutem grafom je na Obr 91 Ako vidno graf obsahuje

5 miest P1 P2 P3 P4 a P5 Hrany vyjadrujuacute z ktoreacuteho mesta do ktoreacuteho možno prejsť Z P1 je

teda možnyacute prechod do P2 a P3 Z P2 je možnyacute prechod do P1 P3 P4 P5 atď

Graf mocircže byť aj orientovanyacute ndash tj v niektoryacutech priacutepadoch mocircže byť cesta len jednosmernaacute

Priacuteklad je na Obr 92

912 Ohodnotenyacute graf

Ak do grafu pridaacuteme dĺžky (ceny) jednotlivyacutech ciest ziacuteskame TSP v reprezentaacutecii ohodnotenyacutem

grafom a okrem hľadania cesty už mocircžeme aj minimalizovať jej cenu Priacuteklad takeacuteho TSP je na

Obr 93

middot 20 middot

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 27: Programovanie ohraničení

Obr 91 TSP reprezentaacutecia neohodnotenyacutem

neorientovanyacutem grafom

Obr 92 TSP reprezentaacutecia neohodnotenyacutem

orientovanyacutem grafom

Obr 93 TSP reprezentaacutecia ohodnotenyacutem ne-

orientovanyacutem grafom

Obr 94 TSP reprezentaacutecia ohodnotenyacutem

orientovanyacutem grafom

Obdobne ako v predchaacutedzajuacutecom priacutepade aj teraz je možneacute aby graf bol aj orientovanyacute ndash

mocircže obsahovať jednosmerneacute cesty Navyše ohodnotenyacute graf mocircže obsahovať obojsmerneacute hrany

s odlišnou cenou v každom smere ndash priacuteklad je na Obr 94

913 Uacuteplnyacute graf

Tyacutem sa dostaacutevame k poslednej možnosti ndash graf TSP mocircže byť uacuteplnyacute tj je možneacute iacutesť z každeacuteho do

každeacuteho mesta Ak graf nie je uacuteplnyacute možno ho na uacuteplnyacute previesť tak že cestu cez viacero vrcholov

nahradiacuteme hranou s cenou rovnou cene cesty V priacutepade že existuje viacero ciest spaacutejajuacutecich daneacute

vrcholy je samozrejme otaacutezne ktoruacute z nich zvoliť

92 SEND MORE MONEY

V priacutepade probleacutemu SEND MORE MONEY dostaacutevame aritmetickyacute vyacuteraz kde namiesto čiacuteslic vy-

stupujuacute piacutesmenaacute Uacutelohou je priradiť ku jednotlivyacutem piacutesmenaacutem takeacute čiacuteslice aby danyacute vyacuteraz platil

middot 21 middot

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 28: Programovanie ohraničení

a pritom sa všetky čiacuteslice navzaacutejom liacutešili

Spomiacutenanyacute aritmetickyacute vyacuteraz maacute nasledujuacuteci tvar

SEND + MORE = MONEY (91)

Ak vyacuteraz rozpiacutešeme podrobnejšie maacuteme

1000S + 100E + 10N + D+ 1000M + 100O + 10R + E

= 10000M + 1000O + 100N + 10E + Y

(92)

Ako ďalšie ohraničenie pridaacutevame S 6= 0 aM 6= 0 Povedali sme okrem toho že všetky čiacuteslice

sa majuacute navzaacutejom liacutešiť tj S 6= E 6= N 6= D 6= M 6= O 6= R 6= Y

93 Probleacutem magickyacutech postupnostiacute

Ďalšiacutem obľuacutebenyacutem probleacutemom na ktorom sa často ilustruje CP je probleacutem magickyacutech postup-

nostiacute (angl magic series) Cieľom je naacutejsť postupnosť čiacutesel v tvare X = x0 x1 xN takuacute aby

platilo že xi sa rovnaacute počtu vyacuteskytov čiacutesla i v X

Ako priacuteklad ndash postupnosť x0 = 2 x1 = 1 x2 = 2 x3 = 0 x4 = 0 je magickaacute postupnosť

pretože čiacuteslo 0 sa v postupnosti vyskytuje dvakraacutet čiacuteslo 1 jedenkraacutet atď ako to ukazuje aj Tab 91

0 1 2 3 4

Počet vyacuteskytov 2 1 2 0 0

Tab 91 Priacuteklad magickej postupnosti [8]

10 | Priacuteklad Riešenie Sudoku pomocou GecodeV tejto časti ukaacutežeme ako možno aplikovať CP pomocou C++ knižnice Gecode Priacuteklad prejdeme

po častiach ndash kompletnyacute listing prikladaacuteme tu Lst 21 ukazuje zaacutepis priacutekladu na ktorom

budeme testovať Ako vidno denujeme pole int-ov example ktoreacute reprezentuje hracie pole

Čiacutesla predstavujuacute hodnoty jednotlivyacutech vyplnenyacutech poliacutečok Nuly označujuacute poliacutečka ktoreacute suacute

ešte nevyplneneacute

Lst 1 Sudoku ndash zaacutepis priacutekladu na ktorom budeme testovať

1 2 Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutecka

3

middot 22 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 29: Programovanie ohraničení

4 const int sudoku_example[] =

5 0 0 0 0 0 0 0 9 0

6 0 5 0 0 4 2 3 6 0

7 3 0 4 6 0 8 1 7 0

8 8 0 0 0 2 0 0 0 9

9 0 0 0 8 0 1 0 0 0

10 4 0 0 0 6 0 0 0 1

11 0 1 6 2 0 4 9 0 7

12 0 4 9 5 7 0 0 1 0

13 0 0 0 0 0 0 0 0 0

14

101 Direktiacutevy include a linkovanie

Na uacutevod pridaacuteme zopaacuter include direktiacutev a importujeme namespace Gecode ndash viď Lst 2 Prvaacute

direktiacuteva importuje potrebnuacute infraštruktuacuteru pre celočiacuteselneacute (int) ohraničenia hlavičkovyacute suacutebor

minimodel sprostredkuje komfortnejšiacute spocircsob zaacutepisu jednotlivyacutech ohraničeniacute a napokon hlavič-

kovyacute suacutebor search rieši prehľadaacutevanie

Lst 2 Sudoku ndash include direktiacutevy a using namespace

1 include ltgecodeinthhgt

2 include ltgecodeminimodelhhgt

3 include ltgecodesearchhhgt

4

5 using namespace Gecode

Docircležitaacute poznaacutemka sa tyacuteka linkovania Keď zdrojovyacute koacuted skompilujeme musiacuteme ešte linkovať

na zodpovedajuacutece dynamickeacute knižnice Gecode Gecode maacute takuacute organizaacuteciu že existuje osobitnaacute

knižnica ku každeacutemu hlavičkoveacutemu suacuteboru V našom priacutepade budeme linkovať na gecodedriver

gecodeint gecodeminimodel gecodesearch gecodesupport gecodekernel

102 Trieda Sudoku

Ďalej musiacuteme zadenovať samotnyacute probleacutem spĺňania ohraničeniacute Z časti 2 vieme že CSP sa skladaacute

jednak z premennyacutech a ich deničnyacutech oborov a jednak z ohraničeniacute V raacutemci knižnice Gecode

existuje viacero spocircsobov ako probleacutem formalizovať ndash my dediacuteme z triedy Space tj denuje

priestor riešeniacute (mohli by sme dediť aj z inyacutech tried napr z triedy Script ktoraacute poskytuje trochu

ineacute rozhranie)

Vydedenaacute trieda je v Lst 3 Ako vidno trieda obsahuje jednu členskuacute premennuacute vars ktoraacute

je typu IntVarArrays Ide o pole celočiacuteselnyacutech premennyacutech ktoreacute predstavujuacute jednotliveacute poliacutečka

Sudoku a ktoreacute spolu previažeme priacuteslušnyacutemi ohraničeniami

middot 23 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 30: Programovanie ohraničení

Za zmienku stojiacute aj funkcia copy ktoraacute umožňuje priestor riešeniacute kopiacuterovať Taacuteto funkcia

sa použiacuteva pri vetveniacute ndash aby v priacutepade neuacutespechu bolo možneacute vraacutetiť sa k predchaacutedzajuacutecemu

vetveniu musiacuteme vedieť obnoviť stav v ktorom vtedy boli deničneacute obory premennyacutech Ako

vidno v našom priacutepade z funkcie copy iba volaacuteme priacuteslušnyacutech kopiacuterovaciacute konštruktor

Funkciu print denujeme preto aby sme vedeli hotoveacute riešenie vypiacutesať do štandardneacuteho vyacute-

stupu

Lst 3 Sudoku ndash dediacuteme z triedy Space

1 2 Trieda definujuacuteca premenneacute pre Sudoku o ohranicenia na nich

3

4 class Sudoku public Space

5 protected

6 Pole celociacuteselnyacutech premennyacutech

7 IntVarArray vars

8

9 public

10 Vytvorenie koacutepie

11 virtual Space copy(bool share)

12 return new Sudoku(share this)

13

14

15 Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupu

16 void print() const

17 stdcout ltlt res ltlt stdendl

18

19 MatrixltIntVarArraygt mat(vars 9 9)

20

21 int rows = matheight() cols = matwidth()

22 for(int i = 0 i lt rows i++)

23 for(int j = 0 j lt cols j++)

24 stdcout ltlt mat(i j) ltlt

25

26 stdcout ltlt stdendl

27

28

29 stdcout ltlt stdendl

30

31

32 public

33 Sudoku(const int example = nullptr)

34 Sudoku(bool share Sudokuamp obj)

35

103 Konštrukcia triedy Sudoku

Konštruktor triedy Sudoku obsahuje najpodstatnejšiu časť koacutedu ndash tu sa určuje koľko bude pre-

mennyacutech a pridaacutevajuacute sa jednotliveacute ohraničenia Zodpovedajuacuteci koacuted ukazuje Zoznam obraacutezkov 4

middot 24 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 31: Programovanie ohraničení

Ako vidno pole celočiacuteselnyacutech premennyacutech vars ktoreacute sme deklarovali vyššie bude obsaho-

vať 99 premennyacutech pričom každaacute bude z deničneacuteho oboru 〈1 9〉V prvom riadku konštruktora vytvaacuterame pomocnyacute objekt mat ndash tento naacutem pocircvodneacute pole pre-

mennyacutech umožňuje reprezentovať ako maticu rozmerov 9times9 Vyacutehodou je že takaacuteto reprezentaacutecia

naacutem umožniacute veľmi prirodzenyacutem spocircsobom zapiacutesať riadkoveacute stĺpcoveacute a štvorcoveacute ohraničenia

Napriacuteklad pre nultyacute riadok stačiacute piacutesať distinct(this matrow(0)) tj že všetky prvky

v nultom riadku sa musia navzaacutejom liacutešiť Obdobne denujeme ohraničenia pre stĺpce (matcol(i))

a štvorce (matslice(i i+3 j j+3))

Ďalej ak sme dostali aj pole s predvyplnenyacutemi poliacutečkami (example) zostaviacuteme priacuteslušneacute ohra-

ničenia Celkom na zaacutever sa zvoliacute typ vetvenia V priacutepade že by sme pracovali s viaceryacutemi po-

ľami premennyacutech a pod registrovalo by sa rovnakyacutem spocircsobom vetvenie pre každeacute osobitne

Pri vetveniacute možno stanoviť cez ktoruacute premennuacute sa bude vetviť ako cez prvuacute (napr premennaacute

s najmenšiacutem deničnyacutem oborom) a od ktorej hodnoty sa začne (napr od najmenšej hodnoty)

Lst 4 Sudoku ndash konštruktor

1 SudokuSudoku(const int example) vars(this 99 1 9)

2 MatrixltIntVarArraygt mat(vars 9 9)

3 int rows = matheight() cols = matwidth()

4

5 Riadkoveacute ohranicenia

6 for(int i = 0 i lt rows i++)

7 distinct(this matrow(i))

8

9

10 Stlpcoveacute ohranicenia

11 for(int i = 0 i lt cols i++)

12 distinct(this matcol(i))

13

14

15 Štvorcoveacute ohranicenia

16 for(int i = 0 i lt 9 i+=3)

17 for(int j = 0 j lt 9 j+=3)

18 distinct(this matslice(i i+3 j j+3))

19

20

21

22 Naciacutetame predplneneacute poliacutecka z priacutekladu ak existuje

23 if(example)

24 for(int i = 0 i lt rows i++)

25 for(int j = 0 j lt cols j++)

26 int val = example[icols + j]

27 if(val) rel(this mat(ij) == val)

28

29

30

31

32 Akeacute sa použije vetvenie

middot 25 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 32: Programovanie ohraničení

33 branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX())

34

Druhyacute konštruktor ako sme už spomenuli vyššie je kopiacuterovaciacute (viď Lst 5)2

Lst 5 Sudoku ndash kopiacuterovaciacute konštruktor

1 Konštruktor ku podpore prehlrsquoadaacutevania

2 SudokuSudoku(bool share Sudokuamp obj)

3 Space(share obj) vars()

4

5 varsupdate(this share objvars)

6

104 Funkcia main

Celkom poslednuacute časť koacutedu tvoriacute funkcia main (hlavnaacute funkcia programu) ktoruacute ukazuje Lst 6

Tu sa najprv vytvaacutera objekt typu Sudoku Naacutesledne sa voliacute typ prehľadaacutevania ndash tu ide o pre-

hľadaacutevanie do hĺbky (angl dept-rst search) Naacutesledne sa hľadajuacute a postupne vypisujuacute všetky

riešenia

Lst 6 Sudoku ndash funkcia main

1 int main()

2 Sudoku sudoku = new Sudoku(sudoku_example)

3 DFSltSudokugt dfs(sudoku) DFS - depth-first search

4 delete sudoku

5

6 Hlrsquoadaacuteme a postupne vypisujeme všetky riešenia

7 while(Sudoku s = dfsnext())

8 s-gtprint()

9 delete s

10

11

12 return 0

13

2Zvlaacuteštnosťou je že okrem referencie na objekt Sudokuamp obj ako argument požaduje ešte boolovskuacute premennuacute

share Ak share je true znamenaacute to že niektoreacute objekty sa buduacute medzi obomi koacutepiami zdieľať ndash koacutepie sa potom smuacute

použiacutevať len spolu v tom istom vlaacutekne Ak share je false vytvoriacute sa uacuteplnaacute koacutepia ktoraacute je už aj vlaacuteknovo bezpečnaacute

[7]

middot 26 middot

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

include ltgecodeinthhgtinclude ltgecodeminimodelhhgtinclude ltgecodesearchhhgtusing namespace Gecode Priacuteklad Sudoku Nuly suacute nevyplneneacute poliacutečkaconst int sudoku_example[] = 0 0 0 0 0 0 0 9 0 0 5 0 0 4 2 3 6 0 3 0 4 6 0 8 1 7 0 8 0 0 0 2 0 0 0 9 0 0 0 8 0 1 0 0 0 4 0 0 0 6 0 0 0 1 0 1 6 2 0 4 9 0 7 0 4 9 5 7 0 0 1 0 0 0 0 0 0 0 0 0 0 Trieda definujuacuteca premenneacute pre Sudoku o ohraničenia na nichclass Sudoku public Space protected Pole celočiacuteselnyacutech premennyacutechIntVarArray varspublic Vytvorenie koacutepievirtual Space copy(bool share) return new Sudoku(share this) Vyacutepis hodnocirct premennyacutech do štandardneacuteho vyacutestupuvoid print() const stdcout ltlt res ltlt stdendlMatrixltIntVarArraygt mat(vars 9 9)int rows = matheight() cols = matwidth()for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) stdcout ltlt mat(i j) ltlt stdcout ltlt stdendlstdcout ltlt stdendlpublic Sudoku(const int example = nullptr) Sudoku(bool share Sudokuamp obj)SudokuSudoku(const int example) vars(this 99 1 9) MatrixltIntVarArraygt mat(vars 9 9) int rows = matheight() cols = matwidth() Riadkoveacute ohraničenia for(int i = 0 i lt rows i++) distinct(this matrow(i)) Stĺpcoveacute ohraničenia for(int i = 0 i lt cols i++) distinct(this matcol(i)) Štvorcoveacute ohraničenia for(int i = 0 i lt 9 i+=3) for(int j = 0 j lt 9 j+=3) distinct(this matslice(i i+3 j j+3)) Načiacutetame predplneneacute poliacutečka z priacutekladu ak existuje if(example) for(int i = 0 i lt rows i++) for(int j = 0 j lt cols j++) int val = example[icols + j] if(val) rel(this mat(ij) == val) Akeacute sa použije vetvenie branch(this vars INT_VAR_SIZE_MIN() INT_VAL_MAX()) Konštruktor ku podpore prehľadaacutevaniaSudokuSudoku(bool share Sudokuamp obj) Space(share obj) vars() varsupdate(this share objvars)int main() Sudoku sudoku = new Sudoku(sudoku_example)DFSltSudokugt dfs(sudoku) DFS - depth-first searchdelete sudoku Hľadaacuteme a postupne vypisujeme všetky riešeniawhile(Sudoku s = dfsnext()) s-gtprint()delete s return 0

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 33: Programovanie ohraničení

11 | Priacuteklad Riešenie Sudoku v jazyku PrologKeďže ako sme povedali vyššie osobitnuacute časť priacutestupov ku programovaniu ohraničeniacute tvoriacute tzv

logickeacute programovanie ohraničeniacute tj aplikaacutecie programovania ohraničeniacute v logickyacutech jazykoch

ako je Prolog uvedieme pre porovnanie aj riešenie Sudoku v prostrediacute SWI-Prolog Toto postupne

prejdeme v nasledujuacutecich častiach Kompletnyacute zdrojovyacute koacuted prikladaacuteme

111 Použiteacute moduly a vloženie Sudoku

Podpora pre logickeacute programovanie ohraničeniacute s konečnyacutemi deničnyacutemi obormi je v prostrediacute

SWI-Prolog poskytovanaacute knižnicou clpfd ktoruacute teda pomocou direktiacutevy use_module importu-

jeme ako to ukazuje Lst 7

V Lst 7 ďalej vidno ako možno vložiť predplneneacute hracie pole Sudoku vkladaacuteme ho pomo-

cou predikaacutetu example formou 2D zoznamu Praacutezdne polia pritom nahraacutedzame znakom _ tj

anonymnou premennou

Lst 7 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 - use_module(library(clpfd))

2

3 4 Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutecka

5

6 example([[_______9_]

7 [_5__4236_]

8 [3_46_817_]

9 [8___2___9]

10 [___8_1___]

11 [4___6___1]

12 [_162_49_7]

13 [_4957__1_]

14 [_________]])

112 Denovanie ohraničeniacute

Jadro programu ukazuje Lst 8 ndash tu sa denujuacute jednotliveacute ohraničenia Ako prveacute sa špecikuje

že veľkosť (length) premennej Rows (zoznam riadkov) musiacute byť 9

Naacutesledne sa volaacute vstavanyacute predikaacutet maplist ndash tento aplikuje prvyacute argument ako predikaacutet na

každyacute prvok zo zoznamu V tomto priacutepade sa na každyacute riadok (prvok zoznamu Rows) aplikuje

predikaacutet length_list(9) ktoryacute kontroluje či maacute danyacute riadok 9 stĺpcov Predikaacutet length nemocirc-

žeme použiť s predikaacutetom maplist priamo kvocircli poradiu argumentov preto použijeme pomocnyacute

predikaacutet length_list ktoryacute ich poradie obracia Jeho presnaacute deniacutecia bude ešte uvedenaacute nižšie

middot 27 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 34: Programovanie ohraničení

Lst 8 Sudoku v SWI-Prolog moduly a vloženie Sudoku

1 2 Predikaacutet s ohraniceniami maplist aplikuje na každyacute prvok

3 zoznamu zadanuacute funkciu

4

5 sudoku(Rows) -

6 Riadkov musiacute bytrsquo 9

7 length(Rows 9)

8 Každyacute riadok musiacute matrsquo 9 prvkov

9 maplist(length_list(9) Rows)

10 Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs

11 append(Rows Vs)

12 Každyacute prvok Vs mocircže matrsquo rozsah od 1 po 9

13 Vs ins 19

14 V každom riadku sa prvky musia liacutešitrsquo

15 maplist(all_distinct Rows)

16 Zo zoznamu riadkov ziacuteskame zoznam stlpcov

17 transpose(Rows Columns)

18 V každom stlpci sa prvky musia liacutešitrsquo

19 maplist(all_distinct Columns)

20 Riadky si oznaciacuteme piacutesmenami

21 Rows = [ABCDEFGHI]

22 Aplikujeme ohranicenia pre bloky najprv

23 pre prveacute tri riadky (A B C) potom pre drsquoalšie 3 atdrsquo

24 blocks(A B C) blocks(D E F) blocks(G H I)

Aby sme denovali deničnyacute obor jednotlivyacutech premennyacutech premietneme pomocou predi-

kaacutetu append všetky riadky do spoločneacuteho 1-rozmerneacuteho zoznamu Vs o ktorom potom povieme

že každyacute jeho prvok musiacute byť z rozsahu od 1 po 9

Ohraničenie pre riadky denujeme tak že pomocou predikaacutetu maplist aplikujeme na každyacute

riadok ohraničenie all_distinct (ekvivalent distinct z knižnice Gecode) Ohraničenia pre stĺpce

riešime obdobne Aby sme ziacuteskali zoznam pre stĺpce Columns deklarujeme že Columns je trans-

poziacutecia zoznamu Rows

O niečo zložitejšie je denovať ohraničenia pre bloky Prolog ako takyacute neobsahuje vhodneacute

naacutestroje na vyacuteber segmentov a blokov zo zoznamov ndash ak by sme teda chceli postupovať obdobne

ako vo vyššie uvedenom C++ koacutede museli by sme si priacuteslušneacute predikaacutety najprv zadenovať

Jednyacutem zo spocircsobov ako sa tomu vyhnuacuteť ukazuje praacuteve Lst 8 Ako vidno najprv si jednotliveacute

riadky označujeme piacutesmenami A B C D E F G H I Naacutesledne volaacuteme predikaacutet blocks (ktoreacuteho

deniacutecia bude evedenaacute nižšie) pre jednotliveacute trojice riadkov ndash tj pre (A B C) (D E F) a (G H I)

Predikaacutet blocks potom postupne vyberie k trojiciam riadkov priacuteslušneacute trojice stĺpcov a na každyacute

takto zloženyacute blok aplikuje ohraničenie all_distinct

middot 28 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 35: Programovanie ohraničení

113 Pomocneacute predikaacutety

Vyššie pri denovaniacute ohraničeniacute sme použili pomocnyacute predikaacutet length_list Jeho deniacuteciu

ukazuje Lst 9 Ako vidno predikaacutet sa odkazuje na vstavanyacute predikaacutet length a iba obracia poradie

argumentov (preto ho možno aplikovať spoločne s predikaacutetom maplist tak ako sme to videli

vyššie)

Lst 9 Sudoku v SWI-Prolog pomocnyacute predikaacutet length_list

1 Predikaacutet na kontrolu rozmerov riadkov

2 length_list(L Ls) - length(Ls L)

Tiež sme použili pomocnyacute predikaacutet blocks na denovanie ohraničeniacute pre bloky Deniacuteciu

ukazuje Lst 10 Ako vidno najprv sa denuje verzia predikaacutetu pre praacutezdne zoznamy ktoraacute sluacuteži

na ukončenie rekurzie

Samotnaacute rekurziacutevna deniacutecia predikaacutetu blocks potom odštepuje z hlavy každeacuteho zoznamu

(tj z každeacuteho riadku) vždy po troch prvkoch Keďže blocks operuje vždy na troch riadkoch

a vyberaacute z nich po troch stĺpcoch vznikajuacute takto bloky rozmeru 3 times 3 o ktoreacute maacuteme zaacuteujem

Keďže jednotliveacute prvky bloku sme aj tu označili piacutesmenami stačiacute už len aplikovať ohraničenie

all_distinct na zoznam všetkyacutech piacutesmen

Lst 10 Sudoku v SWI-Prolog pomocnyacute predikaacutet blocks

1 Bloky predikaacutet na ukoncenie rekurzie

2 blocks([] [] [])

3 Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch

4 prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme

5 že sa prvky nesmuacute opakovatrsquo

6 blocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) -

7 all_distinct([ABCDEFGHI])

8 blocks(Bs1 Bs2 Bs3)

114 Riešenie

Na zaacutever už stačiacute len vypiacutesať riešenie Ak chceme riešenie vypiacutesať hneď po kompilaacutecii suacuteboru

mocircžeme použiť zdrojovyacute koacuted Lst 11 Ako vidno tu najprv unikujeme priacuteklad s premennou Rows

a naacutesledne každyacute riadok osobitne (maplist) vypiacutešeme pomocou predikaacutetu writeln

Lst 11 Sudoku v SWI-Prolog vyacutepis riešenia

1 2 Vypiacutešeme riešenie

3

4 - example(Rows) sudoku(Rows) maplist(writeln Rows)

middot 29 middot

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

- use_module(library(clpfd)) Priacuteklad Sudoku Anonymneacute premenneacute _ suacute nevyplneneacute poliacutečkaexample([[_______9_] [_5__4236_] [3_46_817_] [8___2___9] [___8_1___] [4___6___1] [_162_49_7] [_4957__1_] [_________]]) Predikaacutet s ohraničeniami maplist aplikuje na každyacute prvok zoznamu zadanuacute funkciusudoku(Rows) - Riadkov musiacute byť 9 length(Rows 9) Každyacute riadok musiacute mať 9 prvkov maplist(length_list(9) Rows) Všetky riadky premietneme do 1-rozmerneacuteho zoznamu Vs append(Rows Vs) Každyacute prvok Vs mocircže mať rozsah od 1 po 9 Vs ins 19 V každom riadku sa prvky musia liacutešiť maplist(all_distinct Rows) Zo zoznamu riadkov ziacuteskame zoznam stĺpcov transpose(Rows Columns) V každom stĺpci sa prvky musia liacutešiť maplist(all_distinct Columns) Riadky si označiacuteme piacutesmenami Rows = [ABCDEFGHI] Aplikujeme ohraničenia pre bloky najprv pre prveacute tri riadky (A B C) potom pre ďalšie 3 atď blocks(A B C) blocks(D E F) blocks(G H I) Predikaacutet na kontrolu rozmerov riadkovlength_list(L Ls) - length(Ls L) Bloky predikaacutet na ukončenie rekurzieblocks([] [] []) Z jednotlivyacutech riadkov (argumenty) vyberaacuteme vždy po troch prvkoch (tj bloky 3x3) Pre každyacute takyacuteto blok deklarujeme že sa prvky nesmuacute opakovaťblocks([ABC|Bs1] [DEF|Bs2] [GHI|Bs3]) - all_distinct([ABCDEFGHI]) blocks(Bs1 Bs2 Bs3) Vypiacutešeme riešenie- example(Rows) sudoku(Rows) maplist(writeln Rows)

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 36: Programovanie ohraničení

Literatuacutera[1] Rossi F ndash Van Beek P ndash Walsh T Handbook of constraint programming Elsevier 2006

ISBN 978-0-444-52726-4

[2] Apt K Principles of constraint programming Cambridge University Press 2003 ISBN

978-0-521-82583-2

[3] Hentenryck P V Lecture 22 ndash Constraint programming propagation arithmetic constraints

send+more=money COURSERA Discrete Optimization 2013

[4] Smith B A tutorial on constraint programming University of Leeds School of Computer

Studies 1995

[5] Bartaacutek R Theory and practice of constraint propagation In Proceedings of the 3rd Works-

hop on Constraint Programming in Decision and Control vol 50 2001

[6] Bartaacutek R Constraint Propagation and Backtracking-based Search [online] 2005 URL

lthttpktimlmcunicz~bartakdownloadsCPschool05notespdfgt (cit 14 10 2014)

[7] Schulte C ndash Tack G ndash Lagerkvist M Z Modeling and Programming with Gecode [on-

line] 2013 URL lthttpwwwgecodeorgdoc421MPGpdfgt (cit 18 11 2014)

[8] Hentenryck P V Lecture 23 ndash Constraint programming reication element constraint

magic series stable marriage COURSERA Discrete Optimization 2013

[9] Partee B H Basic Concepts of Set Theory Functions and Relations [online] 2006 URL

lthttppeopleumasseduparteeNZ_2006Set20Theory20Basicspdfgt (cit 25 8 2014)

[10] Ross T J Fuzzy Logic with Engineering Applications John Wiley amp Sons 2004 second

edition ed ISBN 0-470-86075-8

middot 30 middot

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 37: Programovanie ohraničení

Priacutelohy

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 38: Programovanie ohraničení

I

A | Množiny a relaacutecieV tejto časti uvedieme niekoľko zaacutekladnyacutech konceptov tyacutekajuacutecich sa množiacuten a relaacuteciiacute ndash pre priacutepad

že by sa s nimi čitateľ predtyacutem nestretol

A1 Identita a kardinalita množiacuten

Dve množiny suacute identickeacute vtedy a len vtedy keď majuacute presne rovnakeacute prvky tj A = B vtedy a len

vtedy ak forallx x isin AhArr x isin B [9]

Z deniacutecie identity vyplyacuteva zaacutever že existuje len jedna praacutezdna množina ndash neobsahuje žiadne

prvky Praacutezdnu množinu označujeme empty [9]

Počet prvkov ktoreacute obsahuje množina A nazyacutevame kardinalitou A Kardinalitu A označujeme

|A| Kardinalita konečnej množiny je prirodzeneacute čiacuteslo Nekonečneacute množiny majuacute tiež kardinalitu ndash

nedaacute sa však vyjadriť prirodzenyacutem čiacuteslom [9]

A2 Karteziaacutensky suacutečin

Majme dve množinyA aB Povedzme že budeme zostavovať usporiadaneacute dvojice tak že prvyacute prvok

vezmeme z množiny A a druhyacute z množiny B Karteziaacutensky suacutečin ozn AtimesB je množina všetkyacutech

možnyacutech takyacutechto usporiadanyacutech dvojiacutec tj [9]

AtimesB =def 〈x y〉|x isin A y isin B (A1)

Obdobne možno denovať karteziaacutensky suacutečin aplikovať pre viacero množiacuten napr pre tri [9]

AtimesB times C =def (AtimesB)times C (A2)

tj jednoducho sa suacutečin aplikuje zľava a viackraacutet

A21 Vlastnosti karteziaacutenskeho suacutečinu

Karteziaacutensky suacutečin nie je komutatiacutevny tj

AtimesB 6= B times A (A3)

Karteziaacutensky suacutečin nie je ani asociatiacutevny tj

(AtimesB)times C 6= Atimes (B times C) (A4)

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia
Page 39: Programovanie ohraničení

II

A3 Relaacutecie

Neformaacutelne možno povedať že relaacutecie suacute vzťahy medzi objektami Ako priacuteklad binaacuternych relaacuteciiacute

(tj vzťahov medzi dvomi objektami) možno uviesť bdquokoleso je suacutečasť autaldquo bdquoMilan je otec Tomaacutešaldquo

a pod Binaacuternu relaacuteciu R medzi objektmi a a b možno označiť Rab resp aRb v zaacutepise pomocou

usporiadanyacutech dvojiacutec značiacuteme 〈a b〉 isin R [9]

Formaacutelne ndash ak maacuteme dve množiny A a B binaacutera relaacutecia z A do B je [9]

R sube AtimesB (A5)

tj relaacutecia R je vlastne podmnoužinou karteziaacutenskeho suacutečinu oboch množiacuten

Uvedeneacutemu treba rozumieť tak že relaacutecia vyberaacute tie usporiadaneacute dvojice medzi ktoryacutemi platiacute

danyacute vzťah Ak napriacuteklad pracujeme s množinou ľudiacute A = Milan Tomaacuteš Michal Svetozaacuter a relaacute-

ciou R bdquoa je otec bldquo karteziaacutensky suacutečin AtimesA je 〈Milan Milan〉 〈Milan Tomaacuteš〉 〈Milan Michal〉〈Milan Svetozaacuter〉 Vzťah bdquoa je otec bldquo však bude platiť len pre niektoreacute kombinaacutecie prvkov ndash

napr pre Milana a Tomaacuteša ndash preto relaacuteciu možno chaacutepať ako podmnožinu karteziaacutenskeho suacutečinu

Obdobne možno relaacutecie denovať aj pre viacero prvkov ndash napr ternaacuterne relaacutecie pre tri prvky

Ak relaacutecia pracuje s n prvkami hovoriacuteme že maacute aritu n

A4 Charakteristickaacute funkcia

Neformaacutelne ndash charakteristickaacute funkcia množiny hovoriacute ktoryacute prvok do množiny patriacute a ktoryacute nie

Charakteristickaacute funkcia množiny S je teda priradenie typu [9 10]

microS U rarr 0 1 (A6)

Ide teda o priradenie hodnoty 0 ndash tj nepatriacute ndash alebo hodnoty 1 ndash tj patriacute ndash ku každeacutemu prvku

x isin U pričom deničnyacute obor charakteristickej funkcie U nazyacutevame univerzum (univerzum je

množina všetkyacutech hodnocirct o ktoryacutech rozhodujeme či do danej množiny patria alebo nepatria platiacute

S sube U )

Formaacutelne možno charakteristickuacute funkciu množiny denovať nasledovne [9 10]

microS(x) =

1 x isin S

0 x isin S(A7)

Tak ako pre ineacute množiny možno charakteristickuacute funkciu použiť aj na denovanie relaacutecie (ktoraacute

je tiež podmnožinou karteziaacutenskeho suacutečinu) V tom priacutepade U bude karteziaacutensky suacutečin množiacuten nad

ktoryacutemi je relaacutecia denovanaacute a funkcia bude nadobuacutedať hodnotu 1 pre prvky patriace do relaacutecie a 0pre prvky ktoreacute do nej nepatria

Uvedeneacute pojmy ďalej rozviacuteja a stavia na nich oblasť matematiky znaacutema ako relačnaacute algebra

ktoraacute sa široko aplikuje napr v databaacutezovyacutech systeacutemoch

  • Uacutevod
  • Probleacutem spĺňania ohraničeniacute
    • Formulaacutecia hry Sudoku ako CSP
    • Probleacutem SAT
      • Logickeacute programovanie ohraničeniacute
      • Programovanie ohraničeniacute ako riešenie Sudoku
        • Aplikaacutecia ohraničeniacute hry Sudoku
          • Štvorcoveacute ohraničenia
          • Riadkoveacute a stĺpcoveacute ohraničenia
            • Ohraničenia aplikujeme opakovane
            • Vetvenie
              • Naacutevrat
              • Strateacutegie vetvenia
                  • Zaacutekladneacute koncepty v CP
                    • Sklad ohraničeniacute
                      • Interakcia prehľadaacutevania a skladu ohraničeniacute
                      • Propagaacutecia ohraničeniacute
                        • Arita ohraničeniacute
                        • Globaacutelne ohraničenia
                        • Ciele CP a optimalizaacutecia na baacuteze CP
                          • Konzistenčneacute techniky
                            • Vrcholovaacute konzistentnosť
                            • Hranovaacute konzistentnosť
                              • Ako dosiahnuť hranovuacute konzistentnosť
                                • Konzistentnosť po ceste
                                  • Riešenie predeterminovanyacutech CSP
                                    • Maumlkkeacute ohraničenia
                                    • Max-CSP
                                    • Vaacuteženeacute CSP
                                    • Fuzzy CSP
                                    • Ďalšie priacutestupy
                                      • Reifikaacutecia
                                        • Využitie reifikaacutecie pri modelovaniacute
                                          • Zaacutepis disjunkcie
                                          • Nerovnosť prvkov poliacute
                                          • Riešenie probleacutemu max-CSP
                                            • Polovičnaacute reifikaacutecia
                                              • Obľuacutebeneacute benchmark probleacutemy
                                                • Probleacutem obchodneacuteho cestujuacuteceho
                                                  • Neohodnotenyacute graf
                                                  • Ohodnotenyacute graf
                                                  • Uacuteplnyacute graf
                                                    • SEND MORE MONEY
                                                    • Probleacutem magickyacutech postupnostiacute
                                                      • Priacuteklad Riešenie Sudoku pomocou Gecode
                                                        • Direktiacutevy include a linkovanie
                                                        • Trieda Sudoku
                                                        • Konštrukcia triedy Sudoku
                                                        • Funkcia main
                                                          • Priacuteklad Riešenie Sudoku v jazyku Prolog
                                                            • Použiteacute moduly a vloženie Sudoku
                                                            • Definovanie ohraničeniacute
                                                            • Pomocneacute predikaacutety
                                                            • Riešenie
                                                              • Priacutelohy
                                                                • Množiny a relaacutecie
                                                                  • Identita a kardinalita množiacuten
                                                                  • Karteziaacutensky suacutečin
                                                                    • Vlastnosti karteziaacutenskeho suacutečinu
                                                                      • Relaacutecie
                                                                      • Charakteristickaacute funkcia