在C#

时间:2018-11-25 17:22:22

标签: c# algorithm eigenvalue eigenvector

我正在尝试使用PCA为我的网格找到最佳的OOBB匹配框。为此,我需要特征向量,但是我有点迷失了如何在不使用庞大库的情况下计算它们。

我实现了一种算法,该算法在给定3x3矩阵的情况下计算三个特征值。最初的代码来自Wikipedia

private Vector3 CalculateEigenvalues(ref Matrix3 A)
{
    Vector3 val = new Vector3(0, 0, 0);

    float p1 = A.M12 * A.M12 + A.M13 * A.M13 + A.M23 * A.M23;
    if (p1 == 0)
    {
        val.X = A.M11;
        val.Y = A.M22;
        val.Z = A.M33;
    }
    else
    {
        float q = A.Trace / 3f;
        float p2 = (float)(Math.Pow(A.M11 - q, 2) + Math.Pow(A.M22 - q, 2) + Math.Pow(A.M33 - q, 2)) + 2 * p1;
        float p = (float)Math.Sqrt(p2 / 6);
        Matrix4 I = Matrix4.Identity;
        Matrix4.Mult(ref I, q, out Matrix4 tmp);
        Matrix4 tmp2 = Matrix4.Subtract(new Matrix4(A), tmp);
        Matrix4 B = Matrix4.Mult(tmp2, 1 / p);
        float r = new Matrix3(B).Determinant / 2;

        float phi = 0;
        if (r <= -1)
            phi = (float)Math.PI / 3;
        else if (r >= 1)
            phi = 0;
        else
            phi = (float)Math.Acos(r) / 3;
        val.X = q + 2 * p * (float)Math.Cos(phi);
        val.Z = q + 2 * p * (float)Math.Cos(phi + (2 * Math.PI / 3));
        val.Y = 3 * q - val.X - val.Z;
    }
    return val;
}

但是,Wikipedia文章中没有用于计算三个特征值的特征向量的代码。我试图理解该主题,但是我的数学技能非常有限。我将不得不在每个教程中用谷歌搜索第二个单词。

所以我的问题是:

如果我具有3x3矩阵和三个特征值,是否有任何简单的方法可以在不使用外部库的情况下计算相应的特征向量?

1 个答案:

答案 0 :(得分:1)

对于所有特征值具有相同的algebraic and geometric乘数(旋转矩阵就是这种情况)的情况,绝对简单的实现是这样的:

// Observe that the function doesn't use rZ,
// it is expected that it will become zero vector in triangular form
static Vector3 EigenVector(Vector3 rX, Vector3 rY, Vector3 rZ, float lambda)
{
    // Move RHS to LHS
    rX.X -= lambda;
    rY.Y -= lambda;
    // Transform to upper triangle
    rY -= rX * (rY.X / rX.X);
    // Backsubstitute
    var res = new Vector3(1f);
    res.Y = -rY.Z / rY.Y;
    res.X = -(rX.Y * res.Y + rX.Z * res.Z) / rX.X;
    return res;
}

// Case of eigenvalue with algebraic multiplicity two
static (Vector3, Vector3) EigenVector2(Vector3 rX, Vector3 rY, Vector3 rZ, float lambda)
{
    // Move RHS to LHS
    rX.X -= lambda;
    float x2 = rX.Y / rX.X;
    float x3 = rX.Z / rX.X;
    return (new Vector3(x2, 1, 0), new Vector3(x3, 0, 1));
}

static void Main(string[] args)
{
    var rX = new Vector3(1, -3, 3);
    var rY = new Vector3(3, -5, 3);
    var rZ = new Vector3(6, -6, 4);
    var e = EigenVector(rX, rY, rZ, 4);
    var e2 = EigenVector2(rX, rY, rZ, 2);

    System.Diagnostics.Debug.WriteLine(e.ToString());
    System.Diagnostics.Debug.WriteLine(e2.Item1.ToString());
    System.Diagnostics.Debug.WriteLine(e2.Item2.ToString());
}
  

<0.5,0.5,1>
  <3 1 0>
  <-3 0 1>

在现实生活中,需要进行大量错误检查。输入数据取自this paper