Exemple #1
0
        public void DetTest()
        {
            var matrix = new Matrix(new[]
            {
                new Vector(new[] { new Number(1), new Number(-2), new Number(3) }),
                new Vector(new[] { new Number(4), new Number(0), new Number(6) }),
                new Vector(new[] { new Number(-7), new Number(8), new Number(9) })
            });

            var det = matrix.Determinant();

            Assert.AreEqual(204, det);
        }
Exemple #2
0
        public void Simple()
        {
            var matrix = new Matrix(3, 3);

            // [ 3,  1,  8 ]
            // [ 2, -5,  4 ]
            // [-1,  6, -2 ]
            // Determinant = 14

            matrix[0, 0] = 3;
            matrix[0, 1] = 1;
            matrix[0, 2] = 8;

            matrix[1, 0] = 2;
            matrix[1, 1] = -5;
            matrix[1, 2] = 4;

            matrix[2, 0] = -1;
            matrix[2, 1] = 6;
            matrix[2, 2] = -2;

            Assert.AreEqual(14, matrix.Determinant(), 0.000000001);
        }
Exemple #3
0
        /// <summary>
        /// Evaluates the probability density function for the Wishart distribution.
        /// </summary>
        /// <param name="x">The matrix at which to evaluate the density at.</param>
        /// <exception cref="ArgumentOutOfRangeException">If the argument does not have the same dimensions as the scale matrix.</exception>
        /// <returns>the density at <paramref name="x"/>.</returns>
        public double Density(Matrix<double> x)
        {
            var p = _s.RowCount;

            if (x.RowCount != p || x.ColumnCount != p)
            {
                throw Matrix.DimensionsDontMatch<ArgumentOutOfRangeException>(x, _s, "x");
            }

            var dX = x.Determinant();
            var siX = _chol.Solve(x);

            // Compute the multivariate Gamma function.
            var gp = Math.Pow(Constants.Pi, p * (p - 1.0) / 4.0);
            for (var j = 1; j <= p; j++)
            {
                gp *= SpecialFunctions.Gamma((_nu + 1.0 - j) / 2.0);
            }

            return Math.Pow(dX, (_nu - p - 1.0) / 2.0)
                   * Math.Exp(-0.5 * siX.Trace())
                   / Math.Pow(2.0, _nu * p / 2.0)
                   / Math.Pow(_chol.Determinant, _nu / 2.0)
                   / gp;
        }
        public void Matrix_DeterminantCalculatedCorrectly()
        {
            var matrix = new Matrix(
                3, 2, 0, 1, 
                4, 0, 1, 2, 
                3, 0, 2, 1, 
                9, 2, 3, 1);

            var determinant = matrix.Determinant();

            TheResultingValue(determinant)
                .WithinDelta(0.1f).ShouldBe(24.0f);
        }
Exemple #5
0
        public void Determinant()
        {
            Matrix matrix = new Matrix(new double[][] { new double[] { 1.0, 2.0 }, new double[] { 3.0, 4.0 } });

            double result = matrix.Determinant();

            Assert.AreEqual((1.0 * 4.0) - (2.0 * 3.0), result);
        }
Exemple #6
0
        public void DeterminantRaiseException()
        {
            Matrix matrix = new Matrix(new double[][] { new double[] { 1.0, 2.0 }, new double[] { 3.0, 4.0 }, new double[] { 5.0, 6.0 } });

            try
            {
                matrix.Determinant();
                Assert.Fail();
            }
            catch (Exception ex)
            {
                Assert.IsInstanceOfType(ex, typeof(InvalidOperationException));
                Assert.AreEqual("Matrix is not square", ex.Message);
            }
        }
    /// <summary>
    /// Given the transform to be applied to an unknown rectangle, this method finds (in axis-aligned local space)
    /// the largest rectangle that, after transform, fits within <paramref name="localBounds"/>.
    /// Largest rectangle means rectangle of the greatest area in local space (although maximal area in local space
    /// implies maximal area in transform space).
    /// </summary>
    /// <param name="transform">Transformation matrix.</param>
    /// <param name="localBounds">The bounds in local space where the returned size fits when transformed
    /// via the given <paramref name="transform"/>.</param>
    /// <returns>The dimensions, in local space, of the maximal area rectangle found.</returns>
    private static SizeF FindMaxTransformedSize(Matrix transform, SizeF localBounds)
    {
      // X (width) and Y (height) constraints for axis-aligned bounding box in dest. space
      float xConstr = localBounds.Width;
      float yConstr = localBounds.Height;

      // Avoid doing math on an empty rect
      if (IsNear(xConstr, 0) || IsNear(yConstr, 0))
        return new SizeF(0, 0);

      bool xConstrInfinite = float.IsNaN(xConstr);
      bool yConstrInfinite = float.IsNaN(yConstr);

      if (xConstrInfinite && yConstrInfinite)
        return new SizeF(float.NaN, float.NaN);

      if (xConstrInfinite) // Assume square for one-dimensional constraint 
        xConstr = yConstr;
      else if (yConstrInfinite)
        yConstr = xConstr;

      // We only deal with nonsingular matrices here. The nonsingular matrix is the one
      // that has inverse (determinant != 0).
      if (transform.Determinant() == 0)
        return new SizeF(0, 0);

      float a = transform.M11;
      float b = transform.M12;
      float c = transform.M21;
      float d = transform.M22;

      // Result width and height (in child/local space)
      float w;
      float h;

      // Because we are dealing with nonsingular transform matrices, we have (b==0 || c==0) XOR (a==0 || d==0) 
      if (IsNear(b, 0) || IsNear(c, 0))
      { // (b == 0 || c == 0) ==> a != 0 && d != 0
        float yCoverD = yConstrInfinite ? float.PositiveInfinity : Math.Abs(yConstr / d);
        float xCoverA = xConstrInfinite ? float.PositiveInfinity : Math.Abs(xConstr / a);

        if (IsNear(b, 0))
        {
          if (IsNear(c, 0))
          { // b == 0, c == 0, a != 0, d != 0

            // No constraint relation; use maximal width and height 
            h = yCoverD;
            w = xCoverA;
          }
          else
          { // b == 0, a != 0, c != 0, d != 0

            // Maximizing under line (hIntercept=xConstr/c, wIntercept=xConstr/a) 
            // BUT we still have constraint: h <= yConstr/d
            h = Math.Min(0.5f * Math.Abs(xConstr / c), yCoverD);
            w = xCoverA - ((c * h) / a);
          }
        }
        else
        { // c == 0, a != 0, b != 0, d != 0 

          // Maximizing under line (hIntercept=yConstr/d, wIntercept=yConstr/b)
          // BUT we still have constraint: w <= xConstr/a
          w = Math.Min(0.5f * Math.Abs(yConstr / b), xCoverA);
          h = yCoverD - ((b * w) / d);
        }
      }
      else if (IsNear(a, 0) || IsNear(d, 0))
      { // (a == 0 || d == 0) ==> b != 0 && c != 0 
        float yCoverB = Math.Abs(yConstr / b);
        float xCoverC = Math.Abs(xConstr / c);

        if (IsNear(a, 0))
        {
          if (IsNear(d, 0))
          { // a == 0, d == 0, b != 0, c != 0 

            // No constraint relation; use maximal width and height
            h = xCoverC;
            w = yCoverB;
          }
          else
          { // a == 0, b != 0, c != 0, d != 0

            // Maximizing under line (hIntercept=yConstr/d, wIntercept=yConstr/b)
            // BUT we still have constraint: h <= xConstr/c
            h = Math.Min(0.5f * Math.Abs(yConstr / d), xCoverC);
            w = yCoverB - ((d * h) / b);
          }
        }
        else
        { // d == 0, a != 0, b != 0, c != 0

          // Maximizing under line (hIntercept=xConstr/c, wIntercept=xConstr/a)
          // BUT we still have constraint: w <= yConstr/b
          w = Math.Min(0.5f * Math.Abs(xConstr / a), yCoverB);
          h = xCoverC - ((a * w) / c);
        }
      }
      else
      {
        float xCoverA = Math.Abs(xConstr / a); // w-intercept of x-constraint line
        float xCoverC = Math.Abs(xConstr / c); // h-intercept of x-constraint line

        float yCoverB = Math.Abs(yConstr / b); // w-intercept of y-constraint line
        float yCoverD = Math.Abs(yConstr / d); // h-intercept of y-constraint line

        // The tighest constraint governs, so we pick the lowest constraint line

        // The optimal point (w, h) for which Area = w*h is maximized occurs halfway to each intercept.
        w = Math.Min(yCoverB, xCoverA) * 0.5f;
        h = Math.Min(xCoverC, yCoverD) * 0.5f;

        if ((GreaterThanOrClose(xCoverA, yCoverB) &&
             LessThanOrClose(xCoverC, yCoverD)) ||
            (LessThanOrClose(xCoverA, yCoverB) &&
             GreaterThanOrClose(xCoverC, yCoverD)))
        {
          // Constraint lines cross; since the most restrictive constraint wins,
          // we have to maximize under two line segments, which together are discontinuous.
          // Instead, we maximize w*h under the line segment from the two smallest endpoints. 

          // Since we are not (except for in corner cases) on the original constraint lines, 
          // we are not using up all the available area in transform space.  So scale our shape up 
          // until it does in at least one dimension.

          SizeF childSizeTr = new SizeF(w, h);
          transform.TransformIncludingRectangleSize(ref childSizeTr);
          float expandFactor = Math.Min(xConstr / childSizeTr.Width, yConstr / childSizeTr.Height);
          if (!float.IsNaN(expandFactor) && !float.IsInfinity(expandFactor))
          {
            w *= expandFactor;
            h *= expandFactor;
          }
        }
      }
      return new SizeF(w, h);
    }
        /// <summary>
        /// Given a pair of dimensions, this method calculates the size of the largest rectangle that will fit within
        /// those dimensions after having the specified transformation applied to it.
        /// </summary>
        /// <param name="xmax">The available width.</param>
        /// <param name="ymax">The available height.</param>
        /// <param name="transform">The transformation matrix to apply.</param>
        /// <returns>The size of the largest rectangle that will still fit within the available space after the specified transform is applied.</returns>
        private static Size2D CalculateMaximumAvailableSizeBeforeLayoutTransform(Double xmax, Double ymax, Matrix transform)
        {
            /* When using layout transforms, it's possible for an element to produce a desired size which, after the transform
             * is applied, will cause the element to lie outside of its maximum available layout area. To address this problem,
             * we need to shrink the available size that is passed into MeasureCore() such that, even if the element is as big
             * as it possibly can be, its post-transform bounds will still lie within the available layout area.
             *
             * To that end, we need to do a bit of calculus. Given the true maximum area (A_true) and a transformation
             * matrix (M_transform), we need to calculate the largest possible rectangle that will fit within A_true
             * after it has been subjected to M_transform. This will be the area that we pass into MeasureCore().
             *
             * For simplicity's sake, consider the case of a rotation transform. Rotating a rectangle will cause its x-dimension
             * to point partially along both the x- and y-axes of the untransformed space. If we gradually make the rectangle wider,
             * it will eventually reach a point where its size along the untransformed x-axis will exceed our maximum width, and another
             * point where its size along the untransformed y-axis will exceed our maximum width. The smallest of these two widths
             * is the largest possible width of the transformed rectangle. We can do likewise to constrain the rectangle's height;
             * the biggest possible rectangle will have a width and height somewhere below the values established by these constraints. 
             *
             * We can use trigonometry to establish that there is a simple linear relationship between the width of the transformed 
             * rectangle and its dimensions along the untransformed x- and y-axes, such that w / sin(theta) = h / cos(theta). We can
             * use this to graph a pair of lines representing our transformed rectangle's width and height. We can then take the
             * first derivative in order to find the biggest rectangle that will fit under the lines.
             *
             * Let a = w / sin(theta) and b = h / cos(theta).
             *
             * The line formed by intercepts a and b forms a right triangle with the axes, so the total area beneath it is .5ab.
             * Given that we are trying to find the area of a rectangle beneath this line with dimensions x and y, we can equivalently
             * say that the triangle's total area is .5ay + .5bx. Solving for y, we find that y = (ab - bx) / a. We can then plug
             * this into the equation for the area of a rectangle, A = xy, to get A = x((ab - bx) / a). Taking the first derivative
             * and solving for x, we find that x = a / 2. Doing the same for y reveals, likewise, that y = b / 2. Therefore, the 
             * biggest rectangle has dimensions halfway between the intercepts that form the line. */

            if (Double.IsInfinity(xmax) && Double.IsInfinity(ymax))
                return new Size2D(Double.PositiveInfinity, Double.PositiveInfinity);

            xmax = Double.IsInfinity(xmax) ? ymax : xmax;
            ymax = Double.IsInfinity(ymax) ? xmax : ymax;

            if (MathUtil.IsApproximatelyZero(xmax) || MathUtil.IsApproximatelyZero(ymax) || MathUtil.IsApproximatelyZero(transform.Determinant()))
                return Size2D.Zero;
            
            var m11 = transform.M11;
            var m21 = transform.M21;
            var m12 = transform.M12;
            var m22 = transform.M22;
            
            var w = 0.0;
            var h = 0.0;

            var xConstraintInterceptW = MathUtil.IsApproximatelyZero(m11) ? Double.NaN : Math.Abs(xmax / m11);
            var xConstraintInterceptH = MathUtil.IsApproximatelyZero(m12) ? Double.NaN : Math.Abs(xmax / m12);
            var yConstraintInterceptW = MathUtil.IsApproximatelyZero(m21) ? Double.NaN : Math.Abs(ymax / m21);
            var yConstraintInterceptH = MathUtil.IsApproximatelyZero(m22) ? Double.NaN : Math.Abs(ymax / m22);

            var xConstraintIsHorz = Double.IsNaN(xConstraintInterceptW);
            var xConstraintIsVert = Double.IsNaN(xConstraintInterceptH);
            var xConstraintIsHorzOrVert = xConstraintIsHorz || xConstraintIsVert;
            
            var yConstraintIsHorz = Double.IsNaN(yConstraintInterceptW);
            var yConstraintIsVert = Double.IsNaN(yConstraintInterceptH);
            var yConstraintIsHorzOrVert = yConstraintIsHorz || yConstraintIsVert;

            /* Below, we handle special cases where one or both of the constraint lines is vertical or horizontal due to zeroes in
             * the transformation matrix. This causes some of our intercepts to go undefined, which means their constraint lines
             * don't constrain one (or either) of our dimensions. */

            if (xConstraintIsHorzOrVert && yConstraintIsHorzOrVert)
            {
                w = xConstraintIsVert ? xConstraintInterceptW : yConstraintInterceptW;
                h = xConstraintIsVert ? yConstraintInterceptH : xConstraintInterceptH;
                return new Size2D(w, h);
            }

            if (xConstraintIsVert || yConstraintIsVert)
            {
                var slope = xConstraintIsVert ? m21 / m22 : m11 / m12;
                w = xConstraintIsVert ? Math.Min(yConstraintInterceptW * 0.5, xConstraintInterceptW) : Math.Min(xConstraintInterceptW * 0.5, yConstraintInterceptW);
                h = (xConstraintIsVert ? yConstraintInterceptH : xConstraintInterceptH) - (slope * w);
                return new Size2D(w, h);
            }

            if (xConstraintIsHorz || yConstraintIsHorz)
            {
                var slope = xConstraintIsHorz ? m12 / m11 : m22 / m21;
                h = xConstraintIsHorz ? Math.Min(yConstraintInterceptH * 0.5, xConstraintInterceptH) : Math.Min(xConstraintInterceptH * 0.5, yConstraintInterceptH);
                w = (xConstraintIsHorz ? yConstraintInterceptW : xConstraintInterceptW) - (slope * h);
                return new Size2D(w, h);
            }
            
            /* If both constraint lines have a well-defined, non-zero slope, then the dimensions of the maximized rectangle lie halfway between the smaller line's
             * intercepts, as we established above using the first derivative.
             *
             * This is only true if the lines do not cross - otherwise, there is no clear "smaller line." So what we have to do is draw a third line
             * using the smallest intercept on both axes, then maximize beneath that instead. The result will actually be too small, since it doesn't correspond
             * to either of our original constraint lines; to address this problem, we scale the resulting size upwards until it saturates our constraints. */
             
            w = Math.Min(xConstraintInterceptW, yConstraintInterceptW) * 0.5;
            h = Math.Min(xConstraintInterceptH, yConstraintInterceptH) * 0.5;

            var constraintXSlope = xConstraintInterceptH / xConstraintInterceptW;
            var constraintYSlope = yConstraintInterceptH / xConstraintInterceptW;

            var constraintLinesCross = !MathUtil.AreApproximatelyEqual(constraintXSlope, constraintYSlope);
            if (constraintLinesCross)
            {
                RectangleD area = new RectangleD(0, 0, w, h);
                RectangleD.TransformAxisAligned(ref area, ref transform, out area);

                var scale = Math.Min(xmax / area.Width, ymax / area.Height);
                w *= scale;
                h *= scale;
            }

            return new Size2D(w, h);
        }
