Merge branch 'genomix/fullstack_genomix' of https://code.google.com/p/hyracks into genomix/fullstack_genomix
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/VKmerBytesWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/VKmerBytesWritable.java
index 71efb5f..f6061fd 100644
--- a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/VKmerBytesWritable.java
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/VKmerBytesWritable.java
@@ -675,7 +675,12 @@
         }
         return new KmerBytesWritable(bytes, kmerStartOffset);
     }
-        
+    
+    /**
+     * return the edit distance required to transform kemr1 into kmer2 using substitutions, insertions, and deletions.
+     * 
+     * This uses the classic dynamic programming algorithm and takes O(length_1 * length_2) time and space. 
+     */
     public static int editDistance(VKmerBytesWritable kmer1, VKmerBytesWritable kmer2) {
     	int rows = kmer1.getKmerLetterLength() + 1, columns = kmer2.getKmerLetterLength() + 1, r=0, c=0, match=0;
     	int[][] distMat = new int[rows][columns];
@@ -703,9 +708,25 @@
     private static int min(int a, int b, int c) {
     	return a <= b ? (a <= c ? a : c) : (b <= c ? b : c);
     }
+    private static int min(int a, int b) {
+        return a <= b ? a : b;
+    }
     
     public int editDistance(VKmerBytesWritable other) {
     	return editDistance(this, other);
     }
+    
+    /**
+     * return the fractional difference between the given kmers.  This is the edit distance divided by the smaller length.
+     * 
+     * Note: the fraction may be larger than 1 (when the edit distance is larger than the kmer)
+     */
+    public static float fracDissimilar(VKmerBytesWritable kmer1, VKmerBytesWritable kmer2) {
+        return editDistance(kmer1, kmer2) / (float) min(kmer1.getKmerLetterLength(), kmer2.getKmerLetterLength());
+    }
+    
+    public float fracDissimilar(VKmerBytesWritable other) {
+        return fracDissimilar(this, other);
+    }
 
 }
diff --git a/genomix/genomix-data/src/test/java/edu/uci/ics/genomix/data/test/VKmerBytesWritableTest.java b/genomix/genomix-data/src/test/java/edu/uci/ics/genomix/data/test/VKmerBytesWritableTest.java
index 7460776..9bf728d 100644
--- a/genomix/genomix-data/src/test/java/edu/uci/ics/genomix/data/test/VKmerBytesWritableTest.java
+++ b/genomix/genomix-data/src/test/java/edu/uci/ics/genomix/data/test/VKmerBytesWritableTest.java
@@ -564,6 +564,7 @@
     	
     	Assert.assertEquals(kmer1.editDistance(kmer2), 3);
     	Assert.assertEquals(kmer1.editDistance(kmer2), kmer2.editDistance(kmer1));
+    	Assert.assertEquals(kmer1.fracDissimilar(kmer2), .75f);
     	
     	kmer1.setAsCopy("");
     	Assert.assertEquals(kmer1.editDistance(kmer2), kmer2.getKmerLetterLength());
@@ -572,6 +573,8 @@
     	kmer2.setAsCopy("");
     	Assert.assertEquals(kmer1.editDistance(kmer2), kmer2.getKmerLetterLength());
     	Assert.assertEquals(kmer1.editDistance(kmer2), kmer2.editDistance(kmer1));
+    	
+    	
     }
 
 }
diff --git a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/client/Client.java b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/client/Client.java
index 0da4a77..73a8648 100644
--- a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/client/Client.java
+++ b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/client/Client.java
@@ -9,9 +9,7 @@
 import org.kohsuke.args4j.CmdLineParser;
 import org.kohsuke.args4j.Option;
 
-import edu.uci.ics.genomix.pregelix.operator.pathmerge.P2ForPathMergeVertex;
-import edu.uci.ics.genomix.pregelix.operator.pathmerge.P1ForPathMergeVertex;
-import edu.uci.ics.genomix.pregelix.operator.pathmerge.P3ForPathMergeVertex;
+import edu.uci.ics.genomix.pregelix.operator.pathmerge.BasicGraphCleanVertex;
 import edu.uci.ics.pregelix.api.job.PregelixJob;
 import edu.uci.ics.pregelix.core.base.IDriver.Plan;
 import edu.uci.ics.pregelix.core.driver.Driver;
