Repository: incubator-systemml
Updated Branches:
  refs/heads/master 998b0b1a5 -> a23396df6


[SYSTEMML-1187] Updated the documentation for removeEmpty with select and
bugfix for relu_backward

Also, added a multi-input cbind external function.


Project: http://git-wip-us.apache.org/repos/asf/incubator-systemml/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-systemml/commit/a23396df
Tree: http://git-wip-us.apache.org/repos/asf/incubator-systemml/tree/a23396df
Diff: http://git-wip-us.apache.org/repos/asf/incubator-systemml/diff/a23396df

Branch: refs/heads/master
Commit: a23396df60f485c8a6627afbf4e322145922707b
Parents: 998b0b1
Author: Niketan Pansare <[email protected]>
Authored: Sun Jan 22 19:12:13 2017 -0800
Committer: Niketan Pansare <[email protected]>
Committed: Sun Jan 22 19:12:13 2017 -0800

----------------------------------------------------------------------
 docs/dml-language-reference.md                  |   2 +-
 .../java/org/apache/sysml/hops/BinaryOp.java    |   3 +-
 .../apache/sysml/udf/lib/MultiInputCbind.java   | 177 +++++++++++++++++++
 3 files changed, 180 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/a23396df/docs/dml-language-reference.md
----------------------------------------------------------------------
diff --git a/docs/dml-language-reference.md b/docs/dml-language-reference.md
index 80fc8ca..c828e70 100644
--- a/docs/dml-language-reference.md
+++ b/docs/dml-language-reference.md
@@ -628,7 +628,7 @@ nrow(), <br/> ncol(), <br/> length() | Return the number of 
rows, number of colu
 prod() | Return the product of all cells in matrix | Input: matrix <br/> 
Output: scalarj | prod(X)
 rand() | Generates a random matrix | Input: (rows=&lt;value&gt;, 
cols=&lt;value&gt;, min=&lt;value&gt;, max=&lt;value&gt;, 
sparsity=&lt;value&gt;, pdf=&lt;string&gt;, seed=&lt;value&gt;) <br/> 
rows/cols: Number of rows/cols (expression) <br/> min/max: Min/max value for 
cells (either constant value, or variable that evaluates to constant value) 
<br/> sparsity: fraction of non-zero cells (constant value) <br/> pdf: 
"uniform" (min, max) distribution, or "normal" (0,1) distribution; or "poisson" 
(lambda=1) distribution. string; default value is "uniform". Note that, for the 
Poisson distribution, users can provide the mean/lambda parameter as follows: 
<br/> rand(rows=1000,cols=1000, pdf="poisson", lambda=2.5). <br/> The default 
value for lambda is 1. <br/> seed: Every invocation of rand() internally 
generates a random seed with which the cell values are generated. One can 
optionally provide a seed when repeatability is desired.  <br/> Output: matrix 
| X = rand(rows=10, cols=20, min=0, m
 ax=1, pdf="uniform", sparsity=0.2) <br/> The example generates a 10 x 20 
matrix, with cell values uniformly chosen at random between 0 and 1, and 
approximately 20% of cells will have non-zero values.
 rbind() | Row-wise matrix concatenation. Concatenates the second matrix as 
additional rows to the first matrix | Input: (X &lt;matrix&gt;, Y 
&lt;matrix&gt;) <br/>Output: &lt;matrix&gt; <br/> X and Y are matrices, where 
the number of columns in X and the number of columns in Y are the same. | A = 
matrix(1, rows=2,cols=3) <br/> B = matrix(2, rows=2,cols=3) <br/> C = 
rbind(A,B) <br/> print("Dimensions of C: " + nrow(C) + " X " + ncol(C)) <br/> 
Output: <br/> Dimensions of C: 4 X 3
-removeEmpty() | Removes all empty rows or columns from the input matrix target 
X according to the specified margin. | Input : (target= X &lt;matrix&gt;, 
margin="...") <br/> Output : &lt;matrix&gt; <br/> Valid values for margin are 
"rows" or "cols". | A = removeEmpty(target=X, margin="rows")
+removeEmpty() | Removes all empty rows or columns from the input matrix target 
X according to the specified margin. Also, allows to apply a filter F before 
removing the empty rows/cols. | Input : (target= X &lt;matrix&gt;, 
margin="...", select=F) <br/> Output : &lt;matrix&gt; <br/> Valid values for 
margin are "rows" or "cols". | A = removeEmpty(target=X, margin="rows", 
select=F)
 replace() | Creates a copy of input matrix X, where all values that are equal 
to the scalar pattern s1 are replaced with the scalar replacement s2. | Input : 
(target= X &lt;matrix&gt;, pattern=&lt;scalar&gt;, replacement=&lt;scalar&gt;) 
<br/> Output : &lt;matrix&gt; <br/> If s1 is NaN, then all NaN values of X are 
treated as equal and hence replaced with s2. Positive and negative infinity are 
treated as different values. | A = replace(target=X, pattern=s1, replacement=s2)
 rev() | Reverses the rows in a matrix | Input : (&lt;matrix&gt;) <br/> Output 
