0

I am attempting to develop a Matlab program to balance chemical equations. I am able to balance them via solving a system of linear equations. Currently my output is a column vector with the coefficients.

My problem is that I need to return the smallest integer values of these coefficients. For example, if [10, 20, 30] was returned. I want [1, 2, 3] to be returned.

What is the best way to accomplish this?

I want this program to be fully autonomous once it is fed a matrix with the linear system. Thus I can not play around with the values, I need to automate this from the code. Thanks!

% Chemical Equation in Matrix Form
Chem = [1 0 0 -1 0 0 0; 1 0 1 0 0 -3 0; 0 2 0 0 -1 0 0; 0 10 0 0 0 -1 0; 0 35 4 -4 0 12 1; 0 0 2 -1 -3 0 2]

%set x4 = 1 then Chem(:, 4) = b and 
b = Chem(:, 4);     % Arbitrarily set x4 = 1 and set its column equal to b
Chem(:,4) = []      % Delete the x4 column from Chem and shift over
g = 1;              % Initialize variable for LCM 
x = Chem\b          % This is equivalent to the reduced row echelon form of 
                    % Chem | b

% Below is my sad attempt at factoring the values, I divide by the smallest decimal to raise all the values to numbers greater than or equal to 1
for n = 1:numel(x)
   g = x(n)*g
    M = -min(abs(x))
    y = x./M
end


I want code that will take some vector with coefficients, and return an equivalent coefficient vector with the lowest possible integer coefficients. Thanks!
Joshua
  • 177
  • 3
  • 3
  • 14
  • What is the meaning of "return the smallest integer values of these coefficients"? The smallest value of [10, 20, 30] should be 10. – Chan Oct 17 '19 at 01:32
  • When balancing chemical equations, the goal is to find the right "combination" of molecules on each side of the reaction that yields the right proportions. Say you are given CO2 + H2O → C6H12O6 + O2. One needs to find the lowest integer coefficients that make this equation true. In this case, the answer would be: 6 CO2 + 6 H2O → C6H12O6 + 6 O2. Referring to my example of [10, 20, 30], we could think of it as 10x + 20y + 30z = 0, where I want the smallest integer coefficients possible that make the equation true. I am free to divide them, so in this case my answer would be x + 2y + 3z =0 – Joshua Oct 17 '19 at 02:55
  • It seems to me that you are doing somethings like integer programming. You may take a look on https://www.mathworks.com/discovery/integer-programming.html. – Chan Oct 17 '19 at 03:05
  • Thanks for the resource, it seems this may require the Optimization Toolbox, which I do not have access to... – Joshua Oct 17 '19 at 03:53
  • I will look into it more and post a comment either way – Joshua Oct 17 '19 at 03:56
  • 1
    After you get an integer vector as result, you need to compute the GCD of the entries and divide all entries by it. Either matlab has such a function, or you have to implement a vector Euclidean algorithm reducing the vector elements by the smallest non-zero component (of course not reducing this component) until only one non-zero component is left over. – Lutz Lehmann Oct 17 '19 at 09:26
  • @RodrigodeAzevedo You are correct, sorry I am new to stack overflow and wasn't sure where to post the question, since I thought there could be a built-in function on matlab for this. – Joshua Oct 18 '19 at 20:37
  • @LutzL Thank you! I was able to do this with the built-in lcm (least common multiple) function in Matlab. – Joshua Oct 18 '19 at 20:39

1 Answers1

0

I was able to find a solution without using integer programming. I converted the non-integer values to rational expressions, and used a built-in matlab function to extract the denominator of each of these expressions. I then used a built in matlab function to find the least common multiples of these values. Finally, I multiplied the least common multiple by the matrix to find my answer coefficients.

    % Chemical Equation in Matrix Form
clear, clc
% Enter chemical equation as a linear system in matrix form as Chem
Chem = [1 0 0 -1 0 0 0; 1 0 1 0 0 -3 0; 0 2 0 0 -1 0 0; 0 10 0 0 0 -1 0; 0 35 4 -4 0 -12 -1; 0 0 2 -1 -3 0 -2];
% row reduce the system
C = rref(Chem);
% parametrize the system by setting the last variable xend (e.g. x7) = 1
x = [C(:,end);1];
% extract numerator and denominator from the rational expressions of these
% values
[N,D] = rat(x);

% take the least common multiple of the first pair, set this to the
% variable least
least = lcm(D(1),D(2));

% loop through taking the lcm of the previous values with the next value
% through x
for n = 3:numel(x)
  least = lcm(least,D(n));
end

% give answer as column vector with the coefficients (now factored to their
% lowest possible integers
coeff = abs(least.*x)
Joshua
  • 177
  • 3
  • 3
  • 14