@@ -43,11 +41,11 @@
         @Option(name = "-runtime-profiling", usage = "whether to do runtime profifling", required = false)
         public String profiling = "false";
         
-        @Option(name = "-pseudo-rate", usage = "the rate of pseduHead", required = false)
-        public float pseudoRate = -1;
-        
-        @Option(name = "-max-patitionround", usage = "max rounds in partition phase", required = false)
-        public int maxRound = -1;
+//        @Option(name = "-pseudo-rate", usage = "the rate of pseduHead", required = false)
+//        public float pseudoRate = -1;
+//        
+//        @Option(name = "-max-patitionround", usage = "max rounds in partition phase", required = false)
+//        public int maxRound = -1;
     }
 
     public static void run(String[] args, PregelixJob job) throws Exception {
@@ -66,19 +64,15 @@
         for (int i = 1; i < inputs.length; i++)
             FileInputFormat.addInputPaths(job, inputs[0]);
         FileOutputFormat.setOutputPath(job, new Path(options.outputPath));
-        job.getConfiguration().setInt(P1ForPathMergeVertex.KMER_SIZE, options.sizeKmer);
-        job.getConfiguration().setInt(P2ForPathMergeVertex.KMER_SIZE, options.sizeKmer);
-        job.getConfiguration().setInt(P3ForPathMergeVertex.KMER_SIZE, options.sizeKmer);
+        job.getConfiguration().setInt(BasicGraphCleanVertex.KMER_SIZE, options.sizeKmer);
         if (options.numIteration > 0) {
-            job.getConfiguration().setInt(P1ForPathMergeVertex.ITERATIONS, options.numIteration);
-            job.getConfiguration().setInt(P2ForPathMergeVertex.ITERATIONS, options.numIteration);
-            job.getConfiguration().setInt(P3ForPathMergeVertex.ITERATIONS, options.numIteration);
+            job.getConfiguration().setInt(BasicGraphCleanVertex.ITERATIONS, options.numIteration);
         }
         
-        if (options.pseudoRate > 0 && options.pseudoRate <= 1)
-           job.getConfiguration().setFloat(P3ForPathMergeVertex.PSEUDORATE, options.pseudoRate);
-        if (options.maxRound > 0)
-            job.getConfiguration().setInt(P3ForPathMergeVertex.MAXROUND, options.maxRound);
+//        if (options.pseudoRate > 0 && options.pseudoRate <= 1)
+//           job.getConfiguration().setFloat(P3ForPathMergeVertex.PSEUDORATE, options.pseudoRate);
+//        if (options.maxRound > 0)
+//            job.getConfiguration().setInt(P3ForPathMergeVertex.MAXROUND, options.maxRound);
         return options;
         
     }
diff --git a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/io/VertexValueWritable.java b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/io/VertexValueWritable.java
index 70ef13f..245fe85 100644
--- a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/io/VertexValueWritable.java
+++ b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/io/VertexValueWritable.java
@@ -9,7 +9,9 @@
 import edu.uci.ics.genomix.type.VKmerBytesWritable;
 import edu.uci.ics.genomix.type.VKmerListWritable;
 
