(*************************************************************************** * 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"^string_of_int(self#getsol j)^" "^(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#getvar j)^" "^(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;;