2016-08-17 12 views
1

私はmultiplication of two matrixを計算する簡単なプログラムを書いています。ocamlに配列の値を保存できません

(* matrix multiplication *) 
let multiply_row_per_col (m1 : int array array) (m2 : int array array) = 
    (* create matrix *) 
    let nrows = get_num_rows m1 in 
    let ncols = get_num_rows m2 in 
    let matrix = create_matrix nrows ncols in 
    (* evaluation *) 
    for i = 0 to nrows - 1 do 
     for j = 0 to ncols - 1 do 
      let value = sum_row_col (get_row m1 i) (get_col m2 j) in 
      Printf.printf "%i,%i -> %i " i j value; 
      matrix.(i).(j) <- value; 
      Printf.printf "%i\n" matrix.(i).(j); 
     done; 
    done; 
    (* return value *) 
    matrix 
;; 

しかし、正しく動作しません。行列の最後の行は正しいもので、他のすべての行には最後の行の値が含まれています。

utop # matrix;; 
- : int array array = [|[|1; 2; 3|]; [|4; 5; 6|]; [|7; 8; 9|]|] 
utop # multiply_row_per_col matrix matrix ;; 
0,0 -> 30 30 
0,1 -> 36 36 
0,2 -> 42 42 
1,0 -> 66 66 
1,1 -> 81 81 
1,2 -> 96 96 
2,0 -> 102 102 
2,1 -> 126 126 
2,2 -> 150 150 
- : int array array = 
[|[|102; 126; 150|]; [|102; 126; 150|]; [|102; 126; 150|]|] 

正しい結果が次のようになります。Correct result あなたが見ることができるように、単一の値が正しいですが、私は、マトリックスでそれらを保存することはできません。あなたはなにか考えはありますか?

はここで、他のライブラリが(どちらもコアも電池)を使用されていないコードとutopで実行いくつかのテストです:

(* 3x3 matrix *) 
let matrix = [| 
    [| 1; 2; 3|]; 
    [| 4; 5; 6|]; 
    [| 7; 8; 9|] 
|];; 

(* return the cell of the matrix at [i][j] position *) 
let get_cell (matrix : int array array) (row : int) (col : int) : int = 
    Array.get (Array.get matrix row) col 
;; 

(* return the n-th row *) 
let get_row (matrix : int array array) (n : int) : int array = 
    Array.get matrix n 
;; 

(* return the n-th col of the matrix *) 
let get_col (matrix : int array array) (n : int) : int array = 
    Array.map (fun row -> Array.get row n) matrix 
;; 

(* return the number of rows of a matrix *) 
let get_num_rows matrix = 
    Array.length matrix 
;; 

(* return the number of cols of a matrix *) 
let get_num_cols matrix = 
    Array.length (Array.get matrix 0) 
;; 

(* create NxM matrix *) 
let create_matrix rows cols = 
    Array.make rows (Array.make cols 0) 
;; 

(* multiply each position of row and col, then sum all of them *) 
let sum_row_col (row : int array) (col : int array) : int = 
    Array.fold_left (+) 0 (Array.map2 (*) row col) 
;; 

(* matrix multiplication *) 
let multiply_row_per_col (m1 : int array array) (m2 : int array array) = 
    (* create matrix *) 
    let nrows = get_num_rows m1 in 
    let ncols = get_num_rows m2 in 
    let matrix = create_matrix nrows ncols in 
    (* evaluation *) 
    for i = 0 to nrows - 1 do 
     for j = 0 to ncols - 1 do 
      let value = sum_row_col (get_row m1 i) (get_col m2 j) in 
      Printf.printf "%i,%i -> %i " i j value; 
      matrix.(i).(j) <- value; 
      Printf.printf "%i\n" matrix.(i).(j); 
     done; 
    done; 
    (* return value *) 
    matrix 
;; 

(* 
    utop # #use "Matrix_multiplication.ml";; 
    val matrix : int array array = [|[|1; 2; 3|]; [|4; 5; 6|]; [|7; 8; 9|]|] 
    val get_cell : int array array -> int -> int -> int = <fun> 
    val get_row : int array array -> int -> int array = <fun> 
    val get_col : int array array -> int -> int array = <fun> 
    val get_num_rows : 'a array -> int = <fun> 
    val get_num_cols : 'a array array -> int = <fun> 
    val create_matrix : int -> int -> int array array = <fun> 
    val sum_row_col : int array -> int array -> int = <fun> 
    val multiply_row_per_col : 
     int array array -> int array array -> int array array = <fun> 
    ─(14:54:52)─< command 42 >─────────────────────────────────────────────────────────────────────────────{ counter: 0 }─ 
    utop # get_cell matrix 0 0;; 
    - : int = 1 
    ─(14:55:12)─< command 43 >─────────────────────────────────────────────────────────────────────────────{ counter: 0 }─ 
    utop # get_cell matrix 2 2;; 
    - : int = 9 
    ─(14:56:52)─< command 45 >─────────────────────────────────────────────────────────────────────────────{ counter: 0 }─ 
    utop # get_row matrix 1;; 
    - : int array = [|4; 5; 6|] 
    ─(14:57:02)─< command 46 >─────────────────────────────────────────────────────────────────────────────{ counter: 0 }─ 
    utop # get_col matrix 1;; 
    - : int array = [|2; 5; 8|] 
    ─(14:57:08)─< command 47 >─────────────────────────────────────────────────────────────────────────────{ counter: 0 }─ 
    utop # create_matrix 3 3;; 
    - : int array array = [|[|0; 0; 0|]; [|0; 0; 0|]; [|0; 0; 0|]|] 
    ─(14:57:19)─< command 48 >─────────────────────────────────────────────────────────────────────────────{ counter: 0 }─ 
    utop # sum_row_col [|1;2;3|] [|1;2;3|] ;; 
    - : int = 14 
    ─(14:57:31)─< command 49 >─────────────────────────────────────────────────────────────────────────────{ counter: 0 }─ 
    utop # sum_row_col [|1;2;3|] [|1;4;7|] ;; 
    - : int = 30 
    ─(14:57:51)─< command 50 >─────────────────────────────────────────────────────────────────────────────{ counter: 0 }─ 
    utop # multiply_row_per_col matrix matrix ;; 
    0,0 -> 30 30 
    0,1 -> 36 36 
    0,2 -> 42 42 
    1,0 -> 66 66 
    1,1 -> 81 81 
    1,2 -> 96 96 
    2,0 -> 102 102 
    2,1 -> 126 126 
    2,2 -> 150 150 
    - : int array array = 
    [|[|102; 126; 150|]; [|102; 126; 150|]; [|102; 126; 150|]|] 
*) 

答えて

3

問題は、あなたのcreate_matrix機能です。現在のところ、という1つのアレイが作成され、各行に同じ配列が使用されています。つまり、mat.(2).(2)への書き込みは、mat.(1).(2)での書き込みと同じです。

stdlibには、その目的のために作られた関数があります:Array.make_matrix、それを使用します。 ;)

+0

これは機能します! 'Array.make len 0'が要素0をコピーする理由はありますが、' Array.make len array'は実際の配列の代わりに配列の参照をコピーしますか? – incud

+1

@Ignus:Array.makeについては、[documentation](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Array.html)を参照してください。具体的には、 'xが変更可能であれば、それは配列のすべての要素間で共有される。 – Marth

関連する問題