-public class VertexValueWritable implements WritableComparable<VertexValueWritable> {
+public class VertexValueWritable implements WritableComparable<VertexValueWritable>, Serializable {
+
+    private static final long serialVersionUID = 1L;
 
     public static class State extends VertexStateFlag{            
         public static final byte NO_MERGE = 0b00 << 3;
@@ -18,10 +20,12 @@
         public static final byte SHOULD_MERGE_MASK = 0b11 << 3;
         public static final byte SHOULD_MERGE_CLEAR = 0b1100111;
         
+        public static final byte UNCHANGE = 0b0 << 3;
         public static final byte KILL = 0b1 << 3;
         public static final byte KILL_MASK = 0b1 << 3;
         
         public static final byte DIR_FROM_DEADVERTEX = 0b10 << 3;
+        public static final byte DEAD_MASK = 0b10 << 3;
     }
     
     public static class VertexStateFlag extends FakeFlag {
diff --git a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/bubblemerge/BubbleMergeVertex.java b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/bubblemerge/BubbleMergeVertex.java
index 9b8a03d..c92148f 100644
--- a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/bubblemerge/BubbleMergeVertex.java
+++ b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/bubblemerge/BubbleMergeVertex.java
@@ -3,8 +3,10 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 import edu.uci.ics.genomix.type.VKmerBytesWritable;
 import edu.uci.ics.pregelix.api.job.PregelixJob;
@@ -22,10 +24,12 @@
  */
 public class BubbleMergeVertex extends
     BasicGraphCleanVertex {
-
+    public static final String DISSIMILARITY_THRESHOLD = "BubbleMergeVertex.dissimilarThreshold";
+    private float dissimilarThreshold = -1;
+    
     private Map<VKmerBytesWritable, ArrayList<MessageWritable>> receivedMsgMap = new HashMap<VKmerBytesWritable, ArrayList<MessageWritable>>();
     private ArrayList<MessageWritable> receivedMsgList = new ArrayList<MessageWritable>();
-    
+
     /**
      * initiate kmerSize, maxIteration
      */
@@ -34,7 +38,17 @@
             kmerSize = getContext().getConfiguration().getInt(KMER_SIZE, 5);
         if (maxIteration < 0)
             maxIteration = getContext().getConfiguration().getInt(ITERATIONS, 1000000);
-        outgoingMsg.reset();
+        if(dissimilarThreshold == -1)
+            dissimilarThreshold = getContext().getConfiguration().getFloat(DISSIMILARITY_THRESHOLD, (float) 0.05);
+        if(incomingMsg == null)
+            incomingMsg = new MessageWritable();
+        if(outgoingMsg == null)
+            outgoingMsg = new MessageWritable();
+        else
+            outgoingMsg.reset(kmerSize);
+        if(destVertexId == null)
+            destVertexId = new VKmerBytesWritable();
+        outFlag = 0;
     }
     
     public void sendBubbleAndMajorVertexMsgToMinorVertex(){
@@ -64,7 +78,24 @@
         }
     }
     
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({ "unchecked" })
+    public void aggregateBubbleNodesByMajorNode(Iterator<MessageWritable> msgIterator){
+        while (msgIterator.hasNext()) {
+            incomingMsg = msgIterator.next();
+            if(!receivedMsgMap.containsKey(incomingMsg.getStartVertexId())){
+                receivedMsgList.clear();
+                receivedMsgList.add(incomingMsg);
+                receivedMsgMap.put(incomingMsg.getStartVertexId(), (ArrayList<MessageWritable>)receivedMsgList.clone());
+            }
+            else{
+                receivedMsgList.clear();
+                receivedMsgList.addAll(receivedMsgMap.get(incomingMsg.getStartVertexId()));
+                receivedMsgList.add(incomingMsg);
+                receivedMsgMap.put(incomingMsg.getStartVertexId(), (ArrayList<MessageWritable>)receivedMsgList.clone());
+            }
+        }
+    }
+    
     @Override
     public void compute(Iterator<MessageWritable> msgIterator) {
         initVertex();
@@ -82,32 +113,50 @@
                 }
             }
         } else if (getSuperstep() == 3){
-            while (msgIterator.hasNext()) {
-                incomingMsg = msgIterator.next();
-                if(!receivedMsgMap.containsKey(incomingMsg.getStartVertexId())){
-                    receivedMsgList.clear();
-                    receivedMsgList.add(incomingMsg);
-                    receivedMsgMap.put(incomingMsg.getStartVertexId(), (ArrayList<MessageWritable>)receivedMsgList.clone());
-                }
-                else{
-                    receivedMsgList.clear();
-                    receivedMsgList.addAll(receivedMsgMap.get(incomingMsg.getStartVertexId()));
-                    receivedMsgList.add(incomingMsg);
-                    receivedMsgMap.put(incomingMsg.getStartVertexId(), (ArrayList<MessageWritable>)receivedMsgList.clone());
-                }
-            }
+            /** aggregate bubble nodes and grouped by major vertex **/ 
+            aggregateBubbleNodesByMajorNode(msgIterator);
+            
+            Set<MessageWritable> unchangedSet = new HashSet<MessageWritable>();
+            Set<MessageWritable> deletedSet = new HashSet<MessageWritable>();
             for(VKmerBytesWritable prevId : receivedMsgMap.keySet()){
                 if(receivedMsgList.size() > 1){ // filter bubble
                     /** for each startVertex, sort the node by decreasing order of coverage **/
                     receivedMsgList = receivedMsgMap.get(prevId);
                     Collections.sort(receivedMsgList, new MessageWritable.SortByCoverage());
-                    System.out.println("");
-                    
                     
                     /** process similarSet, keep the unchanged set and deleted set & add coverage to unchange node **/
+                    MessageWritable topCoverageMessage = new MessageWritable();
+                    MessageWritable tmpMessage = new MessageWritable();
+                    Iterator<MessageWritable> it;
+                    while(!receivedMsgList.isEmpty()){
+                        it = receivedMsgList.iterator();
+                        topCoverageMessage.set(it.next());
+                        it.remove(); //delete topCoverage node
+                        while(it.hasNext()){
+                            tmpMessage.set(it.next());
+                            //compute the similarity  
+                            float fracDissimilar = (float) 0.02;
+                            if(fracDissimilar < dissimilarThreshold){ //If similar with top node, delete this node and put it in deletedSet 
+                                //TODO add coverage to top node
+                                deletedSet.add(tmpMessage);
+                                it.remove();
+                            }
+                        }
+                        unchangedSet.add(topCoverageMessage);
+                    }
                     
                     /** send message to the unchanged set for updating coverage & send kill message to the deleted set **/ 
-                    
+                    for(MessageWritable msg : unchangedSet){
+                        outFlag = MessageFlag.UNCHANGE;
+                        outgoingMsg.setFlag(outFlag);
+                        outgoingMsg.setAverageCoverage(msg.getAverageCoverage());
+                        sendMsg(msg.getSourceVertexId(), outgoingMsg);
+                    }
+                    for(MessageWritable msg : deletedSet){
+                        outFlag = MessageFlag.KILL;
+                        outgoingMsg.setFlag(outFlag);
+                        sendMsg(msg.getSourceVertexId(), outgoingMsg);
+                    }
                 }
             }
         } else if (getSuperstep() == 4){
@@ -115,12 +164,14 @@
                 incomingMsg = msgIterator.next();
                 if(incomingMsg.getFlag() == MessageFlag.KILL){
                     broadcaseKillself();
-                } 
+                } else if(incomingMsg.getFlag() == MessageFlag.UNCHANGE){
+                    getVertexValue().setAverageCoverage(incomingMsg.getAverageCoverage());
+                }
             }
         } else if(getSuperstep() == 5){
             if(msgIterator.hasNext()) {
                 incomingMsg = msgIterator.next();
-                if(incomingMsg.getFlag() == MessageFlag.KILL){
+                if(isResponseKillMsg()){
                     responseToDeadVertex();
                 }
             }
diff --git a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/pathmerge/BasicGraphCleanVertex.java b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/pathmerge/BasicGraphCleanVertex.java
index 080cf35..58ef4d6 100644
--- a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/pathmerge/BasicGraphCleanVertex.java
+++ b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/pathmerge/BasicGraphCleanVertex.java
@@ -22,14 +22,14 @@
     public static final String KMER_SIZE = "BasicGraphCleanVertex.kmerSize";
     public static final String ITERATIONS = "BasicGraphCleanVertex.iteration";
     public static int kmerSize = -1;
-    protected int maxIteration = -1;
+    public static int maxIteration = -1;
     
     protected MessageWritable incomingMsg = null; 
     protected MessageWritable outgoingMsg = null; 
     protected VKmerBytesWritable destVertexId = null;
     protected Iterator<VKmerBytesWritable> kmerIterator;
-    protected VKmerBytesWritable tmpKmer = new VKmerBytesWritable(kmerSize);
-    byte headFlag;
+    protected VKmerBytesWritable tmpKmer = null;
+    protected byte headFlag;
     protected byte outFlag;
     protected byte inFlag;
     protected byte selfFlag;
@@ -814,9 +814,16 @@
         }
     }
     