Exemple #9
0
        public void Simple2()
        {
            var matrix = new Matrix(4, 4);

            // [ 1,  2,  3,  4 ]
            // [ 5,  6,  7,  8 ]
            // [ 2,  6,  4,  8 ]
            // [ 3,  1,  1,  2 ]
            // Determinant = 72

            matrix[0, 0] = 1;
            matrix[0, 1] = 2;
            matrix[0, 2] = 3;
            matrix[0, 3] = 4;

            matrix[1, 0] = 5;
            matrix[1, 1] = 6;
            matrix[1, 2] = 7;
            matrix[1, 3] = 8;

            matrix[2, 0] = 2;
            matrix[2, 1] = 6;
            matrix[2, 2] = 4;
            matrix[2, 3] = 8;

            matrix[3, 0] = 3;
            matrix[3, 1] = 1;
            matrix[3, 2] = 1;
            matrix[3, 3] = 2;

            Assert.AreEqual(matrix.Determinant(), 72, 0.000000001);
        }
Exemple #10
0
 public void ExceptionNotSquare()
 {
     var matrix = new Matrix(2, 3);
     matrix.Determinant();
 }
Exemple #11
0
 public void DeterminantTest1()
 {
     double[,] data = null; // TODO: инициализация подходящего значения
     Matrix target = new Matrix(data); // TODO: инициализация подходящего значения
     double expected = 0F; // TODO: инициализация подходящего значения
     double actual;
     actual = target.Determinant();
     Assert.AreEqual(expected, actual);
     Assert.Inconclusive("Проверьте правильность этого метода теста.");
 }
