У меня новое развлечение - курс Нейронные сети. Сейчас у меня ликбез по линейной алгебре, а конкретно - умножение матриц. В одном уроке нужно было перемножить матрицы, что мне показалось неплохой возможностью написать кусок кода на OCaml.
Задача
Перемножить матрицы
[1 0 0 0] [1 2 3] [3 0 0] 2 * [0 1 0 0] * [5 6 7] * [0 3 0] = [0 0 1 0] [9 10 11] [0 0 3] [0 0 0 1] [4 8 12]
Решение
В этот раз мне хотелось сделать отдельный модуль с сигнатурой и без конкретных типов в сигнатурах.
matrix.mli
open Core.Std type t val of_list: int list list -> t val of_array: int array array -> t val mult_to_matrix: t -> t -> t val mult_to_int: t -> int -> t val to_string: t -> string
matrix.ml
open Core.Std type t = int array array let of_array a = Array.map a ~f: Array.copy let of_list lst = List.to_array (List.map lst ~f: List.to_array) let mult_to_matrix m1 m2 = let dimx = Array.length m1 in let dimy = Array.length m2.(0) in let vector_length = Array.length m2 in let mult_lines line_number column_number = List.range 0 vector_length |> List.map ~f:(fun k -> m1.(line_number).(k) * m2.(k).(column_number)) |> List.reduce ~f:(+) |> Option.value ~default:0 in let product = Array.make_matrix ~dimx ~dimy 0 in for i = 0 to dimx - 1 do for j = 0 to dimy - 1 do product.(i).(j) <- mult_lines i j done; done; product let mult_to_int matrix multiplier = matrix |> Array.map ~f:(fun line -> Array.map line ~f:(fun i -> i * multiplier)) let to_string matrix = Array.map matrix ~f:(fun line -> Array.map line ~f:Int.to_string |> String.concat_array ~sep:", " ) |> String.concat_array ~sep: "; "
product.ml
open Core.Std let () = let a = Matrix.of_array [| [|1; 0; 0; 0|]; [|0; 1; 0; 0|]; [|0; 0; 1; 0|]; [|0; 0; 0; 1|]; |] in let b = Matrix.of_list [ [1; 2; 3]; [5; 6; 7]; [9; 10; 11]; [4; 8; 12] ] in let c = Matrix.of_list [ [3; 0; 0]; [0; 3; 0]; [0; 0; 3]; ] in Matrix.mult_to_int (Matrix.mult_to_matrix (Matrix.mult_to_matrix a b) c) 2 |> Matrix.to_string |> printf "%s\n"
Заключение
Результат прошёл проверку задания, хотя решить задачу вручную на листе бумаги было бы гораздо быстрее, потому что достаточно было из третьей матрицы сделать единичную, а потом умножить матрицу b на 6. Но сейчас мне важно практиковаться в разработке на OCaml.
Записи процесса разработки в этот раз не будет, во-первых, разработка была не в один присест, а во-вторых, ничего интересного там нет.