Monday, October 6, 2025

OCAML MATRICES

 

REVISED:  Monday, October 6, 2025                                        





 1. OCAML MATRICES

(*
============================
ocaml C:\AI2025\lesson2.ml
Lesson 2: Matrices in OCaml
============================

Objective: Represent matrices and implement basic operations:
1. Matrix addition
2. Scalar multiplication
3. Matrix-vector multiplication
4. Matrix-matrix multiplication
*)

(* -----------------------------
   0. Helper functions (from Lesson 1)
   ----------------------------- *)
(* Implemented missing helpers that the matrix functions rely on.
   Each line added below includes a comment explaining its purpose. *)

(* Add two vectors (lists of floats) element-wise. *)
let rec vector_add v1 v2 =
  (* If both vectors are empty, result is empty. *)
  match v1, v2 with
  | [], [] -> []
  (* Add heads pairwise and recurse on tails. *)
  | x::xs, y::ys -> (x +. y) :: vector_add xs ys
  (* Different lengths -> error. *)
  | _ -> failwith "vector_add: vectors must have same length"
  (* End of vector_add. *)

(* Multiply a vector by a scalar (scalar * vector). *)
let rec scalar_mul scalar v =
  (* Empty vector -> empty result. *)
  match v with
  | [] -> []
  (* Multiply head by scalar and recurse on tail. *)
  | x :: xs -> (scalar *. x) :: scalar_mul scalar xs
  (* End of scalar_mul. *)

(* Dot product of two vectors (lists of floats). *)
let dot_product v1 v2 =
  (* Use List.fold_left2 to accumulate element-wise products. 
     List.fold_left2 raises if lengths mismatch, which is fine here. *)
  List.fold_left2 (fun acc a b -> acc +. (a *. b)) 0.0 v1 v2
  (* End of dot_product. *)

(* -----------------------------
   1. Matrix type
   ----------------------------- *)
(* We'll represent a matrix as a list of lists of floats. *)
type matrix = float list list

(* -----------------------------
   2. Matrix addition
   ----------------------------- *)
(* Adds two matrices element-wise.
   Raises an error if the matrices have different dimensions. *)
let rec matrix_add m1 m2 =
  match m1, m2 with
  | [], [] -> []  (* base case: both matrices empty *)
  | row1::rest1, row2::rest2 ->
      (* add corresponding rows using vector_add, then recurse *)
      (vector_add row1 row2) :: (matrix_add rest1 rest2)
  | _ -> failwith "Matrices must have the same dimensions"

(* -----------------------------
   3. Scalar multiplication
   ----------------------------- *)
(* Multiply each element of a matrix by a scalar *)
let rec scalar_mul_matrix scalar m =
  match m with
  | [] -> []
  | row::rows ->
      (* multiply each row (vector) by scalar using scalar_mul *)
      (scalar_mul scalar row) :: (scalar_mul_matrix scalar rows)

(* -----------------------------
   4. Matrix-vector multiplication
   ----------------------------- *)
(* Multiply a matrix by a vector *)
let matrix_vector_mul m v =
  (* map each row to the dot product of row and vector *)
  List.map (fun row -> dot_product row v) m

(* -----------------------------
   5. Matrix-matrix multiplication
   ----------------------------- *)
(* Multiply two matrices: m1 * m2 *)
let matrix_mul m1 m2 =
  let transpose m =
    (* build a transpose via accumulating columns *)
    let rec aux acc = function
      | [] -> acc
      | row::rows ->
        (* prepend each element of row to corresponding accumulator list.
           List.map2 pairs each element of 'row' with a list in 'acc'. *)
        let new_acc = List.map2 (fun x xs -> x :: xs) row acc in
        aux new_acc rows
    in
    match m with
    | [] -> []
    | first_row::_ -> aux (List.map (fun _ -> []) first_row) m
  in
  let m2_t = transpose m2 in
  (* for each row in m1 produce a row consisting of dot products
     with each column (i.e. each row of m2_t) *)
  List.map (fun row ->
    List.map (fun col -> dot_product row col) m2_t
  ) m1

(* -----------------------------
   6. Examples / Testing
   ----------------------------- *)
let m1 = [[1.;2.;3.]; [4.;5.;6.]]
let m2 = [[7.;8.;9.]; [10.;11.;12.]]

(* Matrix addition *)
let m_add = matrix_add m1 m2
let () =
  Printf.printf "m1 + m2 = [%s]\n"
    (String.concat "; " (List.map (fun row -> "[" ^ (String.concat "; " (List.map string_of_float row)) ^ "]") m_add))

(* Scalar multiplication *)
let m_scaled = scalar_mul_matrix 2.0 m1
let () =
  Printf.printf "2 * m1 = [%s]\n"
    (String.concat "; " (List.map (fun row -> "[" ^ (String.concat "; " (List.map string_of_float row)) ^ "]") m_scaled))

(* Matrix-vector multiplication *)
let v = [1.;2.;3.]
let mv_mul = matrix_vector_mul m1 v
let () =
  Printf.printf "m1 * v = [%s]\n"
    (String.concat "; " (List.map string_of_float mv_mul))

(* Matrix-matrix multiplication *)
let m3 = [[1.;2.]; [3.;4.]; [5.;6.]]
let mm_mul = matrix_mul m1 m3
let () =
  Printf.printf "m1 * m3 = [%s]\n"
    (String.concat "; " (List.map (fun row -> "[" ^ (String.concat "; " (List.map string_of_float row)) ^ "]") mm_mul))

2. CONCLUSION

Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows

OCaml version: The OCaml toplevel, version 5.3.0
Coq-LSP version: 0.2.3
Loading personal and system profiles took 1063ms.
PS C:\Users\User> ocaml C:\AI2025\lesson2.ml
m1 + m2 = [[8.; 10.; 12.]; [14.; 16.; 18.]]
2 * m1 = [[2.; 4.; 6.]; [8.; 10.; 12.]]
m1 * v = [14.; 32.]
m1 * m3 = [[14.; 20.]; [41.; 56.]]
PS C:\Users\User>

3. REFERENCES

Bird, R. (2015). Thinking Functionally with Haskell. Cambridge, England: Cambridge University Press.

Davie, A. (1992). Introduction to Functional Programming Systems Using Haskell. Cambridge, England: Cambridge University Press.

Goerzen, J. & O'Sullivan, B. &  Stewart, D. (2008). Real World Haskell. Sebastopol, CA: O'Reilly Media, Inc.

Hutton, G. (2007). Programming in Haskell. New York: Cambridge University Press.

Lipovača, M. (2011). Learn You a Haskell for Great Good!: A Beginner's Guide. San Francisco, CA: No Starch Press, Inc.

Thompson, S. (2011). The Craft of Functional Programming. Edinburgh Gate, Harlow, England: Pearson Education Limited.