-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfinal.ml
More file actions
207 lines (162 loc) · 5.91 KB
/
final.ml
File metadata and controls
207 lines (162 loc) · 5.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
open Stdlib
let _ = Random.self_init ()
type term =
| Constant of string
| Variable of string
| Function of string * term list
type head = term
type body = term list
type clause = Fact of head | Rule of head * body
type program = clause list
type goal = term list
let rec string_of_f_list f tl =
let _, s = List.fold_left (fun (first, s) t ->
let prefix = if first then "" else s ^ ", " in
false, prefix ^ (f t)) (true,"") tl
in
s
let rec string_of_term t =
match t with
| Constant c -> c
| Variable v -> v
| Function (f,tl) ->
f ^ "(" ^ (string_of_f_list string_of_term tl) ^ ")"
let string_of_term_list fl =
string_of_f_list string_of_term fl
let string_of_goal g =
"?- " ^ (string_of_term_list g)
let string_of_clause c =
match c with
| Fact f -> string_of_term f ^ "."
| Rule (h,b) -> string_of_term h ^ " :- " ^ (string_of_term_list b) ^ "."
let string_of_program p =
let rec loop p acc =
match p with
| [] -> acc
| [c] -> acc ^ (string_of_clause c)
| c::t -> loop t (acc ^ (string_of_clause c) ^ "\n")
in loop p ""
let var v = Variable v
let const c = Constant c
let func f l = Function (f,l)
let fact f = Fact f
let rule h b = Rule (h,b)
(* Problem 1 *)
let rec occurs_check v t =
match t with
| Constant _ -> false
| Variable _ -> if v=t then true else false
| Function (_,tl) -> List.fold_left(fun acc x -> if occurs_check v x then true else acc)false tl
(* Problem 2 *)
module VarSet = Set.Make(struct type t = term let compare = Stdlib.compare end)
(* API Docs for Set : https://caml.inria.fr/pub/docs/manual-ocaml/libref/Set.S.html *)
(*helper function to loop anf apply fucntion f to all the elements*)
let rec loop f t =
match t with
| []-> VarSet.empty
| h::tl -> VarSet.union (f h) (loop f tl)
let rec variables_of_term t =
match t with
| Constant _ -> VarSet.empty
| Variable _ -> VarSet.singleton t
| Function (_,tl) -> loop (variables_of_term) tl
(*helper *)
let variables_of_clause c =
match c with
| Fact f -> variables_of_term f
| Rule (h,b) -> VarSet.union (variables_of_term h) (loop (variables_of_term) b)
(* Problem 3 *)
module Substitution = Map.Make(struct type t = term let compare = Stdlib.compare end)
(* See API docs for OCaml Map: https://caml.inria.fr/pub/docs/manual-ocaml/libref/Map.S.html *)
let string_of_substitution s =
"{" ^ (
Substitution.fold (
fun v t s ->
match v with
| Variable v -> s ^ "; " ^ v ^ " -> " ^ (string_of_term t)
| Constant _ -> assert false (* substitution maps a variable to a term *)
| Function _ -> assert false (* substitution maps a variable to a term *)
) s ""
) ^ "}"
(*helper function ot apply f on each ele,emt*)
let subl f s t =
List.fold_left(fun acc x -> acc@[f s x]) [] t
let rec substitute_in_term s t =
match t with
| Constant _ -> t
| Variable _ ->
(match Substitution.find_opt t s with
| None -> t
| Some t' -> t')
| Function (f,tl) -> Function (f, subl substitute_in_term s tl)
let substitute_in_clause s c =
match c with
| Fact f -> Fact (substitute_in_term s f)
| Rule (h,b) -> Rule (substitute_in_term s h, subl substitute_in_term s b)
(* Problem 4 *)
let counter = ref 0
let fresh () =
let c = !counter in
counter := !counter + 1;
Variable ("_G" ^ string_of_int c)
let freshen c =
let vars = variables_of_clause c in
let s = VarSet.fold (fun v s -> Substitution.add v (fresh()) s) vars Substitution.empty in
substitute_in_clause s c
(*
let c = (rule (func "p" [var "X"; var "Y"; const "a"]) [func "q" [var "X"; const "b"; const "a"]])
let _ = print_endline (string_of_clause c)
let _ = print_endline (string_of_clause (freshen c))
*)
exception Not_unifiable
let unify t1 t2 =
let rec reunify t1 t2 s =
(*apply theta/s to x and y*)
let t1 = substitute_in_term s t1 in
let t2 = substitute_in_term s t2 in
match t1,t2 with
| Variable x, _ -> (*X dne in Y -> ðœƒ{X/Y} ∪ {X/Y}*)
if t1=t2 then s
else if occurs_check t1 t2 then raise Not_unifiable
else Substitution.add t1 t2 (Substitution.map (fun t -> substitute_in_term (Substitution.singleton t1 t2) t) s)
| _,Variable x -> (*Y dne in X -> ðœƒ{Y/X} ∪ {Y/X}*)
if t1=t2 then s
else if occurs_check t2 t1 then raise Not_unifiable
else Substitution.add t2 t1 (Substitution.map (fun t -> substitute_in_term (Substitution.singleton t2 t1) t) s)
| Constant x, Constant y -> (*x=y -> theta*)
if t1=t2 then s
else raise Not_unifiable
|Function(h1,b1),Function(h2,b2)-> (*X is f(X1,...,Xn) and Y is f(Y1,...,Yn) -> (fold_left (fun 𜃠(X,Y) -> unify(X,Y,ðœƒ)) 𜃠[(X1,Y1),...,(Xn,Yn)]) *)
List.fold_left2(fun s x y -> reunify x y s)s b1 b2
| _ -> raise Not_unifiable (*failure*)
in reunify t1 t2 Substitution.empty
(* Problem 5 *)
let nondet_query program goal =
let nondet_query program goal =
(*loop 1*)
let rec query g resolvant =
(*loop while the resolvant is not empty*)
match resolvant with
| [] -> g
| r -> (*putt a random goal out from resolvant*)
let a = List.nth r (Random.int (List.length r)) in
let r = List.fold_left(fun acc x -> if x=a then acc else acc@[x])[] r in
(*get a random renamed clause*)
match freshen (List.nth program (Random.int (List.length program))) with
| Fact f ->(
match unify f a with (*get theta/s from unifying a' and a*)
| exception (Not_unifiable) -> raise (Not_unifiable) (*if no goal and clause exist, break*)
| s -> query (subl substitute_in_term s g) (subl substitute_in_term s r)) (*apply theta/s to g and r*)
| Rule (h,b) ->
match unify h a with
| exception (Not_unifiable) -> raise (Not_unifiable)
| s -> query (subl substitute_in_term s g) (subl substitute_in_term s (r@b)) (*append the [b1...bn] into r*)
(*loop 2*)
in let rec loop () =
match query goal goal with (*initialize the resolvant with the goal*)
| exception (Not_unifiable) -> loop() (*when it fails, try again*)
| result -> result
in loop()
(* Problem Bonus *)
let det_query program goal =
raise (Failure "Problem Bonus Not implemented")