Advertisement
Guest User

Untitled

a guest
Nov 6th, 2014
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 6.69 KB | None | 0 0
  1. (*
  2. 02157 - Functional Programming
  3. Mandatory assignment 3: Solver for Propositional Logic
  4.  
  5. Solved by:
  6. Alexander Rosenberg Johansen
  7. s145706
  8.  
  9.  
  10. *)
  11.  
  12. //For required patternmatching by FSharp, that would denote a pattern not designed for
  13. exception Error of string
  14. //1.
  15. type Prop = | A of string
  16.             | Dis of Prop * Prop
  17.             | Con of Prop * Prop
  18.             | Neg of Prop
  19.  
  20.  
  21. //2.
  22. //dml is short for de Morgan laws
  23. //Argument: Prop, a recursive type responding to a property tree
  24. //Result: Prop, now modified to match the de Morgan Law (dml)
  25. //recursively going over every vertex in the Prop-tree and matches it with the de Morgan Law, modifying the prop if match exists
  26. let rec dml :Prop -> Prop = function
  27.     | Neg(Con(p1,p2))    -> Dis(dml (Neg(p1)), dml (Neg(p2)))   //dml case: "¬(a ∧ b) is equivalent to (¬a) ∨ (¬b)"
  28.     | Neg(Dis(p1,p2))    -> Con(dml (Neg(p1)), dml (Neg(p2)))   //dml case: "¬(a ∨ b) is equivalent to (¬a) ∧ (¬b)"
  29.     | Neg(Neg(p))        -> dml p                               //dml case: "¬(¬a) is equivalent to a"
  30.     | A(p)               -> A(p)                //Base case
  31.     | Dis(p1,p2)         -> Dis(dml p1, dml p2) //Not a "dml", branching
  32.     | Con(p1,p2)         -> Con(dml p1, dml p2) //Not a "dml", branching
  33.     | Neg(p)             -> Neg(dml p)          //Not a "dml", branching
  34.  
  35.  
  36. //3.
  37. //dl is short for distributed law
  38. //Argument: Prop
  39. //Result: Prop, now modified to match the Distributed Law (dl)
  40. //recursively going over every vertex in the Prop-tree and matches it with the Distributed Law, modifying the prop if match exists
  41. let rec dl :Prop -> Prop = function
  42.   //  |Con(a,Dis(b,c)) -> Dis(Con(dl a,dl b),Con(dl a,dl c))   //dl case: "a ∧ (b ∨ c) is equivalent to (a ∧ b) ∨ (a ∧ c)"
  43.   |Con(a,Dis(b,c)) -> Dis(dl (Con(a,b)), dl (Con(a,c)))
  44.   //  |Con(Dis(a,b),c) -> Dis(Con(dl a,dl c),Con(dl b,dl c))   //dl case: "(a ∨ b) ∧ c is equivalent to (a ∧ c) ∨ (b ∧ c)"
  45.   |Con(Dis(a,b),c) -> Dis(dl (Con(a,c)), dl (Con(b,c)))
  46.     |A(p)               -> A(p)             //Base case
  47.     |Dis(p1,p2)         -> Dis(dl p1,dl p2) //Not a "dl", branching
  48.     |Con(p1,p2)         -> Con(dl p1,dl p2) //Not a "dl", branching
  49.     |Neg(p)             -> Neg(dl p)        //Not a "dl", branching
  50.  
  51. //4.1
  52. //Argument: Prop
  53. //Result: Set<Prop> of Prop literals
  54. //recursively going over the prop to find literals, packing these literals in a set, set is used to avoid doubles
  55. //Setting this function as private to dnfToSet would be preferable
  56. let rec litOf :Prop -> Set<Prop> = function
  57.     |A(p)       -> Set [A(p)]               //Base-case, literal found!
  58.     |Neg(A(p))  -> Set [Neg(A(p))]          //Base-case, literal found!
  59.     |Con(p1,p2) -> let setP1 = litOf p1     //For ease of reading
  60.                    let setP2 = litOf p2     //For ease of reading
  61.                    Set.union setP1 setP2    //Unions the Conjunction
  62.     |p          -> raise (Error("litOf cannot resolve"))  //incomplete Pattern matches, should not happen
  63.  
  64. //Simple function to check for having either a literal or a negation of a literal.
  65. //Setting this function as private to dnfToSet would be preferable
  66. let auxNegOrA :Prop*Prop -> bool = function
  67.     |A(p1),A(p2)      -> true
  68.     |Neg(p1),A(p2)    -> true
  69.     |A(p1),Neg(p2)    -> true
  70.     |Neg(p1),Neg(p2)  -> true
  71.     |p1,p2          -> false
  72. //4.2
  73. //Argument: Prop, which matches the de Morgan Law and Distributed Law
  74. //Result: Set<Set<Prop>> for a collection of basic conjunctions
  75. //recursively goes over every disjunction, uses litOf :Prop -> Set<Prop> to get the literals, denoted "Basic conjunct", where after each conjunt is placed into the total set
  76. let rec dnfToSet :Prop -> Set<Set<Prop>> = function
  77.     |Dis(p1,p2)  -> Set.union (dnfToSet(p1))  (dnfToSet(p2))                  
  78.     |Con(p1,p2) when auxNegOrA(p1,p2) -> Set.add (litOf (Con(p1,p2))) Set.empty
  79.     |Con(p1,p2) -> Set.union (dnfToSet(p1)) (dnfToSet(p2))
  80.     |p           -> Set.add (litOf (p)) Set.empty
  81.  
  82. //Argument: Prop
  83. //Result: Prop
  84. //an auxilary function to negate(flip) a literal
  85. let auxIsConsistent :Prop -> Prop = function
  86.     |A(p)       -> Neg(A(p))
  87.     |Neg(p)     -> p
  88.     |p          -> raise (Error("litOf cannot resolve"))
  89.  
  90. //5.1
  91. //Argument: Set<Prop>
  92. //Result: bool to figure if there exists a pair of complementary literals, "False" if so, else "True"
  93. //Setting this function as private to removeInconsistent would be preferable
  94. let rec isConsistent :Set<Prop> -> bool = function
  95.     |latSet ->  let comparisonSet = Set.foldBack(fun x set -> if Set.contains (auxIsConsistent x) (Set.remove x latSet) then Set.add x Set.empty else set) latSet Set.empty
  96.                 if Set.intersect latSet comparisonSet <> Set.empty then false else true
  97.  
  98. //5.2
  99. //Argument: Set<Set<Prop>>
  100. //Result: Set<Set<Prop>> now with inconsistent literals removed
  101. //Uses Set.filter to remove all inconsistent literals
  102. let removeInconsistent :Set<Set<Prop>> -> Set<Set<Prop>> = function
  103.     |allThemLats -> Set.filter(fun x -> (isConsistent x)) allThemLats
  104.  
  105. //6.1
  106. //Calls all previous functions to get a DNF set
  107. let toDNFsets :Prop -> Set<Set<Prop>> = function
  108.     |p   -> removeInconsistent (dnfToSet (dl (dml p)))
  109.  
  110. //6.2
  111. //Logical equivalence
  112. let impl :Prop*Prop -> Prop = function
  113.     |a,b -> Dis(Neg(a),b)
  114.  
  115. //6.3
  116. //Logical equivalence
  117. let iff :Prop*Prop -> Prop = function
  118.     |a,b -> Con(impl(a,b), impl(b,a))
  119.  
  120. //6.4
  121. //Solving
  122. //• ((¬p) ⇒ (¬q)) ⇒ (p ⇒ q)
  123. //• ((¬p) ⇒ (¬q)) ⇒ (q ⇒ p)
  124. //Setting literals for
  125. let p = A("p")
  126. let q = A("q")
  127. let negP = Neg(p)
  128. let negQ = Neg(q)
  129.  
  130. let first1 = impl(negP,negQ)
  131. let first2 = impl(p,q)
  132. let propFirst = impl(first1,first2)
  133. let resFirst = toDNFsets propFirst //((¬p) ⇒ (¬q)) ⇒ (p ⇒ q)
  134.  
  135. let second1 = first1
  136. let second2 = impl(q,p)
  137. let propSecond = impl(second1,second2)
  138. let resSecond = toDNFsets propSecond //((¬p) ⇒ (¬q)) ⇒ (q ⇒ p)
  139.  
  140. //7
  141. //I cannot figure the propositional logic, but an implementation would rely on finding consistent basic conjuncts through a toDNFsets call
  142.  
  143. //8.1
  144. //Argument: int
  145. //Result: Prop with n Conjunctions of Disjunctions
  146. let rec badProp :int -> Prop = function
  147.     |1 -> Dis(A("p"+ string 1),A("q" + string 1))
  148.     |n -> Con(Dis(A("p" + string n),A("q" + string n)),badProp(n-1))
  149.  
  150. //Simple testcases to prove every function in the toDNFsets chain
  151. let testBadProp = badProp 4
  152. let testDML = dml testBadProp
  153. let testDL = dl testDML
  154. let testDnfToSets = dnfToSet testDL
  155. let testRemoveInconsistent = removeInconsistent testDnfToSets
  156.  
  157. //8.2
  158. //Tests badProp n
  159. //KNOWN ERROR: Only gives 2*N as opposed to 2**n = 2^n, maybe because my dl function doesn't "pack" my Props correctly?
  160. let testToDNFsets = toDNFsets testBadProp
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement