Package org.ejml.ops

Source Code of org.ejml.ops.TestMatrixFeatures

/*
* Copyright (c) 2009-2012, Peter Abeles. All Rights Reserved.
*
* This file is part of Efficient Java Matrix Library (EJML).
*
* EJML is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* EJML is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with EJML.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.ejml.ops;

import org.ejml.UtilEjml;
import org.ejml.data.DenseMatrix64F;
import org.junit.Test;

import java.util.Random;

import static org.ejml.UtilEjml.parseMatrix;
import static org.junit.Assert.*;


/**
* @author Peter Abeles
*/
public class TestMatrixFeatures {

    Random rand = new Random(0xff24);

    @Test
    public void hasUncountable() {
        DenseMatrix64F a = new DenseMatrix64F(4,4);

        // check a negative case first
        assertFalse(MatrixFeatures.hasUncountable(a));

        // check two positve cases with different types of uncountables
        a.set(2,2,Double.NaN);
        assertTrue(MatrixFeatures.hasUncountable(a));

        a.set(2,2,Double.POSITIVE_INFINITY);
        assertTrue(MatrixFeatures.hasUncountable(a));
    }

    @Test
    public void isVector() {
        DenseMatrix64F a = new DenseMatrix64F(4,4);

        assertFalse(MatrixFeatures.isVector(a));

        a.reshape(3,1, false);
        assertTrue(MatrixFeatures.isVector(a));

        a.reshape(1,3, false);
        assertTrue(MatrixFeatures.isVector(a));
    }

    /**
     * Check some trial cases.
     */
    @Test
    public void isPositiveDefinite() {
        DenseMatrix64F a = UtilEjml.parseMatrix("2 0 0 2",2);
        DenseMatrix64F b = UtilEjml.parseMatrix("0 1 1 0",2);
        DenseMatrix64F c = UtilEjml.parseMatrix("0 0 0 0",2);

        assertTrue(MatrixFeatures.isPositiveDefinite(a));
        assertFalse(MatrixFeatures.isPositiveDefinite(b));
        assertFalse(MatrixFeatures.isPositiveDefinite(c));

        // make sure the input isn't modified
        assertEquals(2,a.get(0,0),1e-8);
        assertEquals(2,a.get(1,1),1e-8);
    }

    @Test
    public void isPositiveSemidefinite() {
        DenseMatrix64F a = UtilEjml.parseMatrix("2 0 0 2",2);
        DenseMatrix64F b = UtilEjml.parseMatrix("0 1 1 0",2);
        DenseMatrix64F c = UtilEjml.parseMatrix("0 0 0 0",2);

        assertTrue(MatrixFeatures.isPositiveSemidefinite(a));
        assertFalse(MatrixFeatures.isPositiveSemidefinite(b));
        assertTrue(MatrixFeatures.isPositiveSemidefinite(c));

        // make sure the input isn't modified
        assertEquals(2,a.get(0,0),1e-8);
        assertEquals(2,a.get(1,1),1e-8);
    }

    @Test
    public void isSquare() {
        DenseMatrix64F a = new DenseMatrix64F(5,4);

        assertFalse(MatrixFeatures.isSquare(a));

        a.reshape(4,4, false);
        assertTrue(MatrixFeatures.isSquare(a));
    }

    @Test
    public void isDiagonalPositive() {
        DenseMatrix64F m = CommonOps.identity(3);
        assertTrue(MatrixFeatures.isDiagonalPositive(m));

        m.set(1,1,-1);
        assertFalse(MatrixFeatures.isDiagonalPositive(m));

        m.set(1,1,Double.NaN);
        assertFalse(MatrixFeatures.isDiagonalPositive(m));
    }

    @Test
    public void isSymmetric() {
        DenseMatrix64F m = CommonOps.identity(3);
        m.set(1,2,5);m.set(2,1,5);
        assertTrue(MatrixFeatures.isSymmetric(m));

        m.set(1,2,50);
        assertTrue(!MatrixFeatures.isSymmetric(m));

        m.set(1,2,Double.NaN);
        assertTrue(!MatrixFeatures.isSymmetric(m));
    }

    @Test
    public void isSkewSymmetric() {
        DenseMatrix64F m = CommonOps.identity(3);
        m.set(1,2,5);m.set(2,1,-5);
        assertTrue(MatrixFeatures.isSkewSymmetric(m,1e-8));

        m.set(1,2,-5);
        assertTrue(!MatrixFeatures.isSkewSymmetric(m,1e-8));

        m.set(1,2,Double.NaN);
        assertTrue(!MatrixFeatures.isSkewSymmetric(m,1e-8));
    }


    @Test
    public void isEquals() {
        String a = "-0.779094   1.682750   0.039239\n" +
                 "   1.304014  -1.880739   1.438741\n" +
                 "  -0.746918   1.382356  -0.520416";

        DenseMatrix64F m = parseMatrix(a,3);
        DenseMatrix64F n = parseMatrix(a,3);

        assertTrue(MatrixFeatures.isEquals(m,n));

        n.set(2,1,-0.5);
        assertFalse(MatrixFeatures.isEquals(m,n));

        m.set(2,1,Double.NaN);
        n.set(2,1,Double.NaN);
        assertFalse(MatrixFeatures.isEquals(m,n));
        m.set(2,1,Double.POSITIVE_INFINITY);
        n.set(2,1,Double.POSITIVE_INFINITY);
        assertTrue(MatrixFeatures.isEquals(m,n));
    }

    @Test
    public void isEquals_tol() {
        String a = "-0.779094   1.682750   0.039239\n" +
                 "   1.304014  -1.880739   1.438741\n" +
                 "  -0.746918   1.382356  -0.520416";

        DenseMatrix64F m = parseMatrix(a,3);
        DenseMatrix64F n = parseMatrix(a,3);

        assertTrue(MatrixFeatures.isEquals(m,n,1e-6));

        n.set(2,1,n.get(2,1)+1e-25);
        assertTrue(MatrixFeatures.isEquals(m,n,1e-6));

        n.set(2,1,n.get(2,1)+1e-2);
        assertFalse(MatrixFeatures.isEquals(m,n,1e-6));

        m.set(2,1,Double.NaN);
        n.set(2,1,Double.NaN);
        assertFalse(MatrixFeatures.isEquals(m,n,1e-6));
        m.set(2,1,Double.POSITIVE_INFINITY);
        n.set(2,1,Double.POSITIVE_INFINITY);
        assertFalse(MatrixFeatures.isEquals(m,n,1e-6));
    }

    @Test
    public void isEqualsTriangle() {

        // see if it works with different sized matrices
        for( int m = 2; m < 10; m+=3) {
            for( int n = 2; n < 10; n += 3 ) {
                DenseMatrix64F a = RandomMatrices.createRandom(m,n,rand);
                DenseMatrix64F b = a.copy();

                // make the bottom triangle not the same
                b.set(m-1,0,0);

                assertTrue("m = "+m+" n = "+n,MatrixFeatures.isEqualsTriangle(a,b, true, 1e-8));
                assertFalse(MatrixFeatures.isEqualsTriangle(a,b, false, 1e-8));

                // make the upper triangle not the same
                b = a.copy();
                b.set(0,n-1,0);

                assertFalse(MatrixFeatures.isEqualsTriangle(a,b, true, 1e-8));
                assertTrue(MatrixFeatures.isEqualsTriangle(a,b, false, 1e-8));
            }
        }
    }

    @Test
    public void isIdentical() {

        double values[] = new double[]{1.0,Double.NaN,Double.POSITIVE_INFINITY,Double.NEGATIVE_INFINITY};

        for( int i = 0; i < values.length; i++ ) {
            for( int j = 0; j < values.length; j++ ) {
                checkIdentical(values[i],values[j],1e-8,i==j);
            }
        }

        checkIdentical(1.0,1.5,1e-8,false);
        checkIdentical(1.5,1.0,1e-8,false);
        checkIdentical(1.0,1.0000000001,1e-8,true);
        checkIdentical(1.0,Double.NaN,1e-8,false);
        checkIdentical(Double.NaN,1.0,1e-8,false);
    }

    private void checkIdentical( double valA , double valB , double tol , boolean expected ) {
        DenseMatrix64F A = new DenseMatrix64F(2,2);
        CommonOps.fill(A, valA);
        DenseMatrix64F B = new DenseMatrix64F(2,2);
        CommonOps.fill(B, valB);

        assertEquals(expected,MatrixFeatures.isIdentical(A,B,tol));
    }

    @Test
    public void isInverse() {
        DenseMatrix64F A = RandomMatrices.createRandom(3,3,-1,1,rand);
        DenseMatrix64F A_inv = A.copy();

        CommonOps.invert(A_inv);

        assertTrue(MatrixFeatures.isInverse(A,A_inv,1e-10));

        A_inv.set(1,2,3);
        assertFalse(MatrixFeatures.isInverse(A,A_inv,1e-10));

        A_inv.set(1,2,Double.NaN);
        assertFalse(MatrixFeatures.isInverse(A,A_inv,1e-10));
    }

    /**
     * Makes sure it isn't modifying the input
     */
    @Test
    public void isInverse_nomodify() {
        DenseMatrix64F A = RandomMatrices.createRandom(3,3,-1,1,rand);
        DenseMatrix64F B = RandomMatrices.createRandom(3,3,-1,1,rand);
        DenseMatrix64F A_copy = A.copy();
        DenseMatrix64F B_copy = B.copy();

        MatrixFeatures.isInverse(A,B,1e-10);

        assertTrue(MatrixFeatures.isIdentical(A,A_copy,1e-8));
        assertTrue(MatrixFeatures.isIdentical(B,B_copy,1e-8));
    }

    @Test
    public void hasNaN() {
        DenseMatrix64F m = new DenseMatrix64F(3,3);
        assertFalse(MatrixFeatures.hasNaN(m));

        m.set(1,2,-Double.NaN);
        assertTrue(MatrixFeatures.hasNaN(m));
    }

    @Test
    public void isOrthogonal() {
        // rotation matrices are orthogonal
        double c = Math.cos(0.1);
        double s = Math.sin(0.1);

        DenseMatrix64F A = new DenseMatrix64F(new double[][]{{c,s},{-s,c}});

        assertTrue(MatrixFeatures.isOrthogonal(A,1e-6f));

        // try a negative case now
        A.set(0,1,495);

        assertFalse(MatrixFeatures.isOrthogonal(A,1e-6f));

        A.set(0,1,Double.NaN);

        assertFalse(MatrixFeatures.isOrthogonal(A,1e-6f));
    }

    @Test
    public void isRowsLinearIndependent() {
        // test a positive case
        DenseMatrix64F A = new DenseMatrix64F(2,3, true, 1, 2, 3, 2, 3, 4);
        assertTrue(MatrixFeatures.isRowsLinearIndependent(A));

        // make sure the input wasn't modified
        DenseMatrix64F A_copy = new DenseMatrix64F(2,3, true, 1, 2, 3, 2, 3, 4);
        assertTrue(MatrixFeatures.isIdentical(A,A_copy,1e-8));

        // test negative case
        A = new DenseMatrix64F(2,3, true, 1, 2, 3, 1, 2, 3);
        assertFalse(MatrixFeatures.isRowsLinearIndependent(A));
    }

    @Test
    public void isConstantVal() {
        DenseMatrix64F a = new DenseMatrix64F(3,4);

        CommonOps.fill(a, 2.4);

        assertTrue(MatrixFeatures.isConstantVal(a,2.4,1e-8));
        assertFalse(MatrixFeatures.isConstantVal(a,6,1e-8));

        a.set(1,1,Double.NaN);
        assertFalse(MatrixFeatures.isConstantVal(a,2.4,1e-8));
    }

    @Test
    public void isIdentity() {
        DenseMatrix64F I = CommonOps.identity(4);

        assertTrue(MatrixFeatures.isIdentity(I,1e-8));

        I.set(3,2,0.1);
        assertFalse(MatrixFeatures.isIdentity(I,1e-8));

        I.set(3,2,Double.NaN);
        assertFalse(MatrixFeatures.isIdentity(I,1e-8));
    }