Exemple #12
0
        private static Vector3 ScreenRelToWorld(Matrix mView, Vector2 screenCoordsRel)
        {
            mView.Transpose();

            var vForward = mView.Row4;
            var vRight = mView.Row2;
            var vUpward = mView.Row3;

            var d = 1 - vForward.W;
            var h = screenCoordsRel.X - vRight.W;
            var s = -screenCoordsRel.Y - vUpward.W;

            var m = new Matrix(vForward.X, vForward.Y, vForward.Z, 0,
                vRight.X, vRight.Y, vRight.Z, 0,
                vUpward.X, vUpward.Y, vUpward.Z, 0,
                0, 0, 0, 1);
            var det = m.Determinant();

            var mx = new Matrix(d, vForward.Y, vForward.Z, 0,
                h, vRight.Y, vRight.Z, 0,
                s, vUpward.Y, vUpward.Z, 0,
                0, 0, 0, 1);
            var detx = mx.Determinant();

            var my = new Matrix(vForward.X, d, vForward.Z, 0,
                vRight.X, h, vRight.Z, 0,
                vUpward.X, s, vUpward.Z, 0,
                0, 0, 0, 1);
            var dety = my.Determinant();

            var mz = new Matrix(vForward.X, vForward.Y, d, 0,
                vRight.X, vRight.Y, h, 0,
                vUpward.X, vUpward.Y, s, 0,
                0, 0, 0, 1);
            var detz = mz.Determinant();

            var epsilon = 0.0000001;
            return Math.Abs(det) < epsilon ? new Vector3() : new Vector3(detx / det, dety / det, detz / det);
        }
