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

markd 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 d601858  [SYSTEMDS-2678] Fine-Grained Propagation of RBind and CBind
d601858 is described below

commit d601858c74de08d0f3d644227e1a9c10223ee737
Author: sebwrede <[email protected]>
AuthorDate: Fri Oct 30 17:11:55 2020 +0100

    [SYSTEMDS-2678] Fine-Grained Propagation of RBind and CBind
    
    Closes #1066
---
 .../instructions/cp/AppendCPInstruction.java       |    4 +
 .../cp/ListAppendRemoveCPInstruction.java          |    4 +
 .../sysds/runtime/instructions/cp/ListObject.java  |    8 +-
 .../sysds/runtime/privacy/PrivacyConstraint.java   |   15 +
 .../apache/sysds/runtime/privacy/PrivacyUtils.java |   58 +-
 .../finegrained/FineGrainedPrivacyList.java        |   21 +-
 .../privacy/propagation/AppendPropagator.java      |   87 ++
 .../privacy/propagation/CBindPropagator.java       |   49 +
 .../privacy/propagation/ListAppendPropagator.java  |   73 ++
 .../privacy/propagation/ListRemovePropagator.java  |  108 +++
 .../privacy/propagation/PrivacyPropagator.java     |  103 +-
 .../runtime/privacy/propagation/Propagator.java    |    2 +-
 ...{Propagator.java => PropagatorMultiReturn.java} |   10 +-
 .../privacy/propagation/RBindPropagator.java       |   49 +
 .../org/apache/sysds/test/AutomatedTestBase.java   |   33 +
 .../test/functions/privacy/ReadWriteTest.java      |   46 +-
 .../privacy/{ => algorithms}/BuiltinGLMTest.java   |    2 +-
 .../{ => algorithms}/FederatedL2SVMTest.java       |    2 +-
 .../privacy/{ => algorithms}/GLMTest.java          |    2 +-
 .../privacy/propagation/AppendPropagatorTest.java  | 1002 ++++++++++++++++++++
 .../{ => propagation}/CorePropagatorTest.java      |    2 +-
 .../MatrixMultiplicationPropagatorTest.java}       |   90 +-
 src/test/scripts/functions/privacy/CBindTest.dml   |   25 +
 .../scripts/functions/privacy/ListAppendTest.dml   |   25 +
 src/test/scripts/functions/privacy/RBindTest.dml   |   25 +
 .../scripts/functions/privacy/StringAppendTest.dml |   25 +
 26 files changed, 1766 insertions(+), 104 deletions(-)

diff --git 
a/src/main/java/org/apache/sysds/runtime/instructions/cp/AppendCPInstruction.java
 
b/src/main/java/org/apache/sysds/runtime/instructions/cp/AppendCPInstruction.java
index 34d735b..1216f8e 100644
--- 
a/src/main/java/org/apache/sysds/runtime/instructions/cp/AppendCPInstruction.java
+++ 
b/src/main/java/org/apache/sysds/runtime/instructions/cp/AppendCPInstruction.java
@@ -72,4 +72,8 @@ public abstract class AppendCPInstruction extends 
BinaryCPInstruction
                else //DataType.FRAME
                        return new FrameAppendCPInstruction(op, in1, in2, out, 
type, opcode, str);
        }
+
+       public AppendType getAppendType() {
+               return _type;
+       }
 }
diff --git 
a/src/main/java/org/apache/sysds/runtime/instructions/cp/ListAppendRemoveCPInstruction.java
 
b/src/main/java/org/apache/sysds/runtime/instructions/cp/ListAppendRemoveCPInstruction.java
index 1721c4a..1bd582f 100644
--- 
a/src/main/java/org/apache/sysds/runtime/instructions/cp/ListAppendRemoveCPInstruction.java
+++ 
b/src/main/java/org/apache/sysds/runtime/instructions/cp/ListAppendRemoveCPInstruction.java
@@ -74,4 +74,8 @@ public final class ListAppendRemoveCPInstruction extends 
AppendCPInstruction {
                        throw new DMLRuntimeException("Unsupported list 
operation: "+getOpcode());
                }
        }
+
+       public CPOperand getOutput2(){
+               return output2;
+       }
 }
diff --git 
a/src/main/java/org/apache/sysds/runtime/instructions/cp/ListObject.java 
b/src/main/java/org/apache/sysds/runtime/instructions/cp/ListObject.java
index 8798799..4f726ee 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/cp/ListObject.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/cp/ListObject.java
@@ -236,7 +236,13 @@ public class ListObject extends Data {
                        _lineage.add(li);
                return this;
        }
-       
+
+       /**
+        * Removes the element at the specified position from the list
+        * and returns that element as the only element in a new ListObject.
+        * @param pos position of element in the list
+        * @return new ListObject with the specified element
+        */
        public ListObject remove(int pos) {
                ListObject ret = new ListObject(Arrays.asList(_data.get(pos)),
                                null, _lineage != 
null?Arrays.asList(_lineage.get(pos)):null);
diff --git 
a/src/main/java/org/apache/sysds/runtime/privacy/PrivacyConstraint.java 
b/src/main/java/org/apache/sysds/runtime/privacy/PrivacyConstraint.java
index b19d981..e950c22 100644
--- a/src/main/java/org/apache/sysds/runtime/privacy/PrivacyConstraint.java
+++ b/src/main/java/org/apache/sysds/runtime/privacy/PrivacyConstraint.java
@@ -253,4 +253,19 @@ public class PrivacyConstraint implements Externalizable
                }
        }
 
+       @Override
+       public boolean equals(Object other){
+               if ( other instanceof PrivacyConstraint ){
+                       PrivacyConstraint otherPrivacyConstraint = 
(PrivacyConstraint) other;
+                       return otherPrivacyConstraint.privacyLevel == 
privacyLevel
+                               && 
otherPrivacyConstraint.getFineGrainedPrivacy().equals(fineGrainedPrivacy);
+               } else return false;
+       }
+
+       @Override
+       public String toString(){
+               return "General privacy level: " + privacyLevel + 
System.getProperty("line.separator")
+                       + "Fine-grained privacy level: " + 
fineGrainedPrivacy.toString();
+       }
+
 }
