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.
142 lines
5.3 KiB
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)^" -> "
|
|
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)^" -> "
|
|
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;;
|
|
|