    @Test
    public void isNegative() {
        DenseMatrix64F a = RandomMatrices.createRandom(4,5,rand);
        DenseMatrix64F b = a.copy();
        CommonOps.scale(-1,b);

        // test the positive case first
        assertTrue(MatrixFeatures.isNegative(a,b,1e-8));

        // now the negative case
        b.set(2,2,10);
        assertFalse(MatrixFeatures.isNegative(a,b,1e-8));

        b.set(2,2,Double.NaN);
        assertFalse(MatrixFeatures.isNegative(a,b,1e-8));
    }

    @Test
    public void isUpperTriangle() {
        // test matrices that are upper triangular to various degree hessenberg
        for( int hessenberg = 0; hessenberg < 2; hessenberg++ ) {
            DenseMatrix64F A = new DenseMatrix64F(6,6);
            for( int i = 0; i < A.numRows; i++ ) {
                int s = i <= hessenberg ? 0 : i-hessenberg;

                for( int j = s; j < A.numCols; j++ ) {
                   A.set(i,j,2);
                }
            }

            // test positive
            for( int i = hessenberg; i < A.numRows; i++ ) {
                assertTrue(MatrixFeatures.isUpperTriangle(A,i,1e-8));
            }

            // test negative
            for( int i = 0; i < hessenberg; i++ ) {
                assertFalse(MatrixFeatures.isUpperTriangle(A,i,1e-8));
            }

            // see if it handles NaN well
            A.set(4,0,Double.NaN);
            assertFalse(MatrixFeatures.isUpperTriangle(A,0,1e-8));
        }
    }

    @Test
    public void rank() {
        DenseMatrix64F a = UtilEjml.parseMatrix("2 0 0 2",2);
        DenseMatrix64F a_copy = a.copy();

        assertEquals(2,MatrixFeatures.rank(a));
        // make sure the input wasn't modified
        assertTrue(MatrixFeatures.isIdentical(a,a_copy,1e-8));

        a = UtilEjml.parseMatrix("2 0 0 0",2);
        assertEquals(1,MatrixFeatures.rank(a));
    }

    @Test
    public void rank_threshold() {
        DenseMatrix64F a = UtilEjml.parseMatrix("2 0 0 2",2);
        DenseMatrix64F a_copy = a.copy();

        assertEquals(2,MatrixFeatures.rank(a,1e-14));
        // make sure the input wasn't modified
        assertTrue(MatrixFeatures.isIdentical(a,a_copy,1e-8));

        a = UtilEjml.parseMatrix("2 0 0 1e-20",2);
        assertEquals(1,MatrixFeatures.rank(a,1e-14));

        // make sure it's using the threshold parameter
        a = UtilEjml.parseMatrix("2 0 0 1e-20",2);
        assertEquals(2,MatrixFeatures.rank(a,1e-200));
    }

    @Test
    public void nullity() {
        DenseMatrix64F a = UtilEjml.parseMatrix("2 0 0 2",2);
        DenseMatrix64F a_copy = a.copy();

        assertEquals(0,MatrixFeatures.nullity(a));
        // make sure the input wasn't modified
        assertTrue(MatrixFeatures.isIdentical(a,a_copy,1e-8));

        a = UtilEjml.parseMatrix("2 0 0 0",2);
        assertEquals(1,MatrixFeatures.nullity(a));
    }

    @Test
    public void nullity_threshold() {
        DenseMatrix64F a = UtilEjml.parseMatrix("2 0 0 2",2);
        DenseMatrix64F a_copy = a.copy();

        assertEquals(0,MatrixFeatures.nullity(a, 1e-14));
        // make sure the input wasn't modified
        assertTrue(MatrixFeatures.isIdentical(a,a_copy,1e-8));

        a = UtilEjml.parseMatrix("2 0 0 1e-20",2);
        assertEquals(1,MatrixFeatures.nullity(a, 1e-14));

        // make sure it's using the threshold parameter
        a = UtilEjml.parseMatrix("2 0 0 1e-20",2);
        assertEquals(0,MatrixFeatures.nullity(a, 1e-200));
    }
}
TOP

Related Classes of org.ejml.ops.TestMatrixFeatures

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.