(* CSCI 3155: Project 1: Boolean Formulae *) (* This declares an exception constructor that is used as a placeholder for the functions you need to implement. *) exception Unimplemented (***************************************************************************) (* A boolean formula. *) datatype formula = False | True | Var of string | And of formula * formula | Or of formula * formula | Not of formula | Forall of string * formula | Exists of string * formula fun formula_to_string (f: formula) : string = let fun $ False = "false" | $ True = "true" | $ (Var x) = x | $ (And (f1,f2)) = "(" ^ $f1 ^ " /\\ " ^ $f2 ^ ")" | $ (Or (f1,f2)) = "(" ^ $f1 ^ " \\/ " ^ $f2 ^ ")" | $ (Not f) = "~" ^ $f | $ (Forall (x,f)) = "(A " ^ x ^ ". " ^ $f ^ ")" | $ (Exists (x,f)) = "(E " ^ x ^ ". " ^ $f ^ ")" in $f end (***************************************************************************) (* A variable assignment. *) type assignment = (string * bool) list fun asmt_lookup (a: assignment) (x: string) : bool option = case List.find (fn (y,_) => x = y) a of NONE => NONE | SOME (_, b) => SOME b fun asmt_add (a: assignment) (binding: string * bool) : assignment = binding :: a (***************************************************************************) (* Part 1 *) (* to_nnf : formula -> formula *) fun to_nnf (f: formula) = raise Unimplemented (* simp_not : formula -> formula *) fun simp_not (Not True) = False | simp_not (Not False) = True | simp_not f = f (* simp_and : formula -> formula *) fun simp_and (f: formula) = raise Unimplemented (* simp_or : formula -> formula *) fun simp_or (f: formula) = raise Unimplemented (* visit : (formula -> formula) -> formula -> formula *) fun visit (g: formula -> formula) (f: formula) = raise Unimplemented (* eval : assignment -> formula -> bool *) fun eval (a: assignment) (f: formula) = raise Unimplemented (* vars_of : formula -> string list *) fun vars_of (f: formula) = raise Unimplemented (* sat : formula -> assignment option *) fun sat (f: formula) = raise Unimplemented (** You should get to at least here for the checkpoint. **) (***************************************************************************) (* Part 2 *) (* A bit vector. *) type vec = formula list (** These are some bitwise operations you can use for testing. **) val bitnot: vec -> vec = List.map Not (** Note that List.map is curried, so we can define bitnot in this way. The following would also work: fun bitnot (v: vec) = List.map Not v **) val bitand: vec * vec -> vec = ListPair.map And val bitor: vec * vec -> vec = ListPair.map Or (** For bitand and bitor, we assume the input vectors have the same length. **) (** Exercises **) (* double : vec -> vec *) fun double (v: vec) = raise Unimplemented (* int_of_vec : vec -> int *) fun int_of_vec (v: vec) = raise Unimplemented (* vec_of_int : int -> vec *) fun vec_of_int (n: int) = raise Unimplemented (* subst : assignment -> vec -> vec *) fun subst (a: assignment) (v: vec) = raise Unimplemented (* zero : vec -> formula *) fun zero (v: vec) = raise Unimplemented (* eq : vec * vec -> formula *) fun eq (v1: vec, v2: vec) = raise Unimplemented (* add : vec * vec -> vec *) fun add (v1: vec, v2: vec) = raise Unimplemented (* is_digit : vec -> formula *) fun is_digit ([f0, f1, f2, f3]: vec) = raise Unimplemented | is_digit _ = raise Domain (** Note that in is_digit, we pattern match on a list of length 4. Anything else we raise the exception Domain to indicate that we don't handle any other input. This documents a design decision we have made that eliminates a match warning. **) (* disjoint : vec list -> formula *) fun disjoint (vl: vec list) = raise Unimplemented (* is_magic : vec list -> formula *) fun is_magic (vl as [v1, v2, v3, v4, v5, v6, v7, v8, v9]: vec list) = raise Unimplemented | is_magic _ = raise Domain (** We similarly pattern match on a list of length 9 in is_magic. The "as" keyword allows us to also bind a variable vl to the whole list for convenience. You can ignore it if you like. **)