: &lt;matrix&gt; | <span style="white-space: nowrap;">A = matrix("1 2 3 4", 
rows=2, cols=2)</span> <br/> <span style="white-space: nowrap;">B = matrix("1 2 
3 4", rows=4, cols=1)</span> <br/> <span style="white-space: nowrap;">C = 
matrix("1 2 3 4", rows=1, cols=4)</span> <br/> revA = rev(A) <br/> revB = 
rev(B) <br/> revC = rev(C) <br/> Matrix revA: [[3, 4], [1, 2]]<br/> Matrix 
revB: [[4], [3], [2], [1]]<br/> Matrix revC: [[1, 2, 3, 4]]<br/>
 seq() | Creates a single column vector with values starting from &lt;from&gt;, 
to &lt;to&gt;, in increments of &lt;increment&gt; | Input: (&lt;from&gt;, 
&lt;to&gt;, &lt;increment&gt;) <br/> Output: &lt;matrix&gt; | S = seq (10, 200, 
10)

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/a23396df/src/main/java/org/apache/sysml/hops/BinaryOp.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/BinaryOp.java 
b/src/main/java/org/apache/sysml/hops/BinaryOp.java
index 7321d68..6269919 100644
--- a/src/main/java/org/apache/sysml/hops/BinaryOp.java
+++ b/src/main/java/org/apache/sysml/hops/BinaryOp.java
@@ -603,7 +603,8 @@ public class BinaryOp extends Hop
                                                && potentialZero instanceof 
LiteralOp && ((LiteralOp) potentialZero).getDoubleValue() == 0;
                                                
                                if(op == OpOp2.MULT && isLeftXGt0 && 
-                                       !getInput().get(0).isVector() && 
!getInput().get(1).isVector()) {
+                                       !getInput().get(0).isVector() && 
!getInput().get(1).isVector()
+                                       && getInput().get(0).dimsKnown() && 
getInput().get(1).dimsKnown()) {
                                        binary = new 
ConvolutionTransform(getInput().get(0).getInput().get(0).constructLops(), 
                                                                        
getInput().get(1).constructLops(),
                                                                        
ConvolutionTransform.OperationTypes.RELU_BACKWARD, getDataType(), 
getValueType(), et, -1);

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/a23396df/src/main/java/org/apache/sysml/udf/lib/MultiInputCbind.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/udf/lib/MultiInputCbind.java 
b/src/main/java/org/apache/sysml/udf/lib/MultiInputCbind.java
new file mode 100644
index 0000000..30d3571
--- /dev/null
+++ b/src/main/java/org/apache/sysml/udf/lib/MultiInputCbind.java
@@ -0,0 +1,177 @@
+/*
+ * 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.udf.lib;
+
+import java.io.IOException;
+import java.util.Iterator;
+
+import org.apache.sysml.runtime.DMLRuntimeException;
+import org.apache.sysml.runtime.controlprogram.caching.CacheException;
+import org.apache.sysml.runtime.matrix.data.IJV;
+import org.apache.sysml.runtime.matrix.data.InputInfo;
+import org.apache.sysml.runtime.matrix.data.MatrixBlock;
+import org.apache.sysml.runtime.matrix.data.OutputInfo;
+import org.apache.sysml.udf.FunctionParameter;
+import org.apache.sysml.udf.Matrix;
+import org.apache.sysml.udf.PackageFunction;
+import org.apache.sysml.udf.Scalar;
+import org.apache.sysml.udf.Matrix.ValueType;
+
+/**
+ * This external built-in function addresses following two common scenarios:
+ * 1. cbind (cbind (cbind ( X1, X2 ), X3 ), X4)
+ * 2. With spagetization: cbind (cbind (cbind ( matrix(X1, rows=length(X1), 
cols=1), matrix(X2, rows=length(X2), cols=1) ), matrix(X3, rows=length(X3), 
cols=1) ), matrix(X4, rows=length(X4), cols=1))
+ * 
+ * The API of this external built-in function is as follows:
+ * 
+ * func = externalFunction(int numInputs, boolean spagetize, matrix[double] 
X1, matrix[double] X2,  matrix[double] X3, matrix[double] X4) return 
(matrix[double] out) 
+ * implemented in 
(classname="org.apache.sysml.udf.lib.MultiInputCbind",exectype="mem");
+ * 
+ */
+public class MultiInputCbind extends PackageFunction {
+       private static final long serialVersionUID = -4266180315672563097L;
+
+       private Matrix ret;
+       private MatrixBlock retMB;
+       long numRetRows; long numRetCols;
+       boolean spagetize;
+       
+       @Override
+       public int getNumFunctionOutputs() {
+               return 1;
+       }
+
+       @Override
+       public FunctionParameter getFunctionOutput(int pos) {
+               if(pos == 0)
+                       return ret;
+               else
+                       throw new RuntimeException("MultiInputCbind produces 
only one output");
+       }
+
+       @Override
+       public void execute() {
+               int numInputs = 
Integer.parseInt(((Scalar)getFunctionInput(0)).getValue());
+               spagetize = 
Boolean.parseBoolean(((Scalar)getFunctionInput(1)).getValue());
+               
+               // Compute output dimensions
+               try {
+                       numRetCols = 0;
+                       if(spagetize) {
+                               // Assumption the inputs are of same shape
+                               MatrixBlock in = ((Matrix) 
getFunctionInput(2)).getMatrixObject().acquireRead();
+                               numRetRows = in.getNumRows()*in.getNumColumns();
+                               numRetCols = numInputs;
+                               ((Matrix) 
getFunctionInput(2)).getMatrixObject().release();
+                       }
+                       else {
+                               for(int inputID = 2; inputID < numInputs + 2; 
inputID++) {
+                                       MatrixBlock in = ((Matrix) 
getFunctionInput(inputID)).getMatrixObject().acquireRead();
+                                       numRetRows = in.getNumRows();
+                                       numRetCols += in.getNumColumns();
+                                       ((Matrix) 
getFunctionInput(inputID)).getMatrixObject().release();
+                               }
+                       }
+               } catch (CacheException e) {
+                       throw new RuntimeException("Error while executing 
MultiInputCbind", e);
+               }
+               
+               allocateOutput();
+               
+               // Performs cbind (cbind (cbind ( X1, X2 ), X3 ), X4)
+               double [] retData = retMB.getDenseBlock();
+               try {
+                       int startColumn = 0;
+                       for(int inputID = 2; inputID < numInputs + 2; 
inputID++) {
+                               MatrixBlock in = ((Matrix) 
getFunctionInput(inputID)).getMatrixObject().acquireRead();
+                               if(spagetize && 
in.getNumRows()*in.getNumColumns() != numRetRows) {
+                                       throw new RuntimeException("Expected 
the inputs to be of same size when spagetization is turned on.");
+                               }
+                               int inputNumCols = in.getNumColumns();
+                               if(in.isInSparseFormat()) {
+                                       Iterator<IJV> iter = 
in.getSparseBlockIterator();
+                                       while(iter.hasNext()) {
+                                               IJV ijv = iter.next();
+                                               if(spagetize) {
+                                                       // Perform matrix(X1, 
rows=length(X1), cols=1) operation before cbind
+                                                       // Output Column ID = 
inputID-2 for all elements of inputs
+                                                       int outputRowIndex = 
ijv.getI()*inputNumCols + ijv.getJ();
+                                                       int outputColIndex = 
inputID-2;
+                                                       retData[(int) 
(outputRowIndex*retMB.getNumColumns() + outputColIndex)] = ijv.getV();
+                                               }
+                                               else {
+                                                       // Traditional cbind
+                                                       // Row ID remains the 
same as that of input
+                                                       int outputRowIndex = 
ijv.getI();
+                                                       int outputColIndex = 
ijv.getJ() + startColumn;
+                                                       retData[(int) 
(outputRowIndex*retMB.getNumColumns() + outputColIndex)] = ijv.getV();
+                                               }
+                                       }
+                               }
+                               else {
+                                       double [] denseBlock = 
in.getDenseBlock();
+                                       if(denseBlock != null) {
+                                               if(spagetize) {
+                                                       // Perform matrix(X1, 
rows=length(X1), cols=1) operation before cbind
+                                                       // Output Column ID = 
inputID-2 for all elements of inputs
+                                                       int j = inputID-2;
+                                                       for(int i = 0; i < 
numRetRows; i++) {
+                                                               retData[(int) 
(i*numRetCols + j)] = denseBlock[i];
+                                                       }
+                                               }
+                                               else {
+                                                       // Traditional cbind
+                                                       // Row ID remains the 
same as that of input
+                                                       for(int i = 0; i < 
retMB.getNumRows(); i++) {
+                                                               for(int j = 0; 
j < inputNumCols; j++) {
+                                                                       int 
outputColIndex = j + startColumn;
+                                                                       
retData[(int) (i*numRetCols + outputColIndex)] = denseBlock[i*inputNumCols + j];
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               ((Matrix) 
getFunctionInput(inputID)).getMatrixObject().release();
+                               startColumn += inputNumCols;
+                       }
+               } catch (CacheException e) {
+                       throw new RuntimeException("Error while executing 
MultiInputCbind", e);
+               }
+               
+               retMB.recomputeNonZeros();
+               try {
+                       retMB.examSparsity();
+                       ret.setMatrixDoubleArray(retMB, 
OutputInfo.BinaryBlockOutputInfo, InputInfo.BinaryBlockInputInfo);
+               } catch (DMLRuntimeException e) {
+                       throw new RuntimeException("Error while executing 
MultiInputCbind", e);
+               } catch (IOException e) {
+                       throw new RuntimeException("Error while executing 
MultiInputCbind", e);
+               }       
+       }
+       
+       private void allocateOutput() {
+               String dir = createOutputFilePathAndName( "TMP" );
+               ret = new Matrix( dir, numRetRows, numRetCols, ValueType.Double 
);
+               retMB = new MatrixBlock((int) numRetRows, (int) numRetCols, 
false);
+               retMB.allocateDenseBlock();
+       }
+       
+
+}

Reply via email to