-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhw3.ml
277 lines (219 loc) · 7.29 KB
/
hw3.ml
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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
open Common
exception NotImplemented
exception IllegalFormat
module Integer : SCALAR with type t = int
=
struct
type t = int
exception ScalarIllegal
let zero = 0
let one = 1
let (++) x y = x + y
let ( ** ) x y = x * y
let (==) x y = x = y
end
(* Problem 1-1 *)
(* Scalars *)
module Boolean : SCALAR with type t = bool
=
struct
type t = bool
exception ScalarIllegal
let zero = false
let one = true
let (++) x y = x || y
let ( ** ) x y = x && y
let (==) x y = x = y
end
(* Problem 1-2 *)
(* Vectors *)
module VectorFn (Scal : SCALAR) : VECTOR with type elem = Scal.t
=
struct
type elem = Scal.t
type t = elem list
exception VectorIllegal
let create (l: elem list): t = l
let to_list (v: t): elem list = v
let dim (v: t) = List.length v
let nth (v: t) (n: int): elem =
if n >= (dim v) then raise VectorIllegal
else List.nth v n
let (++) (v1: t) (v2: t): t =
if dim v1 <> dim v2 then raise VectorIllegal
else List.map2 (fun x y -> Scal.(++) x y) v1 v2
let (==) (v1: t) (v2: t): bool =
if dim v1 <> dim v2 then raise VectorIllegal
else List.fold_left (fun x y -> x && y) true (List.map2 (fun x y -> Scal.(==) x y) v1 v2)
let innerp (v1: t) (v2: t): elem =
if dim v1 <> dim v2 then raise VectorIllegal
else List.fold_left (fun x y -> Scal.(++) x y) Scal.zero (List.map2 (fun x y -> Scal.( ** ) x y) v1 v2)
end
(* Problem 1-3 *)
(* Matrices *)
module MatrixFn (Scal : SCALAR) : MATRIX with type elem = Scal.t
=
struct
type elem = Scal.t
type t = elem list list
exception MatrixIllegal
let create (l: elem list list): t =
match l with
| [[]] -> raise MatrixIllegal
| _ ->
if List.for_all (fun x -> x = List.length l) (List.map List.length l) then l
else raise MatrixIllegal
let identity (n: int): t =
if n <= 0 then raise MatrixIllegal
else
let rec row_eye (n: int) (c: int) (length: int) (acc: elem list): elem list =
if length = c then acc
else row_eye (n) (c + 1) (length) (acc @ [if c = n then Scal.one else Scal.zero])
in
let rec mat_construct (n: int) (length: int) (acc: elem list list): elem list list =
if length = n then acc
else mat_construct (n + 1) (length) (acc @ [row_eye (n) (0) (length) ([])])
in mat_construct (0) (n) ([])
let dim (m: t): int = List.length m
let rec transpose (m: t): t =
match m with
| []::_ -> []
| r -> [List.map (List.hd) (r)] @ transpose (List.map (List.tl) (r))
let to_list (m: t): elem list list = m
let get (m: t) (r: int) (c: int) =
if List.length m <= r || List.length (List.hd m) <= c then raise MatrixIllegal
else List.nth (List.nth m r) c
let (++) (m1: t) (m2: t): t =
if dim (m1) <> dim (m2) then raise MatrixIllegal
else List.map2 (fun v1 v2 -> List.map2 Scal.(++) v1 v2) (m1) (m2)
let ( ** ) (m1: t) (m2: t): t =
if dim (m1) <> dim (m2) then raise MatrixIllegal
else
let multiply_row_col (r) (c) =
List.fold_left (Scal.(++)) (Scal.zero) (List.map2 (Scal.( ** )) (r) (c))
in
List.map (fun r -> List.map (fun c -> multiply_row_col r c) (transpose m2)) (m1)
let (==) (m1: t) (m2: t): bool =
if dim (m1) <> dim (m2) then raise MatrixIllegal
else List.fold_left (fun x y -> x && y) true (List.map2 (fun v1 v2 -> List.fold_left (fun x y -> x && y) true (List.map2 Scal.(==) v1 v2)) (m1) (m2))
end
(* Problem 2-1 *)
(* Closure *)
module ClosureFn (Mat : MATRIX) :
sig
val closure : Mat.t -> Mat.t
end
=
struct
let closure (mat: Mat.t): Mat.t =
let ident =
Mat.identity (Mat.dim mat)
in
let rec rec_closure (cur_closure: Mat.t): Mat.t =
if Mat.(cur_closure == (ident ++ (cur_closure ** mat))) then cur_closure
else rec_closure Mat.(ident ++ (cur_closure ** mat))
in
rec_closure ident
end
(* Problem 2-2 *)
(* Applications to Graph Problems *)
module BoolMat = MatrixFn (Boolean)
module BoolMatClosure = ClosureFn (BoolMat)
let reach (l: bool list list): bool list list =
let module ReachMat = MatrixFn(Boolean) in
let module ReachCls = ClosureFn(ReachMat) in
let mat_dist = ReachMat.create l in
ReachMat.to_list (ReachCls.closure mat_dist)
let al =
[[true; false; false; false; false; false];
[false; true; true; true; false; false];
[false; true; true; false; true; false];
[false; true; false; true; true; true];
[false; false; true; true; true; false];
[false; false; false; true; false; true]]
let solution_al' =
[[true; false; false; false; false; false];
[false; true; true; true; true; true];
[false; true; true; true; true; true];
[false; true; true; true; true; true];
[false; true; true; true; true; true];
[false; true; true; true; true; true]]
module Distance : SCALAR with type t = int
=
struct
type t = int
exception ScalarIllegal
let zero = -1 (* Dummy value : Rewrite it! *)
let one = 0 (* Dummy value : Rewrite it! *)
let (++) (x: t) (y: t): t =
if x = zero then y
else if y = zero then x
else if x < y then x else y
let ( ** ) (x: t) (y: t): t =
if x = zero || y = zero then zero
else x + y
let (==) (x: t) (y: t) = x = y
end
(* .. Write some code here .. *)
let distance (l: int list list): int list list =
let module DistMat = MatrixFn(Distance) in
let module DistCls = ClosureFn(DistMat) in
let mat_dist = DistMat.create l in
DistMat.to_list (DistCls.closure mat_dist)
let dl =
[[ 0; -1; -1; -1; -1; -1 ];
[ -1; 0 ; 35 ; 200; -1 ; -1 ];
[ -1; 50 ; 0 ; -1 ; 150; -1 ];
[ -1; 75; -1 ; 0 ; 100; 25 ];
[ -1; -1 ; 50 ; 65 ; 0 ; -1 ];
[ -1; -1 ; -1 ; -1 ; -1 ; 0 ]]
let solution_dl' =
[[0; -1; -1; -1; -1; -1 ];
[-1; 0; 35; 200; 185; 225 ];
[-1; 50; 0; 215; 150; 240 ];
[-1; 75; 110; 0; 100; 25 ];
[-1; 100; 50; 65; 0; 90 ];
[-1; -1; -1; -1; -1; 0 ]]
module Weight : SCALAR with type t = int
=
struct
type t = int
exception ScalarIllegal
let zero = 0 (* Dummy value : Rewrite it! *)
let one = -1 (* Dummy value : Rewrite it! *)
let (++) (x: t) (y: t): t =
if x = one || y = one then one
else if x > y then x else y
let ( ** ) (x: t) (y: t): t =
if x = one then y
else if y = one then x
else if x < y then x else y
let (==) (x: t) (y: t) = x = y
end
(* .. Write some code here .. *)
let weight (l: int list list): int list list =
let module WeightMat = MatrixFn(Weight) in
let module WeightCls = ClosureFn(WeightMat) in
let mat_dist = WeightMat.create l in
WeightMat.to_list (WeightCls.closure mat_dist)
let ml =
[[-1; 0 ; 0 ; 0 ; 0 ; 0 ];
[0 ; -1 ; 10 ; 100; 0 ; 0 ];
[0 ; 50 ; -1 ; 0 ; 150; 0 ];
[0 ; 75 ; 0 ; -1 ; 125; 40 ];
[0 ; 0 ; 25 ; -1 ; -1 ; 0 ];
[0 ; 0 ; 0 ; 0 ; 0 ; -1 ]]
let solution_ml' =
[[-1; 0; 0; 0; 0; 0 ];
[0; -1; 25; 100; 100; 40 ];
[0; 75; -1; 150; 150; 40 ];
[0; 75; 25; -1; 125; 40 ];
[0; 75; 25; -1; -1; 40 ];
[0; 0; 0; 0; 0; -1 ]]
let _ =
try
if reach al = solution_al' && distance dl = solution_dl' && weight ml = solution_ml' then
print_endline "\nYour program seems fine (but no guarantee)!"
else
print_endline "\nYour program might have bugs!"
with _ -> print_endline "\nYour program is not complete yet!"