Skip to content

Commit 07cd0c4

Browse files
committed
modules
1 parent ecff855 commit 07cd0c4

File tree

23 files changed

+479
-0
lines changed

23 files changed

+479
-0
lines changed

Week_10/Homework_01_ModulesModellingMatrices/.ocamlformat

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Modules Modelling Matrices
2+
We define the signature
3+
4+
```ocaml
5+
module type Ring = sig
6+
type t
7+
val zero : t
8+
val one : t
9+
val add : t -> t -> t
10+
val mul : t -> t -> t
11+
val compare : t -> t -> int
12+
val to_string : t -> string
13+
end
14+
```
15+
16+
of an [algebraic ring structure](https://en.wikipedia.org/wiki/Ring_(mathematics)), where `add` and `mul` are the two binary operations on the set of elements of type `t`. Values `zero` and `one` represent the identity elements with respect to *addition* and *multiplication*. The function `compare` establishes a total order on the elements of the set. The auxiliary function `to_string` is used to generate a string representation of an element. This signature is available in `ring/libRing.ml`.
17+
18+
Furthermore, a matrix is given by the signature:
19+
20+
```ocaml
21+
module type Matrix = sig
22+
type elem
23+
type t
24+
val create : int -> int -> t
25+
val identity : int -> t
26+
val from_rows : elem list list -> t
27+
val row_count : t -> int
28+
val col_count : t -> int
29+
val set : int -> int -> elem -> t -> t
30+
val get : int -> int -> t -> elem
31+
val transpose : t -> t
32+
val add : t -> t -> t
33+
val mul : t -> t -> t
34+
val to_string : t -> string
35+
end
36+
```
37+
38+
Here, `elem` and `t` represent the types of the elements of the matrix and the matrix itself, respectively. The functions have the following semantics:
39+
40+
- `create n m` creates an empty (all zeroes) $n\times m$ matrix.
41+
- `identity n` creates an $n\times n$ identity matrix.
42+
- `row_count m` and `col_count m` return the number of rows and columns in `m`, respectively.
43+
- `from_rows l` creates a matrix from the given list of rows (lists of elements). You may assume that `l` is non-empty and all lists have the same length.
44+
- `set r c v m` sets the element at row `r` and column `c` in matrix `m` to value `v`.
45+
- `get r c m` returns the element at row `r` and column `c` from matrix `m`.
46+
- `transpose m` returns the transpose of matrix `m`.
47+
- `add a b` adds matrices `a` and `b` component-wise.
48+
- `mul a b` computes the matrix multiplication of `a` and `b`.
49+
- `to_string m` produces a string representation of `m`. Columns shall be separated by single whitespaces and rows by a newline character `\n`.
50+
51+
This signature is available in `matrix/libMatrix.ml`.
52+
53+
Perform these tasks:
54+
55+
- **IntRing**
56+
In the file `intring/libIntRing.ml`: Implement a module `IntRing` that implements the `Ring` signature for the `int` type. [0.5 points]
57+
- **FloatRing**
58+
In the file `floatring/libFloatRing.ml`: Implement a module `FloatRing` that implements the `Ring` signature for the `float` type. [0.5 points]
59+
- **FiniteRing**
60+
In the file `finitering/libFiniteRing.ml`: Define a signature `FiniteRing` that extends the `Ring` signature with a value `elems` that represents a list of all elements of the ring's finite set. Make sure that everything in the `Ring` signature is part of `FiniteRing` (without copy-pasting them)! [0.5 points]
61+
- **BoolRing**
62+
In the file `boolring/libBoolRing.ml`: Implement a module `BoolRing` that implements the `FiniteRing` signature for the `bool` type. The multiplication in a bool ring is *conjunction*, the addition is the *exclusive or*. [0.5 points]
63+
- **SetRing**
64+
In the file `setring/libSetRing.ml`: Implement a functor `SetRing` that models a ring over the power set of the set in the `FiniteRing` passed as the functor's argument. `SetRing` has to implement the `Ring` signature. We use union and intersection as `add` and `mul` operations. The representation produced by `to_string` is $\{e_1,\dots,e_n\}$. For `compare` we use a bit of an unconventional order. First, we order the elements in the set by their own order and then compare the sets lexicographically, e.g. $\emptyset<\{1,2,3\}<\{2\}<\{2,3\}<\{3\}$. The type `t` in `SetRing` should be `D.t list`, if `D` is the module that is passed to the functor. Make sure that this information about `t` is exposed to the outside. [1.5 points]
65+
- **DenseMatrix**
66+
In the file `densematrix/libDenseMatrix.ml`: Implement a functor `DenseMatrix` that satisfies the `Matrix` signature. The argument of the functor is a `Ring` that provides everything to implement the matrix operations. The `DenseMatrix` is supposed to store all elements in the matrix in a list of rows, which are lists of elements. [3 points]
67+
- **SparseMatrix**
68+
In the file `sparsematrix/libSparseMatrix.ml`: Implement a functor `SparseMatrix` that satisfies the `Matrix` signature. The argument of the functor is a `Ring` that provides everything to implement the matrix operations. The `SparseMatrix` stores only those elements of the matrix that are non-zero. More precisely, the representation of a sparse matrix must have memory usage proportional to the number of non-zero entries in the matrix ($\mathcal{O}(n)$). [3.5 points]
69+
70+
*Hint: You may assume that all inputs are valid, e.g. no out-of-bounds access. If you wish to handle invalid input, just throw an exception.*
71+
72+
*Hint: The function implementations need not be particularly efficient or tail-recursive, just keep your implementations simple where possible.*
73+
74+
## Assignment Repository Layout and Tests
75+
Testing your solutions is more difficult this week as a test cannot compile if any module it depends on is not correctly implemented or a module signature is incorrectly defined. Thus, we have separated each module into its own `dune` library (one per directory). This way, we can compile and test each library independently. However, since some tasks require implementations of previous tasks, we have introduced dependencies between the libraries. If building any dependency of a library fails, we cannot test that library (and the corresponding task will receive zero points) as building it would fail too. You can consult the `dune` files or the graph below to see exactly what the dependencies are. If you don't want to submit a solution for some task, check Artemis to make sure that the public tests for the tasks that you do want to submit pass. In particular, look for the `*:build` tests, which pass only if that library can be tested and tell you why it cannot otherwise.
76+
77+
Write any code you want to share between tasks in `common/common.ml`.
78+
79+
To not cause issues with the tests, you should not change the provided `dune` files (the tests on Artemis will ignore your `dune` files).
80+
81+
<details>
82+
<summary>Overview of dependencies</summary>
83+
Example: If your implementation of `libFiniteRing` can't compile, then `libBoolRing` and `libSetRing` will not be tested and receive zero points.
84+
85+
Example: You can reuse any implementations you write in `libMatrix` in `libDenseMatrix` and `libSparseMatrix`, but don't change the `Matrix` signature.
86+
87+
*Tip: You can generate similar graphs for any dune project by installing dune-deps with opam install dune-deps, then running e.g. `dune-deps | dot -Tpng > deps.png`*
88+
</details>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
; auto-generated by deps.sh
2+
(library
3+
(name libBoolRing)
4+
(libraries common libRing libFiniteRing)
5+
(flags
6+
(:standard -warn-error -27-33)))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
open Common
2+
open LibRing
3+
4+
module BoolRing = struct
5+
type t = bool
6+
let elems = [true; false]
7+
let zero = false
8+
let one = true
9+
let add = ( <> ) (* exclusive or *)
10+
let mul = ( && ) (* conjunction *)
11+
let compare = compare
12+
let to_string = string_of_bool
13+
end

Week_10/Homework_01_ModulesModellingMatrices/common/common.ml

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
; auto-generated by deps.sh
2+
(library
3+
(name common)
4+
(flags
5+
(:standard -warn-error -27-33)))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
; auto-generated by deps.sh
2+
(library
3+
(name libDenseMatrix)
4+
(libraries common libRing libMatrix)
5+
(flags
6+
(:standard -warn-error -27-33)))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
open Common
2+
open LibRing
3+
open LibMatrix
4+
5+
module DenseMatrix = functor (R : Ring) ->
6+
struct
7+
type elem = R.t
8+
(* for matrix m*n, rows from 0 to m-1, columns from 0 to n-1 *)
9+
type t = elem list list (* Define that t_{00} is the top of stack *)
10+
11+
let create n m =
12+
let rec create_row j =
13+
if j = 0 then [] else R.zero :: create_row (j - 1)
14+
in
15+
let row = create_row m in
16+
let rec create_rows i =
17+
if i = 0 then [] else row :: create_rows (i - 1)
18+
in
19+
create_rows n
20+
21+
let identity n =
22+
let rec identity_row i j =
23+
if j = 0 then [] else
24+
if i = j then R.one :: identity_row i (j - 1)
25+
else R.zero :: identity_row i (j - 1)
26+
in
27+
let rec identity_rows i =
28+
if i = 0 then [] else identity_row i n :: identity_rows (i - 1)
29+
in
30+
identity_rows n
31+
32+
let row_count m =
33+
let rec row_count_aux acc = function
34+
| [] -> acc
35+
| _::xs -> row_count_aux (acc + 1) xs
36+
in row_count_aux 0 m
37+
38+
let col_count m =
39+
let rec col_count_aux acc = function
40+
| [] -> acc
41+
| _::xs -> col_count_aux (acc + 1) xs
42+
in col_count_aux 0 (List.hd m)
43+
44+
let from_rows l = l
45+
46+
let set r c v m =
47+
let rec set_column c v = function
48+
| [] -> failwith "set: column out of bounds"
49+
| x::xs -> if c = 0 then v::xs else x::set_column (c - 1) v xs
50+
in
51+
let rec set_row r c v = function
52+
| [] -> failwith "set: row out of bounds"
53+
| x::xs -> if r = 0 then set_column c v x::xs else x::set_row (r - 1) c v xs
54+
in
55+
set_row r c v m
56+
57+
let get r c m =
58+
let rec get_column c = function
59+
| [] -> failwith "get: column out of bounds"
60+
| x::xs -> if c = 0 then x else get_column (c - 1) xs
61+
in
62+
let rec get_row r c = function
63+
| [] -> failwith "get: row out of bounds"
64+
| x::xs -> if r = 0 then get_column c x else get_row (r - 1) c xs
65+
in
66+
get_row r c m
67+
68+
let transpose m =
69+
let rec transpose_row i j m acc =
70+
if j = 0 then acc else
71+
transpose_row i (j - 1) m (get (j - 1) (i - 1) m :: acc) (* set i j *)
72+
in
73+
let rec transpose_rows i j m acc =
74+
if i = 0 then acc else
75+
transpose_rows (i - 1) j m (transpose_row i j m [] :: acc)
76+
in
77+
transpose_rows (col_count m) (row_count m) m [] (* swap rows and columns *)
78+
79+
let add a b =
80+
let rec add_row = function
81+
| [], [] -> []
82+
| x::xs, y::ys -> R.add x y :: add_row (xs, ys)
83+
| _ -> failwith "add: matrices have different dimensions"
84+
in
85+
let rec add_rows = function
86+
| [], [] -> []
87+
| x::xs, y::ys -> add_row (x, y) :: add_rows (xs, ys)
88+
| _ -> failwith "add: matrices have different dimensions"
89+
in
90+
add_rows (a, b)
91+
92+
let mul a b = (* c_{ij} = \Sigma_k a_{ik} b_{kj} *)
93+
let a_col = col_count a in
94+
let b_row = row_count b in
95+
let rec sum r c k =
96+
if k = 0 then R.zero else
97+
R.add (R.mul (get (r - 1) (k - 1) a) (get (k - 1) (c - 1) b)) (sum r c (k - 1))
98+
in
99+
let rec mul_row r c acc =
100+
if c = 0 then acc else
101+
mul_row r (c - 1) (sum r c a_col :: acc)
102+
in
103+
let rec mul_rows r c acc =
104+
if r = 0 then acc else
105+
mul_rows (r - 1) c (mul_row r c [] :: acc)
106+
in
107+
if a_col <> b_row then
108+
failwith "mul: matrices have incompatible dimensions"
109+
else
110+
mul_rows (row_count a) (col_count b) []
111+
112+
let to_string m =
113+
let rec to_string_row = function
114+
| [] -> ""
115+
| [x] -> R.to_string x
116+
| x::xs -> R.to_string x ^ " " ^ to_string_row xs
117+
in
118+
let rec to_string_rows = function
119+
| [] -> ""
120+
| [x] -> to_string_row x
121+
| x::xs -> to_string_row x ^ "\n" ^ to_string_rows xs
122+
in
123+
to_string_rows m
124+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(lang dune 2.0)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
; auto-generated by deps.sh
2+
(library
3+
(name libFiniteRing)
4+
(libraries common libRing)
5+
(flags
6+
(:standard -warn-error -27-33)))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
open Common
2+
open LibRing
3+
4+
module type FiniteRing = sig
5+
include Ring
6+
val elems : t list
7+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
; auto-generated by deps.sh
2+
(library
3+
(name libFloatRing)
4+
(libraries common libRing)
5+
(flags
6+
(:standard -warn-error -27-33)))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
open Common
2+
open LibRing
3+
4+
module FloatRing = struct
5+
type t = float
6+
let zero = 0.
7+
let one = 1.
8+
let add = ( +. )
9+
let mul = ( *. )
10+
let compare = compare
11+
let to_string = string_of_float
12+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
; auto-generated by deps.sh
2+
(library
3+
(name libIntRing)
4+
(libraries common libRing)
5+
(flags
6+
(:standard -warn-error -27-33)))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
open Common
2+
open LibRing
3+
4+
module IntRing = struct
5+
type t = int
6+
let zero = 0
7+
let one = 1
8+
let add = ( + )
9+
let mul = ( * )
10+
let compare = compare
11+
let to_string = string_of_int
12+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
; auto-generated by deps.sh
2+
(library
3+
(name libMatrix)
4+
(libraries common)
5+
(flags
6+
(:standard -warn-error -27-33)))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module type Matrix = sig
2+
type elem
3+
type t
4+
val create : int -> int -> t
5+
val identity : int -> t
6+
val from_rows : elem list list -> t
7+
val to_string : t -> string
8+
val set : int -> int -> elem -> t -> t
9+
val get : int -> int -> t -> elem
10+
val transpose : t -> t
11+
val add : t -> t -> t
12+
val mul : t -> t -> t
13+
val row_count : t -> int
14+
val col_count : t -> int
15+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
; auto-generated by deps.sh
2+
(library
3+
(name libRing)
4+
(libraries common)
5+
(flags
6+
(:standard -warn-error -27-33)))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module type Ring = sig
2+
type t
3+
val zero : t
4+
val one : t
5+
val compare : t -> t -> int
6+
val to_string : t -> string
7+
val add : t -> t -> t
8+
val mul : t -> t -> t
9+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
; auto-generated by deps.sh
2+
(library
3+
(name libSetRing)
4+
(libraries common libRing libFiniteRing)
5+
(flags
6+
(:standard -warn-error -27-33)))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
open Common
2+
open LibRing
3+
open LibFiniteRing
4+
5+
module SetRing = functor (D : FiniteRing) ->
6+
struct
7+
type t = D.t list (* set *)
8+
let zero = [] (* empty set *)
9+
let one = D.elems (* universe *)
10+
11+
let rec add a b = (* union *)
12+
match a with
13+
| [] -> b
14+
| x::xs -> if List.mem x b then add xs b else add xs (x::b) (* tail recursive *)
15+
16+
let rec mul a b = (* intersection *)
17+
match a with
18+
| [] -> []
19+
| x::xs -> if List.mem x b then x::(mul xs b) else mul xs b
20+
21+
let compare a b = (* lexicographical *)
22+
let rec compare_aux a b = match a, b with
23+
| [], [] -> 0
24+
| [], _ -> -1
25+
| _, [] -> 1
26+
| x::xs, y::ys -> let c = D.compare x y in if c = 0 then compare_aux xs ys else c
27+
in compare_aux (List.sort_uniq D.compare a) (List.sort_uniq D.compare b)
28+
29+
let to_string s =
30+
let rec to_string_aux = function
31+
| [] -> ""
32+
| [x] -> D.to_string x (* no comma *)
33+
| x::xs -> (D.to_string x) ^ ", " ^ (to_string_aux xs)
34+
in "{" ^ (to_string_aux s) ^ "}"
35+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
; auto-generated by deps.sh
2+
(library
3+
(name libSparseMatrix)
4+
(libraries common libRing libMatrix)
5+
(flags
6+
(:standard -warn-error -27-33)))

0 commit comments

Comments
 (0)