New cholesky cp builtin function, by Shirish, incl cleanups Project: http://git-wip-us.apache.org/repos/asf/incubator-systemml/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-systemml/commit/4f4e94ec Tree: http://git-wip-us.apache.org/repos/asf/incubator-systemml/tree/4f4e94ec Diff: http://git-wip-us.apache.org/repos/asf/incubator-systemml/diff/4f4e94ec
Branch: refs/heads/master Commit: 4f4e94ec11e4dcffbcafc731d7eb685d6d0524ee Parents: 0280696 Author: Matthias Boehm <[email protected]> Authored: Wed Jan 13 20:13:43 2016 -0800 Committer: Matthias Boehm <[email protected]> Committed: Wed Jan 13 20:13:43 2016 -0800 ---------------------------------------------------------------------- src/main/java/org/apache/sysml/hops/Hop.java | 3 +- .../java/org/apache/sysml/hops/UnaryOp.java | 5 +- .../hops/cost/CostEstimatorStaticRuntime.java | 1 + src/main/java/org/apache/sysml/lops/Unary.java | 34 ++++-- .../sysml/parser/BuiltinFunctionExpression.java | 20 ++++ .../org/apache/sysml/parser/DMLTranslator.java | 7 +- .../org/apache/sysml/parser/Expression.java | 1 + .../instructions/CPInstructionParser.java | 1 + .../runtime/matrix/data/LibCommonsMath.java | 119 ++++++++++--------- 9 files changed, 122 insertions(+), 69 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/4f4e94ec/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 3d2c76b..e031a87 100644 --- a/src/main/java/org/apache/sysml/hops/Hop.java +++ b/src/main/java/org/apache/sysml/hops/Hop.java @@ -1026,7 +1026,7 @@ public abstract class Hop public enum OpOp1 { NOT, ABS, SIN, COS, TAN, ASIN, ACOS, ATAN, SIGN, SQRT, LOG, EXP, CAST_AS_SCALAR, CAST_AS_MATRIX, CAST_AS_DOUBLE, CAST_AS_INT, CAST_AS_BOOLEAN, - PRINT, EIGEN, NROW, NCOL, LENGTH, ROUND, IQM, STOP, CEIL, FLOOR, MEDIAN, INVERSE, + PRINT, EIGEN, NROW, NCOL, LENGTH, ROUND, IQM, STOP, CEIL, FLOOR, MEDIAN, INVERSE, CHOLESKY, //cumulative sums, products, extreme values CUMSUM, CUMPROD, CUMMIN, CUMMAX, //fused ML-specific operators for performance @@ -1245,6 +1245,7 @@ public abstract class Hop HopsOpOp1LopsU.put(OpOp1.CUMMIN, org.apache.sysml.lops.Unary.OperationTypes.CUMMIN); HopsOpOp1LopsU.put(OpOp1.CUMMAX, org.apache.sysml.lops.Unary.OperationTypes.CUMMAX); HopsOpOp1LopsU.put(OpOp1.INVERSE, org.apache.sysml.lops.Unary.OperationTypes.INVERSE); + HopsOpOp1LopsU.put(OpOp1.CHOLESKY, org.apache.sysml.lops.Unary.OperationTypes.CHOLESKY); HopsOpOp1LopsU.put(OpOp1.CAST_AS_SCALAR, org.apache.sysml.lops.Unary.OperationTypes.NOTSUPPORTED); HopsOpOp1LopsU.put(OpOp1.CAST_AS_MATRIX, org.apache.sysml.lops.Unary.OperationTypes.NOTSUPPORTED); HopsOpOp1LopsU.put(OpOp1.SPROP, org.apache.sysml.lops.Unary.OperationTypes.SPROP); http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/4f4e94ec/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 a3ca530..4437cdb 100644 --- a/src/main/java/org/apache/sysml/hops/UnaryOp.java +++ b/src/main/java/org/apache/sysml/hops/UnaryOp.java @@ -674,8 +674,11 @@ public class UnaryOp extends Hop setRequiresRecompile(); //ensure cp exec type for single-node operations - if( _op == OpOp1.PRINT || _op == OpOp1.STOP || _op == OpOp1.INVERSE || _op == OpOp1.EIGEN ) + if( _op == OpOp1.PRINT || _op == OpOp1.STOP + || _op == OpOp1.INVERSE || _op == OpOp1.EIGEN || _op == OpOp1.CHOLESKY ) + { _etype = ExecType.CP; + } return _etype; } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/4f4e94ec/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 73203f0..b68285f 100644 --- a/src/main/java/org/apache/sysml/hops/cost/CostEstimatorStaticRuntime.java +++ b/src/main/java/org/apache/sysml/hops/cost/CostEstimatorStaticRuntime.java @@ -1005,6 +1005,7 @@ public class CostEstimatorStaticRuntime extends CostEstimator case BuiltinUnary: //opcodes: exp, abs, sin, cos, tan, sign, sqrt, plogp, print, round, sprop, sigmoid + //TODO add cost functions for commons math builtins: inverse, cholesky if( optype.equals("print") ) //scalar only return 1; else http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/4f4e94ec/src/main/java/org/apache/sysml/lops/Unary.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/lops/Unary.java b/src/main/java/org/apache/sysml/lops/Unary.java index 8375202..1f56d66 100644 --- a/src/main/java/org/apache/sysml/lops/Unary.java +++ b/src/main/java/org/apache/sysml/lops/Unary.java @@ -40,7 +40,7 @@ public class Unary extends Lop ADD, SUBTRACT, SUBTRACTRIGHT, MULTIPLY, MULTIPLY2, DIVIDE, MODULUS, INTDIV, MINUS1_MULTIPLY, POW, POW2, LOG, MAX, MIN, NOT, ABS, SIN, COS, TAN, ASIN, ACOS, ATAN, SIGN, SQRT, EXP, Over, LESS_THAN, LESS_THAN_OR_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUALS, EQUALS, NOT_EQUALS, - ROUND, CEIL, FLOOR, MR_IQM, INVERSE, + ROUND, CEIL, FLOOR, MR_IQM, INVERSE, CHOLESKY, CUMSUM, CUMPROD, CUMMIN, CUMMAX, SPROP, SIGMOID, SELP, SUBTRACT_NZ, LOG_NZ, NOTSUPPORTED @@ -107,27 +107,32 @@ public class Unary extends Lop * * @param input1 * @param op + * @throws LopsException */ - public Unary(Lop input1, OperationTypes op, DataType dt, ValueType vt, ExecType et) { + public Unary(Lop input1, OperationTypes op, DataType dt, ValueType vt, ExecType et) + throws LopsException + { super(Lop.Type.UNARY, dt, vt); init(input1, op, dt, vt, et); } - public Unary(Lop input1, OperationTypes op, DataType dt, ValueType vt) { + public Unary(Lop input1, OperationTypes op, DataType dt, ValueType vt) + throws LopsException + { super(Lop.Type.UNARY, dt, vt); init(input1, op, dt, vt, ExecType.MR); } - private ExecType forceExecType(OperationTypes op, ExecType et) { - if ( op == OperationTypes.INVERSE ) - return ExecType.CP; - return et; - } - private void init(Lop input1, OperationTypes op, DataType dt, ValueType vt, ExecType et) { - operation = op; - - et = forceExecType(op, et); + private void init(Lop input1, OperationTypes op, DataType dt, ValueType vt, ExecType et) + throws LopsException + { + //sanity check + if ( (op == OperationTypes.INVERSE || op == OperationTypes.CHOLESKY) + && (et == ExecType.SPARK || et == ExecType.MR) ) { + throw new LopsException("Invalid exection type "+et.toString()+" for operation "+op.toString()); + } + operation = op; valInput = null; this.addInput(input1); @@ -301,7 +306,10 @@ public class Unary extends Lop case INVERSE: return "inverse"; - + + case CHOLESKY: + return "cholesky"; + case MR_IQM: return "qpick"; http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/4f4e94ec/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 d56aa08..9273590 100644 --- a/src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java +++ b/src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java @@ -949,6 +949,24 @@ public class BuiltinFunctionExpression extends DataIdentifier output.setDimensions(in.getDim1(), in.getDim2()); output.setBlockDimensions(in.getRowsInBlock(), in.getColumnsInBlock()); break; + + case CHOLESKY: + { + // A = L%*%t(L) where L is the lower triangular matrix + checkNumParameters(1); + checkMatrixParam(getFirstExpr()); + + output.setDataType(DataType.MATRIX); + output.setValueType(ValueType.DOUBLE); + + Identifier inA = getFirstExpr().getOutput(); + if(inA.dimsKnown() && inA.getDim1() != inA.getDim2()) + raiseValidateError("Input to cholesky() must be square matrix -- given: a " + inA.getDim1() + "x" + inA.getDim2() + " matrix.", conditional); + + output.setDimensions(inA.getDim1(), inA.getDim2()); + output.setBlockDimensions(inA.getRowsInBlock(), inA.getColumnsInBlock()); + break; + } case OUTER: Identifier id2 = this.getSecondExpr().getOutput(); @@ -1424,6 +1442,8 @@ public class BuiltinFunctionExpression extends DataIdentifier bifop = Expression.BuiltinFunctionOp.MEDIAN; else if (functionName.equals("inv")) bifop = Expression.BuiltinFunctionOp.INVERSE; + else if (functionName.equals("cholesky")) + bifop = Expression.BuiltinFunctionOp.CHOLESKY; else if (functionName.equals("sample")) bifop = Expression.BuiltinFunctionOp.SAMPLE; else if ( functionName.equals("outer") ) http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/4f4e94ec/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 c643396..017c246 100644 --- a/src/main/java/org/apache/sysml/parser/DMLTranslator.java +++ b/src/main/java/org/apache/sysml/parser/DMLTranslator.java @@ -2708,10 +2708,15 @@ public class DMLTranslator break; case INVERSE: - currBuiltinOp=new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), + currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp1.INVERSE, expr); break; + case CHOLESKY: + currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), + Hop.OpOp1.CHOLESKY, expr); + break; + case OUTER: if( !(expr3 instanceof LiteralOp) ) throw new HopsException("Operator for outer builtin function must be a constant: "+expr3); http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/4f4e94ec/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 709a581..99edb74 100644 --- a/src/main/java/org/apache/sysml/parser/Expression.java +++ b/src/main/java/org/apache/sysml/parser/Expression.java @@ -60,6 +60,7 @@ public abstract class Expression CAST_AS_SCALAR, CBIND, //previously APPEND CEIL, + CHOLESKY, COLMAX, COLMEAN, COLMIN, http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/4f4e94ec/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 c70f6a9..4cb67e3 100644 --- a/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java +++ b/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java @@ -167,6 +167,7 @@ public class CPInstructionParser extends InstructionParser String2CPInstructionType.put( "ucummax", CPINSTRUCTION_TYPE.BuiltinUnary); String2CPInstructionType.put( "stop" , CPINSTRUCTION_TYPE.BuiltinUnary); String2CPInstructionType.put( "inverse", CPINSTRUCTION_TYPE.BuiltinUnary); + String2CPInstructionType.put( "cholesky",CPINSTRUCTION_TYPE.BuiltinUnary); String2CPInstructionType.put( "sprop", CPINSTRUCTION_TYPE.BuiltinUnary); String2CPInstructionType.put( "sigmoid", CPINSTRUCTION_TYPE.BuiltinUnary); String2CPInstructionType.put( "sel+", CPINSTRUCTION_TYPE.BuiltinUnary); http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/4f4e94ec/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 52569d1..cb163f8 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 @@ -20,12 +20,12 @@ package org.apache.sysml.runtime.matrix.data; import org.apache.commons.math3.linear.Array2DRowRealMatrix; +import org.apache.commons.math3.linear.CholeskyDecomposition; import org.apache.commons.math3.linear.DecompositionSolver; 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.sysml.runtime.DMLRuntimeException; import org.apache.sysml.runtime.controlprogram.caching.MatrixObject; import org.apache.sysml.runtime.util.DataConverter; @@ -38,62 +38,52 @@ import org.apache.sysml.runtime.util.DataConverter; * matrix inverse, matrix decompositions (QR, LU, Eigen), solve */ public class LibCommonsMath -{ - - public static boolean isSupportedUnaryOperation( String opcode ) - { - if ( opcode.equals("inverse") ) { - return true; - } - return false; +{ + private LibCommonsMath() { + //prevent instantiation via private constructor } - public static boolean isSupportedMultiReturnOperation( String opcode ) - { - - if ( opcode.equals("qr") || opcode.equals("lu") || opcode.equals("eigen") ) { - return true; - } - return false; + public static boolean isSupportedUnaryOperation( String opcode ) { + return ( opcode.equals("inverse") || opcode.equals("cholesky") ); } - public static boolean isSupportedMatrixMatrixOperation( String opcode ) - { - if ( opcode.equals("solve") ) { - return true; - } - return false; + public static boolean isSupportedMultiReturnOperation( String opcode ) { + return ( opcode.equals("qr") || opcode.equals("lu") || opcode.equals("eigen") ); } - private LibCommonsMath() { - //prevent instantiation via private constructor + public static boolean isSupportedMatrixMatrixOperation( String opcode ) { + return ( opcode.equals("solve") ); } - - public static MatrixBlock unaryOperations(MatrixObject inj, String opcode) throws DMLRuntimeException { + + public static MatrixBlock unaryOperations(MatrixObject inj, String opcode) + throws DMLRuntimeException + { Array2DRowRealMatrix matrixInput = DataConverter.convertToArray2DRowRealMatrix(inj); - MatrixBlock out = null; if(opcode.equals("inverse")) - out = computeMatrixInverse(matrixInput); - - return out; + return computeMatrixInverse(matrixInput); + else if (opcode.equals("cholesky")) + return computeCholesky(matrixInput); + return null; } - public static MatrixBlock[] multiReturnOperations(MatrixObject in, String opcode) throws DMLRuntimeException { - MatrixBlock[] out = null; + public static MatrixBlock[] multiReturnOperations(MatrixObject in, String opcode) + throws DMLRuntimeException + { if(opcode.equals("qr")) - out = computeQR(in); + return computeQR(in); else if (opcode.equals("lu")) - out = computeLU(in); + return computeLU(in); else if (opcode.equals("eigen")) - out = computeEigen(in); - return out; + return computeEigen(in); + return null; } - public static MatrixBlock matrixMatrixOperations(MatrixObject in1, MatrixObject in2, String opcode) throws DMLRuntimeException { - MatrixBlock out = null; + public static MatrixBlock matrixMatrixOperations(MatrixObject in1, MatrixObject in2, String opcode) + throws DMLRuntimeException + { if(opcode.equals("solve")) - out = computeSolve(in1, in2); - return out; + return computeSolve(in1, in2); + return null; } /** @@ -104,7 +94,9 @@ public class LibCommonsMath * @return * @throws DMLRuntimeException */ - private static MatrixBlock computeSolve(MatrixObject in1, MatrixObject in2) throws DMLRuntimeException { + private static MatrixBlock computeSolve(MatrixObject in1, MatrixObject in2) + throws DMLRuntimeException + { Array2DRowRealMatrix matrixInput = DataConverter.convertToArray2DRowRealMatrix(in1); Array2DRowRealMatrix vectorInput = DataConverter.convertToArray2DRowRealMatrix(in2); @@ -118,9 +110,7 @@ public class LibCommonsMath // Invoke solve RealMatrix solutionMatrix = solver.solve(vectorInput); - MatrixBlock solution = DataConverter.convertToMatrixBlock(solutionMatrix.getData()); - - return solution; + return DataConverter.convertToMatrixBlock(solutionMatrix.getData()); } /** @@ -130,7 +120,9 @@ public class LibCommonsMath * @return * @throws DMLRuntimeException */ - private static MatrixBlock[] computeQR(MatrixObject in) throws DMLRuntimeException { + private static MatrixBlock[] computeQR(MatrixObject in) + throws DMLRuntimeException + { Array2DRowRealMatrix matrixInput = DataConverter.convertToArray2DRowRealMatrix(in); // Perform QR decomposition @@ -152,7 +144,9 @@ public class LibCommonsMath * @return * @throws DMLRuntimeException */ - private static MatrixBlock[] computeLU(MatrixObject in) throws DMLRuntimeException { + private static MatrixBlock[] computeLU(MatrixObject in) + throws DMLRuntimeException + { if ( in.getNumRows() != in.getNumColumns() ) { throw new DMLRuntimeException("LU Decomposition can only be done on a square matrix. Input matrix is rectangular (rows=" + in.getNumRows() + ", cols="+ in.getNumColumns() +")"); } @@ -181,7 +175,9 @@ public class LibCommonsMath * @return * @throws DMLRuntimeException */ - private static MatrixBlock[] computeEigen(MatrixObject in) throws DMLRuntimeException { + private static MatrixBlock[] computeEigen(MatrixObject in) + throws DMLRuntimeException + { if ( in.getNumRows() != in.getNumColumns() ) { throw new DMLRuntimeException("Eigen Decomposition can only be done on a square matrix. Input matrix is rectangular (rows=" + in.getNumRows() + ", cols="+ in.getNumColumns() +")"); } @@ -228,8 +224,9 @@ public class LibCommonsMath * @return * @throws DMLRuntimeException */ - private static MatrixBlock computeMatrixInverse(Array2DRowRealMatrix in) throws DMLRuntimeException { - + private static MatrixBlock computeMatrixInverse(Array2DRowRealMatrix in) + throws DMLRuntimeException + { if ( !in.isSquare() ) throw new DMLRuntimeException("Input to inv() must be square matrix -- given: a " + in.getRowDimension() + "x" + in.getColumnDimension() + " matrix."); @@ -237,10 +234,26 @@ public class LibCommonsMath DecompositionSolver solver = qrdecompose.getSolver(); RealMatrix inverseMatrix = solver.getInverse(); - MatrixBlock inverse = DataConverter.convertToMatrixBlock(inverseMatrix.getData()); - - return inverse; + return DataConverter.convertToMatrixBlock(inverseMatrix.getData()); } -} + /** + * Function to compute Cholesky decomposition of the given input matrix. + * The input must be a real symmetric positive-definite matrix. + * + * @param in + * @return + * @throws DMLRuntimeException + */ + private static MatrixBlock computeCholesky(Array2DRowRealMatrix in) + throws DMLRuntimeException + { + if ( !in.isSquare() ) + throw new DMLRuntimeException("Input to cholesky() must be square matrix -- given: a " + in.getRowDimension() + "x" + in.getColumnDimension() + " matrix."); + CholeskyDecomposition cholesky = new CholeskyDecomposition(in); + RealMatrix rmL = cholesky.getL(); + + return DataConverter.convertToMatrixBlock(rmL.getData()); + } +}
