Repository: systemml Updated Branches: refs/heads/master 10f8e23d5 -> 7e3c03609
[SYSTEMML-1216] New svd builtin function (compiler/runtime, local only) Closes #605. Project: http://git-wip-us.apache.org/repos/asf/systemml/repo Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/7e3c0360 Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/7e3c0360 Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/7e3c0360 Branch: refs/heads/master Commit: 7e3c0360951ccd46aabf8f9ee12aee6d04947a60 Parents: 10f8e23 Author: Janardhan <[email protected]> Authored: Wed Aug 23 17:49:28 2017 -0700 Committer: Matthias Boehm <[email protected]> Committed: Wed Aug 23 17:49:29 2017 -0700 ---------------------------------------------------------------------- .../java/org/apache/sysml/hops/FunctionOp.java | 10 ++ src/main/java/org/apache/sysml/hops/Hop.java | 2 + .../java/org/apache/sysml/hops/UnaryOp.java | 2 +- .../hops/cost/CostEstimatorStaticRuntime.java | 4 +- .../sysml/parser/BuiltinFunctionExpression.java | 40 +++++- .../org/apache/sysml/parser/DMLTranslator.java | 1 + .../org/apache/sysml/parser/Expression.java | 1 + .../instructions/CPInstructionParser.java | 4 +- .../cp/MultiReturnBuiltinCPInstruction.java | 11 ++ .../runtime/matrix/data/LibCommonsMath.java | 32 ++++- .../unary/matrix/SVDFactorizeTest.java | 136 +++++++++++++++++++ src/test/scripts/functions/unary/matrix/svd.dml | 59 ++++++++ .../functions/unary/matrix/ZPackageSuite.java | 1 + 13 files changed, 296 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/main/java/org/apache/sysml/hops/FunctionOp.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/FunctionOp.java b/src/main/java/org/apache/sysml/hops/FunctionOp.java index 3ad2d15..f40929b 100644 --- a/src/main/java/org/apache/sysml/hops/FunctionOp.java +++ b/src/main/java/org/apache/sysml/hops/FunctionOp.java @@ -167,6 +167,12 @@ public class FunctionOp extends Hop long outputValues = OptimizerUtils.estimateSizeExactSparsity(getOutputs().get(1).getDim1(), 1, 1.0); return outputVectors+outputValues; } + else if ( getFunctionName().equalsIgnoreCase("svd") ) { + long outputU = OptimizerUtils.estimateSizeExactSparsity(getOutputs().get(0).getDim1(), getOutputs().get(0).getDim2(), 1.0); + long outputSigma = OptimizerUtils.estimateSizeExactSparsity(getOutputs().get(1).getDim1(), getOutputs().get(1).getDim2(), 1.0); + long outputV = OptimizerUtils.estimateSizeExactSparsity(getOutputs().get(2).getDim1(), getOutputs().get(2).getDim2(), 1.0); + return outputU+outputSigma+outputV; + } else throw new RuntimeException("Invalid call of computeOutputMemEstimate in FunctionOp."); } @@ -197,6 +203,10 @@ public class FunctionOp extends Hop //System.out.println("EigenInter " + interOutput/1024/1024); return interOutput; } + else if ( getFunctionName().equalsIgnoreCase("svd")) { + double interOutput = OptimizerUtils.estimateSizeExactSparsity(1, getInput().get(0).getDim2(), 1.0); + return interOutput; + } else throw new RuntimeException("Invalid call of computeIntermediateMemEstimate in FunctionOp."); } http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/main/java/org/apache/sysml/hops/Hop.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/Hop.java b/src/main/java/org/apache/sysml/hops/Hop.java index 1cf875f..2d9b1bf 100644 --- a/src/main/java/org/apache/sysml/hops/Hop.java +++ b/src/main/java/org/apache/sysml/hops/Hop.java @@ -1024,6 +1024,7 @@ public abstract class Hop NOT, ABS, SIN, COS, TAN, ASIN, ACOS, ATAN, SIGN, SQRT, LOG, EXP, CAST_AS_SCALAR, CAST_AS_MATRIX, CAST_AS_FRAME, CAST_AS_DOUBLE, CAST_AS_INT, CAST_AS_BOOLEAN, PRINT, EIGEN, NROW, NCOL, LENGTH, ROUND, IQM, STOP, CEIL, FLOOR, MEDIAN, INVERSE, CHOLESKY, + SVD, //cumulative sums, products, extreme values CUMSUM, CUMPROD, CUMMIN, CUMMAX, //fused ML-specific operators for performance @@ -1317,6 +1318,7 @@ public abstract class Hop HopsOpOp12String.put(OpOp1.CAST_AS_SCALAR, "castAsScalar"); HopsOpOp12String.put(OpOp1.COS, "cos"); HopsOpOp12String.put(OpOp1.EIGEN, "eigen"); + HopsOpOp12String.put(OpOp1.SVD, "svd"); HopsOpOp12String.put(OpOp1.EXP, "exp"); HopsOpOp12String.put(OpOp1.IQM, "iqm"); HopsOpOp12String.put(OpOp1.MEDIAN, "median"); http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/main/java/org/apache/sysml/hops/UnaryOp.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/UnaryOp.java b/src/main/java/org/apache/sysml/hops/UnaryOp.java index 0a5bc65..d51fd81 100644 --- a/src/main/java/org/apache/sysml/hops/UnaryOp.java +++ b/src/main/java/org/apache/sysml/hops/UnaryOp.java @@ -693,7 +693,7 @@ public class UnaryOp extends Hop implements MultiThreadedHop //ensure cp exec type for single-node operations if( _op == OpOp1.PRINT || _op == OpOp1.STOP - || _op == OpOp1.INVERSE || _op == OpOp1.EIGEN || _op == OpOp1.CHOLESKY ) + || _op == OpOp1.INVERSE || _op == OpOp1.EIGEN || _op == OpOp1.CHOLESKY || _op == OpOp1.SVD) { _etype = ExecType.CP; } http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/main/java/org/apache/sysml/hops/cost/CostEstimatorStaticRuntime.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/cost/CostEstimatorStaticRuntime.java b/src/main/java/org/apache/sysml/hops/cost/CostEstimatorStaticRuntime.java index 0ca29ea..bb3ce3c 100644 --- a/src/main/java/org/apache/sysml/hops/cost/CostEstimatorStaticRuntime.java +++ b/src/main/java/org/apache/sysml/hops/cost/CostEstimatorStaticRuntime.java @@ -994,13 +994,15 @@ public class CostEstimatorStaticRuntime extends CostEstimator //note: should be invoked independently for multiple outputs return d1m * d1n * d1s * DEFAULT_NFLOP_UNKNOWN; - case MultiReturnBuiltin: //opcodes: qr, lu, eigen + case MultiReturnBuiltin: //opcodes: qr, lu, eigen, svd //note: they all have cubic complexity, the scaling factor refers to commons.math double xf = 2; //default e.g, qr if( optype.equals("eigen") ) xf = 32; else if ( optype.equals("lu") ) xf = 16; + else if ( optype.equals("svd")) + xf = 32; // TODO - assuming worst case for now return xf * d1m * d1n * d1n; //for 1kx1k ~ 2GFLOP -> 1s case ParameterizedBuiltin: //opcodes: cdf, invcdf, groupedagg, rmempty http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java b/src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java index ef3f368..5d3ae93 100644 --- a/src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java +++ b/src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java @@ -199,6 +199,37 @@ public class BuiltinFunctionExpression extends DataIdentifier eigenOut2.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock()); break; + + case SVD: + checkNumParameters(1); + checkMatrixParam(getFirstExpr()); + + long minMN = Math.min(getFirstExpr().getOutput().getDim1(), getFirstExpr().getOutput().getDim2()); + + // setup output properties + DataIdentifier svdOut1 = (DataIdentifier) getOutputs()[0]; + DataIdentifier svdOut2 = (DataIdentifier) getOutputs()[1]; + DataIdentifier svdOut3 = (DataIdentifier) getOutputs()[2]; + + // Output 1 + svdOut1.setDataType(DataType.MATRIX); + svdOut1.setValueType(ValueType.DOUBLE); + svdOut1.setDimensions(getFirstExpr().getOutput().getDim1(), minMN); + svdOut1.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock()); + + // Output 2 + svdOut2.setDataType(DataType.MATRIX); + svdOut2.setValueType(ValueType.DOUBLE); + svdOut2.setDimensions(minMN, minMN); + svdOut2.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock()); + + // Output 3 + svdOut3.setDataType(DataType.MATRIX); + svdOut3.setValueType(ValueType.DOUBLE); + svdOut3.setDimensions(getFirstExpr().getOutput().getDim2(), minMN); + svdOut3.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock()); + + break; default: //always unconditional raiseValidateError("Unknown Builtin Function opcode: " + _opcode, false); @@ -1064,8 +1095,8 @@ public class BuiltinFunctionExpression extends DataIdentifier output.setDimensions(inA.getDim1(), inA.getDim2()); output.setBlockDimensions(inA.getRowsInBlock(), inA.getColumnsInBlock()); break; - } - + } + case OUTER: Identifier id2 = this.getSecondExpr().getOutput(); @@ -1214,7 +1245,7 @@ public class BuiltinFunctionExpression extends DataIdentifier else { // always unconditional (because unsupported operation) BuiltinFunctionOp op = getOpCode(); - if( op==BuiltinFunctionOp.EIGEN || op==BuiltinFunctionOp.LU || op==BuiltinFunctionOp.QR ) + if( op==BuiltinFunctionOp.EIGEN || op==BuiltinFunctionOp.LU || op==BuiltinFunctionOp.QR || op==BuiltinFunctionOp.SVD) raiseValidateError("Function "+op+" needs to be called with multi-return assignment.", false, LanguageErrorCodes.INVALID_PARAMETERS); else raiseValidateError("Unsupported function "+op, false, LanguageErrorCodes.INVALID_PARAMETERS); @@ -1256,6 +1287,7 @@ public class BuiltinFunctionExpression extends DataIdentifier case QR: case LU: case EIGEN: + case SVD: return true; default: return false; @@ -1667,6 +1699,8 @@ public class BuiltinFunctionExpression extends DataIdentifier bifop = Expression.BuiltinFunctionOp.INVERSE; else if (functionName.equals("cholesky")) bifop = Expression.BuiltinFunctionOp.CHOLESKY; + else if (functionName.equals("svd")) + bifop = Expression.BuiltinFunctionOp.SVD; else if (functionName.equals("sample")) bifop = Expression.BuiltinFunctionOp.SAMPLE; else if ( functionName.equals("outer") ) http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/main/java/org/apache/sysml/parser/DMLTranslator.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/parser/DMLTranslator.java b/src/main/java/org/apache/sysml/parser/DMLTranslator.java index 731b300..28202dc 100644 --- a/src/main/java/org/apache/sysml/parser/DMLTranslator.java +++ b/src/main/java/org/apache/sysml/parser/DMLTranslator.java @@ -2471,6 +2471,7 @@ public class DMLTranslator case QR: case LU: case EIGEN: + case SVD: // Number of outputs = size of targetList = #of identifiers in source.getOutputs String[] outputNames = new String[targetList.size()]; http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/main/java/org/apache/sysml/parser/Expression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/parser/Expression.java b/src/main/java/org/apache/sysml/parser/Expression.java index 9ee3fba..e61a932 100644 --- a/src/main/java/org/apache/sysml/parser/Expression.java +++ b/src/main/java/org/apache/sysml/parser/Expression.java @@ -125,6 +125,7 @@ public abstract class Expression SOLVE, SQRT, SUM, + SVD, TABLE, TAN, TRACE, http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java b/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java index e755fa0..f1c9d3e 100644 --- a/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java +++ b/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java @@ -267,10 +267,12 @@ public class CPInstructionParser extends InstructionParser String2CPInstructionType.put( "qr", CPINSTRUCTION_TYPE.MultiReturnBuiltin); String2CPInstructionType.put( "lu", CPINSTRUCTION_TYPE.MultiReturnBuiltin); String2CPInstructionType.put( "eigen", CPINSTRUCTION_TYPE.MultiReturnBuiltin); - + String2CPInstructionType.put( "svd", CPINSTRUCTION_TYPE.MultiReturnBuiltin); + String2CPInstructionType.put( "partition", CPINSTRUCTION_TYPE.Partition); String2CPInstructionType.put( "compress", CPINSTRUCTION_TYPE.Compression); String2CPInstructionType.put( "spoof", CPINSTRUCTION_TYPE.SpoofFused); + //CP FILE instruction String2CPFileInstructionType = new HashMap<String, CPINSTRUCTION_TYPE>(); http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/main/java/org/apache/sysml/runtime/instructions/cp/MultiReturnBuiltinCPInstruction.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/instructions/cp/MultiReturnBuiltinCPInstruction.java b/src/main/java/org/apache/sysml/runtime/instructions/cp/MultiReturnBuiltinCPInstruction.java index 54d206e..32be373 100644 --- a/src/main/java/org/apache/sysml/runtime/instructions/cp/MultiReturnBuiltinCPInstruction.java +++ b/src/main/java/org/apache/sysml/runtime/instructions/cp/MultiReturnBuiltinCPInstruction.java @@ -90,6 +90,17 @@ public class MultiReturnBuiltinCPInstruction extends ComputationCPInstruction return new MultiReturnBuiltinCPInstruction(null, in1, outputs, opcode, str); } + else if ( opcode.equalsIgnoreCase("svd") ) { + CPOperand in1 = new CPOperand(parts[1]); + + // one input and three outputs + outputs.add ( new CPOperand(parts[2], ValueType.DOUBLE, DataType.MATRIX) ); + outputs.add ( new CPOperand(parts[3], ValueType.DOUBLE, DataType.MATRIX) ); + outputs.add ( new CPOperand(parts[4], ValueType.DOUBLE, DataType.MATRIX) ); + + return new MultiReturnBuiltinCPInstruction(null, in1, outputs, opcode, str); + + } else { throw new DMLRuntimeException("Invalid opcode in MultiReturnBuiltin instruction: " + opcode); } http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/main/java/org/apache/sysml/runtime/matrix/data/LibCommonsMath.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/LibCommonsMath.java b/src/main/java/org/apache/sysml/runtime/matrix/data/LibCommonsMath.java index 600e73a..d55499d 100644 --- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibCommonsMath.java +++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibCommonsMath.java @@ -26,6 +26,7 @@ import org.apache.commons.math3.linear.EigenDecomposition; import org.apache.commons.math3.linear.LUDecomposition; import org.apache.commons.math3.linear.QRDecomposition; import org.apache.commons.math3.linear.RealMatrix; +import org.apache.commons.math3.linear.SingularValueDecomposition; import org.apache.sysml.runtime.DMLRuntimeException; import org.apache.sysml.runtime.controlprogram.caching.MatrixObject; import org.apache.sysml.runtime.util.DataConverter; @@ -48,7 +49,7 @@ public class LibCommonsMath } public static boolean isSupportedMultiReturnOperation( String opcode ) { - return ( opcode.equals("qr") || opcode.equals("lu") || opcode.equals("eigen") ); + return ( opcode.equals("qr") || opcode.equals("lu") || opcode.equals("eigen") || opcode.equals("svd") ); } public static boolean isSupportedMatrixMatrixOperation( String opcode ) { @@ -75,6 +76,8 @@ public class LibCommonsMath return computeLU(in); else if (opcode.equals("eigen")) return computeEigen(in); + else if ( opcode.equals("svd")) + return computeSvd(in); return null; } @@ -216,6 +219,33 @@ public class LibCommonsMath return new MatrixBlock[] { mbValues, mbVectors }; } + + + /** + * Performs Singular Value Decomposition. Calls Apache Commons Math SVD. + * X = U * Sigma * Vt, where X is the input matrix, + * U is the left singular matrix, Sigma is the singular values matrix returned as a + * column matrix and Vt is the transpose of the right singular matrix V. + * However, the returned array has { U, Sigma, V} + * + * @param in Input matrix + * @return An array containing U, Sigma & V + * @throws DMLRuntimeException + */ + private static MatrixBlock[] computeSvd(MatrixObject in) throws DMLRuntimeException { + Array2DRowRealMatrix matrixInput = DataConverter.convertToArray2DRowRealMatrix(in); + + SingularValueDecomposition svd = new SingularValueDecomposition(matrixInput); + double[] sigma = svd.getSingularValues(); + RealMatrix u = svd.getU(); + RealMatrix v = svd.getV(); + MatrixBlock U = DataConverter.convertToMatrixBlock(u.getData()); + MatrixBlock Sigma = DataConverter.convertToMatrixBlock(sigma, true); + Sigma = LibMatrixReorg.diag(Sigma, new MatrixBlock(Sigma.rlen, Sigma.rlen, true)); + MatrixBlock V = DataConverter.convertToMatrixBlock(v.getData()); + + return new MatrixBlock[] { U, Sigma, V }; + } /** * Function to compute matrix inverse via matrix decomposition. http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/test/java/org/apache/sysml/test/integration/functions/unary/matrix/SVDFactorizeTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/unary/matrix/SVDFactorizeTest.java b/src/test/java/org/apache/sysml/test/integration/functions/unary/matrix/SVDFactorizeTest.java new file mode 100644 index 0000000..4f09b74 --- /dev/null +++ b/src/test/java/org/apache/sysml/test/integration/functions/unary/matrix/SVDFactorizeTest.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sysml.test.integration.functions.unary.matrix; + +import org.junit.Test; + +import org.apache.sysml.api.DMLScript; +import org.apache.sysml.api.DMLScript.RUNTIME_PLATFORM; +import org.apache.sysml.runtime.matrix.MatrixCharacteristics; +import org.apache.sysml.test.integration.AutomatedTestBase; +import org.apache.sysml.test.integration.TestConfiguration; + +public class SVDFactorizeTest extends AutomatedTestBase +{ + + private final static String TEST_NAME1 = "svd"; + private final static String TEST_DIR = "functions/unary/matrix/"; + private static final String TEST_CLASS_DIR = TEST_DIR + SVDFactorizeTest.class.getSimpleName() + "/"; + + private final static int rows1 = 500; + private final static int rows2 = 2500; + private final static int cols1 = 400; + private final static int cols2 = 2200; + private final static double sparsity = 0.9; + + @Override + public void setUp() + { + addTestConfiguration( + TEST_NAME1, + new TestConfiguration(TEST_CLASS_DIR, TEST_NAME1, + new String[] { "D" }) ); + } + + @Test + public void testSVDFactorizeDenseCP() + { + runTestSVDFactorize( rows1, cols1, RUNTIME_PLATFORM.SINGLE_NODE ); + } + + @Test + public void testSVDFactorizeDenseSP() + { + runTestSVDFactorize( rows1, cols1, RUNTIME_PLATFORM.SPARK ); + } + + @Test + public void testSVDFactorizeDenseMR() + { + runTestSVDFactorize( rows1, cols1, RUNTIME_PLATFORM.HADOOP ); + } + + @Test + public void testSVDFactorizeDenseHybrid() + { + runTestSVDFactorize( rows1, cols1, RUNTIME_PLATFORM.HYBRID ); + } + + @Test + public void testLargeSVDFactorizeDenseCP() + { + runTestSVDFactorize( rows2, cols2, RUNTIME_PLATFORM.SINGLE_NODE ); + } + + @Test + public void testLargeSVDFactorizeDenseSP() + { + runTestSVDFactorize( rows2, cols2, RUNTIME_PLATFORM.SPARK ); + } + + @Test + public void testLargeSVDFactorizeDenseMR() + { + runTestSVDFactorize( rows2, cols2, RUNTIME_PLATFORM.HADOOP ); + } + + @Test + public void testLargeSVDFactorizeDenseHybrid() + { + runTestSVDFactorize( rows2, cols2, RUNTIME_PLATFORM.HYBRID ); + } + + private void runTestSVDFactorize( int rows, int cols, RUNTIME_PLATFORM rt) + { + RUNTIME_PLATFORM rtold = rtplatform; + rtplatform = rt; + + boolean sparkConfigOld = DMLScript.USE_LOCAL_SPARK_CONFIG; + if( rtplatform == RUNTIME_PLATFORM.SPARK ) + DMLScript.USE_LOCAL_SPARK_CONFIG = true; + + try + { + getAndLoadTestConfiguration(TEST_NAME1); + + String HOME = SCRIPT_DIR + TEST_DIR; + fullDMLScriptName = HOME + TEST_NAME1 + ".dml"; + programArgs = new String[]{"-args", input("A"), output("D") }; + + double[][] A = getRandomMatrix(rows, cols, 0, 1, sparsity, 10); + MatrixCharacteristics mc = new MatrixCharacteristics(rows, cols, -1, -1, -1); + writeInputMatrixWithMTD("A", A, false, mc); + + // Expected matrix = 1x1 zero matrix + double[][] D = new double[1][1]; + D[0][0] = 0.0; + writeExpectedMatrix("D", D); + + boolean exceptionExpected = false; + runTest(true, exceptionExpected, null, -1); + compareResults(1e-8); + } + finally + { + rtplatform = rtold; + } + } + +} http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/test/scripts/functions/unary/matrix/svd.dml ---------------------------------------------------------------------- diff --git a/src/test/scripts/functions/unary/matrix/svd.dml b/src/test/scripts/functions/unary/matrix/svd.dml new file mode 100644 index 0000000..0c94af6 --- /dev/null +++ b/src/test/scripts/functions/unary/matrix/svd.dml @@ -0,0 +1,59 @@ +#------------------------------------------------------------- +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +#------------------------------------------------------------- + + +/* + * DML script to test Singular Value Decomposition (SVD) + */ + +A = read($1); + +[U, S, V] = svd(A); + +# U(and V) must be orthogonal i.e., U = U^{-1} and V = V^{-1} +I1 = U %*% t(U); +I2 = V %*% t(V); + +Urows = nrow(U); +Ucols = ncol(U); +Vrows = nrow(V); +Vcols = ncol(V); + +# check for, whether the U and V are square or not. +#if ( Urows == Ucols & Vrows == Vcols) { + a = sum(I1) / Urows; + b = sum(I2) / Vrows; +#} + +D = matrix(1,1,1); + +if ( abs(1-a)<10e-4 & abs(1-b)<10e-4 ) { + + # Multiplying U, S and t(V), we must get back original A + B = U %*% S %*% t(V); + + diff = sum(A - B); + # write the difference between original A and computed B as a dummy 1x1 matrix + D = diff*D; + +} + +write (D, $2); http://git-wip-us.apache.org/repos/asf/systemml/blob/7e3c0360/src/test_suites/java/org/apache/sysml/test/integration/functions/unary/matrix/ZPackageSuite.java ---------------------------------------------------------------------- diff --git a/src/test_suites/java/org/apache/sysml/test/integration/functions/unary/matrix/ZPackageSuite.java b/src/test_suites/java/org/apache/sysml/test/integration/functions/unary/matrix/ZPackageSuite.java index 65bc06b..c556138 100644 --- a/src/test_suites/java/org/apache/sysml/test/integration/functions/unary/matrix/ZPackageSuite.java +++ b/src/test_suites/java/org/apache/sysml/test/integration/functions/unary/matrix/ZPackageSuite.java @@ -42,6 +42,7 @@ import org.junit.runners.Suite; FullSignTest.class, IQMTest.class, LUFactorizeTest.class, + SVDFactorizeTest.class, MatrixInverseTest.class, MinusTest.class, MLUnaryBuiltinTest.class,