-    public boolean isKillMsg(){
+    public boolean isReceiveKillMsg(){
         byte killFlag = (byte) (incomingMsg.getFlag() & MessageFlag.KILL_MASK);
-        return killFlag == MessageFlag.KILL;
+        byte deadFlag = (byte) (incomingMsg.getFlag() & MessageFlag.DEAD_MASK);
+        return killFlag == MessageFlag.KILL & deadFlag != MessageFlag.DIR_FROM_DEADVERTEX;
+    }
+    
+    public boolean isResponseKillMsg(){
+        byte killFlag = (byte) (incomingMsg.getFlag() & MessageFlag.KILL_MASK);
+        byte deadFlag = (byte) (incomingMsg.getFlag() & MessageFlag.DEAD_MASK);
+        return killFlag == MessageFlag.KILL & deadFlag == MessageFlag.DIR_FROM_DEADVERTEX; 
     }
     
     @Override
diff --git a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/pathmerge/MapReduceVertex.java b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/pathmerge/MapReduceVertex.java
index 10137da..5baf492 100644
--- a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/pathmerge/MapReduceVertex.java
+++ b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/pathmerge/MapReduceVertex.java
@@ -171,7 +171,7 @@
         } else if(getSuperstep() == 5){
             while (msgIterator.hasNext()) {
                 incomingMsg = msgIterator.next();
-                if(isKillMsg())
+                if(isReceiveKillMsg())
                     responseToDeadVertex();
             }
         }
