Warning, /education/kalzium/src/solver/datastruct.ml is written in an unsupported language. File is not indexed.

0001 (*
0002     SPDX-FileCopyrightText: 2004 Thomas Nagy <tnagy2^8@yahoo.fr>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 *)
0006 
0007 open List;;
0008 open Chemset;;
0009 open Hashtbl;;
0010 open Array;;
0011 
0012 class eqtable =
0013 object (self)
0014 
0015 (* columns : vars + formula | lines : chemical elements *)
0016 val mutable numtbl = Array.make_matrix 0 0 0
0017 val mutable strtbl = Array.make 0 ""
0018 val mutable vartbl = Array.make 0 ""
0019 val mutable soltbl = Array.make 0 0
0020 val mutable m_solved = false
0021 val mutable m_middle = 0
0022     
0023 (* val mutable (table:int array array) = [||] *)
0024 
0025 (* lines : i : chem element *)
0026 (* columns : vars j *)
0027 method getsize_i () = Array.length numtbl
0028 method getsize_j () = if (self#getsize_i () > 0) then Array.length numtbl.(0) else 0
0029 
0030 method getline j = numtbl.(j)
0031 
0032 method getformula k = strtbl.(k)
0033 method getvar k = vartbl.(k)
0034 method getsol k = soltbl.(k)
0035 
0036 method setsol k v = soltbl.(k) <- v
0037 method isSolved () = m_solved
0038 
0039 method get_eq_sol () =
0040     let str = ref "" in
0041     for j=0 to (self#getsize_j () -1) do
0042         if (j == m_middle) then str := (!str)^" -&gt; "
0043         else if (j>0 && j<self#getsize_j ()) then str := (!str)^" + ";
0044             
0045         str := (!str)^"<b>"^string_of_int(self#getsol j)^"</b> "^(self#getformula j);
0046     done;
0047     !str
0048 
0049 method get_eq_orig () =
0050     let str = ref "" in
0051     for j=0 to (self#getsize_j () -1) do
0052         if (j == m_middle) then str := (!str)^" -&gt; "
0053         else if (j>0 && j<self#getsize_j ()) then str := (!str)^" + ";
0054             
0055         str := (!str)^"<b>"^(self#getvar j)^"</b> "^(self#getformula j);
0056     done;
0057     !str
0058     
0059 method private init i j = numtbl <- Array.make_matrix i j 0;
0060     strtbl <- Array.make j "";
0061     vartbl <- Array.make j "";
0062     soltbl <- Array.make j 0
0063     
0064 method clear () =
0065     self#init 0 0;
0066     
0067 method print_all () =
0068     Printf.printf "--- start print_all ---\n";
0069     for i = 0 to (self#getsize_i ())-1 do
0070         for j = 0 to (self#getsize_j ())-1 do
0071             Printf.printf "%d " (numtbl.(i).(j));
0072         done;
0073         Printf.printf "\n";
0074     done;
0075     Printf.printf "--- end print_all ---\n";
0076     flush_all ()
0077                       
0078 (* build the matrix to solve *)
0079 method build (lst:listitems) = 
0080     let nb_symbols = ref 0 in
0081     let item_array = Array.of_list lst in
0082     let record:(string, int) Hashtbl.t = Hashtbl.create 10 in
0083     let nb_items = ref (Array.length item_array) in
0084     for i=0 to !nb_items-1 do
0085         Hashtbl.iter (fun sym _ ->
0086             (* take all chemical elements but simplify ions (+ or -) into + *)
0087             let symprocessed = if String.contains sym '+' || String.contains sym '-'
0088                 then "+" else sym in
0089             
0090             if not (Hashtbl.mem record symprocessed) then begin
0091                 Hashtbl.add record symprocessed !nb_symbols;
0092                 nb_symbols := !nb_symbols+1
0093             end
0094             ) item_array.(i).itbl.hashtbl
0095     done;
0096     
0097     (* initialize the matrix *)
0098     self#init (!nb_symbols) (!nb_items);
0099     
0100     (* process each atom*)
0101     for i=0 to !nb_items-1 do
0102         (* find the middle (->) - nothing to do with the others things in this loop *)
0103         if (item_array.(i).sign<0 && i>0) then (if (item_array.(i-1).sign>0) then m_middle<-i);
0104         
0105         (* store the molecule formula *)
0106         vartbl.(i) <- item_array.(i).ikey;
0107         strtbl.(i) <- item_array.(i).itbl.formula;
0108 
0109         (* for each molecule, process the atoms *)
0110         Hashtbl.iter (fun sym qte -> 
0111 
0112             if String.contains sym '+' || String.contains sym '-' then begin
0113                 (* it is an electric charge *)
0114                 let chargesign = if String.contains sym '-' then -1 else 1 in
0115                 let line_idx = (Hashtbl.find record "+") in
0116                 numtbl.(line_idx).(i) <- qte * item_array.(i).sign * chargesign
0117             end
0118             else begin
0119                 (* check if the atom is already there *)
0120                 let line_idx = (Hashtbl.find record sym) in
0121                 numtbl.(line_idx).(i) <- (qte * item_array.(i).sign)
0122             end
0123             ) item_array.(i).itbl.hashtbl
0124     done
0125 
0126 end;;