This is an automated email from the ASF dual-hosted git repository.

arnabp20 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/systemds.git


The following commit(s) were added to refs/heads/master by this push:
     new fd4b0d0  [SYSTEMDS-2889] Add initial lineage based debugger
fd4b0d0 is described below

commit fd4b0d05a38a29567c2a44d6c872c1f7d120cef8
Author: Benjamin Rath <[email protected]>
AuthorDate: Wed Jun 2 18:18:07 2021 +0200

    [SYSTEMDS-2889] Add initial lineage based debugger
    
    This patch adds a lineage based debugger which helps tracking
    the first operator responsible for a constraint violation.
    Currently, the supported constraints are NAN, positive infinity
    and negative infinity.
    
    AMLS project SS2021.
    Closes #1286.
---
 src/main/java/org/apache/sysds/api/DMLOptions.java |   3 +
 src/main/java/org/apache/sysds/api/DMLScript.java  |   2 +
 .../controlprogram/context/ExecutionContext.java   |  10 +-
 .../runtime/instructions/cp/CPInstruction.java     |   3 +
 .../runtime/instructions/gpu/GPUInstruction.java   |   3 +
 .../sysds/runtime/lineage/BooleanArray32.java      |  45 ++++
 .../sysds/runtime/lineage/LineageDebugger.java     | 108 ++++++++++
 .../apache/sysds/runtime/lineage/LineageItem.java  |  36 +++-
 .../sysds/runtime/lineage/LineageItemUtils.java    |   3 +
 .../sysds/runtime/lineage/LineageParser.java       |   6 +-
 src/test/java/org/apache/sysds/test/TestUtils.java |   4 +
 .../functions/lineage/LineageDebuggerTest.java     | 236 +++++++++++++++++++++
 .../scripts/functions/lineage/LineageDebugger1.dml |  39 ++++
 13 files changed, 487 insertions(+), 11 deletions(-)

