You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeedu/kalzium/src/solver/datastruct.ml

142 lines
5.3 KiB

(***************************************************************************
* 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;;