Test change - can I push OK?
[kdeedu-porting.git] / kalzium / src / solver / datastruct.ml
blob541ed8cd93208d71bcb499b4dae4e1d05b1818c7
1 (***************************************************************************
2 * Copyright (C) 2004 by Thomas Nagy *
3 * tnagy2^8@yahoo.fr *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************)
21 open List;;
22 open Chemset;;
23 open Hashtbl;;
24 open Array;;
26 class eqtable =
27 object (self)
29 (* columns : vars + formula | lines : chemical elements *)
30 val mutable numtbl = Array.make_matrix 0 0 0
31 val mutable strtbl = Array.make 0 ""
32 val mutable vartbl = Array.make 0 ""
33 val mutable soltbl = Array.make 0 0
34 val mutable m_solved = false
35 val mutable m_middle = 0
37 (* val mutable (table:int array array) = [||] *)
39 (* lines : i : chem element *)
40 (* columns : vars j *)
41 method getsize_i () = Array.length numtbl
42 method getsize_j () = if (self#getsize_i () > 0) then Array.length numtbl.(0) else 0
44 method getline j = numtbl.(j)
46 method getformula k = strtbl.(k)
47 method getvar k = vartbl.(k)
48 method getsol k = soltbl.(k)
50 method setsol k v = soltbl.(k) <- v
51 method isSolved () = m_solved
53 method get_eq_sol () =
54 let str = ref "" in
55 for j=0 to (self#getsize_j () -1) do
56 if (j == m_middle) then str := (!str)^" -&gt; "
57 else if (j>0 && j<self#getsize_j ()) then str := (!str)^" + ";
59 str := (!str)^"<b>"^string_of_int(self#getsol j)^"</b> "^(self#getformula j);
60 done;
61 !str
63 method get_eq_orig () =
64 let str = ref "" in
65 for j=0 to (self#getsize_j () -1) do
66 if (j == m_middle) then str := (!str)^" -&gt; "
67 else if (j>0 && j<self#getsize_j ()) then str := (!str)^" + ";
69 str := (!str)^"<b>"^(self#getvar j)^"</b> "^(self#getformula j);
70 done;
71 !str
73 method private init i j = numtbl <- Array.make_matrix i j 0;
74 strtbl <- Array.make j "";
75 vartbl <- Array.make j "";
76 soltbl <- Array.make j 0
78 method clear () =
79 self#init 0 0;
81 method print_all () =
82 Printf.printf "--- start print_all ---\n";
83 for i = 0 to (self#getsize_i ())-1 do
84 for j = 0 to (self#getsize_j ())-1 do
85 Printf.printf "%d " (numtbl.(i).(j));
86 done;
87 Printf.printf "\n";
88 done;
89 Printf.printf "--- end print_all ---\n";
90 flush_all ()
92 (* build the matrix to solve *)
93 method build (lst:listitems) =
94 let nb_symbols = ref 0 in
95 let item_array = Array.of_list lst in
96 let record:(string, int) Hashtbl.t = Hashtbl.create 10 in
97 let nb_items = ref (Array.length item_array) in
98 for i=0 to !nb_items-1 do
99 Hashtbl.iter (fun sym _ ->
100 (* take all chemical elements but simplify ions (+ or -) into + *)
101 let symprocessed = if String.contains sym '+' || String.contains sym '-'
102 then "+" else sym in
104 if not (Hashtbl.mem record symprocessed) then begin
105 Hashtbl.add record symprocessed !nb_symbols;
106 nb_symbols := !nb_symbols+1
108 ) item_array.(i).itbl.hashtbl
109 done;
111 (* initialize the matrix *)
112 self#init (!nb_symbols) (!nb_items);
114 (* process each atom*)
115 for i=0 to !nb_items-1 do
116 (* find the middle (->) - nothing to do with the others things in this loop *)
117 if (item_array.(i).sign<0 && i>0) then (if (item_array.(i-1).sign>0) then m_middle<-i);
119 (* store the molecule formula *)
120 vartbl.(i) <- item_array.(i).ikey;
121 strtbl.(i) <- item_array.(i).itbl.formula;
123 (* for each molecule, process the atoms *)
124 Hashtbl.iter (fun sym qte ->
126 if String.contains sym '+' || String.contains sym '-' then begin
127 (* it is an electric charge *)
128 let chargesign = if String.contains sym '-' then -1 else 1 in
129 let line_idx = (Hashtbl.find record "+") in
130 numtbl.(line_idx).(i) <- qte * item_array.(i).sign * chargesign
132 else begin
133 (* check if the atom is already there *)
134 let line_idx = (Hashtbl.find record sym) in
135 numtbl.(line_idx).(i) <- (qte * item_array.(i).sign)
137 ) item_array.(i).itbl.hashtbl
138 done
140 end;;