我一直致力于为C#dll实现Jacobi方法,我将扩展,因为我在学校学习了更多可以在代码中实现的数学概念。我一直用3X3矩阵和带3个值的Vector测试它。
我一直在测试的输入如下:
double[][] m = new double[3][];
m[0] = new double[3];
m[1] = new double[3];
m[2] = new double[3];
m[0][0] = 10;
m[0][1] = -4;
m[0][2] = -2;
m[1][0] = -4;
m[1][1] = 10;
m[1][2] = -4;
m[2][0] = -6;
m[2][1] = -2;
m[2][2] = 12;
Matrix inputMatrix = new Matrix(m);
Vector inputVector = new Vector(new double[] { 2, 3, 1 });
LinearSolvers.JacobiMethod(inputMatrix, inputVector, 80);
函数调用结束时的80是迭代次数。 我的功能是:
public static Vector JacobiMethod(Matrix inputMatrix, Vector expectedOutcome, int iterations)
{
Vector solvedVector = new Vector(new double[] { 0, 0, 0});
for(int p = 0; p < iterations; p++)
{
for (int i = 0; i < inputMatrix.RowCount; i++)
{
for (int j = 0; j < inputMatrix.ColumnCount; j++)
{
if (j != i)
solvedVector.vectorValues[i] += solvedVector.vectorValues[i] - (inputMatrix._matrix[i][j] * expectedOutcome.vectorValues[j]);
}
solvedVector.vectorValues[i] /= inputMatrix._matrix[i][i];
}
expectedOutcome = solvedVector;
Console.WriteLine("Step: " + p + "\n" + expectedOutcome.ToString());
}
return solvedVector;
}
我认为我已经正确地实现了该方法,但是我得到了错误的输出值。
编辑:1
根据https://www.easycalculation.com/operations-research/gaussjacobi.php的预期值应为:
Value of x0 = 0.597
Value of x1 = 0.741
Value of x2 = 0.505
Matrix类:
public class Matrix
{
public double[][] _matrix { get; protected set; }
public int RowCount { get; private set; }
public int ColumnCount { get; private set; }
public bool IsDiagonallyDominant { get; private set; }
public Matrix() { }
public Matrix(double[][] matrix)
{
_matrix = matrix;
RowCount = matrix.Length;
ColumnCount = matrix[0].Length;
CheckDiagonalDominance();
}
private void CheckDiagonalDominance()
{
}
/// <summary>
/// Returns the product of two matrices.
/// </summary>
public static Matrix MultiplicationWithMatrix(Matrix matrix1, Matrix matrix2)
{
double[][] multipliedMatrix = new double[matrix1.RowCount][];
//Check the needed requirements for a matrix multiplication.
if (matrix1.ColumnCount == matrix2.RowCount)
{
//Set up the new multiplied matrix.
for (int i = 0; i < multipliedMatrix.Length; i++)
multipliedMatrix[i] = new double[matrix2.ColumnCount];
for (int i = 0; i < matrix1.RowCount; i++)
{
for(int j = 0; j < matrix2.ColumnCount; j++)
{
for(int k = 0; k < matrix2.ColumnCount-1; k++)
{
multipliedMatrix[i][j] += matrix1._matrix[i][k] * matrix2._matrix[k][j];
}
}
}
}
return new Matrix(multipliedMatrix);
}
/// <summary>
/// Returns the product of a matrix and a scalar.
/// </summary>
public static Matrix MultiplicationWithScalar(Matrix matrix, double scalar)
{
//TODO: Multiplication with a scalar.
return new Matrix(new double[4][]);
}
/// <summary>
/// Returns the product of a matrix and a 3D vector.
/// </summary>
public static Vector3D MultiplicationWithVector3D(Matrix matrix, Vector3D vector)
{
//Check the needed requirements for a multiplication.
if(matrix._matrix.Length == 3)
{
//Perform the multiplication and return a new 3D vector, since that is the result.
return new Vector3D(
matrix._matrix[0][0] * vector.X + matrix._matrix[0][1] * vector.Y + matrix._matrix[0][2] * vector.Z,
matrix._matrix[1][0] * vector.X + matrix._matrix[1][1] * vector.Y + matrix._matrix[1][2] * vector.Z,
matrix._matrix[2][0] * vector.X + matrix._matrix[2][1] * vector.Y + matrix._matrix[2][2] * vector.Z);
}
return new Vector3D(0, 0, 0);
}
/// <summary>
/// Returns the product of a matrix and a 4D vector.
/// </summary>
public static Vector4D MultiplicationWithVector(Matrix matrix, Vector4D vector)
{
//Check the needed requirements for a multiplication.
if (matrix._matrix.Length == 4)
{
//Perform the multiplication and return a new 4D vector, since that is the result.
return new Vector4D(
matrix._matrix[0][0] * vector.X + matrix._matrix[0][1] * vector.Y + matrix._matrix[0][2] * vector.Z,
matrix._matrix[1][0] * vector.X + matrix._matrix[1][1] * vector.Y + matrix._matrix[1][2] * vector.Z,
matrix._matrix[2][0] * vector.X + matrix._matrix[2][1] * vector.Y + matrix._matrix[2][2] * vector.Z,
matrix._matrix[3][0] * vector.X + matrix._matrix[3][1] * vector.Y + matrix._matrix[3][2] * vector.Z);
}
return new Vector4D(0, 0, 0, 0);
}
public override string ToString()
{
string matrixAsString = "";
for (int i = 0; i < _matrix.Length; i++)
{
for(int j = 0; j < _matrix[i].Length; j++)
{
matrixAsString += _matrix[i][j] + "\t";
}
matrixAsString += "\n";
}
return matrixAsString;
}
}
和Vector类:
public class Vector
{
public double[] vectorValues;
public Vector(double[] values)
{
vectorValues = values;
}
/// <summary>
/// Returns the dot product of two vectors.
/// </summary>
public static double DotProduct(Vector vector1, Vector vector2)
{
double dotProduct = 0;
if (vector1.vectorValues.Length == vector2.vectorValues.Length)
{
for(int i = 0; i < vector1.vectorValues.Length; i++)
{
dotProduct += vector1.vectorValues[i] * vector2.vectorValues[i];
}
}
return dotProduct;
}
/// <summary>
/// Returns the directional vector between two vectors.
/// </summary>
public static Vector Subtract(Vector vector1, Vector vector2)
{
double[] subtractedValues = new double[vector1.vectorValues.Length];
for(int i = 0; i < vector1.vectorValues.Length; i++)
{
subtractedValues[i] = vector1.vectorValues[i] - vector2.vectorValues[i];
}
return new Vector(subtractedValues);
}
/// <summary>
/// Returns the sum of two vectors.
/// </summary>
public static Vector Add(Vector vector1, Vector vector2)
{
double[] addedValues = new double[vector1.vectorValues.Length];
for (int i = 0; i < vector1.vectorValues.Length; i++)
{
addedValues[i] = vector1.vectorValues[i] + vector2.vectorValues[i];
}
return new Vector(addedValues);
}
/// <summary>
/// Returns the length of a vector.
/// </summary>
public static double Magnitude(Vector vector)
{
double squaredValues = 0;
for (int i = 0; i < vector.vectorValues.Length; i++)
squaredValues += Math.Pow(vector.vectorValues[i], 2);
return Math.Sqrt(squaredValues);
}
/// <summary>
/// Returns the cross product of two vectors.
/// </summary>
public static void CrossProduct(Vector2D vector1, Vector2D vector2)
{
//TODO: Implement CrossProduct logic
}
public override string ToString()
{
string vectorAsString = "";
for (int i = 0; i < vectorValues.Length; i++)
vectorAsString += "|" + vectorValues[i] + "|\n";
return vectorAsString;
}
}
提前致谢!
答案 0 :(得分:1)
您的JacobiMethod
不正确。这是一个工作,我使用了Wikipedia page的算法。
public static Vector JacobiMethod(Matrix inputMatrix, Vector expectedOutcome, int iterations)
{
Vector solvedVector = new Vector(Enumerable.Repeat(0.0, expectedOutcome.vectorValues.Length).ToArray());
for(int p = 0; p < iterations; p++)
{
for (int i = 0; i < inputMatrix.RowCount; i++)
{
double sigma = 0;
for (int j = 0; j < inputMatrix.ColumnCount; j++)
{
if (j != i)
sigma += inputMatrix._matrix[i][j] * solvedVector.vectorValues[j];
}
solvedVector.vectorValues[i] = (expectedOutcome.vectorValues[i] - sigma) / inputMatrix._matrix[i][i];
}
Console.WriteLine("Step #" + p + ": " + String.Join(", ", solvedVector.vectorValues.Select(v => v.ToString()).ToArray()));
}
return solvedVector;
}
此外,我修改了方法,以便expectedOutcome
不会在其中进行更改,而solvedVector
现在是从新的零填充数组创建的。
请注意,您不会检查收敛条件并始终执行指定的迭代次数。对于10次迭代,我得到了以下结果
Step: 0
|0.2|
|0.38|
|0.246666666666667|
Step: 1
|0.401333333333333|
|0.5592|
|0.3772|
Step: 2
|0.49912|
|0.650528|
|0.441314666666667|
Step: 3
|0.548474133333333|
|0.69591552|
|0.47355632|
Step: 4
|0.573077472|
|0.7186535168|
|0.489647655466667|
Step: 5
|0.585390937813333|
|0.730015437312|
|0.497698041792|
Step: 6
|0.5915457832832|
|0.73569753003008|
|0.501722479979947|
Step: 7
|0.594623508008021|
|0.738538395195187|
|0.503734819869875|
Step: 8
|0.59616232205205|
|0.73995885676877|
|0.504740970487487|
Step: 9
|0.596931736805005|
|0.740669082916997|
|0.505244048888669|
答案 1 :(得分:0)
我正在看the Wikipedia page for the Jacobi method。它并不像我正在实施公式x^(k+1) = D^(-1) (b - R x^(k))
那样。你所拥有的似乎是x^(k+1) = D^(-1) (x^(k) - R b)
,虽然我无法确定。
我的建议是,您为程序变量提供与已发布公式中的名称相同的名称,以便更容易验证您是否正确实现了公式。第二个想法是使用诸如Octave之类的数字包来执行几个步骤,这样您就可以比较C#程序中的数字。在Octave和类似的包中,您可以执行矩阵运算,例如D^(-1)*(b - R*x)
。