summaryrefslogtreecommitdiffstats
path: root/kalzium/src/solver/datastruct.ml
diff options
context:
space:
mode:
Diffstat (limited to 'kalzium/src/solver/datastruct.ml')
-rw-r--r--kalzium/src/solver/datastruct.ml141
1 files changed, 141 insertions, 0 deletions
diff --git a/kalzium/src/solver/datastruct.ml b/kalzium/src/solver/datastruct.ml
new file mode 100644
index 00000000..541ed8cd
--- /dev/null
+++ b/kalzium/src/solver/datastruct.ml
@@ -0,0 +1,141 @@
+(***************************************************************************
+ * Copyright (C) 2004 by Thomas Nagy *
+ * tnagy2^8@yahoo.fr *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************)
+
+open List;;
+open Chemset;;
+open Hashtbl;;
+open Array;;
+
+class eqtable =
+object (self)
+
+(* columns : vars + formula | lines : chemical elements *)
+val mutable numtbl = Array.make_matrix 0 0 0
+val mutable strtbl = Array.make 0 ""
+val mutable vartbl = Array.make 0 ""
+val mutable soltbl = Array.make 0 0
+val mutable m_solved = false
+val mutable m_middle = 0
+
+(* val mutable (table:int array array) = [||] *)
+
+(* lines : i : chem element *)
+(* columns : vars j *)
+method getsize_i () = Array.length numtbl
+method getsize_j () = if (self#getsize_i () > 0) then Array.length numtbl.(0) else 0
+
+method getline j = numtbl.(j)
+
+method getformula k = strtbl.(k)
+method getvar k = vartbl.(k)
+method getsol k = soltbl.(k)
+
+method setsol k v = soltbl.(k) <- v
+method isSolved () = m_solved
+
+method get_eq_sol () =
+ let str = ref "" in
+ for j=0 to (self#getsize_j () -1) do
+ if (j == m_middle) then str := (!str)^" -&gt; "
+ else if (j>0 && j<self#getsize_j ()) then str := (!str)^" + ";
+
+ str := (!str)^"<b>"^string_of_int(self#getsol j)^"</b> "^(self#getformula j);
+ done;
+ !str
+
+method get_eq_orig () =
+ let str = ref "" in
+ for j=0 to (self#getsize_j () -1) do
+ if (j == m_middle) then str := (!str)^" -&gt; "
+ else if (j>0 && j<self#getsize_j ()) then str := (!str)^" + ";
+
+ str := (!str)^"<b>"^(self#getvar j)^"</b> "^(self#getformula j);
+ done;
+ !str
+
+method private init i j = numtbl <- Array.make_matrix i j 0;
+ strtbl <- Array.make j "";
+ vartbl <- Array.make j "";
+ soltbl <- Array.make j 0
+
+method clear () =
+ self#init 0 0;
+
+method print_all () =
+ Printf.printf "--- start print_all ---\n";
+ for i = 0 to (self#getsize_i ())-1 do
+ for j = 0 to (self#getsize_j ())-1 do
+ Printf.printf "%d " (numtbl.(i).(j));
+ done;
+ Printf.printf "\n";
+ done;
+ Printf.printf "--- end print_all ---\n";
+ flush_all ()
+
+(* build the matrix to solve *)
+method build (lst:listitems) =
+ let nb_symbols = ref 0 in
+ let item_array = Array.of_list lst in
+ let record:(string, int) Hashtbl.t = Hashtbl.create 10 in
+ let nb_items = ref (Array.length item_array) in
+ for i=0 to !nb_items-1 do
+ Hashtbl.iter (fun sym _ ->
+ (* take all chemical elements but simplify ions (+ or -) into + *)
+ let symprocessed = if String.contains sym '+' || String.contains sym '-'
+ then "+" else sym in
+
+ if not (Hashtbl.mem record symprocessed) then begin
+ Hashtbl.add record symprocessed !nb_symbols;
+ nb_symbols := !nb_symbols+1
+ end
+ ) item_array.(i).itbl.hashtbl
+ done;
+
+ (* initialize the matrix *)
+ self#init (!nb_symbols) (!nb_items);
+
+ (* process each atom*)
+ for i=0 to !nb_items-1 do
+ (* find the middle (->) - nothing to do with the others things in this loop *)
+ if (item_array.(i).sign<0 && i>0) then (if (item_array.(i-1).sign>0) then m_middle<-i);
+
+ (* store the molecule formula *)
+ vartbl.(i) <- item_array.(i).ikey;
+ strtbl.(i) <- item_array.(i).itbl.formula;
+
+ (* for each molecule, process the atoms *)
+ Hashtbl.iter (fun sym qte ->
+
+ if String.contains sym '+' || String.contains sym '-' then begin
+ (* it is an electric charge *)
+ let chargesign = if String.contains sym '-' then -1 else 1 in
+ let line_idx = (Hashtbl.find record "+") in
+ numtbl.(line_idx).(i) <- qte * item_array.(i).sign * chargesign
+ end
+ else begin
+ (* check if the atom is already there *)
+ let line_idx = (Hashtbl.find record sym) in
+ numtbl.(line_idx).(i) <- (qte * item_array.(i).sign)
+ end
+ ) item_array.(i).itbl.hashtbl
+ done
+
+end;;
+