From 1e849a0a454705c107e5c09c70a1d4cde5608c1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Pitois?= <francois.pitois@univ-lyon1.fr>
Date: Thu, 9 Feb 2023 18:33:31 +0100
Subject: [PATCH] inital code

---
 run.sh                                        |   7 +
 src/part1/slashburn.py                        |  60 +++++
 src/part1/unified.py                          | 103 ++++++++
 src/part2/GraphCompress/.idea/.gitignore      |   3 +
 src/part2/GraphCompress/.idea/.name           |   1 +
 src/part2/GraphCompress/.idea/misc.xml        |   6 +
 src/part2/GraphCompress/.idea/modules.xml     |   8 +
 src/part2/GraphCompress/.idea/uiDesigner.xml  | 124 ++++++++++
 src/part2/GraphCompress/.idea/vcs.xml         |   8 +
 src/part2/GraphCompress/GraphCompress.iml     |  20 ++
 .../out/production/GraphCompress/Block.class  | Bin 0 -> 3328 bytes
 .../GraphCompress/CompressMath.class          | Bin 0 -> 1623 bytes
 .../out/production/GraphCompress/Edge.class   | Bin 0 -> 3283 bytes
 .../out/production/GraphCompress/FileIO.class | Bin 0 -> 1071 bytes
 .../out/production/GraphCompress/Graph.class  | Bin 0 -> 5435 bytes
 .../out/production/GraphCompress/Main.class   | Bin 0 -> 3006 bytes
 .../production/GraphCompress/Partition.class  | Bin 0 -> 4015 bytes
 .../production/GraphCompress/Positional.class | Bin 0 -> 144 bytes
 .../GraphCompress/SparseMatrix$1.class        | Bin 0 -> 1495 bytes
 .../GraphCompress/SparseMatrix.class          | Bin 0 -> 3611 bytes
 .../production/GraphCompress/Structure.class  | Bin 0 -> 5163 bytes
 src/part2/GraphCompress/src/Block.java        |  88 +++++++
 src/part2/GraphCompress/src/CompressMath.java |  60 +++++
 src/part2/GraphCompress/src/Edge.java         |  78 ++++++
 src/part2/GraphCompress/src/FileIO.java       |  22 ++
 src/part2/GraphCompress/src/Graph.java        | 143 +++++++++++
 src/part2/GraphCompress/src/Main.java         |  58 +++++
 src/part2/GraphCompress/src/Partition.java    |  99 ++++++++
 src/part2/GraphCompress/src/Positional.java   |   4 +
 src/part2/GraphCompress/src/SparseMatrix.java |  98 ++++++++
 src/part2/GraphCompress/src/Structure.java    | 121 +++++++++
 src/part3/encode.py                           | 233 ++++++++++++++++++
 32 files changed, 1344 insertions(+)
 create mode 100755 run.sh
 create mode 100644 src/part1/slashburn.py
 create mode 100644 src/part1/unified.py
 create mode 100644 src/part2/GraphCompress/.idea/.gitignore
 create mode 100644 src/part2/GraphCompress/.idea/.name
 create mode 100644 src/part2/GraphCompress/.idea/misc.xml
 create mode 100644 src/part2/GraphCompress/.idea/modules.xml
 create mode 100644 src/part2/GraphCompress/.idea/uiDesigner.xml
 create mode 100644 src/part2/GraphCompress/.idea/vcs.xml
 create mode 100644 src/part2/GraphCompress/GraphCompress.iml
 create mode 100644 src/part2/GraphCompress/out/production/GraphCompress/Block.class
 create mode 100644 src/part2/GraphCompress/out/production/GraphCompress/CompressMath.class
 create mode 100644 src/part2/GraphCompress/out/production/GraphCompress/Edge.class
 create mode 100644 src/part2/GraphCompress/out/production/GraphCompress/FileIO.class
 create mode 100644 src/part2/GraphCompress/out/production/GraphCompress/Graph.class
 create mode 100644 src/part2/GraphCompress/out/production/GraphCompress/Main.class
 create mode 100644 src/part2/GraphCompress/out/production/GraphCompress/Partition.class
 create mode 100644 src/part2/GraphCompress/out/production/GraphCompress/Positional.class
 create mode 100644 src/part2/GraphCompress/out/production/GraphCompress/SparseMatrix$1.class
 create mode 100644 src/part2/GraphCompress/out/production/GraphCompress/SparseMatrix.class
 create mode 100644 src/part2/GraphCompress/out/production/GraphCompress/Structure.class
 create mode 100644 src/part2/GraphCompress/src/Block.java
 create mode 100644 src/part2/GraphCompress/src/CompressMath.java
 create mode 100644 src/part2/GraphCompress/src/Edge.java
 create mode 100644 src/part2/GraphCompress/src/FileIO.java
 create mode 100644 src/part2/GraphCompress/src/Graph.java
 create mode 100644 src/part2/GraphCompress/src/Main.java
 create mode 100644 src/part2/GraphCompress/src/Partition.java
 create mode 100644 src/part2/GraphCompress/src/Positional.java
 create mode 100644 src/part2/GraphCompress/src/SparseMatrix.java
 create mode 100644 src/part2/GraphCompress/src/Structure.java
 create mode 100644 src/part3/encode.py

