Repository: incubator-systemml Updated Branches: refs/heads/master dfdd774f6 -> fcfe893f1
[SYSTEMML-510] Generalized wdivmm w/ eps all patterns This patch with related tests extends the existing wdivmm operator by two patterns for four operands: t(t(U)%%(W(U%%t(V)+x))), and (W(U%%t(V)+x)%%V, where x is a scalar (e.g., epsilon). Supporting these patterns allows a DML script to contain epsilon similar to an equivalent R script that included epsilon to prevent divide-by-zero. Closes #77. Project: http://git-wip-us.apache.org/repos/asf/incubator-systemml/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-systemml/commit/fcfe893f Tree: http://git-wip-us.apache.org/repos/asf/incubator-systemml/tree/fcfe893f Diff: http://git-wip-us.apache.org/repos/asf/incubator-systemml/diff/fcfe893f Branch: refs/heads/master Commit: fcfe893f10596407e07b80b374613fe39bcc9375 Parents: dfdd774 Author: Glenn Weidner <[email protected]> Authored: Thu Mar 3 10:50:19 2016 -0800 Committer: Deron Eriksson <[email protected]> Committed: Thu Mar 3 10:50:19 2016 -0800 ---------------------------------------------------------------------- docs/devdocs/MatrixMultiplicationOperators.txt | 5 +- .../org/apache/sysml/hops/QuaternaryOp.java | 28 +++--- .../RewriteAlgebraicSimplificationDynamic.java | 63 +++++++++++++ .../org/apache/sysml/lops/WeightedDivMM.java | 25 ++++-- .../org/apache/sysml/lops/WeightedDivMMR.java | 11 ++- .../cp/QuaternaryCPInstruction.java | 18 +++- .../instructions/mr/QuaternaryInstruction.java | 16 +++- .../spark/QuaternarySPInstruction.java | 9 +- .../runtime/matrix/data/LibMatrixMult.java | 37 +++++--- .../sysml/runtime/matrix/data/MatrixBlock.java | 4 + .../matrix/operators/QuaternaryOperator.java | 21 +++++ .../quaternary/WeightedDivMatrixMultTest.java | 94 +++++++++++++++++++- .../functions/quaternary/WeightedDivMMLeftEps.R | 38 ++++++++ .../quaternary/WeightedDivMMLeftEps.dml | 32 +++++++ .../quaternary/WeightedDivMMRightEps.R | 38 ++++++++ .../quaternary/WeightedDivMMRightEps.dml | 32 +++++++ 16 files changed, 426 insertions(+), 45 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/docs/devdocs/MatrixMultiplicationOperators.txt ---------------------------------------------------------------------- diff --git a/docs/devdocs/MatrixMultiplicationOperators.txt b/docs/devdocs/MatrixMultiplicationOperators.txt index f10672d..9809454 100644 --- a/docs/devdocs/MatrixMultiplicationOperators.txt +++ b/docs/devdocs/MatrixMultiplicationOperators.txt @@ -1,6 +1,6 @@ ##################################################################### # TITLE: An Overview of Matrix Multiplication Operators in SystemML # -# DATE MODIFIED: 11/21/2015 # +# DATE MODIFIED: 02/20/2016 # ##################################################################### In the following, we give an overview of backend-specific physical matrix multiplication operators in SystemML as well as their internally used matrix multiplication block operations. @@ -115,7 +115,8 @@ C) CORE MATRIX MULT PRIMITIVES LibMatrixMult (incl related script patterns) (c) t(t(U)%*%(W*(U%*%t(V)))), (d) (W*(U%*%t(V)))%*%V, (e) W*(U%*%t(V)), (f) t(t(U)%*%((X!=0)*(U%*%t(V)-X))), (g) (X!=0)*(U%*%t(V)-X)%*%V, (h) t(t(U)%*%(W*(U%*%t(V)-X))), - (i) (W*(U%*%t(V)-X)%*%V + (i) (W*(U%*%t(V)-X)%*%V, + (j) t(t(U)%*%(W/(U%*%t(V)+x))), (k) (W/(U%*%t(V)+x))%*%V - sequential / multi-threaded (same block ops, par over rows in X) - all dense, sparse-dense factors, sparse/dense-* x 9 patterns http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/main/java/org/apache/sysml/hops/QuaternaryOp.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/QuaternaryOp.java b/src/main/java/org/apache/sysml/hops/QuaternaryOp.java index 6cfd32c..b011b8e 100644 --- a/src/main/java/org/apache/sysml/hops/QuaternaryOp.java +++ b/src/main/java/org/apache/sysml/hops/QuaternaryOp.java @@ -819,10 +819,10 @@ public class QuaternaryOp extends Hop implements MultiThreadedHop //MR operator selection, part1 double m1Size = OptimizerUtils.estimateSize(U.getDim1(), U.getDim2()); //size U double m2Size = OptimizerUtils.estimateSize(V.getDim1(), V.getDim2()); //size V - boolean isMapWsloss = (!wtype.hasFourInputs() && + boolean isMapWdivmm = ((!wtype.hasFourInputs() || wtype.hasScalar()) && m1Size+m2Size < OptimizerUtils.getRemoteMemBudgetMap(true)); - if( !FORCE_REPLICATION && isMapWsloss ) //broadcast + if( !FORCE_REPLICATION && isMapWdivmm ) //broadcast { //partitioning of U boolean needPartU = !U.dimsKnown() || U.getDim1() * U.getDim2() > DistributedCacheInput.PARTITION_SIZE; @@ -842,7 +842,7 @@ public class QuaternaryOp extends Hop implements MultiThreadedHop setLineNumbers(lV); } - //map-side wsloss always with broadcast + //map-side wdivmm always with broadcast Lop wdivmm = new WeightedDivMM( W.constructLops(), lU, lV, X.constructLops(), DataType.MATRIX, ValueType.DOUBLE, wtype, ExecType.MR); setOutputDimensions(wdivmm); @@ -861,7 +861,7 @@ public class QuaternaryOp extends Hop implements MultiThreadedHop setLineNumbers(grpW); Lop grpX = X.constructLops(); - if( wtype.hasFourInputs() ) + if( wtype.hasFourInputs() && (X.getDataType() != DataType.SCALAR) ) grpX = new Group(grpX, Group.OperationTypes.Sort, DataType.MATRIX, ValueType.DOUBLE); grpX.getOutputParameters().setDimensions(X.getDim1(), X.getDim2(), X.getRowsInBlock(), X.getColsInBlock(), X.getNnz()); setLineNumbers(grpX); @@ -921,7 +921,7 @@ public class QuaternaryOp extends Hop implements MultiThreadedHop lV = grpV; } - //reduce-side wsloss w/ or without broadcast + //reduce-side wdivmm w/ or without broadcast Lop wdivmm = new WeightedDivMMR( grpW, lU, lV, grpX, DataType.MATRIX, ValueType.DOUBLE, wtype, cacheU, cacheV, ExecType.MR); setOutputDimensions(wdivmm); @@ -970,12 +970,12 @@ public class QuaternaryOp extends Hop implements MultiThreadedHop //MR operator selection, part1 double m1Size = OptimizerUtils.estimateSize(U.getDim1(), U.getDim2()); //size U double m2Size = OptimizerUtils.estimateSize(V.getDim1(), V.getDim2()); //size V - boolean isMapWsloss = (!wtype.hasFourInputs() && m1Size+m2Size < memBudgetExec + boolean isMapWdivmm = ((!wtype.hasFourInputs() || wtype.hasScalar()) && m1Size+m2Size < memBudgetExec && 2*m1Size<memBudgetLocal && 2*m2Size<memBudgetLocal); - if( !FORCE_REPLICATION && isMapWsloss ) //broadcast + if( !FORCE_REPLICATION && isMapWdivmm ) //broadcast { - //map-side wsloss always with broadcast + //map-side wdivmm always with broadcast Lop wdivmm = new WeightedDivMM( W.constructLops(), U.constructLops(), V.constructLops(), X.constructLops(), DataType.MATRIX, ValueType.DOUBLE, wtype, ExecType.SPARK); setOutputDimensions(wdivmm); @@ -989,7 +989,7 @@ public class QuaternaryOp extends Hop implements MultiThreadedHop boolean cacheV = !FORCE_REPLICATION && ((!cacheU && m2Size < memBudgetExec ) || (cacheU && m1Size+m2Size < memBudgetExec)) && 2*m2Size < memBudgetLocal; - //reduce-side wsloss w/ or without broadcast + //reduce-side wdivmm w/ or without broadcast Lop wdivmm = new WeightedDivMMR( W.constructLops(), U.constructLops(), V.constructLops(), X.constructLops(), DataType.MATRIX, ValueType.DOUBLE, wtype, cacheU, cacheV, ExecType.SPARK); @@ -1507,7 +1507,11 @@ public class QuaternaryOp extends Hop implements MultiThreadedHop else if( _minus ) return WDivMMType.MULT_MINUS_RIGHT; else - return _mult ? WDivMMType.MULT_RIGHT : WDivMMType.DIV_RIGHT; + return _mult ? WDivMMType.MULT_RIGHT : WDivMMType.DIV_RIGHT; + case 3: //LEFT w/EPS + return WDivMMType.DIV_LEFT_EPS; + case 4: //RIGHT w/EPS + return WDivMMType.DIV_RIGHT_EPS; } return null; @@ -1561,7 +1565,7 @@ public class QuaternaryOp extends Hop implements MultiThreadedHop MatrixCharacteristics mcW = memo.getAllInputStats(getInput().get(0)); ret = new long[]{mcW.getRows(), mcW.getCols(), mcW.getNonZeros()}; } - if( _baseType == 1 ) { //left (w/ transpose) + if( _baseType == 1 || _baseType == 3 ) { //left (w/ transpose or w/ epsilon) MatrixCharacteristics mcV = memo.getAllInputStats(getInput().get(2)); ret = new long[]{mcV.getRows(), mcV.getCols(), -1}; } @@ -1639,7 +1643,7 @@ public class QuaternaryOp extends Hop implements MultiThreadedHop setDim2( inW.getDim2() ); setNnz( inW.getNnz() ); } - else if( _baseType == 1 ){ //left (w/ transpose) + else if( _baseType == 1 || _baseType == 3 ){ //left (w/ transpose or w/ epsilon) Hop inV = getInput().get(2); setDim1( inV.getDim1() ); setDim2( inV.getDim2() ); http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationDynamic.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationDynamic.java b/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationDynamic.java index 68f3a30..f23f87d 100644 --- a/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationDynamic.java +++ b/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationDynamic.java @@ -1871,6 +1871,39 @@ public class RewriteAlgebraicSimplificationDynamic extends HopRewriteRule } } + //Pattern 1e) t(U) %*% (W/(U%*%t(V) + x)) + if( !appliedPattern + && right instanceof BinaryOp && ((BinaryOp)right).getOp() == LOOKUP_VALID_WDIVMM_BINARY[1] //DIV + && HopRewriteUtils.isEqualSize(right.getInput().get(0), right.getInput().get(1)) //prevent mv + && right.getInput().get(1) instanceof BinaryOp + && ((BinaryOp) right.getInput().get(1)).getOp() == Hop.OpOp2.PLUS + && right.getInput().get(1).getInput().get(1).getDataType() == DataType.SCALAR + && HopRewriteUtils.isSingleBlock(right.getInput().get(1).getInput().get(0).getInput().get(0),true) ) //BLOCKSIZE CONSTRAINT + { + Hop W = right.getInput().get(0); + Hop U = right.getInput().get(1).getInput().get(0).getInput().get(0); + Hop V = right.getInput().get(1).getInput().get(0).getInput().get(1); + Hop X = right.getInput().get(1).getInput().get(1); + + if( HopRewriteUtils.isTransposeOfItself(left, U) ) + { + if( !HopRewriteUtils.isTransposeOperation(V) ) + V = HopRewriteUtils.createTranspose(V); + else + V = V.getInput().get(0); + + hnew = new QuaternaryOp(hi.getName(), DataType.MATRIX, ValueType.DOUBLE, + OpOp4.WDIVMM, W, U, V, X, 3, false, false); // 3=>DIV_LEFT_EPS + HopRewriteUtils.setOutputBlocksizes(hnew, W.getRowsInBlock(), W.getColsInBlock()); + + //add output transpose for efficient target indexing (redundant t() removed by other rewrites) + hnew = HopRewriteUtils.createTranspose(hnew); + + appliedPattern = true; + LOG.debug("Applied simplifyWeightedDivMM1e (line "+hi.getBeginLine()+")"); + } + } + //Pattern 2) (W/(U%*%t(V))) %*% V //alternative pattern: (W*(U%*%t(V))) %*% V if( !appliedPattern @@ -1900,6 +1933,36 @@ public class RewriteAlgebraicSimplificationDynamic extends HopRewriteRule } } + //Pattern 2e) (W/(U%*%t(V) + x)) %*% V + if( !appliedPattern + && left instanceof BinaryOp && ((BinaryOp)left).getOp() == LOOKUP_VALID_WDIVMM_BINARY[1] //DIV + && HopRewriteUtils.isEqualSize(left.getInput().get(0), left.getInput().get(1)) //prevent mv + && left.getInput().get(1) instanceof BinaryOp + && ((BinaryOp) left.getInput().get(1)).getOp() == Hop.OpOp2.PLUS + && left.getInput().get(1).getInput().get(1).getDataType() == DataType.SCALAR + && HopRewriteUtils.isSingleBlock(left.getInput().get(1).getInput().get(0).getInput().get(0),true) ) //BLOCKSIZE CONSTRAINT + { + Hop W = left.getInput().get(0); + Hop U = left.getInput().get(1).getInput().get(0).getInput().get(0); + Hop V = left.getInput().get(1).getInput().get(0).getInput().get(1); + Hop X = left.getInput().get(1).getInput().get(1); + + if( HopRewriteUtils.isTransposeOfItself(right, V) ) + { + if( !HopRewriteUtils.isTransposeOperation(V) ) + V = right; + else + V = V.getInput().get(0); + + hnew = new QuaternaryOp(hi.getName(), DataType.MATRIX, ValueType.DOUBLE, + OpOp4.WDIVMM, W, U, V, X, 4, false, false); // 4=>DIV_RIGHT_EPS + HopRewriteUtils.setOutputBlocksizes(hnew, W.getRowsInBlock(), W.getColsInBlock()); + + appliedPattern = true; + LOG.debug("Applied simplifyWeightedDivMM2e (line "+hi.getBeginLine()+")"); + } + } + //Pattern 3) t(U) %*% ((X!=0)*(U%*%t(V)-X)) if( !appliedPattern && right instanceof BinaryOp && ((BinaryOp)right).getOp()==LOOKUP_VALID_WDIVMM_BINARY[0] //MULT http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/main/java/org/apache/sysml/lops/WeightedDivMM.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/lops/WeightedDivMM.java b/src/main/java/org/apache/sysml/lops/WeightedDivMM.java index 94f5c19..19a167d 100644 --- a/src/main/java/org/apache/sysml/lops/WeightedDivMM.java +++ b/src/main/java/org/apache/sysml/lops/WeightedDivMM.java @@ -38,6 +38,8 @@ public class WeightedDivMM extends Lop public enum WDivMMType { DIV_LEFT, //t(t(U) %*% (W / U%*%t(V))) DIV_RIGHT, //(W / U%*%t(V)) %*% V + DIV_LEFT_EPS, //t(t(U) %*% (W / (U%*%t(V) + x))) + DIV_RIGHT_EPS, //(W / (U%*%t(V) + x)) %*% V MULT_BASIC, //(W * U%*%t(V)) MULT_LEFT, //t(t(U) %*% (W * U%*%t(V))) MULT_RIGHT, //(W * U%*%t(V)) %*% V @@ -51,7 +53,7 @@ public class WeightedDivMM extends Lop return (this == MULT_BASIC); } public boolean isLeft() { - return (this == DIV_LEFT || this == MULT_LEFT + return (this == DIV_LEFT || this == DIV_LEFT_EPS || this == MULT_LEFT || this == MULT_MINUS_LEFT || this == MULT_MINUS_4_LEFT); } public boolean isRight() { @@ -66,7 +68,11 @@ public class WeightedDivMM extends Lop || this == MULT_MINUS_4_LEFT || this == MULT_MINUS_4_RIGHT); } public boolean hasFourInputs() { - return (this == MULT_MINUS_4_LEFT || this == MULT_MINUS_4_RIGHT); + return (this == MULT_MINUS_4_LEFT || this == MULT_MINUS_4_RIGHT + || this == DIV_LEFT_EPS || this == DIV_RIGHT_EPS); + } + public boolean hasScalar() { + return (this == DIV_LEFT_EPS || this == DIV_RIGHT_EPS); } public MatrixCharacteristics computeOutputCharacteristics(long Xrlen, long Xclen, long rank) { @@ -145,10 +151,12 @@ public class WeightedDivMM extends Lop { StringBuilder sb = new StringBuilder(); - sb.append(getExecType()); + final ExecType et = getExecType(); + + sb.append(et); sb.append(Lop.OPERAND_DELIMITOR); - if( getExecType() == ExecType.CP ) + if( et == ExecType.CP ) sb.append(OPCODE_CP); else sb.append(OPCODE); @@ -163,7 +171,12 @@ public class WeightedDivMM extends Lop sb.append( getInputs().get(2).prepInputOperand(input3)); sb.append(Lop.OPERAND_DELIMITOR); - sb.append( getInputs().get(3).prepInputOperand(input4)); + if ( (et == ExecType.MR) && (getInputs().get(3).getDataType() == DataType.SCALAR) ) { + sb.append( getInputs().get(3).prepScalarInputOperand(et)); + } + else { + sb.append( getInputs().get(3).prepInputOperand(input4)); + } sb.append(Lop.OPERAND_DELIMITOR); sb.append( prepOutputOperand(output)); @@ -172,7 +185,7 @@ public class WeightedDivMM extends Lop sb.append(_weightsType); //append degree of parallelism - if( getExecType()==ExecType.CP ) { + if( et == ExecType.CP ) { sb.append( OPERAND_DELIMITOR ); sb.append( _numThreads ); } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/main/java/org/apache/sysml/lops/WeightedDivMMR.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/lops/WeightedDivMMR.java b/src/main/java/org/apache/sysml/lops/WeightedDivMMR.java index 790d90d..cb5bccb 100644 --- a/src/main/java/org/apache/sysml/lops/WeightedDivMMR.java +++ b/src/main/java/org/apache/sysml/lops/WeightedDivMMR.java @@ -107,7 +107,9 @@ public class WeightedDivMMR extends Lop { StringBuilder sb = new StringBuilder(); - sb.append(getExecType()); + final ExecType et = getExecType(); + + sb.append(et); sb.append(Lop.OPERAND_DELIMITOR); sb.append(OPCODE); @@ -122,7 +124,12 @@ public class WeightedDivMMR extends Lop sb.append( getInputs().get(2).prepInputOperand(input3)); sb.append(Lop.OPERAND_DELIMITOR); - sb.append( getInputs().get(3).prepInputOperand(input4)); + if ( (et == ExecType.MR) && (getInputs().get(3).getDataType() == DataType.SCALAR) ) { + sb.append( getInputs().get(3).prepScalarInputOperand(et)); + } + else { + sb.append( getInputs().get(3).prepInputOperand(input4)); + } sb.append(Lop.OPERAND_DELIMITOR); sb.append( prepOutputOperand(output)); http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/main/java/org/apache/sysml/runtime/instructions/cp/QuaternaryCPInstruction.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/instructions/cp/QuaternaryCPInstruction.java b/src/main/java/org/apache/sysml/runtime/instructions/cp/QuaternaryCPInstruction.java index 535684c..2e069f2 100644 --- a/src/main/java/org/apache/sysml/runtime/instructions/cp/QuaternaryCPInstruction.java +++ b/src/main/java/org/apache/sysml/runtime/instructions/cp/QuaternaryCPInstruction.java @@ -24,6 +24,7 @@ import org.apache.sysml.lops.WeightedSigmoid.WSigmoidType; import org.apache.sysml.lops.WeightedSquaredLoss.WeightsType; import org.apache.sysml.lops.WeightedCrossEntropy.WCeMMType; import org.apache.sysml.lops.WeightedUnaryMM.WUMMType; +import org.apache.sysml.parser.Expression.DataType; import org.apache.sysml.runtime.DMLRuntimeException; import org.apache.sysml.runtime.DMLUnsupportedOperationException; import org.apache.sysml.runtime.controlprogram.context.ExecutionContext; @@ -124,7 +125,14 @@ public class QuaternaryCPInstruction extends ComputationCPInstruction MatrixBlock matBlock3 = ec.getMatrixInput(input3.getName()); MatrixBlock matBlock4 = null; if( qop.hasFourInputs() ) { - matBlock4 = ec.getMatrixInput(input4.getName()); + if (input4.getDataType() == DataType.SCALAR) { + matBlock4 = new MatrixBlock(1, 1, false); + final double eps = ec.getScalarInput(input4.getName(), input4.getValueType(), input4.isLiteral()).getDoubleValue(); + matBlock4.quickSetValue(0, 0, eps); + } + else { + matBlock4 = ec.getMatrixInput(input4.getName()); + } } //core execute @@ -136,12 +144,16 @@ public class QuaternaryCPInstruction extends ComputationCPInstruction ec.releaseMatrixInput(input3.getName()); if( qop.wtype1 != null || qop.wtype4 != null ) { //wsloss/wcemm if( qop.wtype1 != null && qop.wtype1.hasFourInputs() ) - ec.releaseMatrixInput(input4.getName()); + if (input4.getDataType() == DataType.MATRIX) { + ec.releaseMatrixInput(input4.getName()); + } ec.setVariable(output.getName(), new DoubleObject(out.getValue(0, 0))); } else { //wsigmoid / wdivmm / wumm if( qop.wtype3 != null && qop.wtype3.hasFourInputs() ) - ec.releaseMatrixInput(input4.getName()); + if (input4.getDataType() == DataType.MATRIX) { + ec.releaseMatrixInput(input4.getName()); + } ec.setMatrixOutput(output.getName(), (MatrixBlock)out); } } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/main/java/org/apache/sysml/runtime/instructions/mr/QuaternaryInstruction.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/instructions/mr/QuaternaryInstruction.java b/src/main/java/org/apache/sysml/runtime/instructions/mr/QuaternaryInstruction.java index 58aa63d..4064378 100644 --- a/src/main/java/org/apache/sysml/runtime/instructions/mr/QuaternaryInstruction.java +++ b/src/main/java/org/apache/sysml/runtime/instructions/mr/QuaternaryInstruction.java @@ -97,7 +97,7 @@ public class QuaternaryInstruction extends MRInstruction implements IDistributed } public byte getInput4() { - return _input3; + return _input4; } /** @@ -215,17 +215,19 @@ public class QuaternaryInstruction extends MRInstruction implements IDistributed //parse instruction parts (without exec type) String[] parts = InstructionUtils.getInstructionParts(str); + final WDivMMType wtype = WDivMMType.valueOf(parts[6]); + byte in1 = Byte.parseByte(parts[1]); byte in2 = Byte.parseByte(parts[2]); byte in3 = Byte.parseByte(parts[3]); - byte in4 = Byte.parseByte(parts[4]); + byte in4 = wtype.hasScalar() ? -1 : Byte.parseByte(parts[4]); byte out = Byte.parseByte(parts[5]); //in mappers always through distcache, in reducers through distcache/shuffle boolean cacheU = isRed ? Boolean.parseBoolean(parts[7]) : true; boolean cacheV = isRed ? Boolean.parseBoolean(parts[8]) : true; - return new QuaternaryInstruction(new QuaternaryOperator(WDivMMType.valueOf(parts[6])), in1, in2, in3, in4, out, cacheU, cacheV, str); + return new QuaternaryInstruction(new QuaternaryOperator(wtype), in1, in2, in3, in4, out, cacheU, cacheV, str); } else //wsigmoid / wcemm { @@ -333,8 +335,14 @@ public class QuaternaryInstruction extends MRInstruction implements IDistributed MatrixValue Xij = inVal; //get Wij if existing (null of WeightsType.NONE or WSigmoid any type) - IndexedMatrixValue iWij = cachedValues.getFirst(_input4); + IndexedMatrixValue iWij = (_input4 != -1) ? cachedValues.getFirst(_input4) : null; MatrixValue Wij = (iWij!=null) ? iWij.getValue() : null; + if (null == Wij && qop.hasFourInputs()) { + MatrixBlock mb = new MatrixBlock(1, 1, false); + String[] parts = InstructionUtils.getInstructionParts(instString); + mb.quickSetValue(0, 0, Double.valueOf(parts[4])); + Wij = mb; + } //get Ui and Vj, potentially through distributed cache MatrixValue Ui = (!_cacheU) ? cachedValues.getFirst(_input2).getValue() //U http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/main/java/org/apache/sysml/runtime/instructions/spark/QuaternarySPInstruction.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/instructions/spark/QuaternarySPInstruction.java b/src/main/java/org/apache/sysml/runtime/instructions/spark/QuaternarySPInstruction.java index 3792743..11595ba 100644 --- a/src/main/java/org/apache/sysml/runtime/instructions/spark/QuaternarySPInstruction.java +++ b/src/main/java/org/apache/sysml/runtime/instructions/spark/QuaternarySPInstruction.java @@ -168,7 +168,9 @@ public class QuaternarySPInstruction extends ComputationSPInstruction boolean cacheU = isRed ? Boolean.parseBoolean(parts[7]) : true; boolean cacheV = isRed ? Boolean.parseBoolean(parts[8]) : true; - return new QuaternarySPInstruction(new QuaternaryOperator(WDivMMType.valueOf(parts[6])), in1, in2, in3, in4, out, cacheU, cacheV, opcode, str); + final WDivMMType wt = WDivMMType.valueOf(parts[6]); + QuaternaryOperator qop = (wt.hasScalar() ? new QuaternaryOperator(wt, Double.parseDouble(in4.getName())) : new QuaternaryOperator(wt)); + return new QuaternarySPInstruction(qop, in1, in2, in3, in4, out, cacheU, cacheV, opcode, str); } else //map/redwsigmoid, map/redwcemm { @@ -249,7 +251,7 @@ public class QuaternarySPInstruction extends ComputationSPInstruction PartitionedBroadcastMatrix bc2 = _cacheV ? sec.getBroadcastForVariable( input3.getName() ) : null; JavaPairRDD<MatrixIndexes,MatrixBlock> inU = (!_cacheU) ? sec.getBinaryBlockRDDHandleForVariable( input2.getName() ) : null; JavaPairRDD<MatrixIndexes,MatrixBlock> inV = (!_cacheV) ? sec.getBinaryBlockRDDHandleForVariable( input3.getName() ) : null; - JavaPairRDD<MatrixIndexes,MatrixBlock> inW = qop.hasFourInputs() ? + JavaPairRDD<MatrixIndexes,MatrixBlock> inW = (qop.hasFourInputs() && !_input4.isLiteral()) ? sec.getBinaryBlockRDDHandleForVariable( _input4.getName() ) : null; //preparation of transposed and replicated U @@ -281,6 +283,9 @@ public class QuaternarySPInstruction extends ComputationSPInstruction else if( inU == null && inV != null && inW != null ) out = in.join(inV).join(inW) .mapToPair(new RDDQuaternaryFunction3(qop, bc1, bc2)); + else if( inU == null && inV == null && inW == null ) { + out = in.mapPartitionsToPair(new RDDQuaternaryFunction1(qop, bc1, bc2), false); + } //function call w/ four rdd inputs else //need keys in case of wdivmm out = in.join(inU).join(inV).join(inW) http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java index 52e6b3f..682f272 100644 --- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java +++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java @@ -2576,6 +2576,8 @@ public class LibMatrixMult final boolean mult = wt.isMult(); final boolean minus = wt.isMinus(); final boolean four = wt.hasFourInputs(); + final boolean scalar = wt.hasScalar(); + final double eps = scalar ? mX.quickGetValue(0, 0) : 0; final int n = mW.clen; final int cd = mU.clen; @@ -2604,7 +2606,10 @@ public class LibMatrixMult if( basic ) c[ix+j] = w[ix+j] * dotProduct(u, v, uix, vix, cd); else if( four ) //left/right - wdivmm(w[ix+j], x[ix+j], u, v, c, uix, vix, left, cd); + if (scalar) + wdivmm(w[ix+j], eps, u, v, c, uix, vix, left, scalar, cd); + else + wdivmm(w[ix+j], x[ix+j], u, v, c, uix, vix, left, scalar, cd); else //left/right minus/default wdivmm(w[ix+j], u, v, c, uix, vix, left, mult, minus, cd); } @@ -2631,6 +2636,8 @@ public class LibMatrixMult final boolean mult = wt.isMult(); final boolean minus = wt.isMinus(); final boolean four = wt.hasFourInputs(); + final boolean scalar = wt.hasScalar(); + final double eps = scalar ? mX.quickGetValue(0, 0) : 0; final int cd = mU.clen; SparseBlock w = mW.sparseBlock; @@ -2660,12 +2667,18 @@ public class LibMatrixMult //O(n) where n is nnz in w/x double[] xvals = x.values(i); for( ; k<wpos+wlen && wix[k]<cu; k++ ) - wdivmm(wval[k], xvals[k], u, v, c, uix, wix[k]*cd, left, cd); + if (scalar) + wdivmm(wval[k], eps, u, v, c, uix, wix[k]*cd, left, scalar, cd); + else + wdivmm(wval[k], xvals[k], u, v, c, uix, wix[k]*cd, left, scalar, cd); } else { //O(n log m) where n/m are nnz in w/x for( ; k<wpos+wlen && wix[k]<cu; k++ ) - wdivmm(wval[k], x.get(i, wix[k]), u, v, c, uix, wix[k]*cd, left, cd); + if (scalar) + wdivmm(wval[k], eps, u, v, c, uix, wix[k]*cd, left, scalar, cd); + else + wdivmm(wval[k], x.get(i, wix[k]), u, v, c, uix, wix[k]*cd, left, scalar, cd); } } else { //left/right minus default @@ -2698,6 +2711,8 @@ public class LibMatrixMult final boolean mult = wt.isMult(); final boolean minus = wt.isMinus(); final boolean four = wt.hasFourInputs(); + final boolean scalar = wt.hasScalar(); + final double eps = scalar ? mX.quickGetValue(0, 0) : 0; final int n = mW.clen; final int cd = mU.clen; @@ -2723,8 +2738,8 @@ public class LibMatrixMult ret.appendValue(i, wix[k], uvij); } else if( four ) { //left/right - double xij = mX.quickGetValue(i, wix[k]); - wdivmm(wval[k], xij, mU, mV, c, i, wix[k], left, cd); + double xij = scalar ? eps : mX.quickGetValue(i, wix[k]); + wdivmm(wval[k], xij, mU, mV, c, i, wix[k], left, scalar, cd); } else { //left/right minus/default wdivmm(wval[k], mU, mV, c, i, wix[k], left, mult, minus, cd); @@ -2744,8 +2759,8 @@ public class LibMatrixMult c[ix+j] = dotProductGeneric(mU,mV, i, j, cd); } else if( four ) { //left/right - double xij = mX.quickGetValue(i, j); - wdivmm(w[ix+j], xij, mU, mV, c, i, j, left, cd); + double xij = scalar ? eps : mX.quickGetValue(i, j); + wdivmm(w[ix+j], xij, mU, mV, c, i, j, left, scalar, cd); } else { //left/right minus/default wdivmm(w[ix+j], mU, mV, c, i, j, left, mult, minus, cd); @@ -3654,13 +3669,13 @@ public class LibMatrixMult * @param left * @param len */ - private static void wdivmm( final double wij, final double xij, double[] u, double[] v, double[] c, final int uix, final int vix, final boolean left, final int len ) + private static void wdivmm( final double wij, final double xij, double[] u, double[] v, double[] c, final int uix, final int vix, final boolean left, final boolean scalar, final int len ) { //compute dot product over ui vj double uvij = dotProduct(u, v, uix, vix, len); //compute core wdivmm - double tmpval = wij * (uvij - xij); + double tmpval = scalar ? wij / (uvij + xij) : wij * (uvij - xij); //prepare inputs for final mm int bix = left ? uix : vix; @@ -3714,13 +3729,13 @@ public class LibMatrixMult * @param left * @param len */ - private static void wdivmm( final double wij, final double xij, MatrixBlock u, MatrixBlock v, double[] c, final int uix, final int vix, final boolean left, final int len ) + private static void wdivmm( final double wij, final double xij, MatrixBlock u, MatrixBlock v, double[] c, final int uix, final int vix, final boolean left, final boolean scalar, final int len ) { //compute dot product over ui vj double uvij = dotProductGeneric(u, v, uix, vix, len); //compute core wdivmm - double wtmp = wij * (uvij - xij); + double wtmp = scalar ? wij / (uvij + xij) : wij * (uvij - xij); //prepare inputs for final mm int bix = left ? uix : vix; http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java b/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java index ddafe99..49fb9b0 100644 --- a/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java +++ b/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java @@ -5792,6 +5792,10 @@ public class MatrixBlock extends MatrixValue implements Externalizable else if( qop.wtype3 != null ){ //wdivmm //note: for wdivmm-minus X and W interchanged because W always present MatrixBlock W = qop.wtype3.hasFourInputs() ? checkType(wm) : null; + if( qop.getScalar() != 0 ) { + W = new MatrixBlock(1, 1, false); + W.quickSetValue(0, 0, qop.getScalar()); + } if( k > 1 ) LibMatrixMult.matrixMultWDivMM(X, U, V, W, R, qop.wtype3, k); else http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/main/java/org/apache/sysml/runtime/matrix/operators/QuaternaryOperator.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/matrix/operators/QuaternaryOperator.java b/src/main/java/org/apache/sysml/runtime/matrix/operators/QuaternaryOperator.java index 78ec7af..2fee897 100644 --- a/src/main/java/org/apache/sysml/runtime/matrix/operators/QuaternaryOperator.java +++ b/src/main/java/org/apache/sysml/runtime/matrix/operators/QuaternaryOperator.java @@ -43,6 +43,8 @@ public class QuaternaryOperator extends Operator public ValueFunction fn; + private double eps = 0; + /** * wsloss * @@ -72,6 +74,16 @@ public class QuaternaryOperator extends Operator } /** + * wdivmm w/epsilon + * + * @param wt + */ + public QuaternaryOperator( WDivMMType wt, double epsilon) { + wtype3 = wt; + eps = epsilon; + } + + /** * wcemm * * @param wt @@ -105,4 +117,13 @@ public class QuaternaryOperator extends Operator return (wtype1 != null && wtype1.hasFourInputs()) || (wtype3 != null && wtype3.hasFourInputs()); } + + /** + * + * @return epsilon + */ + public double getScalar() { + return eps; + } + } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/test/java/org/apache/sysml/test/integration/functions/quaternary/WeightedDivMatrixMultTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/quaternary/WeightedDivMatrixMultTest.java b/src/test/java/org/apache/sysml/test/integration/functions/quaternary/WeightedDivMatrixMultTest.java index 3704678..aa7e667 100644 --- a/src/test/java/org/apache/sysml/test/integration/functions/quaternary/WeightedDivMatrixMultTest.java +++ b/src/test/java/org/apache/sysml/test/integration/functions/quaternary/WeightedDivMatrixMultTest.java @@ -56,10 +56,13 @@ public class WeightedDivMatrixMultTest extends AutomatedTestBase private final static String TEST_NAME7 = "WeightedDivMMMultMinusRight"; private final static String TEST_NAME8 = "WeightedDivMM4MultMinusLeft"; private final static String TEST_NAME9 = "WeightedDivMM4MultMinusRight"; + private final static String TEST_NAME10 = "WeightedDivMMLeftEps"; + private final static String TEST_NAME11 = "WeightedDivMMRightEps"; private final static String TEST_DIR = "functions/quaternary/"; private final static String TEST_CLASS_DIR = TEST_DIR + WeightedDivMatrixMultTest.class.getSimpleName() + "/"; private final static double eps = 1e-6; + private final static double div_eps = 0.1; private final static int rows = 1201; private final static int cols = 1103; @@ -80,6 +83,8 @@ public class WeightedDivMatrixMultTest extends AutomatedTestBase addTestConfiguration(TEST_NAME7,new TestConfiguration(TEST_CLASS_DIR, TEST_NAME7,new String[]{"R"})); addTestConfiguration(TEST_NAME8,new TestConfiguration(TEST_CLASS_DIR, TEST_NAME8,new String[]{"R"})); addTestConfiguration(TEST_NAME9,new TestConfiguration(TEST_CLASS_DIR, TEST_NAME9,new String[]{"R"})); + addTestConfiguration(TEST_NAME10,new TestConfiguration(TEST_CLASS_DIR, TEST_NAME10,new String[]{"R"})); + addTestConfiguration(TEST_NAME11,new TestConfiguration(TEST_CLASS_DIR, TEST_NAME11,new String[]{"R"})); if (TEST_CACHE_ENABLED) { setOutAndExpectedDeletionDisabled(true); @@ -465,6 +470,88 @@ public class WeightedDivMatrixMultTest extends AutomatedTestBase runWeightedDivMMTest(TEST_NAME9, false, true, true, ExecType.SPARK); } + //c) testcases for wdivmm w/ DIVIDE LEFT/RIGHT with Epsilon + + @Test + public void testWeightedDivMMLeftEpsDenseCP() { + runWeightedDivMMTest(TEST_NAME10, false, true, false, ExecType.CP); + } + + @Test + public void testWeightedDivMMLeftEpsSparseCP() { + runWeightedDivMMTest(TEST_NAME10, true, true, false, ExecType.CP); + } + + @Test + public void testWeightedDivMMRightEpsDenseCP() { + runWeightedDivMMTest(TEST_NAME11, false, true, false, ExecType.CP); + } + + @Test + public void testWeightedDivMMRightEpsSparseCP() { + runWeightedDivMMTest(TEST_NAME11, true, true, false, ExecType.CP); + } + + @Test + public void testWeightedDivMMLeftEpsDenseMR() { + runWeightedDivMMTest(TEST_NAME10, false, true, false, ExecType.MR); + } + + @Test + public void testWeightedDivMMLeftEpsSparseMR() { + runWeightedDivMMTest(TEST_NAME10, true, true, false, ExecType.MR); + } + + @Test + public void testWeightedDivMMLeftEpsDenseMRRep() { + runWeightedDivMMTest(TEST_NAME10, false, true, true, ExecType.MR); + } + + @Test + public void testWeightedDivMMRightEpsDenseMR() { + runWeightedDivMMTest(TEST_NAME11, false, true, false, ExecType.MR); + } + + @Test + public void testWeightedDivMMRightEpsSparseMR() { + runWeightedDivMMTest(TEST_NAME11, true, true, false, ExecType.MR); + } + + @Test + public void testWeightedDivMMRightEpsDenseMRRep() { + runWeightedDivMMTest(TEST_NAME11, false, true, true, ExecType.MR); + } + + @Test + public void testWeightedDivMMLeftEpsDenseSP() { + runWeightedDivMMTest(TEST_NAME10, false, true, false, ExecType.SPARK); + } + + @Test + public void testWeightedDivMMLeftEpsSparseSP() { + runWeightedDivMMTest(TEST_NAME10, true, true, false, ExecType.SPARK); + } + + @Test + public void testWeightedDivMMLeftEpsDenseSPRep() { + runWeightedDivMMTest(TEST_NAME10, false, true, true, ExecType.SPARK); + } + + @Test + public void testWeightedDivMMRightEpsDenseSP() { + runWeightedDivMMTest(TEST_NAME11, false, true, false, ExecType.SPARK); + } + + @Test + public void testWeightedDivMMRightEpsSparseSP() { + runWeightedDivMMTest(TEST_NAME11, true, true, false, ExecType.SPARK); + } + + @Test + public void testWeightedDivMMRightEpsDenseSPRep() { + runWeightedDivMMTest(TEST_NAME11, false, true, true, ExecType.SPARK); + } + /** * * @param sparseM1 @@ -494,7 +581,8 @@ public class WeightedDivMatrixMultTest extends AutomatedTestBase { boolean basic = testname.equals(TEST_NAME3); boolean left = testname.equals(TEST_NAME1) || testname.equals(TEST_NAME4) - || testname.equals(TEST_NAME6) || testname.equals(TEST_NAME8); + || testname.equals(TEST_NAME6) || testname.equals(TEST_NAME8) + || testname.equals(TEST_NAME10); double sparsity = (sparse) ? spSparse : spDense; String TEST_NAME = testname; String TEST_CACHE_DIR = TEST_CACHE_ENABLED ? @@ -507,10 +595,10 @@ public class WeightedDivMatrixMultTest extends AutomatedTestBase String HOME = SCRIPT_DIR + TEST_DIR; fullDMLScriptName = HOME + TEST_NAME + ".dml"; programArgs = new String[]{"-stats", "-explain", "runtime", "-args", - input("W"), input("U"), input("V"), output("R") }; + input("W"), input("U"), input("V"), output("R"), Double.toString(div_eps) }; fullRScriptName = HOME + TEST_NAME + ".R"; - rCmd = "Rscript" + " " + fullRScriptName + " " + inputDir() + " " + expectedDir(); + rCmd = "Rscript" + " " + fullRScriptName + " " + inputDir() + " " + expectedDir() + " " + div_eps; //generate actual dataset double[][] W = getRandomMatrix(rows, cols, 0, 1, sparsity, 7); http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/test/scripts/functions/quaternary/WeightedDivMMLeftEps.R ---------------------------------------------------------------------- diff --git a/src/test/scripts/functions/quaternary/WeightedDivMMLeftEps.R b/src/test/scripts/functions/quaternary/WeightedDivMMLeftEps.R new file mode 100644 index 0000000..75ebff8 --- /dev/null +++ b/src/test/scripts/functions/quaternary/WeightedDivMMLeftEps.R @@ -0,0 +1,38 @@ +#------------------------------------------------------------- +# +# 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. +# +#------------------------------------------------------------- + + +args <- commandArgs(TRUE) +options(digits=22) + +library("Matrix") + +W = as.matrix(readMM(paste(args[1], "W.mtx", sep=""))) +U = as.matrix(readMM(paste(args[1], "U.mtx", sep=""))) +V = as.matrix(readMM(paste(args[1], "V.mtx", sep=""))) + +x = as.numeric(args[3]) + +R = t(t(U) %*% (W/(U%*%t(V) + x))); + +writeMM(as(R, "CsparseMatrix"), paste(args[2], "R", sep="")); + + http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/test/scripts/functions/quaternary/WeightedDivMMLeftEps.dml ---------------------------------------------------------------------- diff --git a/src/test/scripts/functions/quaternary/WeightedDivMMLeftEps.dml b/src/test/scripts/functions/quaternary/WeightedDivMMLeftEps.dml new file mode 100644 index 0000000..6bc843b --- /dev/null +++ b/src/test/scripts/functions/quaternary/WeightedDivMMLeftEps.dml @@ -0,0 +1,32 @@ +#------------------------------------------------------------- +# +# 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. +# +#------------------------------------------------------------- + + + +W = read($1); +U = read($2); +V = read($3); + +x = $5; + +R = t(t(U) %*% (W/(U%*%t(V) + x))); + +write(R, $4); http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/test/scripts/functions/quaternary/WeightedDivMMRightEps.R ---------------------------------------------------------------------- diff --git a/src/test/scripts/functions/quaternary/WeightedDivMMRightEps.R b/src/test/scripts/functions/quaternary/WeightedDivMMRightEps.R new file mode 100644 index 0000000..8cf786e --- /dev/null +++ b/src/test/scripts/functions/quaternary/WeightedDivMMRightEps.R @@ -0,0 +1,38 @@ +#------------------------------------------------------------- +# +# 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. +# +#------------------------------------------------------------- + + +args <- commandArgs(TRUE) +options(digits=22) + +library("Matrix") + +W = as.matrix(readMM(paste(args[1], "W.mtx", sep=""))) +U = as.matrix(readMM(paste(args[1], "U.mtx", sep=""))) +V = as.matrix(readMM(paste(args[1], "V.mtx", sep=""))) + +x = as.numeric(args[3]) + +R = (W/(U%*%t(V) + x)) %*% V; + +writeMM(as(R, "CsparseMatrix"), paste(args[2], "R", sep="")); + + http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/fcfe893f/src/test/scripts/functions/quaternary/WeightedDivMMRightEps.dml ---------------------------------------------------------------------- diff --git a/src/test/scripts/functions/quaternary/WeightedDivMMRightEps.dml b/src/test/scripts/functions/quaternary/WeightedDivMMRightEps.dml new file mode 100644 index 0000000..de68463 --- /dev/null +++ b/src/test/scripts/functions/quaternary/WeightedDivMMRightEps.dml @@ -0,0 +1,32 @@ +#------------------------------------------------------------- +# +# 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. +# +#------------------------------------------------------------- + + + +W = read($1); +U = read($2); +V = read($3); + +x = $5; + +R = (W/(U%*%t(V) + x)) %*% V; + +write(R, $4);
