We define the signature
module type Ring = sig
type t
val zero : t
val one : t
val add : t -> t -> t
val mul : t -> t -> t
val compare : t -> t -> int
val to_string : t -> string
end
of an algebraic ring structure, 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
.
Furthermore, a matrix is given by the signature:
module type Matrix = sig
type elem
type t
val create : int -> int -> t
val identity : int -> t
val from_rows : elem list list -> t
val row_count : t -> int
val col_count : t -> int
val set : int -> int -> elem -> t -> t
val get : int -> int -> t -> elem
val transpose : t -> t
val add : t -> t -> t
val mul : t -> t -> t
val to_string : t -> string
end
Here, elem
and t
represent the types of the elements of the matrix and the matrix itself, respectively. The functions have the following semantics:
-
create n m
creates an empty (all zeroes)$n\times m$ matrix. -
identity n
creates an$n\times n$ identity matrix. -
row_count m
andcol_count m
return the number of rows and columns inm
, respectively. -
from_rows l
creates a matrix from the given list of rows (lists of elements). You may assume thatl
is non-empty and all lists have the same length. -
set r c v m
sets the element at rowr
and columnc
in matrixm
to valuev
. -
get r c m
returns the element at rowr
and columnc
from matrixm
. -
transpose m
returns the transpose of matrixm
. -
add a b
adds matricesa
andb
component-wise. -
mul a b
computes the matrix multiplication ofa
andb
. -
to_string m
produces a string representation ofm
. Columns shall be separated by single whitespaces and rows by a newline character\n
.
This signature is available in matrix/libMatrix.ml
.
Perform these tasks:
-
IntRing
In the fileintring/libIntRing.ml
: Implement a moduleIntRing
that implements theRing
signature for theint
type. [0.5 points] -
FloatRing
In the filefloatring/libFloatRing.ml
: Implement a moduleFloatRing
that implements theRing
signature for thefloat
type. [0.5 points] -
FiniteRing
In the filefinitering/libFiniteRing.ml
: Define a signatureFiniteRing
that extends theRing
signature with a valueelems
that represents a list of all elements of the ring's finite set. Make sure that everything in theRing
signature is part ofFiniteRing
(without copy-pasting them)! [0.5 points] -
BoolRing
In the fileboolring/libBoolRing.ml
: Implement a moduleBoolRing
that implements theFiniteRing
signature for thebool
type. The multiplication in a bool ring is conjunction, the addition is the exclusive or. [0.5 points] -
SetRing
In the filesetring/libSetRing.ml
: Implement a functorSetRing
that models a ring over the power set of the set in theFiniteRing
passed as the functor's argument.SetRing
has to implement theRing
signature. We use union and intersection asadd
andmul
operations. The representation produced byto_string
is$\left\lbrace e_1,\dots,e_n \right\rbrace$ . Forcompare
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<\left\lbrace 1,2,3 \right\rbrace<\left\lbrace 2 \right\rbrace<\left\lbrace 2,3 \right\rbrace<\left\lbrace 3 \right\rbrace$ . The typet
inSetRing
should beD.t list
, ifD
is the module that is passed to the functor. Make sure that this information aboutt
is exposed to the outside. [1.5 points] -
DenseMatrix
In the filedensematrix/libDenseMatrix.ml
: Implement a functorDenseMatrix
that satisfies theMatrix
signature. The argument of the functor is aRing
that provides everything to implement the matrix operations. TheDenseMatrix
is supposed to store all elements in the matrix in a list of rows, which are lists of elements. [3 points] -
SparseMatrix
In the filesparsematrix/libSparseMatrix.ml
: Implement a functorSparseMatrix
that satisfies theMatrix
signature. The argument of the functor is aRing
that provides everything to implement the matrix operations. TheSparseMatrix
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]
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.
Hint: The function implementations need not be particularly efficient or tail-recursive, just keep your implementations simple where possible.
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.
Write any code you want to share between tasks in common/common.ml
.
To not cause issues with the tests, you should not change the provided dune
files (the tests on Artemis will ignore your dune
files).
Overview of dependencies
Example: If your implementation of
libFiniteRing
can't compile, then libBoolRing
and libSetRing
will not be tested and receive zero points.
Example: You can reuse any implementations you write in libMatrix
in libDenseMatrix
and libSparseMatrix
, but don't change the Matrix
signature.
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