diff --git a/run.sh b/run.sh
new file mode 100755
index 0000000..35ab6c2
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+cp $1 build/graph.graph
+python3 src/part1/unified.py
+java -classpath src/part2/GraphCompress/out/production/GraphCompress Main
+python3 src/part3/encode.py
+# python3 src/part4/draw.py
diff --git a/src/part1/slashburn.py b/src/part1/slashburn.py
new file mode 100644
index 0000000..bc05b2f
--- /dev/null
+++ b/src/part1/slashburn.py
@@ -0,0 +1,60 @@
+import networkx as nx
+from math import sqrt
+
+def add(l,x, key=lambda x:x):
+    m = min([key(x) for x in l])
+    if key(x) <= m:
+        return
+    for i in range(len(l)):
+        if key(l[i]) == m:
+            l[i] = x
+            return
+
+
+def k_max(l,k, key=lambda x:x):
+    if len(l) <= k:
+        return l
+    ans = []
+    for x in l:
+        if len(ans) < k:
+            ans.append(x)
+        else:
+            add(ans,x,key)
+    return ans
+
+def k_struct(H, k, adaptative=False):
+    G = H.copy()
+    while G.order() > k:
+        while G and nx.is_connected(G):
+            sorted_degree = sorted(G.degree, key = lambda x: x[1], reverse=True)
+            k_center = sorted_degree[:k]
+            # k_center = k_max(G.degree, k, key = lambda x: x[1])
+            center = []
+            for v, d in k_center:
+                center.append(v)
+                G.remove_node(v)
+            print(">>> removing center (%d nodes), %d remaining" % (k, G.order()))
+            yield set(center)
+        if G:
+            sorted_comp = sorted(list(nx.connected_components(G)), key = len)
+            bcc = sorted_comp[-1]
+            spokes = set()
+            for component in sorted_comp[:-1]:
+                spokes = spokes.union(component)
+            yield spokes
+
+            # G.remove_nodes_from([n for n in G if n not in set(bcc)])
+            to_remove = [n for n in G if n in spokes]
+            G.remove_nodes_from(to_remove)
+            print(">>> removing spokes (%d nodes), %d remaining" % (len(to_remove), G.order()))
+            if adaptative:
+                k = max(10,G.order()//1000)
+
+def k_slashburn(*args, **kwargs):
+    last = []
+    for s in k_struct(*args, **kwargs):
+        last.append(s)
+    return last
+
+def slashburn(G):
+    return k_slashburn(G, max(10,G.order()//1000), adaptative=True)
diff --git a/src/part1/unified.py b/src/part1/unified.py
new file mode 100644
index 0000000..9c89ff9
--- /dev/null
+++ b/src/part1/unified.py
@@ -0,0 +1,103 @@
+import sys, os
+
+# Disable print
+sys.stdout = open(os.devnull, 'w')
+
+import networkx as nx
+from cdlib import algorithms, readwrite
+from json import loads
+from math import sqrt
+
+import matplotlib.cm as cm
+import matplotlib.pyplot as plt
+import community as community_louvain
+import metis
+
+from slashburn import k_slashburn, slashburn
+
+# Restore print
+sys.stdout = sys.__stdout__
+
+PATH = "build/"
+GRAPH = PATH + "graph.graph"
+OUT = PATH + "struct.txt"
+
+def myprint(f,x):
+    print(x)
+    f.write(x + '\n')
+
+def list_list_to_string(ll, spec="fc"):
+    return '\n'.join(map(lambda l: spec + " " + ' '.join(map(str, l)), ll))
+
+def map_list_list(f, ll):
+    return [list(map(f,l)) for l in ll]
+
+def prune_commu(ll, k):
+    return [l for l in ll if len(l) >= k]
+
+def partition_to_commu(p):
+    n = 1+max(p)
+    commu = [[] for _ in range(n)]
+    for i, u in enumerate(p):
+        commu[u].append(i)
+    return commu
+
+########################
+
+def decorate_cdlib(algo):
+    def f(G):
+        return loads(algo(G).to_json())["communities"]
+    return f
+
+@decorate_cdlib
+def big_clam(G):
+    return algorithms.big_clam(G)
+
+@decorate_cdlib
+def louvain(G):
+    return algorithms.louvain(G)
+
+@decorate_cdlib
+def kcut(G):
+    return algorithms.kcut(G)
+
+def sqrt_metis(G):
+    k = int(sqrt(G.order()/2))
+    _, parts = metis.part_graph(G, k)
+    return partition_to_commu(parts)
+
+def trivial(G):
+    return [list(range(G.order()))]
+
+def unified():
+    with open(GRAPH, 'r') as f:
+        lines = f.readlines()
+    G = nx.parse_edgelist(lines, nodetype=int, delimiter=",", data=False)
+    G = nx.convert_node_labels_to_integers(G, label_attribute="old")
+    threshold = 1
+    '''
+    Each function in flist takes a Graph G created with networkx such that V = [0..n-1] for some n,
+    and returns a list of communities. A community is a list of numbers in [0..n-1]
+    '''
+    flist = [
+        (slashburn, [], "sl"),
+        (big_clam, [], "bc"),
+        (louvain, [], "lv"),
+        (sqrt_metis, [], "mt"),
+    ]
+    print("Part 1")
+    i = 0
+    with open(OUT, 'w') as f:
+        for algo,args,spec in flist:
+            commu = algo(G, *args)
+            pruned = prune_commu(commu, threshold)
+            reverse = map_list_list(lambda x: G.nodes[x]["old"], pruned)
+            formated = list_list_to_string(reverse, spec=spec)
+            f.write(formated + '\n')
+            i += 1
+            print("> Algorithm %d/%d done" % (i, len(flist)))
+
+def main():
+    unified()
+
+main()
diff --git a/src/part2/GraphCompress/.idea/.gitignore b/src/part2/GraphCompress/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/src/part2/GraphCompress/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/src/part2/GraphCompress/.idea/.name b/src/part2/GraphCompress/.idea/.name
new file mode 100644
index 0000000..0c1a9a6
--- /dev/null
+++ b/src/part2/GraphCompress/.idea/.name
@@ -0,0 +1 @@
+GraphCompress
\ No newline at end of file
diff --git a/src/part2/GraphCompress/.idea/misc.xml b/src/part2/GraphCompress/.idea/misc.xml
new file mode 100644
index 0000000..e0844bc
--- /dev/null
+++ b/src/part2/GraphCompress/.idea/misc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/src/part2/GraphCompress/.idea/modules.xml b/src/part2/GraphCompress/.idea/modules.xml
new file mode 100644
index 0000000..6596e23
--- /dev/null
+++ b/src/part2/GraphCompress/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/GraphCompress.iml" filepath="$PROJECT_DIR$/GraphCompress.iml" />
+    </modules>
+  </component>
+</project>
diff --git a/src/part2/GraphCompress/.idea/uiDesigner.xml b/src/part2/GraphCompress/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/src/part2/GraphCompress/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Palette2">
+    <group name="Swing">
+      <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+      </item>
+      <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
+        <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+        <initial-values>
+          <property name="text" value="Button" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="RadioButton" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="CheckBox" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="Label" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+          <preferred-size width="-1" height="20" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+      </item>
+    </group>
+  </component>
+</project>
\ No newline at end of file
diff --git a/src/part2/GraphCompress/.idea/vcs.xml b/src/part2/GraphCompress/.idea/vcs.xml
new file mode 100644
index 0000000..f1f0a09
--- /dev/null
+++ b/src/part2/GraphCompress/.idea/vcs.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$/../../../../.." vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/../../../../../" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/src/part2/GraphCompress/GraphCompress.iml b/src/part2/GraphCompress/GraphCompress.iml
new file mode 100644
index 0000000..0181b11
--- /dev/null
+++ b/src/part2/GraphCompress/GraphCompress.iml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module-library">
+      <library>
+        <CLASSES>
+          <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/20.1.0/annotations-20.1.0.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES />
+      </library>
+    </orderEntry>
+  </component>
+</module>
\ No newline at end of file
diff --git a/src/part2/GraphCompress/out/production/GraphCompress/Block.class b/src/part2/GraphCompress/out/production/GraphCompress/Block.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a3c7b1c93607eaa37af8a033e81436a44c2566c
GIT binary patch
literal 3328
zcmaJ@TX!4P75<KHBa5*uJF!C`2?m>B$qA<A5*no@iDEZS?F3M8a6*8wG}seMGeR>;
zVtRoV!mU>d?J9lpOUp|h%33(d3JX@B`oM4M>f+mH#=01Rv~<os=j_XO_Wt&azWM*%
zuK^sv-!ixt&-NjU=Q4O6C6UgH^nyrBGF*`1MH!Ye7{WyvE@ilUDM=UdiDhsZFB^Ep
zz^ig<$?3{4PhJ~_!kWZz<lu^d^$e=0W#GaSt-68N71DNP)n0J?Kw)IzigneRZU#<u
z`b48)ZOC>(p|9kux>nF^*b4i5=^R^_rIW%8b>j{1nu3~FNR_>6v*s!o+$uS5&^Qxr
zg^Rw5<FA+MR+$H>V~*<tGYb1Ad-*TS^OIXrNEE#a)dv?G*FM{<t=Nt8)=HH-!wX*7
zsxDa#N7m71B3N^L#$PyD^~&o6H`=YWQQy{_=oz+kt?lp`$3Nv*tDb9BdDF?<MTP!S
zV3pSwt$GyGaQxX?J=kDat5T7)Fn^O_e)J6_-MnzPqj1lv9f(#~fjyJCp7&RHp!Z1&
zB3;tc^OAf5WBU8JEJhVDDW7U*J6W!JuEv#Xr6wJCrJ&)ss|vffLsczzbvoQ-@=})T
zU$YyMYfY0Kr}pbjtIBMTM5)xr=T@%R<)9#mQeL-Zbfl16k?N3$YnHzj*0&o$OEWWj
zy=>P5$8&uH1d=Iv%|_XtbA$mIUF1gvnu$l?o7j&71_BdJTs83^9x`!Fq;ZiZWO!JH
zgECylF%uh@Gw~RHWZ(@GzrZgEP5V^X)uS&Y$ggCWRLGw6yuc3{R(;V9*1U>8n8L5q
zc+<pN_)QwWmHBNG@8E`sS<KO(ox$*S2HrLC9^N<bfr$_CI}^{~I4||A=R0y?A>2gU
zs3-+I>jkA|z3w#vyVA;xE<ZbEpsl=U1#8@{S=V`^Nj4JM5wAJy%!IGoGESx{m_@Hv
zZ`i&c>i4skg0-3*IOS4vMO&T`%e|egLV{IUU;-@UmNNJ~{=mDj-H(o`Lt|`q&V@0B
zJvD3HE_!a+3NFwoB|os-fNU8RJiYjoR%&`u<yB50*U6}ej`BR{X(p_%T0ULx>Y}mU
zB#VdId6{<udsPT+T(zoA``l|9PN&;Qqh+R_jA6kTAR&Ymn@b%?BC_V@4g68c{+F)0
zIqp?&-Hv)HOvs#74!p*OfluVA;CbuKI%_fSx^_cjwi)T~of(LHgiJeaxs|HzPlSer
z4j@sYI(E7Y&-3BeL%r8kzU!iBRjVZ@unPwMs_<|-rClMqu_+w*VLi5JmM<&51CT;Y
zx|i|;@`}S4e{5havwii<4%Rc9SkLTZ&i%AuOHx0_)osM-3pkv=4V9nTLM*>;{~g4)
zkkCSM3#t4_VhcuogmO9`+d|*xG>9Y5@gbx+W|83Qvk$}k?!x`pO(-J_GKxdkgDGmv
zgh9AI%oW2$;6)PHF})|i<608v2`vfuBp#(~5_o7i*1GmIB|eWh%4O#0M|6hrUl9Hm
zNNvJMe1=5)CO1RCDXnmy1{FFSia`CCI!VL^kMlu{$6G#Uxe}jQ`itE{<{#hV@<4~n
zY`4n+?eYmcNk;<n=Y%O29u${Tw{XveR#sy=s{=X<<ILy;2KWq?4335-tqcz0DgHqc
zY)|7SJQK%~4Z)fe$N#1fx(n|-*#R&axe2**ltu*{<G9mFLK4^M<WLVM3P0^>oZ4yp
zSWn}bmhnd<iNIeZ{Jz*GiuqeGKgD=HN<Amz28Z+wXE*w5cQ8mUeujNL&cieD(=Poe
z%L_a~#y$zj-ZV3J8b>=oEq2r`f!MUP8ecL|VisX&c;jCpyZj}FmIc;r40F<C<81Jk
zzKvZwb3fA&WIPI@Z~`YI*DEBuFyi30ue<CaEKG4JoZI$%mtDo(w)c=IMUvzcsWPvl
zghV+QMH%4pqR3Mr2H&euyt|AhjdnRd^)Dn7H>duK0VaEtWE}k`lJT2U|3OyDkT}HO
zCZ3|0qR564Oa?_`6Jr$96w{j+p%|k`w0l1NPKONZUOvnGos<9b?EU97)Ugmm1eI{`
zGggHEpqcY|J{e+=rtC-37*PMiNdwvAa*s1D##nSLj5(723imF@1w?6Cijla3y`^R8
zgOrw1lngED5{YyN_w6L;Qb(DNgs8G7$N*{B?$)@4``c9rS!;9{Z}-;%u?fOOUi2*G
c7!&Xj=M4A$gpcuO>_wUD0iIO2XX|nGTcqfhdjJ3c

literal 0
HcmV?d00001

diff --git a/src/part2/GraphCompress/out/production/GraphCompress/CompressMath.class b/src/part2/GraphCompress/out/production/GraphCompress/CompressMath.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d105f92d4750af7187f08f6bac09f5d28e90515
GIT binary patch
literal 1623
zcmZuyOLN**6h0Tduq;E8qL>IfHc3mtZH%4NIMk0MwUY+MX%=L%>cRqRi~>jwh`!dD
zVI~W&JJasG=q59nwu>@d^atb@bk!fwU(m@S?sp{BW>JCeJ@?#uzVn^Og*Weh|AUCu
z>2sY7x~)@{KILI!il%9kr7iU?4)CKxwavpF9`0&%PovKS$zA{OrXaB^NZoWjH`o>=
z6-!UCv*RB)g3^1g=X^2jHJ$zwyV-^2(w^V4yHD-D%j;Mv2W@vCD7Cla_m29`VDQKe
z+8Y3EwS9j8E2UVgm1^)5;Ki(ZPyCMKLFmMS()5Sk0d}Dj9YHgVz;1OO*+;Pp&GCZ1
zfAlS=6?aP@EWQb0>!Eyv^>e&+L7M9Y4fi`Z)j=|7_ng3OVXKGZ-i|#01Em+un%8(f
zwEN62aQeN~ct%FT^)0YChiD9&&=+fUjzji62LUUAAJ|>^#4>_RZnnB{BK3wp?6;f;
zE~o9{WM-D1*<aZPrRjo3I|l92tU>oFZ_o^-40^!QA`c%%(se<`q`9CA3{dXc-eLK1
z^O@5^OsR7fCm(g}xk#mi3WILTal4d9=?yf4Ad5XgN<sz;j2E#gV-}c|rQb;W3?V_6
zFshM~-h*t!a)wN-rsy)wLc_*?l7y2)RVjBuYdPzLR^%;tJ7?t%#+0bYaz!x}Q$8Vc
z&T4PXn@W581)aW7#80Px&&_vVNv~img$|d&lfiX-49F>rvtXQu^a1!Tf$<HjZ{hSh
zWkO=xaBk5R%HmaU{-bb}fJKRN&`Cg8q&Y}3lcae_{8Z^GBtZ+1O_EMwri$<(dP~`V
zU^vCah@-p@Hwhfgr3;5&;~kUK`32ojDEucKzQ*=s;<6Ko%h9zk?+kf8hHL>+flb~T
zExh#W=@NiTXTYV>{{ZVDhdCI|hv17~2>^OO4l0i{6#%aybau!wpqFBYkC6h7AyY_y
z|05~s*UX)R7?Z-}qav^sW2!(%0{Oi98F=O9;gm@vk^nEBwZUHipTWjMYgEgPs<LIZ
zM^!aLYF6%KRll0dCdZV_svW4<;c-PTj%n(+G7SYw_;!vfhN+v=`=+taT@huIX%K2J
zp|%=*3@<lO?PX}nv`Q;<2P2dG5`5tQtilh`0bF4TS8NHy6R^Gqj8w>U14t<ZnFRu;
zDv2{!fqVtMw~DBiA>mgOm}N)?<`w9pmj3|=%&BaR>ej-T^o5t5FeC*<Lr5GpOHoJ~
z+F#u_wTX}}hlO7QwF>UgI!N3`-Kt?2+|Ya_Z^A7<WwbljR082oKvaT7L{x!YL{!Cz
lh^Pi)YiAexT3B!V3xE)6{VU0QyYX9&F}mG6R<KIY`oHC?<XZp$

literal 0
HcmV?d00001

diff --git a/src/part2/GraphCompress/out/production/GraphCompress/Edge.class b/src/part2/GraphCompress/out/production/GraphCompress/Edge.class
new file mode 100644
index 0000000000000000000000000000000000000000..b54c57c9621ba73839a3a6b4bd9561ac191e9dd9
GIT binary patch
literal 3283
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
YZ13_jP0V-jKCZFI9@px^tMa-0AKbad1ONa4

literal 0
HcmV?d00001

diff --git a/src/part2/GraphCompress/out/production/GraphCompress/FileIO.class b/src/part2/GraphCompress/out/production/GraphCompress/FileIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d9c352bded5941d01ee80b1810d290b33df5afc
GIT binary patch
literal 1071
zcmZuw+fLg+5IvjNUU1AET0%<;^ujG9E%bsy6$zmtPy=ZSqT<mQ1E#@7#+3e1pLrot
zk;;4js4t~w?T`{t%if(mGjrz5Z1U^RkDmbE;*ALlPbHq2Na4A}xCsptYME5al*F_|
z&O|$AB=Qmk0pp$Ldr?UsJu$f@pe+Tvu0U7W^WF8+qa8Qgw0CMmddq=h*S74?Q|AV#
zMF-xAKwEj)tGTO{1p)mm^dg3jPm~YsuXdqk`}>8BDD?dOg}aEVC>TAExV)gST6zD?
zagQS}@X4m_+L5hl-{E4>V>>$V?IWgZdn_-|*<?|2m@f7N`dh%yN?k}-$3|p3U)Jp7
zxD$yN5-$bJjo>tNT$L`6Nt(*5+7>#{DPYAqC{wu<HcN50v4mfF<}CDM*1{{5*LM?h
zt383C7>y_N>C}(BBe&VRVtCEVNhAn#{|l|`9J)@_0wwdkDH9WJ9)!VJa&rU!xe7J-
zo(A4%XF*}QQwvVm`{3=ICKp36iVS~a>PdlPL?_oSo(kLrcYUf3aUQ$7xf%(G9@<vJ
z?nNI@?VQg55he=<X-Hz#OQg1^>qxJO^-E~mxjOXqnW+mHGZ&EGF;~<s(Y~G4>M*Zb
zY&{9+DjIQsp#rk{)j4!zF^mzkQFj)(#y-ztMU=3}bB>ler=bKd$5JKbsSJ}MRbDqa
z`pD9QG4wLSLY}?PQ+$!W5`ByGEz!5ejE`(gHN3*6#>jCG_xbP3H?5_HWiY0SLGr7o
ziXmEpl~?cp4>{iq)ePeil|81v1ml_#G>MV;O-YgpiM9{PH+oIUMvGVSx>Q8wcYIr8
IWJ%%4U#-;7Y5)KL

literal 0
HcmV?d00001

diff --git a/src/part2/GraphCompress/out/production/GraphCompress/Graph.class b/src/part2/GraphCompress/out/production/GraphCompress/Graph.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8fdfeee77e0c12474b959d8ce6f7dbf01ed5d77
GIT binary patch
literal 5435
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

literal 0
HcmV?d00001

diff --git a/src/part2/GraphCompress/out/production/GraphCompress/Main.class b/src/part2/GraphCompress/out/production/GraphCompress/Main.class
new file mode 100644
index 0000000000000000000000000000000000000000..562dcf712292d0ff6b837971221fe8d9730c9bd0
GIT binary patch
literal 3006
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

literal 0
HcmV?d00001

diff --git a/src/part2/GraphCompress/out/production/GraphCompress/Partition.class b/src/part2/GraphCompress/out/production/GraphCompress/Partition.class
new file mode 100644
index 0000000000000000000000000000000000000000..98163a67d7dfad29adb6f5061f5f14044404e7b8
GIT binary patch
literal 4015
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

literal 0
HcmV?d00001

diff --git a/src/part2/GraphCompress/out/production/GraphCompress/Positional.class b/src/part2/GraphCompress/out/production/GraphCompress/Positional.class
new file mode 100644
index 0000000000000000000000000000000000000000..d2551c43bdb924e5d6f84b074f78209eb8d5c2e9
GIT binary patch
literal 144
zcmX^0Z`VEs1_pBmE_MbEb_PyH2DbFnlA!!@Mh0dLO;1J!P9WDgKc_S|kCA~ZIKQ+g
zIn^yQCzX+bKOnz2vm`S=FEK|iE3qsQD2)(dWDo#}>E|TorR)1AWu+#UurV?)GB5${
aVqjom0h-Rh!oUEeSwS>Vh7BanzzzU%IUeBv

literal 0
HcmV?d00001

diff --git a/src/part2/GraphCompress/out/production/GraphCompress/SparseMatrix$1.class b/src/part2/GraphCompress/out/production/GraphCompress/SparseMatrix$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4e264c6fbed5b8a237bc0ecf1c062f804e0752a
GIT binary patch
literal 1495
zcmZWp-Ez}L7(KG&$QFumLK0f~7pQ4%1u$s~v`tFuhR~SUNx(Fna@CE|B%8{TN0KS&
zo4{RXdP!&64oPRY-~swjv}a|R$V4-%-96v#`Obc4rGH<&cnRPJ?iDeK%N9zwqDFP~
zx>|&TMGK$cQ;Va|inxaB1>CUkIlfTHmljtonOHXQm5G}gG|ARv+t)A=@5!igRYR%O
z>5DLO+aeC-<0VFxr7vSHpQ?_BYTFu&mEfVP;dD#-?#7_E<A(Rejz?s=6?BESEkdd0
zDQKu98tkU;yWxr_qR8d6JVsktWX`$q-3R><gSjW74fk=ZL9f;xXqfE8qWg1O^hX)|
zBv`7}T3bORV;T6uBVn;4cYP5LLQ2b5Yxh@)&2Z7acqHnc@OSH*JNs@oCcJPG93q2Q
zdi7@Ph9VBaWm4SaYO50r!mfK;szXm@OLs+avox!I*P|4Fx9!Gz!9x>Y+xP|z4TTLi
zir0cDws8hCHfHgyjWVWeOsm%lZkbrMaU0*+SVPmq9UJRtG0kcix`S|D_WD5-N!Hgy
z+r|bqZEWGLjq|ubBeP;Ei>&jThowsiG<GoBlif&}GCeYF8C7g-2dh9cco`;o$(_+K
zn<-c$48=i9Myj-Dj?=w{d50qTD~m@C-o*k9-WJ{<@u}HV9%poS4x-rYacwZ*6-d*_
zpuQDKKkme#D|)ZfjKdntzFOq@+*i$5%w6<mN$J;jU9y&|Oq;zunCEv>0<DCOoN|cY
zU{09?l*`IH&JDI%%yHFOj&>N&v7d1k4xu^!Am`|Z(4E{NjK7HMc#H26d!T_Ly)NMv
z-sWs>xDV&>E@xy&_%*!8u}yY`3}YJJ#|LS?KggtF>&}nQVHiI#jl%(({yQ$J+=hzi
zDxxctO?!^~5hi{^UVo;hDQq0UeDdE5;~D9UMCJt)I9`K=CXaZB>DN&~i@%pPe?^-_
zw-V_?dF!dXW5FY2K4Hw^I;HZ4@}R0zzogQgH#9uOslQQ}E*`-ekDU55;W;kg_q1Z0
zS%1i=a89TgAxZ^{bq*hLkVB>1pqPtk9UJUb9rMl+Y?Wtd)I<U{GW_`y{39fv5`Tn`
alLS@N*c<%+F5psvICzJ>Mb1g~eEtUjFe7^a

literal 0
HcmV?d00001

diff --git a/src/part2/GraphCompress/out/production/GraphCompress/SparseMatrix.class b/src/part2/GraphCompress/out/production/GraphCompress/SparseMatrix.class
new file mode 100644
index 0000000000000000000000000000000000000000..3cb94e18a860849a539e7198f03971b28051aa1c
GIT binary patch
literal 3611
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

literal 0
HcmV?d00001

diff --git a/src/part2/GraphCompress/out/production/GraphCompress/Structure.class b/src/part2/GraphCompress/out/production/GraphCompress/Structure.class
new file mode 100644
index 0000000000000000000000000000000000000000..721a8aadf2c419762861144c6bb27637ac6adb84
GIT binary patch
literal 5163
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

literal 0
HcmV?d00001

diff --git a/src/part2/GraphCompress/src/Block.java b/src/part2/GraphCompress/src/Block.java
new file mode 100644
index 0000000..bffd4d4
--- /dev/null
+++ b/src/part2/GraphCompress/src/Block.java
@@ -0,0 +1,88 @@
+import java.util.ArrayList;
+import java.util.Objects;
+
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+
+public class Block implements Positional{
+    private ArrayList<Edge> edgeList;
+    private int row;
+    private int column;
+    private int rowSize;
+    private int columnSize;
+
+    private int diskSpace;
+
+    public Block(ArrayList<Edge> edgeList, int row, int column, int rowSize, int columnSize) {
+        this.edgeList = edgeList;
+        this.row = max(row, column);
+        this.column =  min(row, column);
+        this.rowSize = rowSize;
+        this.columnSize = columnSize;
+        this.diskSpace = -1 ;
+    }
+
+    public boolean isDiagonal() {
+        return (this.row == this.column);
+    }
+
+    public boolean isEmpty() {
+        return (this.edgeList.size() == 0);
+    }
+
+    public void addEdge(Edge edge){
+        //if (!this.edgeList.contains((edge)))
+            this.edgeList.add(edge);
+        this.diskSpace = -1 ;
+    }
+
+    public ArrayList<Edge> getEdgeList() {
+        return edgeList;
+    }
+
+    public int getRow() {
+        return row;
+    }
+
+    public int getColumn() {
+        return column;
+    }
+
+    public int getDiskSpace(){
+        if (this.diskSpace == -1){
+            if (isDiagonal())
+                this.diskSpace = CompressMath.arithmeticSub(this.edgeList.size(), (long) this.rowSize * (long) this.columnSize / 2);
+            else
+                this.diskSpace = CompressMath.arithmeticSub(this.edgeList.size(), (long) this.rowSize * (long) this.columnSize);
+        }
+        return this.diskSpace;
+    }
+
+    public Block clone(){
+        return new Block(new ArrayList<Edge>(edgeList), row, column, rowSize, columnSize);
+    }
+
+    @Override
+    public String toString() {
+        String answer = "row: " + row + ", col: " + column + "; ";
+        answer += edgeList.size() + "/(" + rowSize + "*" + columnSize + ")";
+        /*
+        for (Edge edge : edgeList)
+            answer += edge.toString();
+         */
+        return  answer;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Block block = (Block) o;
+        return row == block.row && column == block.column && rowSize == block.rowSize && columnSize == block.columnSize && edgeList.equals(block.edgeList);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(edgeList, row, column, rowSize, columnSize);
+    }
+}
diff --git a/src/part2/GraphCompress/src/CompressMath.java b/src/part2/GraphCompress/src/CompressMath.java
new file mode 100644
index 0000000..8ebd7a8
--- /dev/null
+++ b/src/part2/GraphCompress/src/CompressMath.java
@@ -0,0 +1,60 @@
+import static java.lang.Math.log;
+import static java.lang.Math.min;
+import static java.lang.Math.ceil;
+
+public class CompressMath {
+    private static final double log2 = log(2);
+
+    public static int choose(int n, int k){
+        if (0 <= k && k <= n){
+            int nToken = 1;
+            int kToken = 1;
+            int bound = min(k, n-k);
+            for (int t=1; t <= bound; t++){
+                nToken *= n;
+                kToken *= t;
+                n -= 1;
+            }
+            return nToken / kToken;
+        }
+        return 0;
+    }
+
+    public static double entropy(double x){
+        return -(1-x)*log(1-x)/log2 - x*log(x)/log2;
+    }
+
+    public static double entropy(int p, long q){
+        double x = (double) p / (double) q;
+        return -(1-x)*log(1-x)/log2 - x*log(x)/log2;
+    }
+
+    public static double intSize(double n){
+        if (n < 1){
+            return 1;
+        }
+        return ceil(log(n)/log2);
+    }
+
+    public static int arithmetic(int n,int m){
+        // n = nbVertices
+        // m = nbEdges
+        double nCast = (double) n;
+        double mCast = (double) m;
+        double nSquare = (double) (n*n);
+        double x = 2 * mCast / nSquare;
+        int term1 = (int) (ceil(entropy(x) * nSquare / 2));
+        int term2 = (int) (intSize(nCast));
+        int term3 = (int) (2*intSize(intSize(nCast)));
+        return term1 + term2 + term3;
+    }
+
+    public static int arithmeticSub(int ones, long total){
+        double oneCast = (double) ones;
+        int term1 = (int) (ceil(entropy(ones, total) * total));
+        int term2 = (int) (intSize(oneCast));
+        int term3 = (int) (2*intSize(intSize(oneCast)));
+        return term1 + term2 + term3;
+    }
+
+}
diff --git a/src/part2/GraphCompress/src/Edge.java b/src/part2/GraphCompress/src/Edge.java
new file mode 100644
index 0000000..c9460c5
--- /dev/null
+++ b/src/part2/GraphCompress/src/Edge.java
@@ -0,0 +1,78 @@
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Objects;
+import java.util.Scanner;
+
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+
+public class Edge {
+    private final int u;
+    private final int v;
+
+    public Edge(int u, int v) {
+        this.u = max(u,v);
+        this.v = min(u,v);
+    }
+
+    public int getU() {
+        return u;
+    }
+
+    public int getV() {
+        return v;
+    }
+
+    public static ArrayList<Edge> parseString(String edgeString){
+        ArrayList<Edge> edgeList = new ArrayList<Edge>();
+        String[] separated = edgeString.split(";");
+        for (String edge : separated){
+            String[] cut = edge.split(",");
+            int u = Integer.parseInt(cut[0]);
+            int v = Integer.parseInt(cut[1]);
+            edgeList.add(new Edge(u,v));
+        }
+        return edgeList;
+    }
+
+    public static ArrayList<Edge> readFile(String filename){
+        ArrayList<Edge> edgeList = new ArrayList<Edge>();
+        try {
+            File myObj = new File(filename);
+            Scanner myReader = new Scanner(myObj);
+            while (myReader.hasNextLine()) {
+                String data = myReader.nextLine();
+                if (!data.isEmpty()) {
+                    String[] cut = data.split(",");
+                    int u = Integer.parseInt(cut[0]);
+                    int v = Integer.parseInt(cut[1]);
+                    edgeList.add(new Edge(u, v));
+                }
+            }
+            myReader.close();
+        } catch (FileNotFoundException e) {
+            System.out.println("An error occurred.");
+            e.printStackTrace();
+        }
+        return edgeList;
+    }
+
+    @Override
+    public String toString() {
+        return "(" + u + "," + v + ')';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Edge edge = (Edge) o;
+        return u == edge.u && v == edge.v;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(u, v);
+    }
+}
diff --git a/src/part2/GraphCompress/src/FileIO.java b/src/part2/GraphCompress/src/FileIO.java
new file mode 100644
index 0000000..a711350
--- /dev/null
+++ b/src/part2/GraphCompress/src/FileIO.java
@@ -0,0 +1,22 @@
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class FileIO {
+    public static void write(String data, String pathname) {
+        File file = new File(pathname);
+        FileWriter f = null;
+        try {
+            f = new FileWriter(file);
+            f.write(data);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } finally {
+            try {
+                f.close();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+}
diff --git a/src/part2/GraphCompress/src/Graph.java b/src/part2/GraphCompress/src/Graph.java
new file mode 100644
index 0000000..16442b0
--- /dev/null
+++ b/src/part2/GraphCompress/src/Graph.java
@@ -0,0 +1,143 @@
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+
+public class Graph {
+    private final int nbVertices;
+    private Partition partition;
+    private SparseMatrix<Block> blockMatrix;
+    private Partition copyPartition;
+
+    public Graph(int nbVertices){
+        this.nbVertices = nbVertices;
+        this.partition = null;
+        this.blockMatrix = null;
+        this.copyPartition = null;
+    }
+    public Graph(ArrayList<Edge> edgeList, int nbVertices){
+        Block block = new Block(edgeList, 0, 0, nbVertices, nbVertices);
+        Structure[] structList = new Structure[0];
+
+        this.nbVertices = nbVertices;
+        this.partition = new Partition(nbVertices, structList, this);
+        this.blockMatrix = new SparseMatrix<Block>();
+        this.copyPartition = null;
+        this.blockMatrix.scale(1);
+        this.blockMatrix.set(0,0,block);
+    }
+
+    public static Graph fromFile(String filename){
+        ArrayList<Edge> edgeList = Edge.readFile(filename);
+        int n = 0;
+        for(Edge edge: edgeList){
+            n = max(n, max(edge.getU(), edge.getV()));
+        }
+        return new Graph(edgeList, n+1);
+    }
+
+    /*
+    The graph clones creates a deep copy of the partition and a shallow copy of the blockMatrix.
+    Hence, methods like addStructure operates on the new partition and on the original blockMatrix.
+    This is not a problem, as SparseMatrix<E> is given undo operations to undo those method calls.
+     */
+    public Graph clone(){
+        Graph graph = new Graph(this.nbVertices);
+        graph.partition = this.partition.clone(graph);
+        graph.blockMatrix = this.blockMatrix;
+        graph.copyPartition = null;
+        return graph;
+    }
+
+    public void addStructure(Structure structure){
+        this.partition.addStructure(structure);
+    }
+
+    @Override
+    public String toString() {
+        String answer = this.partition.toString() + "\n";
+        String matrix = this.blockMatrix.toString();
+        return answer + matrix;
+    }
+
+    private void deleteBlock(int row, int column){
+        this.blockMatrix.delete(row, column);
+    }
+
+    private void addEdge(Edge edge){
+        int u = edge.getU();
+        int v = edge.getV();
+        int row = this.partition.getVertexAssignment(u);
+        int column = this.partition.getVertexAssignment(v);
+        if(this.blockMatrix.hasValue(row, column)){
+            this.blockMatrix.get(row, column).addEdge(edge);
+        } else {
+            ArrayList<Edge> edgeList = new ArrayList<Edge>();
+            edgeList.add(edge);
+            Block block = new Block(edgeList, row, column, partition.getPartSize(u), partition.getPartSize(v));
+            this.blockMatrix.set(row, column, block);
+        }
+    }
+
+    public void split(int oldRowIndex, int targetSize) {
+        int n = this.blockMatrix.getSize();
+        int columnIndex;
+        this.blockMatrix.scale(targetSize);
+        for (columnIndex = 0; columnIndex < n; columnIndex++) {
+            if (blockMatrix.hasValue(oldRowIndex, columnIndex)) {
+                Block block = blockMatrix.get(oldRowIndex, columnIndex);
+                this.deleteBlock(oldRowIndex, columnIndex);
+                for (Edge edge : block.getEdgeList()) {
+                    this.addEdge(edge);
+                }
+            }
+        }
+    }
+
+    public int diskSpace(){
+        int answer = 0;
+        int nbBlock = 0;
+        for (Block block : this.blockMatrix) {
+            answer += block.getDiskSpace();
+            nbBlock++;
+        }
+        answer += CompressMath.arithmetic(this.blockMatrix.getSize(), nbBlock);
+        return answer;
+    }
+
+    public void undoInit(){
+        this.blockMatrix.undoInit();
+        this.copyPartition = this.partition.clone(this);
+    }
+
+    public void undoAction(){
+        this.blockMatrix.undoAction();
+        this.partition = this.copyPartition;
+        this.copyPartition = null;
+    }
+
+    public boolean check(ArrayList<Edge> edgeList){
+        int i = 0;
+        int x, y;
+        for(Block block: this.blockMatrix)
+            for(Edge edge: block.getEdgeList()) {
+                i++;
+                x = this.partition.getVertexAssignment(edge.getU());
+                y = this.partition.getVertexAssignment(edge.getV());
+                if (block.getRow() != max(x,y)) {return false;}
+                if (block.getColumn() != min(x,y)) {return false;}
+                if(!edgeList.contains(edge)) {return false;}
+            }
+        return (i == edgeList.size());
+    }
+
+    public Partition getPartition() {
+        return partition;
+    }
+
+    public SparseMatrix<Block> getBlockMatrix() {
+        return blockMatrix;
+    }
+}
diff --git a/src/part2/GraphCompress/src/Main.java b/src/part2/GraphCompress/src/Main.java
new file mode 100644
index 0000000..5fff43d
--- /dev/null
+++ b/src/part2/GraphCompress/src/Main.java
@@ -0,0 +1,58 @@
+import java.io.File;
+import java.sql.SQLOutput;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+public class Main {
+    public static void greedy(){
+        String path;
+        path = "build/";
+        String graphFilename = path + "graph.graph";
+        String structFilename = path + "struct.txt";
+        String partFilename = path + "partition.txt";
+        Graph graph = Graph.fromFile(graphFilename);
+        ArrayList<Structure> structList = Structure.listFromFile(structFilename);
+        int i, n;
+        n = structList.size();
+        Structure struct;
+        ArrayList<Integer> bestStructList= new ArrayList<Integer>();
+        int bestCompression = 10*graph.diskSpace();
+        int bestStructure;
+        int currentDiskSpace;
+        System.out.println("Part 2");
+        System.out.println("> Without structure, estimate size is " + graph.diskSpace() + " bits");
+        int j = 0;
+        while (true) {
+            bestStructure = -1;
+            for (i = 0; i < n; i++) {
+                if (!bestStructList.contains(i)) {
+                    struct = structList.get(i);
+                    graph.undoInit();
+                    graph.addStructure(struct);
+                    currentDiskSpace = graph.diskSpace();
+                    if (currentDiskSpace < bestCompression) {
+                        bestCompression = currentDiskSpace;
+                        bestStructure = i;
+                    }
+                    graph.undoAction();
+                }
+            }
+            if(bestStructure >= 0){
+                bestStructList.add(bestStructure);
+                graph.addStructure(structList.get(bestStructure));
+                System.out.println("> Selecting structure " + bestStructure + ", estimate size is " + graph.diskSpace() + " bits");
+                j++;
+            } else {
+                break;
+            }
+        }
+
+        FileIO.write(graph.getPartition().toFormattedString(), partFilename);
+
+    }
+
+    public static void main(String[] args) {
+        greedy();
+    }
+}
\ No newline at end of file
diff --git a/src/part2/GraphCompress/src/Partition.java b/src/part2/GraphCompress/src/Partition.java
new file mode 100644
index 0000000..d24546e
--- /dev/null
+++ b/src/part2/GraphCompress/src/Partition.java
@@ -0,0 +1,99 @@
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class Partition {
+    private int nbVertices;
+    private int[] vertexAssignmentList;
+    private ArrayList<Structure> partList; //assert: partList is a partition of [nbVertices] into Structures
+    private Graph graph;
+
+    /*
+    k in partList.get(i).getList() <=> vertexAssignmentList[k] == i
+     */
+
+
+    public Partition(){
+        this.nbVertices = 0;
+        this.vertexAssignmentList = null;
+        this.partList = null;
+        this.graph = null;
+    }
+    public Partition(int nbVertices, Structure[] structureList, Graph graph) {
+        this.graph = graph;
+        this.nbVertices = nbVertices;
+        this.partList = new ArrayList<Structure>();
+        this.vertexAssignmentList = new int[nbVertices];
+
+        this.partList.add(new Structure(nbVertices));
+        for(Structure structure: structureList){
+            this.addStructure(structure);
+        }
+    }
+
+    public Partition clone(Graph graph){
+        int n = this.vertexAssignmentList.length;
+        Partition partition = new Partition();
+        partition.nbVertices = this.nbVertices;
+        partition.vertexAssignmentList = new int[n];
+        partition.partList = new ArrayList<Structure>();
+        partition.graph = graph;
+        System.arraycopy(this.vertexAssignmentList, 0, partition.vertexAssignmentList, 0, n);
+        for(Structure structure: this.partList)
+            partition.partList.add(structure.clone());
+        return partition;
+    }
+
+    public void addStructure(Structure structure){
+        int n = this.partList.size();
+        int i, m;
+        Structure part;
+        ArrayList<Integer> todo = new ArrayList<Integer>();
+        for(i=0; i<n; i++){
+            part = this.partList.get(i);
+            Structure intersection = new Structure(0);
+            Structure difference = new Structure(0);
+            part.split(structure, intersection, difference);
+            if (!intersection.isEmpty()){
+                this.partList.set(i, intersection);
+                if (!difference.isEmpty()){
+                    todo.add(i);
+                    this.partList.add(difference);
+                }
+            }
+        }
+        m = this.partList.size();
+        for(i=n; i<m; i++){
+            part = this.partList.get(i);
+            for(int vertex: part.getList()){
+                this.vertexAssignmentList[vertex] = i;
+            }
+        }
+        for(int j=0; j<todo.size(); j++){
+            this.graph.split(todo.get(j),m);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return Arrays.toString(vertexAssignmentList) + "\n" + partList.toString();
+    }
+
+    public String toFormattedString() {
+        String ans = "";
+        int n = this.partList.size();
+        int i;
+        Structure part;
+        for(i=0; i<n; i++) {
+            part = this.partList.get(i);
+            ans += part.toFormattedString() + "\n";
+        }
+        return ans;
+    }
+
+    public int getVertexAssignment(int i) { return vertexAssignmentList[i]; }
+    public int getPartSize(int i) { return partList.get(vertexAssignmentList[i]).size(); }
+
+    public ArrayList<Structure> getPartList() {
+        return partList;
+    }
+}
diff --git a/src/part2/GraphCompress/src/Positional.java b/src/part2/GraphCompress/src/Positional.java
new file mode 100644
index 0000000..9719273
--- /dev/null
+++ b/src/part2/GraphCompress/src/Positional.java
@@ -0,0 +1,4 @@
+public interface Positional {
+    public int getRow();
+    public int getColumn();
+}
diff --git a/src/part2/GraphCompress/src/SparseMatrix.java b/src/part2/GraphCompress/src/SparseMatrix.java
new file mode 100644
index 0000000..0ae4989
--- /dev/null
+++ b/src/part2/GraphCompress/src/SparseMatrix.java
@@ -0,0 +1,98 @@
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+
+public class SparseMatrix<E extends Positional> implements Iterable<E> {
+    private int size;
+    private ArrayList<ArrayList<E>> matrix;
+    private int undoSize;
+    private ArrayList<E> undoList;
+
+    public SparseMatrix() {
+        this.size = 0;
+        this.undoSize = -1;
+        this.matrix = new ArrayList<ArrayList<E>>();
+        this.undoList = new ArrayList<E>();
+    }
+
+    // Guaranty that the matrix has size at least n
+    // No guaranty on the exact size
+    public void scale(int n){
+        this.size = n;
+        while(this.matrix.size() < n)
+            this.matrix.add(new ArrayList<E>(Collections.nCopies(1 + this.matrix.size(), null)));
+    }
+
+    public E get(int i, int j){
+        return this.matrix.get(max(i,j)).get(min(i,j));
+    }
+    public boolean hasValue(int i, int j){return this.get(max(i,j), min(i,j)) != null;}
+
+    public void set(int i, int j, E element){
+        this.matrix.get(max(i,j)).set(min(i,j), element);
+    }
+    public void delete(int i, int j){
+        this.undoList.add(this.get(i,j));
+        this.set(i,j, null);
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public void undoInit(){
+        this.undoSize = this.size;
+        this.undoList = new ArrayList<E>();
+    }
+
+    public void undoAction(){
+        // Undo actions in reverse order
+        for(int i = this.undoList.size() - 1; i>= 0; i--){
+            E element = this.undoList.get(i);
+            this.set(element.getRow(), element.getColumn(), element);
+        }
+        for(int i = this.size; i > this.undoSize; i--)
+            this.matrix.remove(i-1);
+        this.size = this.undoSize;
+        this.undoSize = -1;
+    }
+
+
+    public Iterator<E> iterator() {
+        return new Iterator<E> () {
+
+            private int i = 0;
+            private int j = -1;
+
+            public boolean hasNext() {
+                while(true){
+                    j++;
+                    if (j>i) {
+                        j = 0;
+                        i++;
+                        if (i >= SparseMatrix.this.matrix.size())
+                            return false;
+                    }
+                    if (SparseMatrix.this.hasValue(i,j))
+                        return true;
+                }
+            }
+
+            public E next() {
+                if (!SparseMatrix.this.hasValue(i,j))
+                    System.out.println("Erreur impossible");
+                return SparseMatrix.this.get(i,j);
+            }
+        };
+    }
+    @Override
+    public String toString() {
+        String answer = "";
+        for(E element: this)
+            answer += element.toString() + "\n";
+        return answer;
+    }
+}
diff --git a/src/part2/GraphCompress/src/Structure.java b/src/part2/GraphCompress/src/Structure.java
new file mode 100644
index 0000000..acdb877
--- /dev/null
+++ b/src/part2/GraphCompress/src/Structure.java
@@ -0,0 +1,121 @@
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Scanner;
+
+import static java.lang.Integer.parseInt;
+
+public class Structure {
+    private int[] list;
+
+    public Structure(int[] list) {
+        this.list = list;
+    }
+
+    public Structure(int n) {
+        this.list = new int[n];
+        for (int i=0; i<n; i++)
+            this.list[i]=i;
+    }
+
+    public Structure(ArrayList<Integer> list) {
+        int n = list.size();
+        this.list = new int[n];
+        for(int i=0; i<n; i++){
+            this.list[i] = list.get(i);
+        }
+    }
+
+    public Structure(String input){
+        String inputNoNewLine = input.replace("\n", "");
+        String inputNoFC = inputNoNewLine.substring(3);
+        String[] inputSplit = inputNoFC.split(" ");
+        int n = inputSplit.length;
+        this.list = new int[n];
+        int i = 0;
+        for (String vertex: inputSplit) {
+            this.list[i] = parseInt(vertex);
+            i++;
+        }
+    }
+
+    public int[] getList() {
+        return list;
+    }
+    public int size() {return list.length;}
+
+    public void setListFromArray(ArrayList<Integer> list) {
+        int n = list.size();
+        this.list = new int[n];
+        for (int i = 0; i < n; i++) {
+            this.list[i] = list.get(i);
+        }
+    }
+
+    public boolean contains(int vertex){
+        for (int u: this.getList()){
+            if (u == vertex)
+                return true;
+        }
+        return false;
+    }
+
+    public void split(Structure structure, Structure sIntersection, Structure sDifference){
+        ArrayList<Integer> intersection = new ArrayList(); // this inter structure
+        ArrayList<Integer> difference = new ArrayList();  // this minus structure
+        for (int vertex: this.getList()){
+            if (structure.contains(vertex)){
+                intersection.add(vertex);
+            } else {
+                difference.add(vertex);
+            }
+        }
+        sIntersection.setListFromArray(intersection);
+        sDifference.setListFromArray(difference);
+    }
+
+    public boolean isEmpty(){
+        return this.list.length == 0;
+    }
+
+    public static ArrayList<Structure> listFromFile(String filename){
+        ArrayList<Structure> structList = new ArrayList<Structure>();
+        try {
+            File myObj = new File(filename);
+            Scanner myReader = new Scanner(myObj);
+            while (myReader.hasNextLine()) {
+                String data = myReader.nextLine();
+                if (!data.isEmpty()) {
+                    structList.add(new Structure(data));
+                }
+            }
+            myReader.close();
+        } catch (FileNotFoundException e) {
+            System.out.println("An error occurred.");
+            e.printStackTrace();
+        }
+        return structList;
+    }
+
+    @Override
+    public String toString() {
+        return "Structure{" + Arrays.toString(list) + '}';
+    }
+
+    public String toFormattedString(){
+        String ans = "pt";
+        for (int k : this.list){
+            ans += " " + Integer.toString(k);
+        }
+        return ans;
+    }
+
+    public Structure clone(){
+        int n = this.size();
+        int[] list = new int[n];
+        System.arraycopy(this.list, 0, list, 0, n);
+        return new Structure(list);
+    }
+
+}
diff --git a/src/part3/encode.py b/src/part3/encode.py
new file mode 100644
index 0000000..9084aa1
--- /dev/null
+++ b/src/part3/encode.py
@@ -0,0 +1,233 @@
+from math import ceil
+
+PATH = "build/"
+THRESHOLD = 8192
+
+def listMap(f,x): return list(map(f,x))
+
+def keySplit(s):
+    pq = s.split()
+    return (int(pq[0]), int(pq[1]))
+
+def stringToStruct(string):
+    string.replace('\n', '')
+    struct = string[3:]
+    vertexList = []
+    for vertexString in struct.split(' '):
+        if vertexString: vertexList.append(int(vertexString))
+    return vertexList
+
+def splitLongString(string, threshold):
+    count = 0
+    partIndex = [0]
+    for i in range(len(string)):
+        if string[i] == '1':
+            count += 1
+        if count > threshold:
+            partIndex.append(i)
+            count -= threshold
+    partIndex.append(len(string))
+    partList = []
+    for i in range(len(partIndex)-1):
+        start = partIndex[i]
+        end = partIndex[i+1]
+        partList.append(string[start:end])
+    return partList
+
+def getEdge(fileGraph):
+    with open(fileGraph, 'r') as f:
+        edgeList = f.readlines()
+    def stringToCouple(x):
+        [i,j,w] = x.replace('\n', '').split(',')
+        ni = min(int(i), int(j))
+        nj = max(int(i), int(j))
+        return(int(ni),int(nj))
+    edgeList = listMap(stringToCouple, edgeList)
+    return(edgeList)
+
+def getPartition(filePartition):
+    with open(filePartition, 'r') as f:
+        partList = f.readlines()
+    partList = listMap(stringToStruct, partList)
+    return(partList)
+
+def writeBinary(binary_string, file):
+    data = bytes(int(binary_string[i:i+8], 2) for i in range(0, len(binary_string), 8))
+    with open(file, 'wb') as f:
+        f.write(data)
+
+############
+
+def choose(n, k):
+    """
+    A fast way to calculate binomial coefficients by Andrew Dalke.
+    See http://stackoverflow.com/questions/3025162/statistics-combinations-in-python
+    """
+    if 0 <= k <= n:
+        ntok = 1
+        ktok = 1
+        for t in range(1, min(k, n - k) + 1):
+            ntok *= n
+            ktok *= t
+            n -= 1
+        if k % 100 == 0:
+            print(">>>", n, k)
+        return ntok // ktok
+    else:
+        return 0
+
+def ar_encode(list):
+    sum = 0
+    k = 1
+    for i, x in enumerate(list[::-1]):
+        if x in [1, '1']:
+            sum += choose(i,k)
+            k += 1
+    return sum
+
+def encodeBigInt(n):
+    a = bin(n)[2:]
+    b = bin(len(a))[2:]
+    n = ceil(len(b)/4)
+    c = '1' * n + '0'
+    return c + b.zfill(4*n) + a
+
+def encodeSmallInt(n):
+    a = bin(n)[2:]
+    n = ceil(len(a)/4)
+    b = '0' * n + '1'
+    return b + a.zfill(4*n)
+
+def encodeInt(n):
+    if n <= 2**25:
+        return encodeSmallInt(n)
+    return encodeBigInt(n)
+
+############
+
+class GraphEncode():
+    def __init__(self, edgeList, partList):
+        self.edgeList = edgeList
+        self.partList = partList
+        self.order = sum(listMap(len,partList))
+        self.vertexAssign = [] # if i = vertexAssign[vertex], then vertex is in partList[i]
+        self.vertexRank = [] # if i = vertexAssign[vertex] and j = vertexRank[vertex], then partList[i][j] == vertex
+        self.blocDict = {}
+
+        self._computeVertexPOV()
+        print("> Graph imported")
+        for edge in self.edgeList:
+            self._addEdge(edge)
+
+    def _computeVertexPOV(self):
+        n = self.order
+        self.vertexAssign = [0]*n
+        self.vertexRank = [0]*n
+        for i,part in enumerate(self.partList):
+            for j,vertex in enumerate(part):
+                self.vertexAssign[vertex] = i
+                self.vertexRank[vertex] = j
+
+    def _addEdge(self, edge):
+        part1 = self.vertexAssign[edge[0]]
+        part2 = self.vertexAssign[edge[1]]
+        if part1 > part2:
+            part1, part2 = part2, part1
+            edge = edge[::-1]
+        key = str(part1) + " " + str(part2)
+        if key in self.blocDict:
+            self.blocDict[key].append(edge)
+        else:
+            self.blocDict[key] = [edge]
+
+    def getPartSize(self, part):
+        return len(self.partList[part])
+
+    def getSortedBlocList(self):
+        return sorted(map(lambda x: (keySplit(x[0]), x[1]), self.blocDict.items()))
+
+    def metaMatrixToString(self):
+        n = len(self.partList)
+        print(">>> Data made of %d bits (%d ones)" % ((n*(n-1))//2, len(self.blocDict)))
+        ans = [[0] * n for _ in range(n)]
+        for key, value in self.blocDict.items():
+            p,q = keySplit(key)
+            ans[p][q] = 1
+        s = ""
+        for k,l in enumerate(ans):
+            for b in l[k:]:
+                s += str(b)
+        return s
+
+    def blockToString(self, i, j):
+        assert i <= j
+        key = str(i) + " " + str(j)
+        if key not in self.blocDict:
+            return ""
+        p = self.getPartSize(i)
+        q = self.getPartSize(j)
+        print(">>> Data made of %d bits (%d ones)" % (p*q, len(self.blocDict[key])))
+        ans = [[0] * q for _ in range(p)]
+        for edge in self.blocDict[key]:
+            x = self.vertexRank[edge[0]]
+            y = self.vertexRank[edge[1]]
+            ans[x][y] = 1
+        s = ""
+        if i == j:
+            for k,l in enumerate(ans):
+                for b in l[k+1:]:
+                    s += str(b)
+        else:
+            for l in ans:
+                for b in l:
+                    s += str(b)
+        return s
+
+    def encodeBlock(self, i, j):
+        s = ""
+        for part in splitLongString(self.blockToString(i, j), THRESHOLD):
+            s += encodeInt(ar_encode(part))
+        return s
+
+    def encodeMetaMatrix(self):
+        s = ""
+        for part in splitLongString(self.metaMatrixToString(), THRESHOLD):
+            s += encodeInt(ar_encode(part))
+        return s
+
+    def encode(self):
+        s = ""
+        s += encodeInt(self.order)
+        s += encodeInt(len(self.partList))
+        for i in range(len(self.partList)):
+            s += encodeInt(self.getPartSize(i))
+        print("> Part lenghs encoded")
+        s += encodeInt(len(self.blocDict))
+        s += self.encodeMetaMatrix()
+        print("> Meta-matrix encoded")
+        l = self.getSortedBlocList()
+        for kv in l:
+            value = kv[1]
+            s += encodeInt(len(value))
+        print("> Header encoded, current size is %d bits" % len(s))
+        for i, kv in enumerate(l):
+            key = kv[0]
+            s += self.encodeBlock(*key)
+            print("> Bloc %d/%d encoded, current size is %d bits" % (i, len(l), len(s)))
+        return s
+
+############
+
+def main():
+    print("Part 3")
+    fileGraph = PATH + "graph.graph"
+    filePartition = PATH + "partition.txt"
+    fileOut = PATH + "compress.out"
+    edgeList = getEdge(fileGraph)
+    partList = getPartition(filePartition)
+    graph = GraphEncode(edgeList, partList)
+    output = graph.encode()
+    writeBinary(output, fileOut)
+    print("> Encoding done in %d bits" % len(output))
+
+main()
-- 
GitLab