Intro Mer om snitt Snittexempel Generera och testa CLP Exempel Intro Mer om snitt Idag • • • Intro Snittexempel Generera och testa CLP Exempel Senast: Negationer virginBirth(X) :mother(_, X), \+ father(_, X). Snittexempel Generera och testa Villkorsprogrammerings (CLP) Mer om snitt Snittexempel Generera och testa CLP | ?- virginBirth(X). X = anakin ? yes Exempel Intro Mer om snitt Syntax för negation Snittexempel Generera och testa CLP Exempel Senast: Snitt • Snitt (eng: cut) begränsar ”backtracking”: • Exempel: Har vi hittat en lösning så är det bra. sibling(X,Y) :- parent(Z, X),parent(Z, Y), woman(Z), \+ X=Y. permSort(X, Y) :permutation(X, Y), ordered(Y), !. • not skrivs \+. • I lådmodellen: Call permSort permutation \+ X=Y ordered Exit ! X=Y • Gröna snitt: Påverkar inte programmets Fail Intro Mer om snitt S S Snittexempel Generera och testa funktion. • Röda snitt: Förändrar programmets logiska läsning. Redo CLP Exempel Intro Implementera negation med snitt, not/1 • Hjälp: call/1: Försöker lösa det mål som ges som argument: |?- call(disjoint([1,2,3], [4,5,6])). yes • Hjälp: fail/0: Mål som alltid misslyckas. • Lösning för not/1: not(X) :- call(X), !, fail. not(X). (I princip samma för \+) Intro Mer om snitt Snittexempel Generera och testa CLP Exempelprogram: Sortera gener Exempel Mer om snitt Snittexempel Generera och testa CLP Exempel: if-then-else (Från Sterling&Shapiro) Konstruktiv användning av rött snitt: ifThenElse(P, Q, ifThenElse(_, _, | ?- X=5, ifThenElse(X<10, hello X = 5 ? yes | ?- X=11, ifThenElse(X<10, goodbye X = 11 ? yes | ?Intro Mer om snitt _) :- call(P), !, call(Q). R) :- call(R). write(hello), write(goodbye)). write(hello), write(goodbye)). Snittexempel Generera och testa CLP Ett beräkningsproblem • Vitt skilda organismer har mycket lika • Antalet inversioner är proportionellt mot genuppsättning • Genordning ofta delvis bevarad! • Betrakta ett genom: • Hur många inversioner har krävts för att 1 5 2 3 4 • Se genomet som en permutation av gener: (1, 2, 3, 4, 5) • Liknande genom: (1, 4, 3, 2, 5) • En inversion byter ordning på en delsekvens. Exempel tiden sedan artdelningen. komma från ett genom till ett annat? • Heuristik: Plocka bort brytpunkter. • Brytpunkt: När två intilliggande gener inte har närliggande tal 1|4 3 2|5 12345 Exempel Intro Mer om snitt Snittexempel Generera och testa CLP Exempel Intro Mer om snitt Snittexempel Heuristiken Generera och testa CLP Exempel Huvudprogram Basfall: • Om n gener, lägg till 0 och n + 1: sortByInversions(L, []) :countBreakpoints(L, N), N=0. 5, 4, 3, 2, 1 ⇒ 0, 5, 4, 3, 2, 1, 6 Rekursion: • Om det finns en inversion som plockar bort sortByInversions(Perm, [NextPerm|StateList]) :removeBreakpoints(Perm, NextPerm), sortByInversions(NextPerm, StateList). två brytpunkter, ta den. • Annars, om det finns en inversion som plockar bort en brytpunkt, ta den. • Iterera tills inga fler brytpunkter. Hjälppredikat: removeBreakpoints(L, NextL) :findInversionTwo(L, NextL), !. removeBreakpoints(L, NextL) :findInversionOne(L, NextL). Obs: Ej optimalt! Alltför beräkningskrävande att lösa optimalt Intro Mer om snitt Snittexempel Generera och testa CLP Exempel Testfall Intro 9, 2, 1, 6, 5, 4, 3, 8, 7, 10 1, 2, 9, 6, 5, 4, 3, 8, 7, 10 1, 2, 3, 4, 5, 6, 9, 8, 7, 10 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 Snittexempel Generera och testa Generera och testa CLP Exempel Indata: Resultat x1 , x2 , . . . , xk från k kast.P Kast i ger poäng pi . En serie har poäng ki=1 pi . Regler: 1. Strajk: Om i < k och xi = 10 räknas påföljande två kast dubbelt. 2. Strajk sist: Om i = k och xi = 10 är pi = 20. 3. Annars är pi = xi . Beräkna poängen! | ?- p4(X), inversions(X, N). .9.1........ ...96.43.... .......9.7.. N = 3, X = [9,2,1,6,5,4,3,8,7,10] ? yes Mer om snitt Snittexempel Generaliserad bowling: Räkna poäng Genom A: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 Genom B: 9, 2, 1, 6, 5, 4, 3, 8, 7, 10 Intro Mer om snitt CLP Exempel Intro Mer om snitt Snittexempel Exempelräkning Generera och testa CLP Exempel Lösning bowling([], 0). Serie: 10, 2, 3 Poäng: 10 + 2 + 3 + 2 + 3 = 20 bowling([10], 20) :- !. bowling([10, X2, X3 | Tail], P) :P is 10 + X2 + X3 + PT, bowling([X2, X3 | Tail], PT), !. Serie: 5, 10 Poäng: 5 + 2 × 10 = 25 bowling([10, X2 | Tail], P) :P is 10 + X2 + PT, bowling([X2 | Tail], PT), !. Serie: 10, 10, 5, 10 Poäng: 10 + 10 + 5 + 10 + 5 + 10 + 5 + 2 × 10 = 75 Intro Mer om snitt Snittexempel Generera och testa CLP bowling([X | Tail], P) :P is X + PT, bowling(Tail, PT). Exempel Intro Mer om snitt Snittexempel Generera och testa searchProblem(X) :generate(X), testSolution(X). • Används i lab L2. CLP Sudoku 6 8 7 • Programstruktur: Generera och testa 9 8 Placera ut siffrorna 1 – 9 så 6 2 4 att varje siffra 4 3 återfinns endast 3 7 6 en gång i varje rad, kolumn, och 9 7 3 1 delkvadrat. 9 3 6 8 1 2 9 Exempel Intro Mer om snitt Snittexempel Generera och testa CLP Exempel Intro Datastruktur för Sudoku Mer om snitt Snittexempel Generera och testa CLP Exempel Ansats med generera/testa sudoku(S) :transform(S, ByColumn, BySubsquare), verifyLists(S), verifyLists(ByColumn), verifyLists(BySubsquare). Lista av rader [[X11,X12,X13,X14,X15,X16,X17,X18,X19], [X21,X22,X23,X24,X25,X26,X27,X28,X29], [X31,X32,X33,X34,X35,X36,X37,X38,X39], [X41,X42,X43,X44,X45,X46,X47,X48,X49], [X51,X52,X53,X54,X55,X56,X57,X58,X59], [X61,X62,X63,X64,X65,X66,X67,X68,X69], [X71,X72,X73,X74,X75,X76,X77,X78,X79], [X81,X82,X83,X84,X85,X86,X87,X88,X89], [X91,X92,X93,X94,X95,X96,X97,X98,X99]] verifyLists([]). verifyLists([L|Ls]) :verifyList(L), verifyLists(Ls). verifyList(L) :permutation([1,2,3,4,5,6,7,8,9], L). Intro Mer om snitt Snittexempel Generera och testa CLP Exempel Intro Intro Mer om snitt Snittexempel Generera och testa CLP Exempel • Testning snabbt (”är detta en sudoku?”) [[X11,X21,X31,X41,X51,X61,X71,X81,X91], [X12,X22,X32,X42,X52,X62,X72,X82,X92], [X13,X23,X33,X43,X53,X63,X73,X83,X93], [X14,X24,X34,X44,X54,X64,X74,X84,X94], [X15,X25,X35,X45,X55,X65,X75,X85,X95], [X16,X26,X36,X46,X56,X66,X76,X86,X96], [X17,X27,X37,X47,X57,X67,X77,X87,X97], [X18,X28,X38,X48,X58,X68,X78,X88,X98], [X19,X29,X39,X49,X59,X69,X79,X89,X99]], X21,X22,X23, X24,X25,X26, X27,X28,X29, X51,X52,X53, X54,X55,X56, X57,X58,X59, X81,X82,X83, X84,X85,X86, X87,X88,X89, Snittexempel Hur funkar det? transform([[X11,X12,X13,X14,X15,X16,X17,X18,X19], [X21,X22,X23,X24,X25,X26,X27,X28,X29], [X31,X32,X33,X34,X35,X36,X37,X38,X39], [X41,X42,X43,X44,X45,X46,X47,X48,X49], [X51,X52,X53,X54,X55,X56,X57,X58,X59], [X61,X62,X63,X64,X65,X66,X67,X68,X69], [X71,X72,X73,X74,X75,X76,X77,X78,X79], [X81,X82,X83,X84,X85,X86,X87,X88,X89], [X91,X92,X93,X94,X95,X96,X97,X98,X99]], [[X11,X12,X13, [X14,X15,X16, [X17,X18,X19, [X41,X42,X43, [X44,X45,X46, [X47,X48,X49, [X71,X72,X73, [X74,X75,X76, [X77,X78,X79, Mer om snitt • Långsamt att lösa en sudoku! • Klarar bara ett litet antal okända (klarar inte ICAs ”enkla” sudoku med 45 okända) • ”17 okända går på några sekunder” X31,X32,X33], X34,X35,X36], X37,X38,X39], X61,X62,X63], X64,X65,X66], X67,X68,X69], X91,X92,X93], X94,X95,X96], X97,X98,X99]]). Generera och testa • Vad göra? • Generera smartare! CLP Exempel Intro Mer om snitt Färga en karta Snittexempel Generera och testa CLP Exempel Datastruktur region(Area, AreaColor, NeighborColors). • Sats: Varje planär graf kan färgas med fyra Exempelinstans: färger. • Alltså: Varje karta kan färgas med fyra färger. • Skriv ett program som färgar en karta! [region(a, region(b, region(c, region(d, region(e, region(f, (Från Sterling-Shapiro: The Art of Prolog) Intro Mer om snitt Snittexempel Generera och testa CLP Exempel En bit av Europa % färg, map(europe, [region(portugal, P, region(spain, E, region(france, F, region(belgium, B, region(holland, H, region(germany, G, region(luxembourg,L, region(italy, I, region(switzerl, S, region(austria, A, ). grannars färger [E]), [F, P]), [E, I, S, B, G, L]), [F, H, L, G]), [B, G]), [F, A, S, H, B, L]), [F, B, G]), [F, A, S]), [F, I, A, G]), [I, S, G])]) Intro Mer om snitt A, B, C, D, E, F, [B,C,D]), [A, C, D]), [A,B,D,E,F]), [A,C, F]), [B, C, F]), [C, D, E])] Snittexempel Generera och testa CLP Exempel Programmet % colorMap(Map, ColorList) % För varje region: Välj en färg colorMap([],_). colorMap([Region|Regions], Colors) :colorRegion(Region, Colors), colorMap(Regions, Colors). % colorRegion(Region, ColorList) % En region tar en färg och kräver att grannregionerna % inte använder den färgen colorRegion(region(Name, Color, Neighbors), Colors) :select(Color, Colors, Colors1), %Generera members(Neighbors, Colors1). %Testa Intro Mer om snitt Snittexempel Generera och testa CLP Exempel Intro Mer om snitt Exempelkörning Snittexempel Generera och testa CLP Exempel Om programmet | ?- map(europe, M), colorMap(M, [red,blue,green,yellow]). M = [region(portugal,red,[blue]),region(spain,blue,[red,red]),region(france,red,[blue,blue,green,blue,yellow,green]),r egion(belgium,blue,[red,red,green,yellow]),region(holland,red,[blue,yellow]),region(germany,yellow,[red,red,green,red| ...]),region(luxembourg,green,[red,blue,yellow]),region(italy,blue,[red,red|...]),region(switzerl,green,[red|...]),reg • Implementerar en snål algoritm. ion(...)] ? yes • Riskerar vara ineffektiv. | ?- map(europe, M), • Fler färger ⇒ snabbare colorMap(M, [red,blue,green]). no Intro Mer om snitt Snittexempel Generera och testa CLP Exempel Intro Mer om snitt CLP Snittexempel Generera och testa CLP Exempel Bakgrund Constraint Logic Programming Två typproblem: 1. Hitta tilldelning på X så att villkoren C uppfylls 2. ... och maximerar f (X ). Logikvillkorsprogrammering Tillämpning: Constraint Satisfaction Problems Notera: ”Programmering” ≈ planering! Intro Mer om snitt Snittexempel Generera och testa CLP Exempel Intro • Sudoku: Hitta tilldelning på elementen i X Snittexempel Generera och testa Generera och testa CLP Exempel • Samma grundproblem återkommer så att rader, kolumner, och nio delkvadrater är unika element. • SL: Vilken är den snabbaste vägen från Fridhemsplan till KTH som går via Karlaplan? • Genomik: Givet 4, 2 × 107 läsningar av DNA, delvis och slumpvis överlappande, vilket är den kortaste sammanfogningen? Mer om snitt Snittexempel Typproblem ⇒ typlösningar Exempelproblem Intro Mer om snitt CLP Exempel: Linjärprogrammering • Samma lösningstekniker återanvänds • Kan vi standardisera? Ja: Standardalgoritmer Ja: Standardisera även programmeringsmetodiken. Varför återimplementera algoritmer? Exempel Intro Mer om snitt Snittexempel Generera och testa CLP Exempel Exempel: Linjärprogrammering Maximera 7x1 + 2x2 − x3 då x1 + x2 ≤ 7 x1 + 2x3 ≥ 11 Maximera cx då Mx ≤ b och x ≥ 0. och c = (7, 2, −1), M = x1 ≥ 0, x2 ≥ 0, x3 ≥ 0 eller allmänt: maximera cx då Mx ≤ b. Kan du formulera ditt optimeringsproblem på denna form? 1 1 0 1 0 2 , b= 7 −11 Algoritmer: Simplex: Icke-polynomiell, men enkel och praktisk. Inrepunktsmetod: Polynomiell, praktisk Utbytbara lösare på samma formulering! Intro Mer om snitt Snittexempel Generera och testa CLP Exempel Intro Mer om snitt Olika områden Snittexempel Generera och testa CLP Exempel Klassiskt problem • Linjärprogrammering Telegram: SEND+MORE=MONEY Hur många kronor behövdes? • Semidefinit programmering • Icke-linjär programmering S E N D + M O R E M O N E Y • Linjär heltalsprogrammering • Boolsk villkorsprogrammering • CP över ändliga domäner Variablerna S, E, N, D, M, O, R, Y tar värden ur {0, 1, . . . , 9}. Domänen skiljer! Vi tittar på ändliga domäner (finite domains). Intro Mer om snitt Snittexempel Generera och testa CLP Exempel Intro Mer om snitt Mål Snittexempel Generera och testa CLP • Måste ange den ändliga domänen för varje domänvariabel. • Domänvariabler ingår i relationer. • Relationer anslås (are posted) till en lösare. Exempel Intro Mer om snitt :10*N + D 10*R + E 10*E + Y. Snott och anpassat från Sicstus-manualen Snittexempel Generera och testa CLP Exempel Ange variabeldomän: • fd_domain(Xs, Min, Max): Variablerna i Xs ska ligga i {M in, M in + 1, . . . , M ax}. Ex: fd_domain([S,E,N,D,M,O,R,Y],0,9) • fd_domain(Team, [aik,dif,hif]), m.m. Bivillkor: • A + B #> 0, • 4*X + 7 * Y #= 0, och andra linjära uttryck. mm([S,E,N,D,M,O,R,Y]) :fd_domain([S,E,N,D,M,O,R,Y], 0, 9), S#>0, M#>0, fd_all_different([S,E,N,D,M,O,R,Y]), summera(S,E,N,D,M,O,R,Y), fd_labeling([S,E,N,D,M,O,R,Y]). summera(S, E, N, D, M, O, R, Y) 1000*S + 100*E + + 1000*M + 100*O + #= 10000*M + 1000*O + 100*N + Snittexempel Predikat för CLP S E N D + M O R E M O N E Y Mer om snitt Exempel • Kan ha ”vanliga” Prologvariabler Klassikern i CLP Intro CLP • Vi optimerar/löser över domänvariabler. • Formellt språk för optimeringsproblem • Inbyggda generella sökheuristiker • Generella algoritmer en utopi • ”Förvånansvärt stora satisfierbarhetsproblem kan lösas idag” Mer om snitt Generera och testa Grunder i CLP • Formellt språk för sökproblem Intro Snittexempel Generera och testa CLP Exempel Intro Mer om snitt Fler predikat för CLP Snittexempel Generera och testa CLP Tilldelningspredikat • fd_labeling(Vars, Opts). Kombinatoriska villkor: • fd_all_different(L). Alla domänvariabler i L har olika värden. • fd_atleast(N, Xs, V). Minst N variabler i listan Xs har värdet V . Vi har också fd_atmost och fd_exactly. • fd_cardinality(Constr, Count). Sätt Count till antalet uppfyllda villkor i listan Constraints. T.ex., fd_cardinality([X#=0,Y#=0,Z#=0], Count) räknar antalet nollvärda variabler. Hitta värden för domänvariabler i Vars. Val med Opts: • • Hur välja “nästa” variabel? Hur välja dess värde? Enklast: fd_labeling(Xs). “Hitta en tilldelning av värden Xs enligt givna villkor.” • fd_minimize(Goal, Var). • fd_maximize(Goal, Var). Anropa Goal och använd “branch-and-bound” för att minimera/maximera värdet på Var. Exempel Intro Mer om snitt Snittexempel Generera och testa CLP Exempel Intro Mer om snitt Snittexempel Sudoku igen Generera och testa CLP Sudoku igen • Indata: Matris som lista av rader. • Indata: Matris som lista av rader. • Predikat transform för att växla rader till • Predikat transform för att växla rader till kolumner till delkvadrater: transform(R,C,S). kolumner till delkvadrater: transform(R,C,S). R = [[X11,X12,X13,X14,X15,X16,X17,X18,X19], [X21,X22,X23,X24,X25,X26,X27,X28,X29], [X31,X32,X33,X34,X35,X36,X37,X38,X39], [X41,X42,X43,X44,X45,X46,X47,X48,X49], [X51,X52,X53,X54,X55,X56,X57,X58,X59], [X61,X62,X63,X64,X65,X66,X67,X68,X69], [X71,X72,X73,X74,X75,X76,X77,X78,X79], [X81,X82,X83,X84,X85,X86,X87,X88,X89], [X91,X92,X93,X94,X95,X96,X97,X98,X99]] Intro Mer om snitt Snittexempel Exempel Generera och testa CLP Exempel C = [[X11,X21,X31,X41,X51,X61,X71,X81,X91], [X12,X22,X32,X42,X52,X62,X72,X82,X92], [X13,X23,X33,X43,X53,X63,X73,X83,X93], [X14,X24,X34,X44,X54,X64,X74,X84,X94], [X15,X25,X35,X45,X55,X65,X75,X85,X95], [X16,X26,X36,X46,X56,X66,X76,X86,X96], [X17,X27,X37,X47,X57,X67,X77,X87,X97], [X18,X28,X38,X48,X58,X68,X78,X88,X98], [X19,X29,X39,X49,X59,X69,X79,X89,X99]] Intro Mer om snitt Sudoku igen Snittexempel Generera och testa CLP Exempel Huvudprogram • Indata: Matris som lista av rader. 81 variabler i Xs • Predikat transform för att växla rader till kolumner till delkvadrater: transform(R,C,S). S = [[X11,X12,X13, [X14,X15,X16, [X17,X18,X19, [X41,X42,X43, [X44,X45,X46, [X47,X48,X49, [X71,X72,X73, [X74,X75,X76, [X77,X78,X79, Intro Mer om snitt Snittexempel X21,X22,X23, X24,X25,X26, X27,X28,X29, X51,X52,X53, X54,X55,X56, X57,X58,X59, X81,X82,X83, X84,X85,X86, X87,X88,X89, Generera och testa sudoku(ByRow) :flatten(ByRow, Xs), fd_domain(Xs, 1,9), transform(ByRow, ByCol, ByQuad), distinct_rows(ByRow), distinct_rows(ByCol), distinct_rows(ByQuad), fd_labeling(Xs). X31,X32,X33], X34,X35,X36], X37,X38,X39], X61,X62,X63], X64,X65,X66], X67,X68,X69], X91,X92,X93], X94,X95,X96], X97,X98,X99]]) CLP Exempel Intro Mer om snitt Hjälppredikat Snittexempel Generera och testa CLP Exempel Sudokuresultat sm05([[6, [3, [_, [_, [_, [8, [_, [9, [_, distinct_rows([]). distinct_rows([R|Rest]) :fd_all_different(R), distinct_rows(Rest). 7, _, _, _, _, _, _, 4, _, _, _, _, 7, _, 5, _, _, _, _, _, _, 1, _, _, _, 2, 7, _, _, 8, _, 4, _, 6, _, _, 1, 9, _, _, _, 6, _, _, _, _, _, _, 9, _, 4, _, _, _, _, 8, _, _, _, _, _, _, 4, _], 6], _], 3], _], _], _], 7], 1]]). | ?- sm05(X), sudoku(X). X = [[6,7,8,4,3,1,2,9,5],[3,1,4,5,2,9,7, • 56 okända enkelt • Hur så fort? Intro Mer om snitt Snittexempel Generera och testa CLP Grundmetod 1. 2. 3. 4. Välj en obunden domänvariabel Xi Tilldela ett värde från domänen D(Xi ) Verifiera bivillkor som använder Xi Om inga fler obundna domänvariabler: Klart! 5. Annars, gå till 1. Exempel Intro Mer om snitt Snittexempel Generera och testa CLP Frågeställningar • Hur välja nästa variabel? Standardval: Variabler i turordning. • Vilka konsekvenser har en tilldelning? Ignoreras. • Kan man undvika ”dåliga” tilldelningar? Nej. Standardalgoritmen är naiv! ... som alla heuristiker! Exempel Intro Mer om snitt Snittexempel Generera och testa CLP Avslutningsvis • Svåra problem är svåra. • Ingen heuristik är alltid bra. • System för villkorsprogrammering även i andra språk. Kurs: ID2204 Villkorsprogrammering, med Christian Schulte. Exempel