diff --git a/src/main/java/org/apache/sysds/runtime/privacy/PrivacyUtils.java 
b/src/main/java/org/apache/sysds/runtime/privacy/PrivacyUtils.java
index 15fff32..206f59d 100644
--- a/src/main/java/org/apache/sysds/runtime/privacy/PrivacyUtils.java
+++ b/src/main/java/org/apache/sysds/runtime/privacy/PrivacyUtils.java
@@ -33,6 +33,62 @@ import org.apache.wink.json4j.JSONObject;
 
 public class PrivacyUtils {
 
+       /**
+        * Returns true if the privacy constraint is not null and the privacy 
level is set to Private or PrivateAggregation.
+        * This only works for the general privacy levels, the fine-grained 
constraints are not checked!
+        * @param constraint to check
+        * @return true if the privacy constraint is not null and activated
+        */
+       public static boolean privacyConstraintActivated(PrivacyConstraint 
constraint){
+               return constraint != null &&
+                       (constraint.getPrivacyLevel() == PrivacyLevel.Private
+                               || constraint.getPrivacyLevel() == 
PrivacyLevel.PrivateAggregation);
+       }
+
+       /**
+        * Returns true if the privacy constraint is not null and it has 
fine-grained constraints.
+        * @param constraint to check
+        * @return true if the privacy constraint is not null and has 
fine-grained constraints
+        */
+       public static boolean 
privacyConstraintFineGrainedActivated(PrivacyConstraint constraint){
+               return constraint != null && 
constraint.getFineGrainedPrivacy().hasConstraints();
+       }
+
+       /**
+        * Returns true if some constraints are set for either of two input 
privacy constraints.
+        * This only checks first two elements in privacy constraint array.
+        * @param privacyConstraints input privacy constraints
+        * @return true if one of the two constraints are activated
+        */
+       public static boolean someConstraintSetBinary(PrivacyConstraint... 
privacyConstraints){
+               return privacyConstraints != null &&
+                       ((privacyConstraints[0] != null && 
privacyConstraints[0].hasConstraints())
+                               || (privacyConstraints[1] != null && 
privacyConstraints[1].hasConstraints()));
+       }
+
+       /**
+        * Returns true if the constraint is set for the input privacy 
constraint.
+        * @param privacyConstraint input to check
+        * @return true if any constraint is activated
+        */
+       public static boolean someConstraintSetUnary(PrivacyConstraint 
privacyConstraint){
+               return privacyConstraint != null && 
privacyConstraint.hasConstraints();
+       }
+
+       public static PrivacyLevel getGeneralPrivacyLevel(PrivacyConstraint 
privacyConstraint){
+               if ( privacyConstraint != null ){
+                       return privacyConstraint.getPrivacyLevel();
+               }
+               else return PrivacyLevel.None;
+       }
+
+       public static PrivacyLevel[] 
getGeneralPrivacyLevels(PrivacyConstraint[] privacyConstraints){
+               PrivacyLevel[] privacyLevels = new 
PrivacyLevel[privacyConstraints.length];
+               for ( int i = 0; i < privacyConstraints.length; i++)
+                       privacyLevels[i] = 
getGeneralPrivacyLevel(privacyConstraints[i]);
+               return privacyLevels;
+       }
+
        public static void setFineGrainedPrivacy(PrivacyConstraint 
privacyConstraint, Expression eFineGrainedPrivacy){
                FineGrainedPrivacy fineGrainedPrivacy = 
privacyConstraint.getFineGrainedPrivacy();
                StringIdentifier fgPrivacyIdentifier = (StringIdentifier) 
eFineGrainedPrivacy;
@@ -45,7 +101,7 @@ public class PrivacyUtils {
                
privacyConstraint.setFineGrainedPrivacyConstraints(fineGrainedPrivacy);
        }
 
-       private static void 
putFineGrainedConstraintsFromString(FineGrainedPrivacy fineGrainedPrivacy, 
String fgPrivacyValue)
+       public static void 
putFineGrainedConstraintsFromString(FineGrainedPrivacy fineGrainedPrivacy, 
String fgPrivacyValue)
                throws JSONException {
                JSONArtifact fgPrivacyJson = JSON.parse(fgPrivacyValue);
                JSONObject fgPrivacyObject = (JSONObject)fgPrivacyJson;
diff --git 
a/src/main/java/org/apache/sysds/runtime/privacy/finegrained/FineGrainedPrivacyList.java
 
b/src/main/java/org/apache/sysds/runtime/privacy/finegrained/FineGrainedPrivacyList.java
index 2992606..54cb639 100644
--- 
a/src/main/java/org/apache/sysds/runtime/privacy/finegrained/FineGrainedPrivacyList.java
+++ 
b/src/main/java/org/apache/sysds/runtime/privacy/finegrained/FineGrainedPrivacyList.java
@@ -159,8 +159,25 @@ public class FineGrainedPrivacyList implements 
FineGrainedPrivacy {
                                return true;
                        if ( !otherFGP.hasConstraints() || !hasConstraints() )
                                return false;
-                       return 
otherFGP.getAllConstraintsList().equals(constraintCollection);
-                       
+                       return listEquals(otherFGP.getAllConstraintsList());
+               }
+               return false;
+       }
+
+       private boolean listEquals(ArrayList<Map.Entry<DataRange,PrivacyLevel>> 
otherFGP){
+               if ( otherFGP.size() == constraintCollection.size() ){
+                       for ( Map.Entry<DataRange, PrivacyLevel> constraint : 
constraintCollection){
+                               if ( !innerEquals(constraint, otherFGP) )
+                                       return false;
+                       }
+                       return true;
+               } else return false;
+       }
+
+       private boolean innerEquals(Map.Entry<DataRange, PrivacyLevel> 
constraint, ArrayList<Map.Entry<DataRange,PrivacyLevel>> otherFGP){
+               for (Map.Entry<DataRange, PrivacyLevel> otherConstraint : 
otherFGP){
+                       if ( constraint.equals(otherConstraint) )
+                               return true;
                }
                return false;
        }
diff --git 
a/src/main/java/org/apache/sysds/runtime/privacy/propagation/AppendPropagator.java
 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/AppendPropagator.java
new file mode 100644
index 0000000..58d1220
--- /dev/null
+++ 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/AppendPropagator.java
@@ -0,0 +1,87 @@
+/*
+ * 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.privacy.propagation;
+
+import org.apache.sysds.runtime.matrix.data.MatrixBlock;
+import org.apache.sysds.runtime.privacy.PrivacyConstraint;
+import org.apache.sysds.runtime.privacy.PrivacyConstraint.PrivacyLevel;
+import org.apache.sysds.runtime.privacy.PrivacyUtils;
+import org.apache.sysds.runtime.privacy.finegrained.DataRange;
+import org.apache.sysds.runtime.privacy.finegrained.FineGrainedPrivacy;
+
+public abstract class AppendPropagator implements Propagator {
+
+       protected MatrixBlock input1, input2;
+       protected PrivacyConstraint privacyConstraint1, privacyConstraint2;
+
+       public AppendPropagator(MatrixBlock input1, PrivacyConstraint 
privacyConstraint1,
+               MatrixBlock input2, PrivacyConstraint privacyConstraint2){
+               setFields(input1, privacyConstraint1, input2, 
privacyConstraint2);
+       }
+
+       public void setFields(MatrixBlock input1, PrivacyConstraint 
privacyConstraint1,
+               MatrixBlock input2, PrivacyConstraint privacyConstraint2){
+               this.input1 = input1;
+               this.input2 = input2;
+               this.privacyConstraint1 = privacyConstraint1;
+               this.privacyConstraint2 = privacyConstraint2;
+       }
+
+       @Override
+       public PrivacyConstraint propagate() {
+               PrivacyConstraint mergedPrivacyConstraint = new 
PrivacyConstraint();
+               propagateInput1Constraint(mergedPrivacyConstraint);
+               propagateInput2Constraint(mergedPrivacyConstraint);
+               return mergedPrivacyConstraint;
+       }
+
+       private void propagateInput1Constraint(PrivacyConstraint 
mergedPrivacyConstraint){
+               if ( 
PrivacyUtils.privacyConstraintActivated(privacyConstraint1) ){
+                       //Get dimensions of input1 and make a fine-grained 
constraint of that size with privacy level
+                       long[] endDims = new long[]{input1.getNumRows()-1, 
input1.getNumColumns()-1};
+                       mergedPrivacyConstraint.getFineGrainedPrivacy().put(new 
DataRange(new long[]{0,0}, endDims), privacyConstraint1.getPrivacyLevel());
+               }
+               if ( 
PrivacyUtils.privacyConstraintFineGrainedActivated(privacyConstraint1) ){
+                       
privacyConstraint1.getFineGrainedPrivacy().getAllConstraintsList().forEach(
+                               constraint -> 
mergedPrivacyConstraint.getFineGrainedPrivacy().put(constraint.getKey(), 
constraint.getValue())
+                       );
+               }
+       }
+
+       private void propagateInput2Constraint(PrivacyConstraint 
mergedPrivacyConstraint){
+               if ( 
PrivacyUtils.privacyConstraintActivated(privacyConstraint2) ){
+                       //Get dimensions of input2 and ...
+                       long[] endDims = new long[]{input2.getNumRows()-1, 
input2.getNumColumns()-1};
+                       
appendInput2(mergedPrivacyConstraint.getFineGrainedPrivacy(),
+                               new DataRange(new long[]{0,0}, endDims), 
privacyConstraint2.getPrivacyLevel());
+               }
+               if ( 
PrivacyUtils.privacyConstraintFineGrainedActivated(privacyConstraint2) ){
+                       // propagate fine-grained constraints
+                       
privacyConstraint2.getFineGrainedPrivacy().getAllConstraintsList().forEach(
+                               constraint -> appendInput2(
+                                       
mergedPrivacyConstraint.getFineGrainedPrivacy(),
+                                       constraint.getKey(), 
constraint.getValue()
+                               )
+                       );
+               }
+       }
+
+       protected abstract void appendInput2(FineGrainedPrivacy 
mergedConstraint, DataRange range, PrivacyLevel privacyLevel);
+}
diff --git 
a/src/main/java/org/apache/sysds/runtime/privacy/propagation/CBindPropagator.java
 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/CBindPropagator.java
new file mode 100644
index 0000000..1c0af3e
--- /dev/null
+++ 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/CBindPropagator.java
@@ -0,0 +1,49 @@
+/*
+ * 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.privacy.propagation;
+
+import org.apache.sysds.runtime.matrix.data.MatrixBlock;
+import org.apache.sysds.runtime.privacy.PrivacyConstraint;
+import org.apache.sysds.runtime.privacy.finegrained.DataRange;
+import org.apache.sysds.runtime.privacy.finegrained.FineGrainedPrivacy;
+
+public class CBindPropagator extends AppendPropagator {
+
+       public CBindPropagator(MatrixBlock input1, PrivacyConstraint 
privacyConstraint1, MatrixBlock input2,
+               PrivacyConstraint privacyConstraint2) {
+               super(input1, privacyConstraint1, input2, privacyConstraint2);
+       }
+
+       @Override
+       protected void appendInput2(FineGrainedPrivacy mergedConstraint, 
DataRange range,
+               PrivacyConstraint.PrivacyLevel privacyLevel) {
+               long rowBegin = range.getBeginDims()[0]; //same as before
+               long colBegin = range.getBeginDims()[1] + 
input1.getNumColumns();
+               long[] beginDims = new long[]{rowBegin, colBegin};
+
+               long rowEnd = range.getEndDims()[0]; //same as before
+               long colEnd = range.getEndDims()[1] + input1.getNumColumns();
+               long[] endDims = new long[]{rowEnd, colEnd};
+
+               DataRange outputRange = new DataRange(beginDims, endDims);
+
+               mergedConstraint.put(outputRange, privacyLevel);
+       }
+}
diff --git 
a/src/main/java/org/apache/sysds/runtime/privacy/propagation/ListAppendPropagator.java
 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/ListAppendPropagator.java
new file mode 100644
index 0000000..3c88ea3
--- /dev/null
+++ 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/ListAppendPropagator.java
@@ -0,0 +1,73 @@
+/*
+ * 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.privacy.propagation;
+
+import org.apache.sysds.runtime.instructions.cp.ListObject;
+import org.apache.sysds.runtime.privacy.PrivacyConstraint;
+import org.apache.sysds.runtime.privacy.PrivacyUtils;
+import org.apache.sysds.runtime.privacy.finegrained.DataRange;
+
+import java.util.Map;
+
+public class ListAppendPropagator implements Propagator {
+
+       private final ListObject input1, input2;
+       private final PrivacyConstraint privacyConstraint1, privacyConstraint2;
+
+       public ListAppendPropagator(ListObject input1, PrivacyConstraint 
privacyConstraint1, ListObject input2, PrivacyConstraint privacyConstraint2){
+               this.input1 = input1;
+               this.input2 = input2;
+               this.privacyConstraint1 = privacyConstraint1;
+               this.privacyConstraint2 = privacyConstraint2;
+       }
+
+       @Override public PrivacyConstraint propagate() {
+               PrivacyConstraint mergedPrivacyConstraint = new 
PrivacyConstraint();
+               propagateInput1Constraint(mergedPrivacyConstraint);
+               propagateInput2Constraint(mergedPrivacyConstraint);
+               return mergedPrivacyConstraint;
+       }
+
+       private void propagateInput1Constraint(PrivacyConstraint 
mergedPrivacyConstraint){
+               if(PrivacyUtils.privacyConstraintActivated(privacyConstraint1)) 
{
+                       mergedPrivacyConstraint.getFineGrainedPrivacy()
+                               .put(new DataRange(new long[] {0}, new long[] 
{input1.getLength()-1}), privacyConstraint1.getPrivacyLevel());
+               }
+               if ( 
PrivacyUtils.privacyConstraintFineGrainedActivated(privacyConstraint1) ){
+                       
privacyConstraint1.getFineGrainedPrivacy().getAllConstraintsList().forEach(
+                               constraint -> 
mergedPrivacyConstraint.getFineGrainedPrivacy().put(constraint.getKey(), 
constraint.getValue()));
+               }
+       }
+
+       private void propagateInput2Constraint(PrivacyConstraint 
mergedPrivacyConstraint){
+               if ( 
PrivacyUtils.privacyConstraintActivated(privacyConstraint2) ){
+                       mergedPrivacyConstraint.getFineGrainedPrivacy()
+                               .put(new DataRange(new 
long[]{input1.getLength()}, new long[]{input1.getLength() + input2.getLength() 
- 1}), privacyConstraint2.getPrivacyLevel());
+               }
+               if ( 
PrivacyUtils.privacyConstraintFineGrainedActivated(privacyConstraint2) ){
+                       for ( Map.Entry<DataRange, 
PrivacyConstraint.PrivacyLevel> constraint : 
privacyConstraint2.getFineGrainedPrivacy().getAllConstraintsList()){
+                               long beginIndex = 
constraint.getKey().getBeginDims()[0] + input1.getLength();
+                               long endIndex = 
constraint.getKey().getEndDims()[0] + input1.getLength();
+                               mergedPrivacyConstraint.getFineGrainedPrivacy()
+                                       .put(new DataRange(new 
long[]{beginIndex}, new long[]{endIndex}), constraint.getValue());
+                       }
+               }
+       }
+}
diff --git 
a/src/main/java/org/apache/sysds/runtime/privacy/propagation/ListRemovePropagator.java
 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/ListRemovePropagator.java
new file mode 100644
index 0000000..47d2e24
--- /dev/null
+++ 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/ListRemovePropagator.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.privacy.propagation;
+
+import org.apache.sysds.runtime.instructions.cp.ListObject;
+import org.apache.sysds.runtime.instructions.cp.ScalarObject;
+import org.apache.sysds.runtime.privacy.PrivacyConstraint;
+import org.apache.sysds.runtime.privacy.PrivacyConstraint.PrivacyLevel;
+import org.apache.sysds.runtime.privacy.PrivacyUtils;
+import org.apache.sysds.runtime.privacy.finegrained.DataRange;
+
+import java.util.Map;
+
+public class ListRemovePropagator implements PropagatorMultiReturn {
+       private final ScalarObject removePosition;
+       private final PrivacyConstraint removePositionPrivacyConstraint;
+       private final ListObject list;
+       private final PrivacyConstraint listPrivacyConstraint;
+
+
+       public ListRemovePropagator(ListObject list, PrivacyConstraint 
listPrivacyConstraint, ScalarObject removePosition, PrivacyConstraint 
removePositionPrivacyConstraint){
+               this.list = list;
+               this.listPrivacyConstraint = listPrivacyConstraint;
+               this.removePosition = removePosition;
+               this.removePositionPrivacyConstraint = 
removePositionPrivacyConstraint;
+       }
+
+       @Override
+       public PrivacyConstraint[] propagate() {
+               PrivacyConstraint output1PrivacyConstraint = new 
PrivacyConstraint();
+               PrivacyConstraint output2PrivacyConstraint = new 
PrivacyConstraint();
+               propagateGeneralConstraints(output1PrivacyConstraint, 
output2PrivacyConstraint);
+               propagateFineGrainedConstraints(output1PrivacyConstraint, 
output2PrivacyConstraint);
+               return new PrivacyConstraint[]{output1PrivacyConstraint, 
output2PrivacyConstraint};
+       }
+
+       private void propagateFineGrainedConstraints(PrivacyConstraint 
output1PrivacyConstraint, PrivacyConstraint output2PrivacyConstraint){
+               if ( 
PrivacyUtils.privacyConstraintFineGrainedActivated(listPrivacyConstraint) ){
+                       propagateFirstHalf(output1PrivacyConstraint);
+                       propagateSecondHalf(output1PrivacyConstraint);
+                       propagateRemovedElement(output2PrivacyConstraint);
+               }
+       }
+
+       private void propagateFirstHalf(PrivacyConstraint 
output1PrivacyConstraint){
+               // The newEndDimension is minus 2 since removePosition is given 
in 1-index terms whereas the data
+               // and privacy constraints are 0-index and the privacy 
constraints are given as closed intervals
+               long[] newEndDimension = new 
long[]{removePosition.getLongValue()-2};
+               Map<DataRange, PrivacyLevel> output1Ranges = 
listPrivacyConstraint.getFineGrainedPrivacy()
+                       .getPrivacyLevel(new DataRange(new long[]{0}, 
newEndDimension));
+               output1Ranges.forEach(
+                       (range, privacyLevel) -> {
+                               long endDim = Long.min(range.getEndDims()[0], 
removePosition.getLongValue()-2);
+                               DataRange cappedRange = new 
DataRange(range.getBeginDims(),new long[]{endDim});
+                               
output1PrivacyConstraint.getFineGrainedPrivacy().put(cappedRange, privacyLevel);
+                       }
+               );
+       }
+
+       private void propagateSecondHalf(PrivacyConstraint 
output1PrivacyConstraint){
+               Map<DataRange, PrivacyLevel> output2Ranges = 
listPrivacyConstraint.getFineGrainedPrivacy()
+                       .getPrivacyLevel(new DataRange(new 
long[]{removePosition.getLongValue()}, new long[]{list.getLength()}));
+               output2Ranges.forEach(
+                       (range, privacyLevel) -> {
+                               long[] beginDims = new 
long[]{range.getBeginDims()[0]-1};
+                               long[] endDims = new 
long[]{range.getEndDims()[0]-1};
+                               
output1PrivacyConstraint.getFineGrainedPrivacy().put(new DataRange(beginDims, 
endDims), privacyLevel);
+                       }
+               );
+       }
+
+       private void propagateRemovedElement(PrivacyConstraint 
output2PrivacyConstraint){
+               if ( output2PrivacyConstraint.getPrivacyLevel() != 
PrivacyLevel.Private ){
+                       Map<DataRange, PrivacyLevel> elementPrivacy = 
listPrivacyConstraint.getFineGrainedPrivacy()
+                               .getPrivacyLevelOfElement(new 
long[]{removePosition.getLongValue()-1});
+                       if ( elementPrivacy.containsValue(PrivacyLevel.Private) 
)
+                               
output2PrivacyConstraint.setPrivacyLevel(PrivacyLevel.Private);
+                       else if ( 
elementPrivacy.containsValue(PrivacyLevel.PrivateAggregation) )
+                               
output2PrivacyConstraint.setPrivacyLevel(PrivacyLevel.PrivateAggregation);
+               }
+       }
+
+       private void propagateGeneralConstraints(PrivacyConstraint 
output1PrivacyConstraint, PrivacyConstraint output2PrivacyConstraint){
+               PrivacyLevel[] inputPrivacyLevels = 
PrivacyUtils.getGeneralPrivacyLevels(new PrivacyConstraint[]{
+                       listPrivacyConstraint, removePositionPrivacyConstraint
+               });
+               PrivacyLevel outputPrivacyLevel = 
PrivacyPropagator.corePropagation(inputPrivacyLevels, 
OperatorType.NonAggregate);
+               output1PrivacyConstraint.setPrivacyLevel(outputPrivacyLevel);
+               output2PrivacyConstraint.setPrivacyLevel(outputPrivacyLevel);
+       }
+}
diff --git 
a/src/main/java/org/apache/sysds/runtime/privacy/propagation/PrivacyPropagator.java
 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/PrivacyPropagator.java
index b6b845d..2776a49 100644
--- 
a/src/main/java/org/apache/sysds/runtime/privacy/propagation/PrivacyPropagator.java
+++ 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/PrivacyPropagator.java
@@ -22,29 +22,15 @@ package org.apache.sysds.runtime.privacy.propagation;
 import java.util.*;
 
 import org.apache.sysds.parser.DataExpression;
+import org.apache.sysds.runtime.DMLRuntimeException;
 import org.apache.sysds.runtime.controlprogram.context.ExecutionContext;
 import org.apache.sysds.runtime.instructions.Instruction;
-import org.apache.sysds.runtime.instructions.cp.AggregateBinaryCPInstruction;
-import org.apache.sysds.runtime.instructions.cp.AggregateUnaryCPInstruction;
-import org.apache.sysds.runtime.instructions.cp.BinaryCPInstruction;
-import org.apache.sysds.runtime.instructions.cp.BuiltinNaryCPInstruction;
-import org.apache.sysds.runtime.instructions.cp.CPInstruction;
-import org.apache.sysds.runtime.instructions.cp.CPOperand;
-import org.apache.sysds.runtime.instructions.cp.ComputationCPInstruction;
-import org.apache.sysds.runtime.instructions.cp.CovarianceCPInstruction;
-import org.apache.sysds.runtime.instructions.cp.Data;
-import org.apache.sysds.runtime.instructions.cp.FunctionCallCPInstruction;
-import 
org.apache.sysds.runtime.instructions.cp.MultiReturnParameterizedBuiltinCPInstruction;
-import 
org.apache.sysds.runtime.instructions.cp.ParameterizedBuiltinCPInstruction;
-import 
org.apache.sysds.runtime.instructions.cp.MultiReturnBuiltinCPInstruction;
-import org.apache.sysds.runtime.instructions.cp.QuaternaryCPInstruction;
-import org.apache.sysds.runtime.instructions.cp.SqlCPInstruction;
-import org.apache.sysds.runtime.instructions.cp.UnaryCPInstruction;
-import org.apache.sysds.runtime.instructions.cp.VariableCPInstruction;
+import org.apache.sysds.runtime.instructions.cp.*;
 import org.apache.sysds.runtime.matrix.data.MatrixBlock;
 import org.apache.sysds.runtime.privacy.DMLPrivacyException;
 import org.apache.sysds.runtime.privacy.PrivacyConstraint;
 import org.apache.sysds.runtime.privacy.PrivacyConstraint.PrivacyLevel;
+import org.apache.sysds.runtime.privacy.PrivacyUtils;
 import org.apache.wink.json4j.JSONException;
 import org.apache.wink.json4j.JSONObject;
 
@@ -188,6 +174,7 @@ public class PrivacyPropagator
                                // Assumption: aggregates in one or several 
dimensions, number of dimensions may change, only certain slices of the data 
may be aggregated upon, elements do not change position
                                return 
preprocessAggregateUnaryCPInstruction((AggregateUnaryCPInstruction)inst, ec);
                        case Append:
+                               return 
preprocessAppendCPInstruction((AppendCPInstruction) inst, ec);
                        case Binary:
                                // TODO: Support propagation of fine-grained 
privacy constraints
                                return 
preprocessBinaryCPInstruction((BinaryCPInstruction) inst, ec);
@@ -281,24 +268,62 @@ public class PrivacyPropagator
        }
 
        private static Instruction 
preprocessAggregateBinaryCPInstruction(AggregateBinaryCPInstruction inst, 
ExecutionContext ec){
-               PrivacyConstraint privacyConstraint1 = 
getInputPrivacyConstraint(ec, inst.input1);
-               PrivacyConstraint privacyConstraint2 = 
getInputPrivacyConstraint(ec, inst.input2);
-               if ( (privacyConstraint1 != null && 
privacyConstraint1.hasConstraints()) 
-                       || (privacyConstraint2 != null && 
privacyConstraint2.hasConstraints()) ){
-                               PrivacyConstraint mergedPrivacyConstraint;
-                               if ( (privacyConstraint1 != null && 
privacyConstraint1.hasFineGrainedConstraints() ) || (privacyConstraint2 != null 
&& privacyConstraint2.hasFineGrainedConstraints() )){
-                                       MatrixBlock input1 = 
ec.getMatrixInput(inst.input1.getName());
-                                       MatrixBlock input2 = 
ec.getMatrixInput(inst.input2.getName());
-                                       Propagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst(input1, privacyConstraint1, input2, 
privacyConstraint2);
-                                       mergedPrivacyConstraint = 
propagator.propagate();
-                                       
ec.releaseMatrixInput(inst.input1.getName(), inst.input2.getName());
-                               }
-                               else {
-                                       mergedPrivacyConstraint = mergeNary(new 
PrivacyConstraint[]{privacyConstraint1,privacyConstraint2},
-                                               OperatorType.NonAggregate);
-                                       
inst.setPrivacyConstraint(mergedPrivacyConstraint);
+               PrivacyConstraint[] privacyConstraints = 
getInputPrivacyConstraints(ec, inst.getInputs());
+               if ( PrivacyUtils.someConstraintSetBinary(privacyConstraints) ){
+                       PrivacyConstraint mergedPrivacyConstraint;
+                       if ( (privacyConstraints[0] != null && 
privacyConstraints[0].hasFineGrainedConstraints() ) ||
+                               (privacyConstraints[1] != null && 
privacyConstraints[1].hasFineGrainedConstraints() )){
+                               MatrixBlock input1 = 
ec.getMatrixInput(inst.input1.getName());
+                               MatrixBlock input2 = 
ec.getMatrixInput(inst.input2.getName());
+                               Propagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst(input1, privacyConstraints[0], 
input2, privacyConstraints[1]);
+                               mergedPrivacyConstraint = 
propagator.propagate();
+                               ec.releaseMatrixInput(inst.input1.getName(), 
inst.input2.getName());
+                       }
+                       else {
+                               mergedPrivacyConstraint = 
mergeNary(privacyConstraints, OperatorType.NonAggregate);
+                               
inst.setPrivacyConstraint(mergedPrivacyConstraint);
+                       }
+                       
inst.output.setPrivacyConstraint(mergedPrivacyConstraint);
+               }
+               return inst;
+       }
+
+       public static Instruction 
preprocessAppendCPInstruction(AppendCPInstruction inst, ExecutionContext ec){
+               PrivacyConstraint[] privacyConstraints = 
getInputPrivacyConstraints(ec, inst.getInputs());
+               if ( PrivacyUtils.someConstraintSetBinary(privacyConstraints) ){
+                       if ( inst.getAppendType() == 
AppendCPInstruction.AppendType.STRING ){
+                               PrivacyLevel[] privacyLevels = new 
PrivacyLevel[2];
+                               privacyLevels[0] = 
PrivacyUtils.getGeneralPrivacyLevel(privacyConstraints[0]);
+                               privacyLevels[1] =  
PrivacyUtils.getGeneralPrivacyLevel(privacyConstraints[1]);
+                               PrivacyConstraint outputConstraint = new 
PrivacyConstraint(corePropagation(privacyLevels, OperatorType.NonAggregate));
+                               
inst.output.setPrivacyConstraint(outputConstraint);
+                       } else if ( inst.getAppendType() == 
AppendCPInstruction.AppendType.LIST ){
+                               ListObject input1 = (ListObject) 
ec.getVariable(inst.input1);
+                               if ( inst.getOpcode().equals("remove")){
+                                       ScalarObject removePosition = 
ec.getScalarInput(inst.input2);
+                                       PropagatorMultiReturn propagator = new 
ListRemovePropagator(input1, privacyConstraints[0], removePosition, 
removePosition.getPrivacyConstraint());
+                                       PrivacyConstraint[] outputConstraints = 
propagator.propagate();
+                                       
inst.output.setPrivacyConstraint(outputConstraints[0]);
+                                       ((ListAppendRemoveCPInstruction) 
inst).getOutput2().setPrivacyConstraint(outputConstraints[1]);
+                               } else {
+                                       ListObject input2 = (ListObject) 
ec.getVariable(inst.input2);
+                                       Propagator propagator = new 
ListAppendPropagator(input1, privacyConstraints[0], input2, 
privacyConstraints[1]);
+                                       
inst.output.setPrivacyConstraint(propagator.propagate());
                                }
-                               
inst.output.setPrivacyConstraint(mergedPrivacyConstraint);
+                       }
+                       else {
+                               MatrixBlock input1 = 
ec.getMatrixInput(inst.input1.getName());
+                               MatrixBlock input2 = 
ec.getMatrixInput(inst.input2.getName());
+                               Propagator propagator = null;
+                               if ( inst.getAppendType() == 
AppendCPInstruction.AppendType.RBIND )
+                                       propagator = new 
RBindPropagator(input1, privacyConstraints[0], input2, privacyConstraints[1]);
+                               else if ( inst.getAppendType() == 
AppendCPInstruction.AppendType.CBIND )
+                                       propagator = new 
CBindPropagator(input1, privacyConstraints[0], input2, privacyConstraints[1]);
+                               else throw new DMLPrivacyException("Instruction 
" + inst.getCPInstructionType() + " with append type " +
+                                               inst.getAppendType() + " is not 
supported by the privacy propagator");
+                               
inst.output.setPrivacyConstraint(propagator.propagate());
+                               ec.releaseMatrixInput(inst.input1.getName(), 
inst.input2.getName());
+                       }
                }
                return inst;
        }
@@ -583,18 +608,12 @@ public class PrivacyPropagator
                if (!instOutputs.isEmpty()){
                        for ( CPOperand output : instOutputs ){
                                PrivacyConstraint outputPrivacyConstraint = 
output.getPrivacyConstraint();
-                               if ( 
privacyConstraintActivated(outputPrivacyConstraint) || (outputPrivacyConstraint 
!= null && outputPrivacyConstraint.hasFineGrainedConstraints()))
+                               if ( 
PrivacyUtils.someConstraintSetUnary(outputPrivacyConstraint) )
                                        setOutputPrivacyConstraint(ec, 
outputPrivacyConstraint, output.getName());
                        }
                }
        }
 
-       private static boolean privacyConstraintActivated(PrivacyConstraint 
instructionPrivacyConstraint){
-               return instructionPrivacyConstraint != null && 
-                       (instructionPrivacyConstraint.getPrivacyLevel() == 
PrivacyLevel.Private
-                       || instructionPrivacyConstraint.getPrivacyLevel() == 
PrivacyLevel.PrivateAggregation);
-       }
-
        @SuppressWarnings("unused")
        private static String[] getOutputVariableName(Instruction inst){
                String[] instructionOutputNames = null;
@@ -624,6 +643,8 @@ public class PrivacyPropagator
                        return getSingletonList(((VariableCPInstruction) 
inst).getOutput());
                else if ( inst instanceof SqlCPInstruction )
                        return getSingletonList(((SqlCPInstruction) 
inst).getOutput());
+               else if ( inst instanceof BuiltinNaryCPInstruction )
+                       return 
getSingletonList(((BuiltinNaryCPInstruction)inst).getOutput());
                return new ArrayList<>();
        }
 
diff --git 
a/src/main/java/org/apache/sysds/runtime/privacy/propagation/Propagator.java 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/Propagator.java
index 48a261a..f14e250 100644
--- a/src/main/java/org/apache/sysds/runtime/privacy/propagation/Propagator.java
+++ b/src/main/java/org/apache/sysds/runtime/privacy/propagation/Propagator.java
@@ -22,7 +22,7 @@ package org.apache.sysds.runtime.privacy.propagation;
 import org.apache.sysds.runtime.privacy.PrivacyConstraint;
 
 /**
- * Interface for all propagator instances.
+ * Interface for all propagator instances with a single output.
  */
 public interface Propagator {
        /**
diff --git 
a/src/main/java/org/apache/sysds/runtime/privacy/propagation/Propagator.java 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/PropagatorMultiReturn.java
similarity index 84%
copy from 
src/main/java/org/apache/sysds/runtime/privacy/propagation/Propagator.java
copy to 
src/main/java/org/apache/sysds/runtime/privacy/propagation/PropagatorMultiReturn.java
index 48a261a..841ed61 100644
--- a/src/main/java/org/apache/sysds/runtime/privacy/propagation/Propagator.java
+++ 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/PropagatorMultiReturn.java
@@ -22,12 +22,12 @@ package org.apache.sysds.runtime.privacy.propagation;
 import org.apache.sysds.runtime.privacy.PrivacyConstraint;
 
 /**
- * Interface for all propagator instances.
+ * Interface for all propagator instances with multiple outputs.
  */
-public interface Propagator {
+public interface PropagatorMultiReturn {
        /**
-        * Activates the propagation and returns the output privacy constraint.
-        * @return output privacy constraint.
+        * Activates the propagation and returns the output privacy constraints.
+        * @return output privacy constraints.
         */
-       PrivacyConstraint propagate();
+       PrivacyConstraint[] propagate();
 }
diff --git 
a/src/main/java/org/apache/sysds/runtime/privacy/propagation/RBindPropagator.java
 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/RBindPropagator.java
new file mode 100644
index 0000000..15ec6e5
--- /dev/null
+++ 
b/src/main/java/org/apache/sysds/runtime/privacy/propagation/RBindPropagator.java
@@ -0,0 +1,49 @@
+/*
+ * 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.privacy.propagation;
+
+import org.apache.sysds.runtime.matrix.data.MatrixBlock;
+import org.apache.sysds.runtime.privacy.PrivacyConstraint;
+import org.apache.sysds.runtime.privacy.finegrained.DataRange;
+import org.apache.sysds.runtime.privacy.finegrained.FineGrainedPrivacy;
+
+public class RBindPropagator extends AppendPropagator {
+
+       public RBindPropagator(MatrixBlock input1, PrivacyConstraint 
privacyConstraint1, MatrixBlock input2,
+               PrivacyConstraint privacyConstraint2) {
+               super(input1, privacyConstraint1, input2, privacyConstraint2);
+       }
+
+       @Override
+       protected void appendInput2(FineGrainedPrivacy mergedConstraint, 
DataRange range,
+               PrivacyConstraint.PrivacyLevel privacyLevel) {
+               long rowBegin = range.getBeginDims()[0] + input1.getNumRows();
+               long colBegin = range.getBeginDims()[1]; //same as before
+               long[] beginDims = new long[]{rowBegin, colBegin};
+
+               long rowEnd = range.getEndDims()[0] + input1.getNumRows();
+               long colEnd = range.getEndDims()[1]; //same as before
+               long[] endDims = new long[]{rowEnd, colEnd};
+
+               DataRange outputRange = new DataRange(beginDims, endDims);
+
+               mergedConstraint.put(outputRange, privacyLevel);
+       }
+}
diff --git a/src/test/java/org/apache/sysds/test/AutomatedTestBase.java 
b/src/test/java/org/apache/sysds/test/AutomatedTestBase.java
index b97d907..c269742 100644
--- a/src/test/java/org/apache/sysds/test/AutomatedTestBase.java
+++ b/src/test/java/org/apache/sysds/test/AutomatedTestBase.java
@@ -70,6 +70,7 @@ import org.apache.sysds.runtime.meta.MatrixCharacteristics;
 import org.apache.sysds.runtime.privacy.CheckedConstraintsLog;
 import org.apache.sysds.runtime.privacy.PrivacyConstraint;
 import org.apache.sysds.runtime.privacy.PrivacyConstraint.PrivacyLevel;
+import org.apache.sysds.runtime.privacy.PrivacyUtils;
 import org.apache.sysds.runtime.util.DataConverter;
 import org.apache.sysds.runtime.util.HDFSTool;
 import org.apache.sysds.utils.ParameterBuilder;
@@ -828,6 +829,38 @@ public abstract class AutomatedTestBase {
                return new DataExpression().readMetadataFile(fname, false);
        }
 
+       /**
+        * Returns the privacy constraint as read from metadata file.
+        * @param fileName name of file
+        * @return loaded privacy constraint
+        * @throws DMLRuntimeException in case of problems with reading the 
metadata file
+        */
+       public static PrivacyConstraint getPrivacyConstraintFromMetaData(String 
fileName, String dir) throws DMLRuntimeException {
+               PrivacyConstraint outputPrivacyConstraint = new 
PrivacyConstraint();
+               try {
+                       JSONObject metadata = getMetaDataJSON(fileName, dir);
+                       if ( metadata != null ){
+                               if ( 
metadata.containsKey(DataExpression.PRIVACY) ){
+                                       PrivacyLevel readPrivacyLevel = 
PrivacyLevel.valueOf(metadata.get(DataExpression.PRIVACY).toString());
+                                       
outputPrivacyConstraint.setPrivacyLevel(readPrivacyLevel);
+                               } else {
+                                       
outputPrivacyConstraint.setPrivacyLevel(PrivacyLevel.None);
+                               }
+                               if ( 
metadata.containsKey(DataExpression.FINE_GRAINED_PRIVACY)){
+                                       JSONObject fineGrainedJSON = 
(JSONObject) metadata.get(DataExpression.FINE_GRAINED_PRIVACY);
+                                       
PrivacyUtils.putFineGrainedConstraintsFromString(outputPrivacyConstraint.getFineGrainedPrivacy(),
 fineGrainedJSON.toString());
+                               }
+                       }
+               } catch (JSONException e){
+                       throw new DMLRuntimeException("Exception when reading 
from meta data file", e);
+               }
+               return outputPrivacyConstraint;
+       }
+
+       public static PrivacyConstraint getPrivacyConstraintFromMetaData(String 
fileName) throws DMLRuntimeException {
+               return getPrivacyConstraintFromMetaData(fileName, OUTPUT_DIR);
+       }
+
        public static String readDMLMetaDataValue(String fileName, String 
outputDir, String key) throws JSONException {
                JSONObject meta = getMetaDataJSON(fileName, outputDir);
                return meta.get(key).toString();
diff --git 
a/src/test/java/org/apache/sysds/test/functions/privacy/ReadWriteTest.java 
b/src/test/java/org/apache/sysds/test/functions/privacy/ReadWriteTest.java
index 02bcc31..6b0f941 100644
--- a/src/test/java/org/apache/sysds/test/functions/privacy/ReadWriteTest.java
+++ b/src/test/java/org/apache/sysds/test/functions/privacy/ReadWriteTest.java
@@ -37,6 +37,7 @@ import 
org.apache.sysds.runtime.privacy.finegrained.FineGrainedPrivacyList;
 import org.apache.sysds.test.AutomatedTestBase;
 import org.apache.sysds.test.TestConfiguration;
 import org.apache.wink.json4j.JSONObject;
+import org.junit.Assert;
 import org.junit.Test;
 
 public class ReadWriteTest extends AutomatedTestBase {
@@ -88,19 +89,56 @@ public class ReadWriteTest extends AutomatedTestBase {
                assertTrue(metadata.containsKey("fine_grained_privacy"));
        }
 
+       @Test
+       public void writeAndEqualsFineGrainedConstraintsTest(){
+               TestConfiguration config = 
availableTestConfigurations.get("ReadWriteTest");
+               loadTestConfiguration(config);
+
+               writeA();
+
+               JSONObject metadata = getMetaDataJSON("a", "in/");
+               assertTrue(metadata.containsKey("fine_grained_privacy"));
+
+               PrivacyConstraint expectedPC = new PrivacyConstraint();
+               setFineGrained(expectedPC);
+               PrivacyConstraint constraint = 
getPrivacyConstraintFromMetaData("a", "in/");
+               Assert.assertEquals(expectedPC, constraint);
+       }
+
+       @Test
+       public void writeAndEqualsFineGrainedConstraintsTest2(){
+               TestConfiguration config = 
availableTestConfigurations.get("ReadWriteTest");
+               loadTestConfiguration(config);
+
+               writeA();
+
+               JSONObject metadata = getMetaDataJSON("a", "in/");
+               assertTrue(metadata.containsKey("fine_grained_privacy"));
+
+               PrivacyConstraint expectedPC = new PrivacyConstraint();
+               setFineGrained(expectedPC);
+               expectedPC.getFineGrainedPrivacy().put(new DataRange(new 
long[]{12,6}, new long[]{15,8}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint = 
getPrivacyConstraintFromMetaData("a", "in/");
+               Assert.assertNotEquals(expectedPC, constraint);
+       }
+
        private double[][] writeA(){
                int k = 15;
                double[][] a = getRandomMatrix(m, n, -1, 1, 1, -1);
 
                PrivacyConstraint privacyConstraint = new PrivacyConstraint();
-               FineGrainedPrivacy fgp = new FineGrainedPrivacyList();
+               setFineGrained(privacyConstraint);
+               MatrixCharacteristics dataCharacteristics = new 
MatrixCharacteristics(m,n,k,k);
+               writeInputMatrixWithMTD("a", a, false, dataCharacteristics, 
privacyConstraint);
+               return a;
+       }
+
+       private void setFineGrained(PrivacyConstraint privacyConstraint){
+               FineGrainedPrivacy fgp = 
privacyConstraint.getFineGrainedPrivacy();
                fgp.put(new DataRange(new long[]{1,2}, new long[]{5,4}), 
PrivacyLevel.Private);
                fgp.put(new DataRange(new long[]{7,1}, new long[]{9,1}), 
PrivacyLevel.Private);
                fgp.put(new DataRange(new long[]{10,5}, new long[]{10,9}), 
PrivacyLevel.PrivateAggregation);
                privacyConstraint.setFineGrainedPrivacyConstraints(fgp);
-               MatrixCharacteristics dataCharacteristics = new 
MatrixCharacteristics(m,n,k,k);
-               writeInputMatrixWithMTD("a", a, false, dataCharacteristics, 
privacyConstraint);
-               return a;
        }
 
        @Test
diff --git 
a/src/test/java/org/apache/sysds/test/functions/privacy/BuiltinGLMTest.java 
b/src/test/java/org/apache/sysds/test/functions/privacy/algorithms/BuiltinGLMTest.java
similarity index 99%
rename from 
src/test/java/org/apache/sysds/test/functions/privacy/BuiltinGLMTest.java
rename to 
src/test/java/org/apache/sysds/test/functions/privacy/algorithms/BuiltinGLMTest.java
index 9de2265..7359e2f 100644
--- a/src/test/java/org/apache/sysds/test/functions/privacy/BuiltinGLMTest.java
+++ 
b/src/test/java/org/apache/sysds/test/functions/privacy/algorithms/BuiltinGLMTest.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.sysds.test.functions.privacy;
+package org.apache.sysds.test.functions.privacy.algorithms;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git 
a/src/test/java/org/apache/sysds/test/functions/privacy/FederatedL2SVMTest.java 
b/src/test/java/org/apache/sysds/test/functions/privacy/algorithms/FederatedL2SVMTest.java
similarity index 99%
rename from 
src/test/java/org/apache/sysds/test/functions/privacy/FederatedL2SVMTest.java
rename to 
src/test/java/org/apache/sysds/test/functions/privacy/algorithms/FederatedL2SVMTest.java
index 8991b13..f849e2b 100644
--- 
a/src/test/java/org/apache/sysds/test/functions/privacy/FederatedL2SVMTest.java
+++ 
b/src/test/java/org/apache/sysds/test/functions/privacy/algorithms/FederatedL2SVMTest.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.sysds.test.functions.privacy;
+package org.apache.sysds.test.functions.privacy.algorithms;
 
 import org.apache.sysds.runtime.DMLRuntimeException;
 import org.junit.Test;
diff --git a/src/test/java/org/apache/sysds/test/functions/privacy/GLMTest.java 
b/src/test/java/org/apache/sysds/test/functions/privacy/algorithms/GLMTest.java
similarity index 99%
rename from src/test/java/org/apache/sysds/test/functions/privacy/GLMTest.java
rename to 
src/test/java/org/apache/sysds/test/functions/privacy/algorithms/GLMTest.java
index 5919523..350ff4a 100644
--- a/src/test/java/org/apache/sysds/test/functions/privacy/GLMTest.java
+++ 
b/src/test/java/org/apache/sysds/test/functions/privacy/algorithms/GLMTest.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.sysds.test.functions.privacy;
+package org.apache.sysds.test.functions.privacy.algorithms;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git 
a/src/test/java/org/apache/sysds/test/functions/privacy/propagation/AppendPropagatorTest.java
 
b/src/test/java/org/apache/sysds/test/functions/privacy/propagation/AppendPropagatorTest.java
new file mode 100644
index 0000000..560db59
--- /dev/null
+++ 
b/src/test/java/org/apache/sysds/test/functions/privacy/propagation/AppendPropagatorTest.java
@@ -0,0 +1,1002 @@
+/*
+ * 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.privacy.propagation;
+
+import org.apache.sysds.api.DMLScript;
+import org.apache.sysds.common.Types;
+import org.apache.sysds.parser.DataExpression;
+import org.apache.sysds.runtime.instructions.cp.*;
+import org.apache.sysds.runtime.matrix.data.MatrixBlock;
+import org.apache.sysds.runtime.meta.MatrixCharacteristics;
+import org.apache.sysds.runtime.privacy.PrivacyConstraint;
+import org.apache.sysds.runtime.privacy.PrivacyConstraint.PrivacyLevel;
+import org.apache.sysds.runtime.privacy.PrivacyUtils;
+import org.apache.sysds.runtime.privacy.finegrained.DataRange;
+import org.apache.sysds.runtime.privacy.finegrained.FineGrainedPrivacy;
+import org.apache.sysds.runtime.privacy.propagation.*;
+import org.apache.sysds.test.AutomatedTestBase;
+import org.apache.sysds.test.TestConfiguration;
+import org.apache.sysds.test.TestUtils;
+import 
org.apache.sysds.test.functions.federated.primitives.FederatedRCBindTest;
+import org.apache.wink.json4j.JSONException;
+import org.apache.wink.json4j.JSONObject;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class AppendPropagatorTest extends AutomatedTestBase {
+
+       private final static String TEST_DIR = "functions/privacy/";
+       private final static String TEST_NAME_RBIND = "RBindTest";
+       private final static String TEST_NAME_CBIND = "CBindTest";
+       private final static String TEST_NAME_STRING = "StringAppendTest";
+       private final static String TEST_NAME_LIST = "ListAppendTest";
+       private final static String TEST_CLASS_DIR = TEST_DIR + 
AppendPropagatorTest.class.getSimpleName() + "/";
+
+       @Override public void setUp() {
+               TestUtils.clearAssertionInformation();
+               addTestConfiguration(TEST_NAME_RBIND, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME_RBIND, new String[] {"C"}));
+               addTestConfiguration(TEST_NAME_CBIND, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME_CBIND, new String[] {"C"}));
+               addTestConfiguration(TEST_NAME_STRING, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME_STRING, new String[] {"C"}));
+               addTestConfiguration(TEST_NAME_LIST, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME_LIST, new String[] {"C"}));
+       }
+
+       @Test
+       public void generalOnlyRBindPrivate1Test(){
+               generalOnlyRBindTest(new 
PrivacyConstraint(PrivacyLevel.Private), new PrivacyConstraint());
+       }
+
+       @Test
+       public void generalOnlyRBindPrivateAggregation1Test(){
+               generalOnlyRBindTest(new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation), new PrivacyConstraint());
+       }
+
+       @Test
+       public void generalOnlyRBindNoneTest(){
+               generalOnlyRBindTest(new PrivacyConstraint(), new 
PrivacyConstraint());
+       }
+
+       @Test
+       public void generalOnlyRBindPrivate2Test(){
+               generalOnlyRBindTest(new PrivacyConstraint(), new 
PrivacyConstraint(PrivacyLevel.Private));
+       }
+
+       @Test
+       public void generalOnlyRBindPrivateAggregation2Test(){
+               generalOnlyRBindTest(new PrivacyConstraint(), new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation));
+       }
+
+       @Test
+       public void generalOnlyRBindPrivatePrivateTest(){
+               generalOnlyRBindTest(new 
PrivacyConstraint(PrivacyLevel.Private), new 
PrivacyConstraint(PrivacyLevel.Private));
+       }
+
+       @Test
+       public void generalOnlyRBindPrivatePrivateAggregationTest(){
+               generalOnlyRBindTest(new 
PrivacyConstraint(PrivacyLevel.Private), new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation));
+       }
+
+       private void generalOnlyRBindTest(PrivacyConstraint constraint1, 
PrivacyConstraint constraint2){
+               int columns = 2;
+               int rows1 = 4;
+               int rows2 = 3;
+               MatrixBlock inputMatrix1 = new MatrixBlock(rows1,columns,3);
+               MatrixBlock inputMatrix2 = new MatrixBlock(rows2,columns,4);
+               AppendPropagator propagator = new RBindPropagator(inputMatrix1, 
constraint1, inputMatrix2, constraint2);
+               PrivacyConstraint mergedConstraint = propagator.propagate();
+               Assert.assertEquals(mergedConstraint.getPrivacyLevel(), 
PrivacyLevel.None);
+               Map<DataRange, PrivacyLevel> firstHalfPrivacy = 
mergedConstraint.getFineGrainedPrivacy().getPrivacyLevel(
+                       new DataRange(new long[]{0,0}, new 
long[]{rows1-1,columns-1}));
+               firstHalfPrivacy.forEach((range,level) -> 
Assert.assertEquals(constraint1.getPrivacyLevel(),level));
+               Map<DataRange, PrivacyLevel> secondHalfPrivacy = 
mergedConstraint.getFineGrainedPrivacy().getPrivacyLevel(
+                       new DataRange(new long[]{rows1,0}, new 
long[]{rows1+rows2-1,columns-1}));
+               secondHalfPrivacy.forEach((range,level) -> 
Assert.assertEquals(constraint2.getPrivacyLevel(),level));
+       }
+
+       @Test
+       public void generalOnlyCBindPrivate1Test(){
+               generalOnlyCBindTest(new 
PrivacyConstraint(PrivacyLevel.Private), new PrivacyConstraint());
+       }
+
+       @Test
+       public void generalOnlyCBindPrivateAggregation1Test(){
+               generalOnlyCBindTest(new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation), new PrivacyConstraint());
+       }
+
+       @Test
+       public void generalOnlyCBindNoneTest(){
+               generalOnlyCBindTest(new PrivacyConstraint(), new 
PrivacyConstraint());
+       }
+
+       @Test
+       public void generalOnlyCBindPrivate2Test(){
+               generalOnlyCBindTest(new PrivacyConstraint(), new 
PrivacyConstraint(PrivacyLevel.Private));
+       }
+
+       @Test
+       public void generalOnlyCBindPrivateAggregation2Test(){
+               generalOnlyCBindTest(new PrivacyConstraint(), new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation));
+       }
+
+       @Test
+       public void generalOnlyCBindPrivatePrivateTest(){
+               generalOnlyCBindTest(new 
PrivacyConstraint(PrivacyLevel.Private), new 
PrivacyConstraint(PrivacyLevel.Private));
+       }
+
+       @Test
+       public void generalOnlyCBindPrivatePrivateAggregationTest(){
+               generalOnlyCBindTest(new 
PrivacyConstraint(PrivacyLevel.Private), new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation));
+       }
+
+       private void generalOnlyCBindTest(PrivacyConstraint constraint1, 
PrivacyConstraint constraint2){
+               int rows = 2;
+               int columns1 = 4;
+               int columns2 = 3;
+               MatrixBlock inputMatrix1 = new MatrixBlock(rows,columns1,3);
+               MatrixBlock inputMatrix2 = new MatrixBlock(rows,columns2,4);
+               AppendPropagator propagator = new CBindPropagator(inputMatrix1, 
constraint1, inputMatrix2, constraint2);
+               PrivacyConstraint mergedConstraint = propagator.propagate();
+               Assert.assertEquals(mergedConstraint.getPrivacyLevel(), 
PrivacyLevel.None);
+               Map<DataRange, PrivacyLevel> firstHalfPrivacy = 
mergedConstraint.getFineGrainedPrivacy().getPrivacyLevel(
+                       new DataRange(new long[]{0,0}, new 
long[]{rows-1,columns1-1}));
+               firstHalfPrivacy.forEach((range,level) -> 
Assert.assertEquals(constraint1.getPrivacyLevel(),level));
+               Map<DataRange, PrivacyLevel> secondHalfPrivacy = 
mergedConstraint.getFineGrainedPrivacy().getPrivacyLevel(
+                       new DataRange(new long[]{0,columns1}, new 
long[]{rows,columns1+columns2-1}));
+               secondHalfPrivacy.forEach((range,level) -> 
Assert.assertEquals(constraint2.getPrivacyLevel(),level));
+       }
+
+       @Test
+       public void generalOnlyListAppendPrivate1Test(){
+               generalOnlyListAppendTest(new 
PrivacyConstraint(PrivacyLevel.Private), new PrivacyConstraint());
+       }
+
+       @Test
+       public void generalOnlyListAppendPrivateAggregation1Test(){
+               generalOnlyCBindTest(new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation), new PrivacyConstraint());
+       }
+
+       @Test
+       public void generalOnlyListAppendNoneTest(){
+               generalOnlyListAppendTest(new PrivacyConstraint(), new 
PrivacyConstraint());
+       }
+
+       @Test
+       public void generalOnlyListAppendPrivate2Test(){
+               generalOnlyListAppendTest(new PrivacyConstraint(), new 
PrivacyConstraint(PrivacyLevel.Private));
+       }
+
+       @Test
+       public void generalOnlyListAppendPrivateAggregation2Test(){
+               generalOnlyListAppendTest(new PrivacyConstraint(), new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation));
+       }
+
+       @Test
+       public void generalOnlyListAppendPrivatePrivateTest(){
+               generalOnlyListAppendTest(new 
PrivacyConstraint(PrivacyLevel.Private), new 
PrivacyConstraint(PrivacyLevel.Private));
+       }
+
+       @Test
+       public void generalOnlyListAppendPrivatePrivateAggregationTest(){
+               generalOnlyListAppendTest(new 
PrivacyConstraint(PrivacyLevel.Private), new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation));
+       }
+
+       private void generalOnlyListAppendTest(PrivacyConstraint constraint1, 
PrivacyConstraint constraint2){
+               int length1 = 6;
+               List<Data> dataList1 = Arrays.asList(new Data[length1]);
+               ListObject input1 = new ListObject(dataList1);
+               int length2 = 11;
+               List<Data> dataList2 = Arrays.asList(new Data[length2]);
+               ListObject input2 = new ListObject(dataList2);
+               Propagator propagator = new ListAppendPropagator(input1, 
constraint1, input2, constraint2);
+               PrivacyConstraint mergedConstraint = propagator.propagate();
+               Map<DataRange, PrivacyLevel> firstHalfPrivacy = 
mergedConstraint.getFineGrainedPrivacy().getPrivacyLevel(
+                       new DataRange(new long[]{0}, new long[]{length1-1})
+               );
+               firstHalfPrivacy.forEach((range,level) -> 
Assert.assertEquals(constraint1.getPrivacyLevel(),level));
+               Map<DataRange, PrivacyLevel> secondHalfPrivacy = 
mergedConstraint.getFineGrainedPrivacy().getPrivacyLevel(
+                       new DataRange(new long[length1], new 
long[]{length1+length2-1})
+               );
+               secondHalfPrivacy.forEach((range,level) -> 
Assert.assertEquals(constraint2.getPrivacyLevel(),level));
+       }
+
+       @Test
+       public void generalOnlyListRemoveAppendPrivate1Test(){
+               generalOnlyListRemoveAppendTest(new 
PrivacyConstraint(PrivacyLevel.Private), new PrivacyConstraint(),
+                       PrivacyLevel.Private, PrivacyLevel.Private);
+       }
+
+       @Test
+       public void generalOnlyListRemoveAppendPrivateAggregation1Test(){
+               generalOnlyListRemoveAppendTest(new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation), new PrivacyConstraint(),
+                       PrivacyLevel.PrivateAggregation, 
PrivacyLevel.PrivateAggregation);
+       }
+
+       @Test
+       public void generalOnlyListRemoveAppendNoneTest(){
+               generalOnlyListRemoveAppendTest(new PrivacyConstraint(), new 
PrivacyConstraint(),
+                       PrivacyLevel.None, PrivacyLevel.None);
+       }
+
+       @Test
+       public void generalOnlyListRemoveAppendPrivate2Test(){
+               generalOnlyListRemoveAppendTest(new PrivacyConstraint(), new 
PrivacyConstraint(PrivacyLevel.Private),
+                       PrivacyLevel.Private, PrivacyLevel.Private);
+       }
+
+       @Test
+       public void generalOnlyListRemoveAppendPrivateAggregation2Test(){
+               generalOnlyListRemoveAppendTest(new PrivacyConstraint(), new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation),
+                       PrivacyLevel.PrivateAggregation, 
PrivacyLevel.PrivateAggregation);
+       }
+
+       @Test
+       public void generalOnlyListRemoveAppendPrivatePrivateTest(){
+               generalOnlyListRemoveAppendTest(new 
PrivacyConstraint(PrivacyLevel.Private), new 
PrivacyConstraint(PrivacyLevel.Private),
+                       PrivacyLevel.Private, PrivacyLevel.Private);
+       }
+
+       @Test
+       public void generalOnlyListRemoveAppendPrivatePrivateAggregationTest(){
+               generalOnlyListRemoveAppendTest(new 
PrivacyConstraint(PrivacyLevel.Private), new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation),
+                       PrivacyLevel.Private, PrivacyLevel.Private);
+       }
+
+       private void generalOnlyListRemoveAppendTest(
+               PrivacyConstraint constraint1, PrivacyConstraint constraint2, 
PrivacyLevel expected1, PrivacyLevel expected2){
+               int dataLength = 9;
+               List<Data> dataList = new ArrayList<>();
+               for ( int i = 0; i < dataLength; i++){
+                       dataList.add(new DoubleObject(i));
+               }
+               ListObject inputList = new ListObject(dataList);
+
+               int removePositionInt = 5;
+               ScalarObject removePosition = new IntObject(removePositionInt);
+
+               PropagatorMultiReturn propagator = new 
ListRemovePropagator(inputList, constraint1, removePosition, constraint2);
+               PrivacyConstraint[] mergedConstraints = propagator.propagate();
+
+               Assert.assertEquals(expected1, 
mergedConstraints[0].getPrivacyLevel());
+               Assert.assertEquals(expected2, 
mergedConstraints[1].getPrivacyLevel());
+               Assert.assertFalse("The first output constraint should have no 
fine-grained constraints", mergedConstraints[0].hasFineGrainedConstraints());
+               Assert.assertFalse("The second output constraint should have no 
fine-grained constraints", mergedConstraints[1].hasFineGrainedConstraints());
+       }
+
+       @Test
+       public void finegrainedRBindPrivate1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               finegrainedRBindTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedRBindPrivateAndPrivateAggregate1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0},new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               finegrainedRBindTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedRBindPrivate2(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               finegrainedRBindTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedRBindPrivateAndPrivateAggregate2(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0},new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               finegrainedRBindTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedRBindPrivate12(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               finegrainedRBindTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedRBindPrivateAndPrivateAggregate12(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0},new long[]{0,1}), PrivacyLevel.Private);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0},new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0},new long[]{0,1}), PrivacyLevel.Private);
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{2,0}), PrivacyLevel.PrivateAggregation);
+               finegrainedRBindTest(constraint1, constraint2);
+       }
+
+       private void finegrainedRBindTest(PrivacyConstraint constraint1, 
PrivacyConstraint constraint2){
+               int columns = 2;
+               int rows1 = 4;
+               int rows2 = 3;
+               MatrixBlock inputMatrix1 = new MatrixBlock(rows1,columns,3);
+               MatrixBlock inputMatrix2 = new MatrixBlock(rows2,columns,4);
+               AppendPropagator propagator = new RBindPropagator(inputMatrix1, 
constraint1, inputMatrix2, constraint2);
+               PrivacyConstraint mergedConstraint = propagator.propagate();
+               Assert.assertEquals(mergedConstraint.getPrivacyLevel(), 
PrivacyLevel.None);
+               Map<DataRange, PrivacyLevel> firstHalfPrivacy = 
mergedConstraint.getFineGrainedPrivacy().getPrivacyLevel(
+                       new DataRange(new long[]{0,0}, new 
long[]{rows1-1,columns-1}));
+               
constraint1.getFineGrainedPrivacy().getAllConstraintsList().forEach(
+                       constraint -> Assert.assertTrue("Merged constraint 
should contain same privacy levels as input 1",
+                               
firstHalfPrivacy.containsValue(constraint.getValue()))
+               );
+               Map<DataRange, PrivacyLevel> secondHalfPrivacy = 
mergedConstraint.getFineGrainedPrivacy().getPrivacyLevel(
+                       new DataRange(new long[]{rows1,0}, new 
long[]{rows1+rows2-1,columns-1}));
+               
constraint2.getFineGrainedPrivacy().getAllConstraintsList().forEach(
+                       constraint -> Assert.assertTrue("Merged constraint 
should contain same privacy levels as input 2",
+                               
secondHalfPrivacy.containsValue(constraint.getValue()))
+               );
+       }
+
+       @Test
+       public void finegrainedCBindPrivate1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               finegrainedCBindTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedCBindPrivateAndPrivateAggregate1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0},new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               finegrainedCBindTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedCBindPrivate2(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               finegrainedCBindTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedCBindPrivateAndPrivateAggregate2(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0},new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               finegrainedCBindTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedCBindPrivate12(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               finegrainedCBindTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedCBindPrivateAndPrivateAggregate12(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0},new long[]{0,1}), PrivacyLevel.Private);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0},new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0},new long[]{0,1}), PrivacyLevel.Private);
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{2,0}), PrivacyLevel.PrivateAggregation);
+               finegrainedCBindTest(constraint1, constraint2);
+       }
+
+       private void finegrainedCBindTest(PrivacyConstraint constraint1, 
PrivacyConstraint constraint2){
+               int rows = 6;
+               int columns1 = 4;
+               int columns2 = 3;
+               MatrixBlock inputMatrix1 = new MatrixBlock(rows,columns1,3);
+               MatrixBlock inputMatrix2 = new MatrixBlock(rows,columns2,4);
+               AppendPropagator propagator = new CBindPropagator(inputMatrix1, 
constraint1, inputMatrix2, constraint2);
+               PrivacyConstraint mergedConstraint = propagator.propagate();
+               Assert.assertEquals(mergedConstraint.getPrivacyLevel(), 
PrivacyLevel.None);
+               Map<DataRange, PrivacyLevel> firstHalfPrivacy = 
mergedConstraint.getFineGrainedPrivacy().getPrivacyLevel(
+                       new DataRange(new long[]{0,0}, new 
long[]{rows-1,columns1-1}));
+               
constraint1.getFineGrainedPrivacy().getAllConstraintsList().forEach(
+                       constraint -> Assert.assertTrue("Merged constraint 
should contain same privacy levels as input 1",
+                               
firstHalfPrivacy.containsValue(constraint.getValue()))
+               );
+               Map<DataRange, PrivacyLevel> secondHalfPrivacy = 
mergedConstraint.getFineGrainedPrivacy().getPrivacyLevel(
+                       new DataRange(new long[]{0,columns1}, new 
long[]{rows,columns1+columns2-1}));
+               
constraint2.getFineGrainedPrivacy().getAllConstraintsList().forEach(
+                       constraint -> Assert.assertTrue("Merged constraint 
should contain same privacy levels as input 2",
+                               
secondHalfPrivacy.containsValue(constraint.getValue()))
+               );
+       }
+
+       @Test
+       public void finegrainedListAppendPrivate1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1},new long[]{2}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               finegrainedListAppendTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedListAppendPrivateAndPrivateAggregate1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1},new long[]{2}), PrivacyLevel.Private);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{3},new long[]{5}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               finegrainedListAppendTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedListAppendPrivate2(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1},new long[]{2}), PrivacyLevel.Private);
+               finegrainedListAppendTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedListAppendPrivateAndPrivateAggregate2(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1},new long[]{2}), PrivacyLevel.Private);
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{3},new long[]{5}), PrivacyLevel.PrivateAggregation);
+               finegrainedListAppendTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedListAppendPrivate12(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1},new long[]{2}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1},new long[]{4}), PrivacyLevel.Private);
+               finegrainedListAppendTest(constraint1, constraint2);
+       }
+
+       @Test
+       public void finegrainedListAppendPrivateAndPrivateAggregate12(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0},new long[]{0}), PrivacyLevel.Private);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2},new long[]{3}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0},new long[]{1}), PrivacyLevel.Private);
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{3},new long[]{5}), PrivacyLevel.PrivateAggregation);
+               finegrainedListAppendTest(constraint1, constraint2);
+       }
+
+       private void finegrainedListAppendTest(PrivacyConstraint constraint1, 
PrivacyConstraint constraint2){
+               int length1 = 6;
+               List<Data> dataList1 = Arrays.asList(new Data[length1]);
+               ListObject input1 = new ListObject(dataList1);
+               int length2 = 11;
+               List<Data> dataList2 = Arrays.asList(new Data[length2]);
+               ListObject input2 = new ListObject(dataList2);
+               Propagator propagator = new ListAppendPropagator(input1, 
constraint1, input2, constraint2);
+               PrivacyConstraint mergedConstraint = propagator.propagate();
+               Assert.assertEquals(mergedConstraint.getPrivacyLevel(), 
PrivacyLevel.None);
+               Map<DataRange, PrivacyLevel> firstHalfPrivacy = 
mergedConstraint.getFineGrainedPrivacy().getPrivacyLevel(
+                       new DataRange(new long[]{0}, new long[]{length1-1})
+               );
+               
constraint1.getFineGrainedPrivacy().getAllConstraintsList().forEach(
+                       constraint -> Assert.assertTrue("Merged constraint 
should contain same privacy levels as input 1",
+                               
firstHalfPrivacy.containsValue(constraint.getValue()))
+               );
+               Map<DataRange, PrivacyLevel> secondHalfPrivacy = 
mergedConstraint.getFineGrainedPrivacy().getPrivacyLevel(
+                       new DataRange(new long[]{length1}, new 
long[]{length1+length2-1})
+               );
+               
constraint2.getFineGrainedPrivacy().getAllConstraintsList().forEach(
+                       constraint -> Assert.assertTrue("Merged constraint 
should contain same privacy levels as input 2",
+                               
secondHalfPrivacy.containsValue(constraint.getValue()))
+               );
+       }
+
+       @Test
+       public void testFunction(){
+               int dataLength = 9;
+               List<Data> dataList = new ArrayList<>();
+               for ( int i = 0; i < dataLength; i++){
+                       dataList.add(new DoubleObject(i));
+               }
+               ListObject l = new ListObject(dataList);
+               ListObject lCopy = l.copy();
+               int position = 4;
+               ListObject output = l.remove(position);
+               Assert.assertEquals(lCopy.getData(position), 
output.getData().get(0));
+       }
+
+       @Test
+       public void finegrainedListRemoveAppendNone1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1},new long[]{2}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               finegrainedListRemoveAppendTest(constraint1, constraint2, 
PrivacyLevel.None);
+       }
+
+       @Test
+       public void finegrainedListRemoveAppendPrivate1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1},new long[]{6}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               finegrainedListRemoveAppendTest(constraint1, constraint2, 
PrivacyLevel.Private);
+       }
+
+       @Test
+       public void finegrainedListRemoveAppendPrivate2(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1},new long[]{6}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
+               finegrainedListRemoveAppendTest(constraint1, constraint2, 
PrivacyLevel.Private);
+       }
+
+       @Test
+       public void finegrainedListRemoveAppendPrivate3(){
+               PrivacyConstraint constraint1 = new 
PrivacyConstraint(PrivacyLevel.Private);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1},new long[]{6}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               finegrainedListRemoveAppendTest(constraint1, constraint2, 
PrivacyLevel.Private);
+       }
+
+       @Test
+       public void finegrainedListRemoveAppendPrivate4(){
+               PrivacyConstraint constraint1 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{4},new long[]{4}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               finegrainedListRemoveAppendTest(constraint1, constraint2, 
PrivacyLevel.Private, true);
+       }
+
+       @Test
+       public void finegrainedListRemoveAppendPrivateAndPrivateAggregate1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1},new long[]{2}), PrivacyLevel.Private);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{3},new long[]{5}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               finegrainedListRemoveAppendTest(constraint1, constraint2, 
PrivacyLevel.PrivateAggregation);
+       }
+
+       @Test
+       public void finegrainedListRemoveAppendPrivateAggregate2(){
+               PrivacyConstraint constraint1 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{5},new long[]{8}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               finegrainedListRemoveAppendTest(constraint1, constraint2, 
PrivacyLevel.PrivateAggregation);
+       }
+
+       private void finegrainedListRemoveAppendTest(
+               PrivacyConstraint constraint1, PrivacyConstraint constraint2, 
PrivacyLevel expectedOutput2){
+               finegrainedListRemoveAppendTest(constraint1, constraint2, 
expectedOutput2, false);
+       }
+
+       private void finegrainedListRemoveAppendTest(
+               PrivacyConstraint constraint1, PrivacyConstraint constraint2, 
PrivacyLevel expectedOutput2, boolean singleElementPrivacy){
+               int dataLength = 9;
+               List<Data> dataList = new ArrayList<>();
+               for ( int i = 0; i < dataLength; i++){
+                       dataList.add(new DoubleObject(i));
+               }
+               ListObject inputList = new ListObject(dataList);
+               int removePositionInt = 5;
+               ScalarObject removePosition = new IntObject(removePositionInt);
+               PropagatorMultiReturn propagator = new 
ListRemovePropagator(inputList, constraint1, removePosition, constraint2);
+               PrivacyConstraint[] mergedConstraints = propagator.propagate();
+
+               if ( !singleElementPrivacy ){
+                       Map<DataRange, PrivacyLevel> outputPrivacy = 
mergedConstraints[0].getFineGrainedPrivacy().getPrivacyLevel(
+                               new DataRange(new long[]{0}, new 
long[]{dataLength-1})
+                       );
+                       
constraint1.getFineGrainedPrivacy().getAllConstraintsList().forEach(
+                               constraint -> Assert.assertTrue("Merged 
constraint should contain same privacy levels as input 1",
+                                       
outputPrivacy.containsValue(constraint.getValue()))
+                       );
+               }
+
+               Assert.assertEquals(expectedOutput2, 
mergedConstraints[1].getPrivacyLevel());
+               
Assert.assertFalse(mergedConstraints[1].hasFineGrainedConstraints());
+       }
+
+       @Test
+       public void integrationRBindTestNoneNone(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pcExpected = new 
PrivacyConstraint(PrivacyLevel.None);
+               integrationRBindTest(pc1, pc2, pcExpected);
+       }
+
+       @Test
+       public void integrationRBindTestPrivateNone(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.Private);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0}, new long[]{19,9}), PrivacyLevel.Private);
+               integrationRBindTest(pc1, pc2, pcExpected);
+       }
+
+       @Test
+       public void integrationRBindTestPrivateAggregateNone(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0}, new long[]{19,9}), PrivacyLevel.PrivateAggregation);
+               integrationRBindTest(pc1, pc2, pcExpected);
+       }
+
+       @Test
+       public void integrationRBindTestNonePrivateAggregate(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{20,0}, new long[]{49, 9}), PrivacyLevel.PrivateAggregation);
+               integrationRBindTest(pc1, pc2, pcExpected);
+       }
+
+       @Test
+       public void integrationRBindTestNonePrivate(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.Private);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{20,0}, new long[]{49, 9}), PrivacyLevel.Private);
+               integrationRBindTest(pc1, pc2, pcExpected);
+       }
+
+       @Test
+       public void integrationFinegrainedRBindPrivate1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               integrationRBindTest(constraint1, constraint2, constraint1);
+       }
+
+       @Test
+       public void integrationFinegrainedRBindPrivateAndPrivateAggregate1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0},new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               integrationRBindTest(constraint1, constraint2, constraint1);
+       }
+
+       @Test
+       public void integrationFinegrainedRBindPrivate2(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               PrivacyConstraint pcExcepted = new PrivacyConstraint();
+               pcExcepted.getFineGrainedPrivacy().put(new DataRange(new 
long[]{21,0}, new long[]{21,1}), PrivacyLevel.Private);
+               integrationRBindTest(constraint1, constraint2, pcExcepted);
+       }
+
+       @Test
+       public void integrationFinegrainedRBindPrivateAndPrivateAggregate2(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0},new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint pcExcepted = new PrivacyConstraint();
+               pcExcepted.getFineGrainedPrivacy().put(new DataRange(new 
long[]{21,0},new long[]{21,1}), PrivacyLevel.Private);
+               pcExcepted.getFineGrainedPrivacy().put(new DataRange(new 
long[]{22,0}, new long[]{23,1}), PrivacyLevel.PrivateAggregation);
+               integrationRBindTest(constraint1, constraint2, pcExcepted);
+       }
+
+       @Test
+       public void integrationFinegrainedRBindPrivate12(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{21,0},new long[]{21,1}), PrivacyLevel.Private);
+               integrationRBindTest(constraint1, constraint2, pcExpected);
+       }
+
+       @Test
+       public void integrationFinegrainedRBindPrivateAndPrivateAggregate12(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0},new long[]{0,1}), PrivacyLevel.Private);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0},new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0},new long[]{0,1}), PrivacyLevel.Private);
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{2,0}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0},new long[]{0,1}), PrivacyLevel.Private);
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{20,0},new long[]{20,1}), PrivacyLevel.Private);
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0}, new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{21,0}, new long[]{22,0}), PrivacyLevel.PrivateAggregation);
+               integrationRBindTest(constraint1, constraint2, pcExpected);
+       }
+
+       private void integrationRBindTest(PrivacyConstraint privacyConstraint1, 
PrivacyConstraint privacyConstraint2,
+               PrivacyConstraint expectedOutput){
+               TestConfiguration config = 
getAndLoadTestConfiguration(TEST_NAME_RBIND);
+               fullDMLScriptName = SCRIPT_DIR + TEST_DIR + 
config.getTestScript() + ".dml";
+
+               int rows1 = 20;
+               int rows2 = 30;
+               int cols = 10;
+               double[][] A = getRandomMatrix(rows1, cols, -10, 10, 0.5, 1);
+               double[][] B = getRandomMatrix(rows2, cols, -10, 10, 0.5, 1);
+               writeInputMatrixWithMTD("A", A, false, new 
MatrixCharacteristics(rows1, cols),  privacyConstraint1);
+               writeInputMatrixWithMTD("B", B, false, new 
MatrixCharacteristics(rows2, cols),  privacyConstraint2);
+
+               programArgs = new String[]{"-nvargs", "A=" + input("A"), "B=" + 
input("B"), "C=" + output("C")};
+               runTest(true,false,null,-1);
+
+               PrivacyConstraint outputConstraint = 
getPrivacyConstraintFromMetaData("C");
+               Assert.assertEquals(expectedOutput, outputConstraint);
+       }
+
+       @Test
+       public void integrationCBindTestNoneNone(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pcExpected = new 
PrivacyConstraint(PrivacyLevel.None);
+               integrationCBindTest(pc1, pc2, pcExpected);
+       }
+
+       @Test
+       public void integrationCBindTestPrivateNone(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.Private);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0}, new long[]{9,19}), PrivacyLevel.Private);
+               integrationCBindTest(pc1, pc2, pcExpected);
+       }
+
+       @Test
+       public void integrationCBindTestPrivateAggregateNone(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0}, new long[]{9,19}), PrivacyLevel.PrivateAggregation);
+               integrationCBindTest(pc1, pc2, pcExpected);
+       }
+
+       @Test
+       public void integrationCBindTestNonePrivateAggregate(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,20}, new long[]{9, 49}), PrivacyLevel.PrivateAggregation);
+               integrationCBindTest(pc1, pc2, pcExpected);
+       }
+
+       @Test
+       public void integrationCBindTestNonePrivate(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.Private);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,20}, new long[]{9, 49}), PrivacyLevel.Private);
+               integrationCBindTest(pc1, pc2, pcExpected);
+       }
+
+       @Test
+       public void integrationFinegrainedCBindPrivate1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               integrationCBindTest(constraint1, constraint2, constraint1);
+       }
+
+       @Test
+       public void integrationFinegrainedCBindPrivateAndPrivateAggregate1(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0},new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               integrationCBindTest(constraint1, constraint2, constraint1);
+       }
+
+       @Test
+       public void integrationFinegrainedCBindPrivate2(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               PrivacyConstraint pcExcepted = new PrivacyConstraint();
+               pcExcepted.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,20}, new long[]{1,21}), PrivacyLevel.Private);
+               integrationCBindTest(constraint1, constraint2, pcExcepted);
+       }
+
+       @Test
+       public void integrationFinegrainedCBindPrivateAndPrivateAggregate2(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0},new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint pcExcepted = new PrivacyConstraint();
+               pcExcepted.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,20},new long[]{1,21}), PrivacyLevel.Private);
+               pcExcepted.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,20}, new long[]{3,21}), PrivacyLevel.PrivateAggregation);
+               integrationCBindTest(constraint1, constraint2, pcExcepted);
+       }
+
+       @Test
+       public void integrationFinegrainedCBindPrivate12(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{1,1}), PrivacyLevel.Private);
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,20},new long[]{1,21}), PrivacyLevel.Private);
+               integrationCBindTest(constraint1, constraint2, pcExpected);
+       }
+
+       @Test
+       public void integrationFinegrainedCBindPrivateAndPrivateAggregate12(){
+               PrivacyConstraint constraint1 = new PrivacyConstraint();
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0},new long[]{0,1}), PrivacyLevel.Private);
+               constraint1.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0},new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint constraint2 = new PrivacyConstraint();
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0},new long[]{0,1}), PrivacyLevel.Private);
+               constraint2.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,0},new long[]{2,0}), PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,0},new long[]{0,1}), PrivacyLevel.Private);
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0,20},new long[]{0,21}), PrivacyLevel.Private);
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{2,0}, new long[]{3,1}), PrivacyLevel.PrivateAggregation);
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{1,20}, new long[]{2,20}), PrivacyLevel.PrivateAggregation);
+               integrationCBindTest(constraint1, constraint2, pcExpected);
+       }
+
+       private void integrationCBindTest(PrivacyConstraint privacyConstraint1, 
PrivacyConstraint privacyConstraint2,
+               PrivacyConstraint expectedOutput){
+               TestConfiguration config = 
getAndLoadTestConfiguration(TEST_NAME_CBIND);
+               fullDMLScriptName = SCRIPT_DIR + TEST_DIR + 
config.getTestScript() + ".dml";
+
+               int cols1 = 20;
+               int cols2 = 30;
+               int rows = 10;
+               double[][] A = getRandomMatrix(rows, cols1, -10, 10, 0.5, 1);
+               double[][] B = getRandomMatrix(rows, cols2, -10, 10, 0.5, 1);
+               writeInputMatrixWithMTD("A", A, false, new 
MatrixCharacteristics(rows, cols1),  privacyConstraint1);
+               writeInputMatrixWithMTD("B", B, false, new 
MatrixCharacteristics(rows, cols2),  privacyConstraint2);
+
+               programArgs = new String[]{"-nvargs", "A=" + input("A"), "B=" + 
input("B"), "C=" + output("C")};
+               runTest(true,false,null,-1);
+
+               PrivacyConstraint outputConstraint = 
getPrivacyConstraintFromMetaData("C");
+               Assert.assertEquals(expectedOutput, outputConstraint);
+       }
+
+       @Test
+       public void integrationStringAppendTestNoneNone(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.None);
+               integrationStringAppendTest(pc1, pc2, pc1);
+       }
+
+       @Test
+       public void integrationStringAppendTestPrivateNone(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.Private);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.None);
+               integrationStringAppendTest(pc1, pc2, pc1);
+       }
+
+       @Test
+       public void integrationStringAppendTestPrivateAggregateNone(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.None);
+               integrationStringAppendTest(pc1, pc2, pc1);
+       }
+
+       @Test
+       public void integrationStringAppendTestNonePrivateAggregate(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
+               integrationStringAppendTest(pc1, pc2, pc2);
+       }
+
+       @Test
+       public void integrationStringAppendTestNonePrivate(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.Private);
+               integrationStringAppendTest(pc1, pc2, pc2);
+       }
+
+       private void integrationStringAppendTest(PrivacyConstraint 
privacyConstraint1, PrivacyConstraint privacyConstraint2,
+               PrivacyConstraint expectedOutput){
+               TestConfiguration config = 
getAndLoadTestConfiguration(TEST_NAME_STRING);
+               fullDMLScriptName = SCRIPT_DIR + TEST_DIR + 
config.getTestScript() + ".dml";
+
+               int cols = 1;
+               int rows = 1;
+               double[][] A = getRandomMatrix(rows, cols, -10, 10, 0.5, 1);
+               double[][] B = getRandomMatrix(rows, cols, -10, 10, 0.5, 1);
+               writeInputMatrixWithMTD("A", A, false, new 
MatrixCharacteristics(rows, cols),  privacyConstraint1);
+               writeInputMatrixWithMTD("B", B, false, new 
MatrixCharacteristics(rows, cols),  privacyConstraint2);
+
+               programArgs = new String[]{"-nvargs", "A=" + input("A"), "B=" + 
input("B"), "C=" + output("C")};
+               runTest(true,false,null,-1);
+
+               PrivacyConstraint outputConstraint = 
getPrivacyConstraintFromMetaData("C");
+               Assert.assertEquals(expectedOutput, outputConstraint);
+       }
+
+       @Ignore
+       @Test
+       public void integrationListAppendTestNoneNone(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.None);
+               integrationListAppendTest(pc1, pc2, pc1);
+       }
+
+       @Ignore
+       @Test
+       public void integrationListAppendTestPrivateNone(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.Private);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pcExpected = new PrivacyConstraint();
+               pcExpected.getFineGrainedPrivacy().put(new DataRange(new 
long[]{0}, new long[]{0}), PrivacyLevel.Private);
+               integrationListAppendTest(pc1, pc2, pcExpected);
+       }
+
+       @Ignore
+       @Test
+       public void integrationListAppendTestPrivateAggregateNone(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.None);
+               integrationListAppendTest(pc1, pc2, pc1);
+       }
+
+       @Ignore
+       @Test
+       public void integrationListAppendTestNonePrivateAggregate(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
+               integrationListAppendTest(pc1, pc2, pc2);
+       }
+
+       @Ignore
+       @Test
+       public void integrationListAppendTestNonePrivate(){
+               PrivacyConstraint pc1 = new 
PrivacyConstraint(PrivacyLevel.None);
+               PrivacyConstraint pc2 = new 
PrivacyConstraint(PrivacyLevel.Private);
+               integrationListAppendTest(pc1, pc2, pc2);
+       }
+
+       private void integrationListAppendTest(PrivacyConstraint 
privacyConstraint1, PrivacyConstraint privacyConstraint2,
+               PrivacyConstraint expectedOutput){
+               TestConfiguration config = 
getAndLoadTestConfiguration(TEST_NAME_LIST);
+               fullDMLScriptName = SCRIPT_DIR + TEST_DIR + 
config.getTestScript() + ".dml";
+
+               int cols = 1;
+               int rows = 5;
+               double[][] A = getRandomMatrix(rows, cols, -10, 10, 0.5, 1);
+               double[][] B = getRandomMatrix(rows, cols, -10, 10, 0.5, 1);
+               writeInputMatrixWithMTD("A", A, false, new 
MatrixCharacteristics(rows, cols),  privacyConstraint1);
+               writeInputMatrixWithMTD("B", B, false, new 
MatrixCharacteristics(rows, cols),  privacyConstraint2);
+
+               programArgs = new String[]{"-nvargs", "A=" + input("A"), "B=" + 
input("B"), "C=" + output("C")};
+               runTest(true,false,null,-1);
+
+               PrivacyConstraint outputConstraint = 
getPrivacyConstraintFromMetaData("C");
+               Assert.assertEquals(expectedOutput, outputConstraint);
+       }
+}
diff --git 
a/src/test/java/org/apache/sysds/test/functions/privacy/CorePropagatorTest.java 
b/src/test/java/org/apache/sysds/test/functions/privacy/propagation/CorePropagatorTest.java
similarity index 98%
rename from 
src/test/java/org/apache/sysds/test/functions/privacy/CorePropagatorTest.java
rename to 
src/test/java/org/apache/sysds/test/functions/privacy/propagation/CorePropagatorTest.java
index a359a7d..15a625e 100644
--- 
a/src/test/java/org/apache/sysds/test/functions/privacy/CorePropagatorTest.java
+++ 
b/src/test/java/org/apache/sysds/test/functions/privacy/propagation/CorePropagatorTest.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.sysds.test.functions.privacy;
+package org.apache.sysds.test.functions.privacy.propagation;
 
 import org.apache.sysds.test.AutomatedTestBase;
 import org.junit.Test;
diff --git 
a/src/test/java/org/apache/sysds/test/functions/privacy/PrivacyPropagatorTest.java
 
b/src/test/java/org/apache/sysds/test/functions/privacy/propagation/MatrixMultiplicationPropagatorTest.java
similarity index 88%
rename from 
src/test/java/org/apache/sysds/test/functions/privacy/PrivacyPropagatorTest.java
rename to 
src/test/java/org/apache/sysds/test/functions/privacy/propagation/MatrixMultiplicationPropagatorTest.java
index 0092247..e4b3631 100644
--- 
a/src/test/java/org/apache/sysds/test/functions/privacy/PrivacyPropagatorTest.java
+++ 
b/src/test/java/org/apache/sysds/test/functions/privacy/propagation/MatrixMultiplicationPropagatorTest.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.sysds.test.functions.privacy;
+package org.apache.sysds.test.functions.privacy.propagation;
 
 import java.util.List;
 import java.util.Map;
@@ -35,7 +35,7 @@ import org.junit.Test;
 
 import static org.junit.Assert.*;
 
-public class PrivacyPropagatorTest extends AutomatedTestBase {
+public class MatrixMultiplicationPropagatorTest extends AutomatedTestBase {
 
        @Override
        public void setUp() {
@@ -44,7 +44,7 @@ public class PrivacyPropagatorTest extends AutomatedTestBase {
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateGeneralNoFineGrained(){
+       public void mMPTestPrivateGeneralNoFineGrained(){
                PrivacyConstraint constraint1 = new 
PrivacyConstraint(PrivacyLevel.Private);
                PrivacyConstraint constraint2 = new PrivacyConstraint();
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
@@ -52,7 +52,7 @@ public class PrivacyPropagatorTest extends AutomatedTestBase {
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateGeneralNoFineGrained2(){
+       public void mMPTestPrivateGeneralNoFineGrained2(){
                PrivacyConstraint constraint1 = new PrivacyConstraint();
                PrivacyConstraint constraint2 = new 
PrivacyConstraint(PrivacyLevel.Private);
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
@@ -60,7 +60,7 @@ public class PrivacyPropagatorTest extends AutomatedTestBase {
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateGeneralNoFineGrainedNaive(){
+       public void mMPTestPrivateGeneralNoFineGrainedNaive(){
                PrivacyConstraint constraint1 = new 
PrivacyConstraint(PrivacyLevel.Private);
                PrivacyConstraint constraint2 = new PrivacyConstraint();
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
@@ -68,7 +68,7 @@ public class PrivacyPropagatorTest extends AutomatedTestBase {
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateGeneralNoFineGrained2Naive(){
+       public void mMPTestPrivateGeneralNoFineGrained2Naive(){
                PrivacyConstraint constraint1 = new PrivacyConstraint();
                PrivacyConstraint constraint2 = new 
PrivacyConstraint(PrivacyLevel.Private);
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
@@ -76,7 +76,7 @@ public class PrivacyPropagatorTest extends AutomatedTestBase {
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateGeneralNoFineGrained3(){
+       public void mMPTestPrivateGeneralNoFineGrained3(){
                PrivacyConstraint constraint1 = new 
PrivacyConstraint(PrivacyLevel.Private);
                PrivacyConstraint constraint2 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
@@ -84,7 +84,7 @@ public class PrivacyPropagatorTest extends AutomatedTestBase {
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateGeneralNoFineGrained3Naive(){
+       public void mMPTestPrivateGeneralNoFineGrained3Naive(){
                PrivacyConstraint constraint1 = new 
PrivacyConstraint(PrivacyLevel.Private);
                PrivacyConstraint constraint2 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
@@ -92,7 +92,7 @@ public class PrivacyPropagatorTest extends AutomatedTestBase {
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateGeneralNoFineGrained4(){
+       public void mMPTestPrivateGeneralNoFineGrained4(){
                PrivacyConstraint constraint1 = new 
PrivacyConstraint(PrivacyLevel.Private);
                PrivacyConstraint constraint2 = new 
PrivacyConstraint(PrivacyLevel.Private);
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
@@ -100,7 +100,7 @@ public class PrivacyPropagatorTest extends 
AutomatedTestBase {
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateGeneralNoFineGrained4Naive(){
+       public void mMPTestPrivateGeneralNoFineGrained4Naive(){
                PrivacyConstraint constraint1 = new 
PrivacyConstraint(PrivacyLevel.Private);
                PrivacyConstraint constraint2 = new 
PrivacyConstraint(PrivacyLevel.Private);
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
@@ -108,7 +108,7 @@ public class PrivacyPropagatorTest extends 
AutomatedTestBase {
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateGeneralNoFineGrained5(){
+       public void mMPTestPrivateGeneralNoFineGrained5(){
                PrivacyConstraint constraint1 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
                PrivacyConstraint constraint2 = new 
PrivacyConstraint(PrivacyLevel.Private);
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
@@ -116,7 +116,7 @@ public class PrivacyPropagatorTest extends 
AutomatedTestBase {
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateGeneralNoFineGrained5Naive(){
+       public void mMPTestPrivateGeneralNoFineGrained5Naive(){
                PrivacyConstraint constraint1 = new 
PrivacyConstraint(PrivacyLevel.PrivateAggregation);
                PrivacyConstraint constraint2 = new 
PrivacyConstraint(PrivacyLevel.Private);
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
@@ -124,91 +124,91 @@ public class PrivacyPropagatorTest extends 
AutomatedTestBase {
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestPrivateGeneral(){
+       public void mMPTestPrivateGeneral(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
                mmPropagationPrivateGeneralized(PrivacyLevel.Private, 
propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestPrivateGeneral2() {
+       public void mMPTestPrivateGeneral2() {
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
                
mmPropagationPrivateGeneralized(PrivacyLevel.PrivateAggregation, propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestPrivateGeneralNaive(){
+       public void mMPTestPrivateGeneralNaive(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
                mmPropagationPrivateGeneralized(PrivacyLevel.Private, 
propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestPrivateGeneral2Naive() {
+       public void mMPTestPrivateGeneral2Naive() {
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
                
mmPropagationPrivateGeneralized(PrivacyLevel.PrivateAggregation, propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateGeneralPrivateFirstOptimized(){
+       public void mMPTestPrivateGeneralPrivateFirstOptimized(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirstOptimized();
                mmPropagationPrivateGeneralized(PrivacyLevel.Private, 
propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateGeneral2PrivateFirstOptimized() {
+       public void mMPTestPrivateGeneral2PrivateFirstOptimized() {
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirstOptimized();
                
mmPropagationPrivateGeneralized(PrivacyLevel.PrivateAggregation, propagator);
        }
        
        @Test
-       public void matrixMultiplicationPropagationTestPrivateFineGrained(){
+       public void mMPTestPrivateFineGrained(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
                mmPropagationTestPrivateFineGrainedGeneralized(propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateFineGrainedNaive(){
+       public void mMPTestPrivateFineGrainedNaive(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
                mmPropagationTestPrivateFineGrainedGeneralized(propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateFineGrainedPrivateFirstOptimized(){
+       public void mMPTestPrivateFineGrainedPrivateFirstOptimized(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirstOptimized();
                mmPropagationTestPrivateFineGrainedGeneralized(propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestPrivateFineGrained2(){
+       public void mMPTestPrivateFineGrained2(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
                mmPropagationTestPrivateFineGrained2Generalized(propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateFineGrained2Naive(){
+       public void mMPTestPrivateFineGrained2Naive(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
                mmPropagationTestPrivateFineGrained2Generalized(propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivateFineGrained2PrivateFirstOptimized(){
+       public void mMPTestPrivateFineGrained2PrivateFirstOptimized(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirstOptimized();
                mmPropagationTestPrivateFineGrained2Generalized(propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivatePrivateAggregationFineGrained(){
+       public void mMPTestPrivatePrivateAggregationFineGrained(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
                
mmPropagationTestPrivatePrivateAggregationFineGrainedGeneralized(propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivatePrivateAggregationFineGrainedNaive(){
+       public void mMPTestPrivatePrivateAggregationFineGrainedNaive(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
                
mmPropagationTestPrivatePrivateAggregationFineGrainedGeneralized(propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestPrivatePrivateAggregationFineGrainedPrivateFirstOptimized(){
+       public void 
mMPTestPrivatePrivateAggregationFineGrainedPrivateFirstOptimized(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirstOptimized();
                
mmPropagationTestPrivatePrivateAggregationFineGrainedGeneralized(propagator);
        }
@@ -277,109 +277,109 @@ public class PrivacyPropagatorTest extends 
AutomatedTestBase {
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAgg(){
+       public void mMPTestNonAgg(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
                NonAggGeneralizedTest(PrivacyLevel.PrivateAggregation, 
propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAggPrivate(){
+       public void mMPTestNonAggPrivate(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
                NonAggGeneralizedTest(PrivacyLevel.Private, propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAggNaive(){
+       public void mMPTestNonAggNaive(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
                NonAggGeneralizedTest(PrivacyLevel.PrivateAggregation, 
propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAggPrivateNaive(){
+       public void mMPTestNonAggPrivateNaive(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
                NonAggGeneralizedTest(PrivacyLevel.Private, propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAggPrivateOptimized(){
+       public void mMPTestNonAggPrivateOptimized(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirstOptimized();
                NonAggGeneralizedTest(PrivacyLevel.PrivateAggregation, 
propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestNonAggPrivatePrivateOptimized(){
+       public void mMPTestNonAggPrivatePrivateOptimized(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirstOptimized();
                NonAggGeneralizedTest(PrivacyLevel.Private, propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAgg2(){
+       public void mMPTestNonAgg2(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
                NonAggGeneralizedColTest(PrivacyLevel.PrivateAggregation, 
propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAggPrivate2(){
+       public void mMPTestNonAggPrivate2(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
                NonAggGeneralizedColTest(PrivacyLevel.Private, propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAgg2Naive(){
+       public void mMPTestNonAgg2Naive(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
                NonAggGeneralizedColTest(PrivacyLevel.PrivateAggregation, 
propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAggPrivate2Naive(){
+       public void mMPTestNonAggPrivate2Naive(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
                NonAggGeneralizedColTest(PrivacyLevel.Private, propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestNonAgg2PrivateFirstOptimized(){
+       public void mMPTestNonAgg2PrivateFirstOptimized(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirstOptimized();
                NonAggGeneralizedColTest(PrivacyLevel.PrivateAggregation, 
propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestNonAggPrivate2PrivateFirstOptimized(){
+       public void mMPTestNonAggPrivate2PrivateFirstOptimized(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirstOptimized();
                NonAggGeneralizedColTest(PrivacyLevel.Private, propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAggRowColNA(){
+       public void mMPTestNonAggRowColNA(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
                NonAggGeneralizedRowColTest(PrivacyLevel.PrivateAggregation, 
true, propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAggRowColNAA(){
+       public void mMPTestNonAggRowColNAA(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirst();
                NonAggGeneralizedRowColTest(PrivacyLevel.PrivateAggregation, 
false, propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAggRowColNaiveNA(){
+       public void mMPTestNonAggRowColNaiveNA(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
                NonAggGeneralizedRowColTest(PrivacyLevel.PrivateAggregation, 
true, propagator);
        }
 
        @Test
-       public void matrixMultiplicationPropagationTestNonAggRowColNaiveNAA(){
+       public void mMPTestNonAggRowColNaiveNAA(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorNaive();
                NonAggGeneralizedRowColTest(PrivacyLevel.PrivateAggregation, 
false, propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestNonAggRowColPrivateFirstOptimizedNA(){
+       public void mMPTestNonAggRowColPrivateFirstOptimizedNA(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirstOptimized();
                NonAggGeneralizedRowColTest(PrivacyLevel.PrivateAggregation, 
true, propagator);
        }
 
        @Test
-       public void 
matrixMultiplicationPropagationTestNonAggRowColPrivateFirstOptimizedNAA(){
+       public void mMPTestNonAggRowColPrivateFirstOptimizedNAA(){
                MatrixMultiplicationPropagator propagator = new 
MatrixMultiplicationPropagatorPrivateFirstOptimized();
                NonAggGeneralizedRowColTest(PrivacyLevel.PrivateAggregation, 
false, propagator);
        }
diff --git a/src/test/scripts/functions/privacy/CBindTest.dml 
b/src/test/scripts/functions/privacy/CBindTest.dml
new file mode 100644
index 0000000..e38dfcb
--- /dev/null
+++ b/src/test/scripts/functions/privacy/CBindTest.dml
@@ -0,0 +1,25 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+A = read($A)
+B = read($B)
+C = cbind(A,B)
+write(C, $C)
\ No newline at end of file
diff --git a/src/test/scripts/functions/privacy/ListAppendTest.dml 
b/src/test/scripts/functions/privacy/ListAppendTest.dml
new file mode 100644
index 0000000..0f097c2
--- /dev/null
+++ b/src/test/scripts/functions/privacy/ListAppendTest.dml
@@ -0,0 +1,25 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+A = read($A)
+B = read($B)
+C = cbind(list(A),list(B))
+write(C, $C)
\ No newline at end of file
diff --git a/src/test/scripts/functions/privacy/RBindTest.dml 
b/src/test/scripts/functions/privacy/RBindTest.dml
new file mode 100644
index 0000000..ad37b29
--- /dev/null
+++ b/src/test/scripts/functions/privacy/RBindTest.dml
@@ -0,0 +1,25 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+A = read($A)
+B = read($B)
+C = rbind(A,B)
+write(C, $C)
\ No newline at end of file
diff --git a/src/test/scripts/functions/privacy/StringAppendTest.dml 
b/src/test/scripts/functions/privacy/StringAppendTest.dml
new file mode 100644
index 0000000..80852cc
--- /dev/null
+++ b/src/test/scripts/functions/privacy/StringAppendTest.dml
@@ -0,0 +1,25 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+A = read($A)
+B = read($B)
+C = cbind("A: " + as.scalar(A), "B: " + as.scalar(B))
+write(C, $C)
\ No newline at end of file

Reply via email to