Exemple #13
0
 public int Test(Matrix matrix1, Matrix matrix2, double[] means1, double[] means2, double[] vector)
 {
     var m1 = new Matrix(matrix1);
     var m2 = new Matrix(matrix2);
     var matrix_means1 = new Vector(means1);
     var matrix_means2 = new Vector(means2);
     var matrix_vector = new Vector(vector);
     // Calculate A B C
     var A = m2.Inverse() - m1.Inverse();
     var B = 2 * (Matrix.Multiply(matrix_means1.ToMatrix().Transpose(), m1.Inverse()) - Matrix.Multiply(matrix_means2.ToMatrix().Transpose(), m2.Inverse()));
     var C = (Matrix.Multiply(Matrix.Multiply(matrix_means2.ToMatrix().Transpose(), m2.Inverse()), matrix_means2.ToMatrix())).Determinant() - (Matrix.Multiply(Matrix.Multiply(matrix_means1.ToMatrix().Transpose(), m1.Inverse()), matrix_means1.ToMatrix()).Determinant() - 2 * (Math.Log10(m1.Determinant() / m2.Determinant())));
     var result = Matrix.Multiply(Matrix.Multiply(matrix_vector.ToMatrix().Transpose(), A), matrix_vector.ToMatrix()).Determinant() + B[0, 0] * matrix_vector[0] + B[0, 2] * matrix_vector[2] + B[0, 2] * matrix_vector[2] + C;
     if (result > 0)
     {
         return 1;
     }
     return 2;
 }
