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 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 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