В настоящее время я работаю над проектом, который предусматривает решение систем N уравнений с N неизвестными методом Ньютона. Есть класс "система уравнений":
public class EquationsSystem
{
/// <summary>
/// Функции, определяющие внешний вид уравнений системы. Каждое уравнение имеет вид F(x1,x2,...xN) = 0.
/// </summary>
public List<Func<double[], double[], double>> EquationFunctions { get; set; }
/// <summary>
/// Коэффициенты в уравнениях системы.
/// </summary>
public List<double[]> EquationsCoefficients { get; set; }
}
о ходу дела столкнулся с необходимостью решать системы из однотипных уравнений. Вот так, к примеру, выглядит сама функция, определяющая внешний вид уравнения:
static double EquationFunction(double[] x, double[] beta, int inxX)
{
double equationValue = 0.0;
int qVars= x.Length;
equationValue = beta[0] + beta[1] * x[inxX] + (beta[2] / (qVars-1)) * (x.Sum() - x[inxX]);
return equationValue;
}
А вот так выглядит фрагмент функции, где создается система уравнений:
static EquationsSystem CreateEquationsSystem(List<double[]> lstCoeffsInEquations)
{
int qEquations = lstCoeffsInEquations.Count;
int qCoeffs = lstCoeffsInEquations[0].Length;
EquationsSystem system = new EquationsSystem()
{
EquationFunctions = new List<Func<double[], double[], double>>(),
EquationsCoefficients = new List<double[]>(),
};
for (int i = 0; i < qEquations; i++)
{
system.EquationFunctions.Add(new Func<double[], double[], double>((x, beta) =>
EquationFunction(x, beta, i));
}
for (int i = 0; i < qEquations; i++)
{
system.EquationsCoefficients.Add(new double[qCoeffs]);
for (int j = 0; j < qCoeffs; j++)
{
system.EquationsCoefficients[i][j] = lstCoeffsInEquations[i][j];
}
}
return system;
}
В системе 4 уравнения, каждое из которых описывается функцией вроде приведенной выше.
При самом процессе создания системы сложностей не возникает. Но в момент, когда надо выполнить численное дифференцирование этих функций (для матрицы первых производных, которая строится на каждой итерации решения), программа впадает в ересь. Вот функция, которая выполняет вычисление производной:
public static double GetDerivative(Func<double[], double[], double> function, double[] variables, int inxVariable, double[] coefficients, double eps)
{
...
//Остальная часть не важна
double f = function(variables, coefficients);
...
}
На этом самом месте программа пытается вычислить значение функции и выдает ошибку IndexOutOfRangeException. Судя по данным в панели Call Stack, она снова прыгает в функцию CreateEquationsSystem() вот на это место:
...
for (int i = 0; i < qEquations; i++)
{
system.EquationFunctions.Add(new Func<double[], double[], double>((x, beta) =>
EquationFunction(x, beta, i));
}
...
,
потом в функцию EquationFunction():
static double EquationFunction(double[] x, double[] beta, int inxX)
{
double equationValue = 0.0;
int qVars= x.Length;
equationValue = beta[0] + beta[1] * x[inxX] + (beta[2] / (qVars-1)) * (x.Sum() - x[inxX]);
return equationValue;
}
и выдает ошибку там. Учитывая, что у меня 4 уравнения, inxX по всем расчетам должен изменяться от 0 до 3 и никак иначе. Но программа считает, что в этот момент inxX там равен 4 и по этому поводу посылает меня лесом.
Соответственно, 2 вопроса:
- как так получилось?
- как решить проблему? Ведь уравнений может быть на самом деле сколько угодно, не добавлять же каждое вручную по отдельности.