diff --git a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/pathmerge/P2ForPathMergeVertex.java b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/pathmerge/P2ForPathMergeVertex.java
index 6b7ad1f..c042f49 100644
--- a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/pathmerge/P2ForPathMergeVertex.java
+++ b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/operator/pathmerge/P2ForPathMergeVertex.java
@@ -249,7 +249,7 @@
                         processFinalMerge(incomingMsg);
                         /** NON-FAKE and Final vertice send msg to FAKE vertex **/
                         sendMsgToFakeVertex();
-                    } else if(isKillMsg()){
+                    } else if(isReceiveKillMsg()){
                         responseToDeadVertex();
                     }
                 }
diff --git a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/type/MessageFlag.java b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/type/MessageFlag.java
index 9468681..3ce6c5a 100644
--- a/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/type/MessageFlag.java
+++ b/genomix/genomix-pregelix/src/main/java/edu/uci/ics/genomix/pregelix/type/MessageFlag.java
@@ -2,11 +2,6 @@
 
 public class MessageFlag extends DirectionFlag {
     
-    //public static final byte FLIP = 1 << 6;
-    public static final byte HEAD_SHOULD_MERGEWITHPREV = 0b101 << 0;
-    public static final byte HEAD_SHOULD_MERGEWITHNEXT = 0b111 << 0;
-
-    
     public static String getFlagAsString(byte code) {
         // TODO: allow multiple flags to be set
         return "ERROR_BAD_MESSAGE";
diff --git a/genomix/genomix-pregelix/src/test/java/edu/uci/ics/genomix/pregelix/JobGen/JobGenerator.java b/genomix/genomix-pregelix/src/test/java/edu/uci/ics/genomix/pregelix/JobGen/JobGenerator.java
index e810623..de2fcd3 100644
--- a/genomix/genomix-pregelix/src/test/java/edu/uci/ics/genomix/pregelix/JobGen/JobGenerator.java
+++ b/genomix/genomix-pregelix/src/test/java/edu/uci/ics/genomix/pregelix/JobGen/JobGenerator.java
@@ -12,6 +12,7 @@
 import edu.uci.ics.genomix.pregelix.operator.bridgeremove.BridgeAddVertex;
 import edu.uci.ics.genomix.pregelix.operator.bridgeremove.BridgeRemoveVertex;
 import edu.uci.ics.genomix.pregelix.operator.bubblemerge.BubbleAddVertex;
+import edu.uci.ics.genomix.pregelix.operator.bubblemerge.BubbleMergeVertex;
 import edu.uci.ics.genomix.pregelix.operator.pathmerge.P2ForPathMergeVertex;
 import edu.uci.ics.genomix.pregelix.operator.pathmerge.MapReduceVertex;
 import edu.uci.ics.genomix.pregelix.operator.splitrepeat.SplitRepeatVertex;
@@ -208,42 +209,32 @@
         generateBubbleAddGraphJob("BubbleAddGraph", outputBase
                 + "BubbleAddGraph.xml");
     }
-//    
-//    private static void generateBubbleMergeGraphJob(String jobName, String outputPath) throws IOException {
-//        PregelixJob job = new PregelixJob(jobName);
-//        job.setVertexClass(BubbleMergeVertex.class);
-//        job.setVertexInputFormatClass(NaiveAlgorithmForPathMergeInputFormat.class);
-//        job.setVertexOutputFormatClass(GraphCleanOutputFormat.class);
-//        job.setDynamicVertexValueSize(true);
-//        job.setOutputKeyClass(PositionWritable.class);
-//        job.setOutputValueClass(VertexValueWritable.class);
-//        job.getConfiguration().setInt(BubbleMergeVertex.KMER_SIZE, 5);
-//        job.getConfiguration().writeXml(new FileOutputStream(new File(outputPath)));
-//    }
-//
-//    private static void genBubbleMergeGraph() throws IOException {
-//        generateBubbleMergeGraphJob("BubbleMergeGraph", outputBase
-//                + "BubbleMergeGraph.xml");
-//    }
+    
+    private static void generateBubbleMergeGraphJob(String jobName, String outputPath) throws IOException {
+        PregelixJob job = new PregelixJob(jobName);
+        job.setVertexClass(BubbleMergeVertex.class);
+        job.setVertexInputFormatClass(GraphCleanInputFormat.class);
+        job.setVertexOutputFormatClass(GraphCleanOutputFormat.class);
+        job.setDynamicVertexValueSize(true);
+        job.setOutputKeyClass(VKmerBytesWritable.class);
+        job.setOutputValueClass(VertexValueWritable.class);
+        job.getConfiguration().setInt(BubbleMergeVertex.KMER_SIZE, 3);
+        job.getConfiguration().writeXml(new FileOutputStream(new File(outputPath)));
+    }
+
+    private static void genBubbleMergeGraph() throws IOException {
+        generateBubbleMergeGraphJob("BubbleMergeGraph", outputBase
+                + "BubbleMergeGraph.xml");
+    }
     
     public static void main(String[] args) throws IOException {
-        //genNaiveAlgorithmForMergeGraph();
-//        genLogAlgorithmForMergeGraph();
-        //genP3ForMergeGraph();
-        //genTipAddGraph();
-//        genTipRemoveGraph();
-//        genBridgeAddGraph();
-//        genBridgeRemoveGraph();
-//        genBubbleAddGraph();
-//        genBubbleMergeGraph();
-//        genP4ForMergeGraph();
-//        genMapReduceGraph();
         genSplitRepeatGraph();
         genTipAddGraph();
         genBridgeAddGraph();
         genTipRemoveGraph();
         genBridgeRemoveGraph();
         genBubbleAddGraph();
+        genBubbleMergeGraph();
     }
 
 }
