COP 4020 Lecture -*- Outline -*- * The relational computation model (9.1) ** syntax ------------------------------------------ SYNTAX ::= ... | choice [] ... [] end | fail | {Solve } Expression sugars R = choice E1 [] ... [] En end ==> choice R=E1 [] ... [] R=En end L = {Solve E} ==> {Solve E L} ------------------------------------------ The Solve function is not really built-in, but defined in the book's supplement file in terms of computation spaces (ch. 12) Q: Can "fail" be used as an expression? no! Q: Would you use a choice expression or statement in a fun? an expression ** semantics *** semantics by example ------------------------------------------ SEMANTICS BY EXAMPLE \insert 'SolveFirst.oz' declare proc {Vowel ?R} choice R=a [] R=e [] R=i [] R=o [] R=u end end % Solve returns a lazy List L = {Solve Vowel} {Browse L} {Delay 5000} _={List.take L 2} % A choice suspends if used directly % {Browse {Vowel $}} % But can be used in a search with Solve {Browse {List.take {Solve Vowel} 4}} % fail continues with next alternative of most recent choice declare proc {Distinct ?Res} V1 V2 in {Vowel V1} {Vowel V2} if V1 == V2 then fail end Res=V1#V2 end {Browse {List.take {Solve Distinct} 7}} {Browse {List.take {Solve proc {$ ?Z} {Distinct Z} end} 15}} {Browse {List.take {Solve Distinct} 21}} ------------------------------------------ see ChoiceExamples.oz Q: In what order are choices used? left to right (top to bottom) Q: Does a fail statement have to occur nested within the execution of a choice statement? no! it affects the temporally most recent Q: What happens when there are no more choices and a fail occurs? it fails to the previous choice, etc. ------------------------------------------ FAILURE BY UNIFICATION FAILURE % Unification failures are also failures declare V3=3 {Browse V3} fun {Example} choice V3=3 a [] V3=0 b [] fail c end end {Browse example#{List.take {Solve Example} 3}} ------------------------------------------ See SolveExamples.oz This produces 3 [a] Do you see why? Q: Is there a difference between unification failure and fail? not really Q: Do we need fail as a primitive then? no, just to be clear we're not making a mistake ------------------------------------------ % Unification failures are also failures declare V3=3 {Browse V3} proc {Example ?R} choice V3=3 R=a [] V3=0 R=b [] fail R=c end end {Browse example#{List.take {Solve Example} 3}} % Solve encapsulates search. % Can only read variables declared before solving declare V4 {Browse V4} fun {Example2 ?R} choice V4=1 R=a [] V4=2 R=b [] V4=3 R=c end end {Browse example2#{List.take {Solve Example2} 3}} % suspends % feeding this makes it go... % V4=2 ------------------------------------------ See SolveExamples.oz note the suspension created at the end above, it seems that V4 is treated as a read-only variable. *** Search tree (9.1.2) compare figure 9.1 ------------------------------------------ SEARCH TREE (9.1.2) ------------------------------------------ ... *draw this tree* top down, left to right... each branch for a Vowel node is a choice {Distinct Res} | | {Vowel V1} {Vowel V2} if V1 == V2 then fail end Res=V1#V2 / \ V1=a / V1=e \ / \ {Vowel V2} {Vowel V2} if V1 == V2 then fail end if V1 == V2 then fail end Res=V1#V2 REs=V1#V2 | \ \ ... | \ \ ... V2=a| V2=e \ V2=i \ V2=a | V2=e \ V2=i \ fail Res=V1#V2 Res=V1#V2 Res=V1#V2 fail Res=V1#V2 Q: What happens to variable bindings after a failure? ------------------------------------------ FOR YOU TO DO Given proc {Vowel ?R} choice R=a [] R=e [] R=i [] R=o [] R=u end end Draw a search tree for the query: {Solve proc {$ ?V} V={Vowel} V=i end} ------------------------------------------ *** summary ------------------------------------------ SEMANTICS SUMMARY choice S1 [] ... [] Sn end - pushes a new choice point choice point = case choosing between S1 ... Sn in a suspended thread + CCC (choice case counter) The CCC is 1 initially (will do S1) - when demanded if CCC <= n then make a new compuation space execute CCC'th statement in new space advance CCC by 1 else pop stack of choice points demand the choice point at the top fail - demand execution of top of choice point stack {Solve F} - A lazy list is produced by: - Call F to set up a choice point (suspends) - When the first element is needed: - demand execution of top of choice point stack - unify the result with the first element of the result list - Repeat for other elements when needed ------------------------------------------ ** Encapsulated search ------------------------------------------ ENCAPSULATED SEARCH (9.1.3) Solve encapsulates a search - runs in own computation space - treats existing variables as read-only except for result of the function argument - new bindings created for each path in the tree - keeps track of its own choice point stack This is: modular: concurrent threads can search without affecting each other compositional: Solve can be used inside Solve ------------------------------------------