COP 4020 Lecture -*- Outline -*- * examples of relational programming (9.2) Overall, these are all generate and test, but we'll start with simple relations, where the generation is trivial (matching)... ** List examples *** AddToEnd ------------------------------------------ LIST EXAMPLES {AddToEnd L X R} % R is the list with % the elements of L followed by X Examples: {AddToEnd nil 5 5|nil} {AddToEnd 6|nil 5 6|5|nil} {AddToEnd 2|9|6|nil 5 2|9|6|5|nil} ------------------------------------------ See AddToEnd.oz AddToEndTest.oz ... Best to think if this as a 3 argument procedure You can also think of describing the table of these relationships Q: What are some facts about the relation between inputs and outputs? Q: What's true about the base case? Q: What's a recursive case? A related simpler case? How are they related? {AddToEnd nil X X|nil} {AddToEnd E|Es X E|Rest} where {AddToEnd Es X Rest} Write each set of facts down as a set of bindings in a choice, being sure to declare the free variables in each case! Also show the functionally sugared version *** Reverse ------------------------------------------ FOR YOU TO DO {Reverse L1 L2} % L2 is the reverse of L1 Examples: {Reverse nil nil} {Reverse [1 2 3 4] [4 3 2 1]} ------------------------------------------ Q: What are some facts about the relation between inputs and outputs? Q: What's true about the base case? Q: What's a recursive case? A related simpler case? How are they related? {Reverse nil nil} {Reverse X|Xs Zs} where {Reverse Xs Ys} and {AddToEnd Ys X Zs} Write each set of facts down as a set of bindings in a choice, being sure to declare the free variables in each case! Q: How do these differ from procedures in the declarative model? We can vary the roles of the arguments... *** More examples Do RMember (membership in a list, see RMember.oz), SubstFirst Association lists lookup Note that RMember can be done using RAppend! Note that Oz will suspend if you try to compare (with ==) two unbound datastructures, like _|3|_ and _|3|_, when doing the comparisons ** Unary number examples ------------------------------------------ NATURAL NUMBERS (UNARY) ::= z "zero" | s() "successor" Code the following as relations: Count Examples: {List.take {Solve Count} 3} == [z s(z) s(s(z))] LT (less than) Examples: {LT z s(z)} {LT z s(s(s(z)))} {LT s(s(z)) s(s(s(z)))} LE (less than or equal to) GT (greater than) GE (greater than or equal to) Plus Diff (subtraction) Times ToInt ToNat ------------------------------------------ code these! (See Unary.oz UnaryTest.oz) Note that ToNat and ToInt can only be run in one direction, due to the use of arithmetic (+ and -) in Oz, which can only be run in one direction ** Generate and Test ------------------------------------------ GENERATE AND TEST Architecture: 1. generate all possibilities 2. test to find correct answers Example: declare proc {GenFromTo I N ?R} (I =< N) = true % i.e., fail if I > N choice R=I [] {GenFromTo I+1 N R} end end proc {AtLeast50 ?Sol} {GenFromTo 0 60 Sol} % Generate (Sol >= 50) = true % Test end {Test {List.take {Solve proc {$ Z} {GenFromTo 1 5 Z} end} 5} '==' [1 2 3 4 5]} {Test {SolveAll AtLeast50} '==' [50 51 52 53 54 55 56 57 58 59 60]} ------------------------------------------ See SimpleGenTest.oz and SimpleGenTestTest.oz ------------------------------------------ VIDEO TIMES EXAMPLE Example: - A VCR has SP and EP speeds, with SP 3 times faster than EP. - A tape is 2*60 min at SP speed, and 6*60 min at EP speed. - SP is better quality - How to tape a N minute show to use the most SP speed? Generate: tuples of form time(ep: MinutesEP sp: MinutesSP) where 3*MinutesSP + MinutesEP = 6*60 Test: find which ones have length N min total ------------------------------------------ ... see VideoTimes.oz VideoTimesTest.oz (compare to the constraint version in VideoTapeTimes.oz) declare Hours = 60 % Minutes in an hour proc {GenTimes MinutesSP ?Sol} choice Sol = time(ep: 6*Hours - 3*MinutesSP sp: MinutesSP) [] (MinutesSP < 120) = true {GenTimes MinutesSP+1 Sol} end end proc {VideoTimes Min ?Sol} (2*Hours =< Min) = true % first precondition (Min =< 6*Hours) = true % second precondition {GenTimes 0 Sol} % Generate (Sol.sp + Sol.ep) = Min % Test end