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,

Reply via email to