summaryrefslogtreecommitdiffstats
path: root/kalzium/src/solver/datastruct.ml
blob: 541ed8cd93208d71bcb499b4dae4e1d05b1818c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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;;