Exemple #14
0
        public void DrawDiscreminant(Panel p, Matrix matrix1, Matrix matrix2, double[] means1, double[] means2, int x, int y)
        {
            var m1 = new Matrix(matrix1);
            var m2 = new Matrix(matrix2);
            var matrix_means1 = new Vector(means1);
            var matrix_means2 = new Vector(means2);
            // Calculate A B C
            var A = m2.Inverse() - m1.Inverse();
            var B = 2 * (Matrix.Multiply(matrix_means1.ToMatrix().Transpose(), m1.Inverse()) - Matrix.Multiply(matrix_means2.ToMatrix().Transpose(), m2.Inverse()));
            var C = (Matrix.Multiply(Matrix.Multiply(matrix_means2.ToMatrix().Transpose(), m2.Inverse()), matrix_means2.ToMatrix())).Determinant() - (Matrix.Multiply(Matrix.Multiply(matrix_means1.ToMatrix().Transpose(), m1.Inverse()), matrix_means1.ToMatrix()).Determinant() - 2 * (Math.Log10(m1.Determinant() / m2.Determinant())));
            var a11 = A[x, x];
            var a12 = A[x, y];
            var a21 = A[y, x];
            var a22 = A[y, y];
            var b1 = B[0, x];
            var b2 = B[0, y];
            for (double i = -20; i < 20; i = i + 0.1)
            {
                var quad = a22;
                var line = a12 * i + a21 * i + b2;
                var cons = C + b1 * i + a11 * i * i;

                if ((line * line - 4 * quad * cons) >= 0)
                {
                    try
                    {
                        if (quad != 0)
                        {
                            var j = (-line + Math.Sqrt(line * line - 4 * quad * cons)) / (2 * quad);
                            Draw(p, Color.Black, i, j);

                            j = (-line - Math.Sqrt(line * line - 4 * quad * cons)) / (2 * quad);
                            Draw(p, Color.Black, i, j);
                        }
                        else if (line != 0)
                        {
                            var j = -cons / line;
                            Draw(p, Color.Black, i, j);
                        }
                    }
                    catch(Exception)
                    { }
                }
            }
        }