diff --git a/genomix/genomix-pregelix/src/test/java/edu/uci/ics/genomix/pregelix/JobRun/BubbleMergeSmallTestSuite.java b/genomix/genomix-pregelix/src/test/java/edu/uci/ics/genomix/pregelix/JobRun/BubbleMergeSmallTestSuite.java
index 57647ab..21020ce 100644
--- a/genomix/genomix-pregelix/src/test/java/edu/uci/ics/genomix/pregelix/JobRun/BubbleMergeSmallTestSuite.java
+++ b/genomix/genomix-pregelix/src/test/java/edu/uci/ics/genomix/pregelix/JobRun/BubbleMergeSmallTestSuite.java
@@ -43,9 +43,9 @@
 public class BubbleMergeSmallTestSuite extends TestSuite {
     private static final Logger LOGGER = Logger.getLogger(BubbleMergeSmallTestSuite.class.getName());
 
-    public static final String PreFix = "data/input"; //"graphbuildresult";
+    public static final String PreFix = "data/actual/bubbleadd/BubbleAddGraph/bin"; 
     public static final String[] TestDir = { PreFix + File.separator
-    + "graphs/bubblemerge/fr_bubble"};
+    + "5"};
     private static final String ACTUAL_RESULT_DIR = "data/actual/bubblemerge";
     private static final String PATH_TO_HADOOP_CONF = "src/test/resources/hadoop/conf";
     private static final String PATH_TO_CLUSTER_STORE = "src/test/resources/cluster/stores.properties";