unsigned int AtomicCompositionTable::CorrectStoichiometry(Reaction& reaction)
	{
		Eigen::VectorXd reactant_side(element_weights_list_.size());
		Eigen::VectorXd product_side(element_weights_list_.size());
		reactant_side.setZero();
		product_side.setZero();
		for (unsigned int i = 0; i<reaction.reactant_nu_indices().size(); i++)
		for (int j = 0; j<reactant_side.size(); j++)
			reactant_side(j) += element_coefficients_list_(reaction.reactant_nu_indices()[i], j)*reaction.reactant_nu()[i];
		for (unsigned int i = 0; i<reaction.product_nu_indices().size(); i++)
		for (int j = 0; j<product_side.size(); j++)
			product_side(j) += element_coefficients_list_(reaction.product_nu_indices()[i], j)*reaction.product_nu()[i];

		// Propose correction
		{
			// List of available elements
			std::vector<unsigned int>	indices_available_elements;
			for (int k = 0; k<reactant_side.size(); k++)
			if (reactant_side(k) > 0.)
				indices_available_elements.push_back(k);

			unsigned int m = indices_available_elements.size();
			unsigned int n = reaction.product_nu_indices().size();

			if (m <= n)
			{
				Eigen::VectorXd	beta(m);
				for (unsigned int k = 0; k < m; k++)
				{
					unsigned int j = indices_available_elements[k];
					beta(k) = reactant_side(j) - product_side(j);
				}

				Eigen::MatrixXd nu(m, n);
				for (unsigned int i = 0; i<reaction.product_nu_indices().size(); i++)
				for (unsigned int k = 0; k < m; k++)
				{
					unsigned int j = indices_available_elements[k];
					nu(k, i) = element_coefficients_list_(reaction.product_nu_indices()[i], j);
				}

				Eigen::VectorXd delta(n);
				if (m == n)
					delta = nu.fullPivLu().solve(beta);
				else
					delta = nu.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(beta);

				for (unsigned int i = 0; i < reaction.product_nu_indices().size(); i++)
				{
					const double new_coefficient = reaction.product_nu()[i] + delta(i);
					reaction.set_product_nu(i, new_coefficient);
				}

				return 1;
			}
			else
			{
				return 0;
			}
		}
	}