diff --git a/src/main/java/org/apache/sysds/api/DMLOptions.java 
b/src/main/java/org/apache/sysds/api/DMLOptions.java
index a4dae4b..0949c06 100644
--- a/src/main/java/org/apache/sysds/api/DMLOptions.java
+++ b/src/main/java/org/apache/sysds/api/DMLOptions.java
@@ -66,6 +66,7 @@ public class DMLOptions {
        public ReuseCacheType       linReuseType  = ReuseCacheType.NONE; // 
reuse type (full, partial, hybrid)
        public LineageCachePolicy   linCachePolicy= 
LineageCachePolicy.COSTNSIZE; // lineage cache eviction policy
        public boolean              lineage_estimate = false;         // 
whether estimate reuse benefits
+       public boolean              lineage_debugger = false;         // 
whether enable lineage debugger
        public boolean              fedWorker     = false;
        public int                  fedWorkerPort = -1;
        public boolean              checkPrivacy  = false;            // Check 
which privacy constraints are loaded and checked during federated execution 
@@ -140,6 +141,8 @@ public class DMLOptions {
                                                        
dmlOptions.linCachePolicy = LineageCachePolicy.DAGHEIGHT;
                                                else if 
(lineageType.equalsIgnoreCase("estimate"))
                                                        
dmlOptions.lineage_estimate = lineageType.equalsIgnoreCase("estimate");
+                                               else if 
(lineageType.equalsIgnoreCase("debugger"))
+                                                       
dmlOptions.lineage_debugger = lineageType.equalsIgnoreCase("debugger");         
                                        
                                                else
                                                        throw new 
org.apache.commons.cli.ParseException(
                                                                "Invalid 
argument specified for -lineage option: " + lineageType);
diff --git a/src/main/java/org/apache/sysds/api/DMLScript.java 
b/src/main/java/org/apache/sysds/api/DMLScript.java
index c60fa3e..5072830 100644
--- a/src/main/java/org/apache/sysds/api/DMLScript.java
+++ b/src/main/java/org/apache/sysds/api/DMLScript.java
@@ -100,6 +100,7 @@ public class DMLScript
        public static ReuseCacheType LINEAGE_REUSE = 
DMLOptions.defaultOptions.linReuseType;   // whether lineage-based reuse
        public static LineageCachePolicy LINEAGE_POLICY = 
DMLOptions.defaultOptions.linCachePolicy; // lineage cache eviction policy
        public static boolean     LINEAGE_ESTIMATE = 
DMLOptions.defaultOptions.lineage_estimate; // whether estimate reuse benefits
+       public static boolean     LINEAGE_DEBUGGER = 
DMLOptions.defaultOptions.lineage_debugger; // whether enable lineage debugger
        public static boolean     CHECK_PRIVACY = 
DMLOptions.defaultOptions.checkPrivacy;      // Check which privacy constraints 
are loaded and checked during federated execution
 
        public static boolean           USE_ACCELERATOR     = 
DMLOptions.defaultOptions.gpu;
@@ -224,6 +225,7 @@ public class DMLScript
                        LINEAGE_POLICY      = dmlOptions.linCachePolicy;
                        LINEAGE_ESTIMATE    = dmlOptions.lineage_estimate;
                        CHECK_PRIVACY       = dmlOptions.checkPrivacy;
+                       LINEAGE_DEBUGGER        = dmlOptions.lineage_debugger;
 
                        String fnameOptConfig = dmlOptions.configFile;
                        boolean isFile = dmlOptions.filePath != null;
diff --git 
a/src/main/java/org/apache/sysds/runtime/controlprogram/context/ExecutionContext.java
 
b/src/main/java/org/apache/sysds/runtime/controlprogram/context/ExecutionContext.java
index f0448f1..6b1054b 100644
--- 
a/src/main/java/org/apache/sysds/runtime/controlprogram/context/ExecutionContext.java
+++ 
b/src/main/java/org/apache/sysds/runtime/controlprogram/context/ExecutionContext.java
@@ -48,6 +48,7 @@ import 
org.apache.sysds.runtime.instructions.gpu.context.CSRPointer;
 import org.apache.sysds.runtime.instructions.gpu.context.GPUContext;
 import org.apache.sysds.runtime.instructions.gpu.context.GPUObject;
 import org.apache.sysds.runtime.lineage.Lineage;
+import org.apache.sysds.runtime.lineage.LineageDebugger;
 import org.apache.sysds.runtime.lineage.LineageItem;
 import org.apache.sysds.runtime.matrix.data.FrameBlock;
 import org.apache.sysds.runtime.matrix.data.MatrixBlock;
@@ -808,9 +809,16 @@ public class ExecutionContext {
        public void traceLineage(Instruction inst) {
                if( _lineage == null )
                        throw new DMLRuntimeException("Lineage Trace 
unavailable.");
+               // TODO bra: store all newly created lis in active list
                _lineage.trace(inst, this);
        }
-
+       
+       public void maintainLineageDebuggerInfo(Instruction inst) {
+               if( _lineage == null )
+                       throw new DMLRuntimeException("Lineage Trace 
unavailable.");
+               LineageDebugger.maintainSpecialValueBits(_lineage, inst, this);
+       }
+       
        public LineageItem getLineageItem(CPOperand input) {
                if( _lineage == null )
                        throw new DMLRuntimeException("Lineage Trace 
unavailable.");
diff --git 
a/src/main/java/org/apache/sysds/runtime/instructions/cp/CPInstruction.java 
b/src/main/java/org/apache/sysds/runtime/instructions/cp/CPInstruction.java
index 014b854..84b2332 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/cp/CPInstruction.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/cp/CPInstruction.java
@@ -152,6 +152,9 @@ public abstract class CPInstruction extends Instruction
                if (!LineageCacheConfig.ReuseCacheType.isNone() && 
DMLScript.USE_ACCELERATOR
                        && LineageCacheConfig.CONCURRENTGPUEVICTION)
                        LineageCacheConfig.STOPBACKGROUNDEVICTION = true;
+               
+               if (DMLScript.LINEAGE_DEBUGGER)
+                       ec.maintainLineageDebuggerInfo(this);
        }
        
        /** 
diff --git 
a/src/main/java/org/apache/sysds/runtime/instructions/gpu/GPUInstruction.java 
b/src/main/java/org/apache/sysds/runtime/instructions/gpu/GPUInstruction.java
index 4c51c70..700145b 100644
--- 
a/src/main/java/org/apache/sysds/runtime/instructions/gpu/GPUInstruction.java
+++ 
b/src/main/java/org/apache/sysds/runtime/instructions/gpu/GPUInstruction.java
@@ -226,6 +226,9 @@ public abstract class GPUInstruction extends Instruction 
implements LineageTrace
                                if(gpuCtx != null)
                                        gpuCtx.printMemoryInfo(getOpcode());
                }
+               
+               //default post-process behavior
+               super.postprocessInstruction(ec);
        }
 
        /**
diff --git a/src/main/java/org/apache/sysds/runtime/lineage/BooleanArray32.java 
b/src/main/java/org/apache/sysds/runtime/lineage/BooleanArray32.java
new file mode 100644
index 0000000..f3cc5e6
--- /dev/null
+++ b/src/main/java/org/apache/sysds/runtime/lineage/BooleanArray32.java
@@ -0,0 +1,45 @@
+/*
+ * 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.sysds.runtime.lineage;
+
+public class BooleanArray32 {
+       private int _value;
+       
+       public BooleanArray32(int value){
+               _value = value;
+       }
+       
+       public boolean get(int pos) {
+               return (_value & (1 << pos)) != 0;
+       }
+       
+       public void set(int pos, boolean value) {
+               int mask = 1 << pos;
+               _value = (_value & ~mask) | (value ? mask : 0);
+       }
+       
+       public int getValue() {
+               return _value;
+       }
+       
+       public void setValue(int value) {
+               _value = value;
+       }
+} 
diff --git 
a/src/main/java/org/apache/sysds/runtime/lineage/LineageDebugger.java 
b/src/main/java/org/apache/sysds/runtime/lineage/LineageDebugger.java
new file mode 100644
index 0000000..1730c5a
--- /dev/null
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageDebugger.java
@@ -0,0 +1,108 @@
+/*
+ * 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.sysds.runtime.lineage;
+
+
+import org.apache.sysds.runtime.controlprogram.caching.CacheableData;
+import org.apache.sysds.runtime.controlprogram.context.ExecutionContext;
+import org.apache.sysds.runtime.instructions.Instruction;
+import org.apache.sysds.runtime.instructions.cp.*;
+import org.apache.sysds.runtime.matrix.data.MatrixBlock;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Queue;
+import java.util.LinkedList;
+
+public class LineageDebugger {
+       public static final int POS_NAN = 0;
+       public static final int POS_POSITIVE_INFINITY = 1;
+       public static final int POS_NEGATIVE_INFINITY = 2;
+       
+       public static void maintainSpecialValueBits(Lineage lineage, 
Instruction inst, ExecutionContext ec) {
+               ArrayList<CPOperand> outputs = new ArrayList<>();
+               
+               // Only CP instructions are supported right now
+               CPOperand singleOutput =
+                               inst instanceof ComputationCPInstruction ? 
((ComputationCPInstruction) inst).getOutput() :
+                               inst instanceof BuiltinNaryCPInstruction ? 
((BuiltinNaryCPInstruction) inst).getOutput() :
+                               inst instanceof SqlCPInstruction ? 
((SqlCPInstruction) inst).getOutput() :
+                               inst instanceof VariableCPInstruction ? 
((VariableCPInstruction) inst).getOutput() :
+                               null;
+               if (singleOutput != null)
+                       outputs.add(singleOutput);
+               
+               Collection<CPOperand> multiOutputs =
+                               inst instanceof MultiReturnBuiltinCPInstruction 
? ((MultiReturnBuiltinCPInstruction) inst).getOutputs() :
+                               inst instanceof 
MultiReturnParameterizedBuiltinCPInstruction ? 
((MultiReturnParameterizedBuiltinCPInstruction) inst).getOutputs() :
+                               null;
+               if (multiOutputs != null)
+                       outputs.addAll(multiOutputs);
+               
+               for (CPOperand output : outputs) {
+                       CacheableData<MatrixBlock> cd = 
ec.getMatrixObject(output);
+                       MatrixBlock mb = cd.acquireReadAndRelease();
+                       LineageItem li = lineage.get(output);
+                       
+                       updateSpecialValueBit(mb, li, POS_NAN, Double.NaN);
+                       updateSpecialValueBit(mb, li, POS_POSITIVE_INFINITY, 
Double.POSITIVE_INFINITY);
+                       updateSpecialValueBit(mb, li, POS_NEGATIVE_INFINITY, 
Double.NEGATIVE_INFINITY);
+               }
+       }
+       
+       public static LineageItem firstOccurrenceOfNR(LineageItem li, int pos) {
+               if (!li.getSpecialValueBit(pos))
+                       return null;
+               
+               LineageItem tmp;
+               Queue<LineageItem> q = new LinkedList<>();
+               q.add(li);
+               
+               while ((tmp = q.poll()) != null) {
+                       if (tmp.isVisited())
+                               continue;
+                       
+                       if (tmp.getInputs() != null) {
+                               boolean flag = false;
+                               for (LineageItem in : tmp.getInputs()) {
+                                       flag |= in.getSpecialValueBit(pos);
+                                       q.add(in);
+                               }
+                               if (!flag)
+                                       break;
+                       }
+                       tmp.setVisited(true);
+               }
+               li.resetVisitStatusNR();
+               return tmp;
+       }
+       
+       private static void updateSpecialValueBit(MatrixBlock mb, LineageItem 
li, int pos, double pattern) {
+               boolean flag = false;
+               for (LineageItem input : li.getInputs()) {
+                       if (input.getSpecialValueBit(pos)) {
+                               flag = true;
+                               break;
+                       }
+               }
+               flag |= mb.containsValue(pattern);
+               li.setSpecialValueBit(pos, flag);
+       }
+}
diff --git a/src/main/java/org/apache/sysds/runtime/lineage/LineageItem.java 
b/src/main/java/org/apache/sysds/runtime/lineage/LineageItem.java
index cd2346d..14b9894 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageItem.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageItem.java
@@ -37,6 +37,7 @@ public class LineageItem {
        private int _hash = 0;
        private LineageItem _dedupPatch;
        private long _distLeaf2Node;
+       private final BooleanArray32 _specialValueBits;  // TODO: Move this to 
a new subclass
        // init visited to true to ensure visited items are
        // not hidden when used as inputs to new items
        private boolean _visited = true;
@@ -53,30 +54,30 @@ public class LineageItem {
        }
 
        public LineageItem(long id, String data) {
-               this(id, data, "", null);
+               this(id, data, "", null, 0);
        }
        
        public LineageItem(String data, String opcode) {
-               this(_idSeq.getNextID(), data, opcode, null);
+               this(_idSeq.getNextID(), data, opcode, null, 0);
        }
        
        public LineageItem(String opcode, LineageItem[] inputs) { 
-               this(_idSeq.getNextID(), "", opcode, inputs);
+               this(_idSeq.getNextID(), "", opcode, inputs, 0);
        }
 
        public LineageItem(String data, String opcode, LineageItem[] inputs) {
-               this(_idSeq.getNextID(), data, opcode, inputs);
+               this(_idSeq.getNextID(), data, opcode, inputs, 0);
        }
 
        public LineageItem(String opcode, LineageItem dedupPatch, LineageItem[] 
inputs) { 
-               this(_idSeq.getNextID(), "", opcode, inputs);
+               this(_idSeq.getNextID(), "", opcode, inputs, 0);
                // maintain a pointer to the dedup patch
                _dedupPatch = dedupPatch;
                _hash = _dedupPatch._hash;
        }
 
        public LineageItem(String opcode, LineageItem dedupPatch, int 
dpatchHash, LineageItem[] inputs) { 
-               this(_idSeq.getNextID(), "", opcode, inputs);
+               this(_idSeq.getNextID(), "", opcode, inputs, 0);
                // maintain a pointer to the dedup patch
                _dedupPatch = dedupPatch;
                _hash = dpatchHash;
@@ -87,14 +88,14 @@ public class LineageItem {
        }
        
        public LineageItem(long id, LineageItem li) {
-               this(id, li._data, li._opcode, li._inputs);
+               this(id, li._data, li._opcode, li._inputs, 0);
        }
 
        public LineageItem(long id, String data, String opcode) {
-               this(id, data, opcode, null);
+               this(id, data, opcode, null, 0);
        }
        
-       public LineageItem(long id, String data, String opcode, LineageItem[] 
inputs) {
+       public LineageItem(long id, String data, String opcode, LineageItem[] 
inputs, int specialValueBits) {
                _id = id;
                _opcode = opcode;
                _data = data;
@@ -104,6 +105,7 @@ public class LineageItem {
                _hash = hashCode();
                // store the distance of this node from the leaves. 
(O(#inputs)) operation
                _distLeaf2Node = distLeaf2Node();
+               _specialValueBits = new BooleanArray32(specialValueBits);
        }
        
        public LineageItem[] getInputs() {
@@ -142,6 +144,14 @@ public class LineageItem {
                _visited = flag;
        }
        
+       public void setSpecialValueBit(int pos, boolean flag) {
+               _specialValueBits.set(pos, flag);
+       }
+       
+       public void setSpecialValueBits(int value) {
+               _specialValueBits.setValue(value);
+       }
+
        private long distLeaf2Node() {
                // Derive height only if the corresponding reuse
                // policy is selected, otherwise set -1.
@@ -169,6 +179,14 @@ public class LineageItem {
                return _opcode;
        }
        
+       public boolean getSpecialValueBit(int pos) {
+               return _specialValueBits.get(pos);
+       }
+
+       public int getSpecialValueBits() {
+               return _specialValueBits.getValue();
+       }
+
        public boolean isPlaceholder() {
                return _opcode.startsWith(LineageItemUtils.LPLACEHOLDER);
        }
diff --git 
a/src/main/java/org/apache/sysds/runtime/lineage/LineageItemUtils.java 
b/src/main/java/org/apache/sysds/runtime/lineage/LineageItemUtils.java
index edd9a73..ca8d2cb 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageItemUtils.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageItemUtils.java
@@ -135,6 +135,9 @@ public class LineageItemUtils {
                                .map(i -> String.format("(%d)", i.getId()))
                                .collect(Collectors.joining(" "));
                        sb.append(ids);
+                       
+                       if (DMLScript.LINEAGE_DEBUGGER)
+                               sb.append(" 
").append("[").append(li.getSpecialValueBits()).append("]");
                }
                return sb.toString().trim();
        }
diff --git a/src/main/java/org/apache/sysds/runtime/lineage/LineageParser.java 
b/src/main/java/org/apache/sysds/runtime/lineage/LineageParser.java
index 46dff8e..439fe1f 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageParser.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageParser.java
@@ -108,15 +108,19 @@ public class LineageParser
                }*/
 
                ArrayList<LineageItem> inputs = new ArrayList<>();
+               int specialValueBits = 0;
                for( int i=1; i<tokens.length; i++ ) {
                        String token = tokens[i];
                        if (token.startsWith("(") && token.endsWith(")")) {
                                token = token.substring(1, token.length()-1); 
//rm parentheses
                                inputs.add(map.get(Long.valueOf(token)));
+                       } else if (token.startsWith("[") && 
token.endsWith("]")) {
+                               token = token.substring(1, token.length() - 1); 
//rm parentheses
+                               specialValueBits = Integer.parseInt(token);
                        } else
                                throw new ParseException("Invalid format for 
LineageItem reference");
                }
-               return new LineageItem(id, "", opcode, inputs.toArray(new 
LineageItem[0]));
+               return new LineageItem(id, "", opcode, inputs.toArray(new 
LineageItem[0]), specialValueBits);
        }
        
        protected static void parseLineageTraceDedup(String str) {
diff --git a/src/test/java/org/apache/sysds/test/TestUtils.java 
b/src/test/java/org/apache/sysds/test/TestUtils.java
index 42cec58..e8fdb2f 100644
--- a/src/test/java/org/apache/sysds/test/TestUtils.java
+++ b/src/test/java/org/apache/sysds/test/TestUtils.java
@@ -1020,6 +1020,10 @@ public class TestUtils
        public static void compareScalars(String expected, String actual) {
                        assertEquals(expected, actual);
        }
+       
+       public static void compareScalars(Boolean expected, Boolean actual) {
+                       assertEquals(expected, actual);
+       }
 
        public static boolean compareMatrices(HashMap<CellIndex, Double> m1, 
HashMap<CellIndex, Double> m2,
                        double tolerance, String name1, String name2)
diff --git 
a/src/test/java/org/apache/sysds/test/functions/lineage/LineageDebuggerTest.java
 
b/src/test/java/org/apache/sysds/test/functions/lineage/LineageDebuggerTest.java
new file mode 100644
index 0000000..8f0cee5
--- /dev/null
+++ 
b/src/test/java/org/apache/sysds/test/functions/lineage/LineageDebuggerTest.java
@@ -0,0 +1,236 @@
+/*
+ * 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.sysds.test.functions.lineage;
+
+import org.apache.sysds.hops.OptimizerUtils;
+import org.apache.sysds.hops.recompile.Recompiler;
+import org.apache.sysds.runtime.lineage.Lineage;
+import org.apache.sysds.runtime.lineage.LineageDebugger;
+import org.apache.sysds.runtime.lineage.LineageItem;
+import org.apache.sysds.runtime.lineage.LineageParser;
+import org.apache.sysds.test.TestConfiguration;
+import org.apache.sysds.test.TestUtils;
+import org.apache.sysds.utils.Explain;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LineageDebuggerTest extends LineageBase {
+       
+       protected static final String TEST_DIR = "functions/lineage/";
+       protected static final String TEST_NAME1 = "LineageDebugger1";
+       protected String TEST_CLASS_DIR = TEST_DIR + 
LineageDebuggerTest.class.getSimpleName() + "/";
+       
+       protected static final int numRecords = 10;
+       protected static final int numFeatures = 5;
+       
+       
+       @Override
+       public void setUp() {
+               TestUtils.clearAssertionInformation();
+               addTestConfiguration(TEST_NAME1, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME1));
+       }
+       
+       @Test
+       public void testLineageDebuggerNaN() {
+               testLineageDebuggerNaN(TEST_NAME1);
+       }
+       
+       @Test
+       public void testLineageDebuggerInf1() {
+               testLineageDebuggerInf(TEST_NAME1, true, false);
+       }
+       
+       @Test
+       public void testLineageDebuggerInf2() { 
testLineageDebuggerInf(TEST_NAME1, false, true); }
+       
+       @Test
+       public void testLineageDebuggerInf3() { 
testLineageDebuggerInf(TEST_NAME1, true, true); }
+       
+       @Test
+       public void testLineageDebuggerFirstOccurrence1() { 
testLineageDebuggerFirstOccurrence(TEST_NAME1); }
+       
+       public void testLineageDebuggerNaN(String testname) {
+               boolean old_simplification = 
OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION;
+               boolean old_sum_product = 
OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES;
+               
+               try {
+                       LOG.debug("------------ BEGIN " + testname + 
"------------");
+                       
+                       OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = false;
+                       OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES = false;
+                       
+                       int rows = numRecords;
+                       int cols = numFeatures;
+                       
+                       getAndLoadTestConfiguration(testname);
+                       
+                       List<String> proArgs = new ArrayList<>();
+                       
+                       proArgs.add("-stats");
+                       proArgs.add("-lineage");
+                       proArgs.add("debugger");                        
+                       proArgs.add("-args");
+                       proArgs.add(input("X"));
+                       proArgs.add(input("Y"));
+                       proArgs.add(output("Z"));
+                       programArgs = proArgs.toArray(new 
String[proArgs.size()]);
+                       
+                       fullDMLScriptName = getScript();
+                       
+                       double[][] X = getRandomMatrix(rows, cols, 0, 1, 0.8, 
-1);
+                       writeInputMatrixWithMTD("X", X, true);
+                       
+                       double[][] Y = getRandomMatrix(rows, cols, 0, 1, 0.8, 
-1);
+                       Y[3][3] = Double.NaN;
+                       writeInputMatrixWithMTD("Y", Y, true);
+                       
+                       Lineage.resetInternalState();
+                       runTest(true, EXCEPTION_NOT_EXPECTED, null, -1);
+                       
+                       String Z_lineage = readDMLLineageFromHDFS("Z");
+                       LineageItem Z_li = 
LineageParser.parseLineageTrace(Z_lineage);
+                       TestUtils.compareScalars(Z_lineage, 
Explain.explain(Z_li));
+                       
+                       TestUtils.compareScalars(true, 
Z_li.getSpecialValueBit(LineageDebugger.POS_NAN));
+                       TestUtils.compareScalars(false, 
Z_li.getSpecialValueBit(LineageDebugger.POS_NEGATIVE_INFINITY));
+                       TestUtils.compareScalars(false, 
Z_li.getSpecialValueBit(LineageDebugger.POS_POSITIVE_INFINITY));
+               }
+               finally {
+                       OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = 
old_simplification;
+                       OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES = 
old_sum_product;
+                       Recompiler.reinitRecompiler(); 
+               }
+       }
+       
+       public void testLineageDebuggerInf(String testname, boolean positive, 
boolean negative) {
+               boolean old_simplification = 
OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION;
+               boolean old_sum_product = 
OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES;
+               
+               try {
+                       LOG.debug("------------ BEGIN " + testname + 
"------------");
+                       
+                       OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = false;
+                       OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES = false;
+                       
+                       int rows = numRecords;
+                       int cols = numFeatures;
+                       
+                       getAndLoadTestConfiguration(testname);
+                       
+                       List<String> proArgs = new ArrayList<>();
+                       
+                       proArgs.add("-stats");
+                       proArgs.add("-lineage");
+                       proArgs.add("debugger");
+                       proArgs.add("-args");
+                       proArgs.add(input("X"));
+                       proArgs.add(input("Y"));
+                       proArgs.add(output("Z"));
+                       programArgs = proArgs.toArray(new 
String[proArgs.size()]);
+                       
+                       fullDMLScriptName = getScript();
+                       
+                       double[][] X = getRandomMatrix(rows, cols, 0, 1, 0.8, 
-1);
+                       writeInputMatrixWithMTD("X", X, true);
+                       
+                       double[][] Y = getRandomMatrix(rows, cols, 0, 1, 0.8, 
-1);
+                       if (positive)
+                               Y[2][2] = Double.POSITIVE_INFINITY;
+                       if (negative)
+                               Y[3][3] = Double.NEGATIVE_INFINITY;
+                       writeInputMatrixWithMTD("Y", Y, true);
+                       
+                       Lineage.resetInternalState();
+                       runTest(true, EXCEPTION_NOT_EXPECTED, null, -1);
+                       
+                       String Z_lineage = readDMLLineageFromHDFS("Z");
+                       LineageItem Z_li = 
LineageParser.parseLineageTrace(Z_lineage);
+                       TestUtils.compareScalars(Z_lineage, 
Explain.explain(Z_li));
+                       
+                       if (positive)
+                               TestUtils.compareScalars(true, 
Z_li.getSpecialValueBit(LineageDebugger.POS_POSITIVE_INFINITY));
+                       if (negative)
+                               TestUtils.compareScalars(true, 
Z_li.getSpecialValueBit(LineageDebugger.POS_NEGATIVE_INFINITY));
+               }
+               finally {
+                       OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = 
old_simplification;
+                       OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES = 
old_sum_product;
+                       Recompiler.reinitRecompiler();
+               }
+       }
+       
+       public void testLineageDebuggerFirstOccurrence(String testname) {
+               boolean old_simplification = 
OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION;
+               boolean old_sum_product = 
OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES;
+               
+               try {
+                       LOG.debug("------------ BEGIN " + testname + 
"------------");
+                       
+                       OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = false;
+                       OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES = false;
+                       
+                       int rows = numRecords;
+                       int cols = numFeatures;
+                       
+                       getAndLoadTestConfiguration(testname);
+                       
+                       List<String> proArgs = new ArrayList<>();
+                       
+                       proArgs.add("-stats");
+                       proArgs.add("-lineage");
+                       proArgs.add("debugger");
+                       proArgs.add("-args");
+                       proArgs.add(input("X"));
+                       proArgs.add(input("Y"));
+                       proArgs.add(output("Z"));
+                       programArgs = proArgs.toArray(new 
String[proArgs.size()]);
+                       
+                       fullDMLScriptName = getScript();
+                       
+                       double[][] X = getRandomMatrix(rows, cols, 0, 1, 0.8, 
-1);
+                       
+                       writeInputMatrixWithMTD("X", X, true);
+                       
+                       double[][] Y = getRandomMatrix(rows, cols, 0, 1, 0.8, 
-1);
+                       Y[3][3] = Double.NaN;
+                       writeInputMatrixWithMTD("Y", Y, true);
+                       
+                       Lineage.resetInternalState();
+                       runTest(true, EXCEPTION_NOT_EXPECTED, null, -1);
+                       
+                       String Z_lineage = readDMLLineageFromHDFS("Z");
+                       LineageItem Z_li = 
LineageParser.parseLineageTrace(Z_lineage);
+                       TestUtils.compareScalars(Z_lineage, 
Explain.explain(Z_li));
+                       
+                       LineageItem firstOccurrence = 
LineageDebugger.firstOccurrenceOfNR(Z_li, LineageDebugger.POS_NAN);
+                       TestUtils.compareScalars(true, 
firstOccurrence.getSpecialValueBit(LineageDebugger.POS_NAN));
+                       for (LineageItem li : firstOccurrence.getInputs())
+                               TestUtils.compareScalars(false, 
li.getSpecialValueBit(LineageDebugger.POS_NAN));
+               }
+               finally {
+                       OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = 
old_simplification;
+                       OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES = 
old_sum_product;
+                       Recompiler.reinitRecompiler();
+               }
+       }
+       
+}
diff --git a/src/test/scripts/functions/lineage/LineageDebugger1.dml 
b/src/test/scripts/functions/lineage/LineageDebugger1.dml
new file mode 100644
index 0000000..6061b42
--- /dev/null
+++ b/src/test/scripts/functions/lineage/LineageDebugger1.dml
@@ -0,0 +1,39 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+# How to invoke this dml script LineageTrace.dml?
+# Assume LR_HOME is set to the home of the dml script
+# Assume rows = 20 and cols = 20 for X
+# hadoop jar SystemDS.jar -f $LR_HOME/LineageTrace.dml -args "$INPUT_DIR/X" 
"$OUTPUT_DIR/X" "$OUTPUT_DIR/Y"
+
+X = read($1);
+Y = read($2);
+
+X = X + 3;
+X = X * 5;
+
+X = X * Y;
+
+Z = t(X) %*% X;
+
+# write(X, $3, format="text");
+# write(Y, $4, format="text");
+write(Z, $3, format="text");

Reply via email to