Skip to content

Commit

Permalink
last commit before internship
Browse files Browse the repository at this point in the history
  • Loading branch information
ariez-xyz committed Jun 25, 2019
1 parent ed6c6de commit 9d7674c
Show file tree
Hide file tree
Showing 9 changed files with 310 additions and 133 deletions.
6 changes: 5 additions & 1 deletion src/graph/Graph.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* abstract base class, doesn't support adding nodes, adding edges is only supported for reading from files etc
* pseudo-immutable
*/
public abstract class Graph {
public abstract class Graph implements Comparable<Graph> {
int n;
int e;
double ev = -1;
Expand Down Expand Up @@ -273,4 +273,8 @@ public double getNodeOverlapPercent(Graph other) {
return (double) getOverlappingNodes(other).size() / n;
}

@Override
public int compareTo(Graph other) {
return this.n - other.n;
}
}
14 changes: 13 additions & 1 deletion src/graph/InducedSubgraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public boolean hasOriginalNode(int originalNodeId) {
}

public InducedSubgraph merge(InducedSubgraph other) {
assert other.g == this.g : "cannot merge induced subgraphs stemming from different main graphs";
assert other.g == this.g : "cannot merge induced subgraphs from different main graphs";

ArrayList<Integer> nodesOfThis = toNodeList();
ArrayList<Integer> nodesOfOther = other.toNodeList();
Expand All @@ -177,4 +177,16 @@ public InducedSubgraph merge(InducedSubgraph other) {
public ReentrantLock getLock() {
return lock;
}

/**
* @return size of this induced subgraph... DEBUG
*/
@Override
public String toString() {
return n + "";
}

public Graph getOriginalGraph() {
return g;
}
}
47 changes: 26 additions & 21 deletions src/index/InverseIndex.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import graph.InducedSubgraph;

import java.util.ArrayList;
import java.util.Collections;

public class InverseIndex {
private ArrayList<InducedSubgraph>[] index;
Expand All @@ -22,55 +23,59 @@ public InverseIndex(Graph main, ArrayList<InducedSubgraph> subgraphs) {
for (InducedSubgraph s : subgraphs)
for (int node : s.toNodeList())
index[node].add(s);
}

public ArrayList<InducedSubgraph> getGraphsHaving(int node) {
return index[node];
for (ArrayList<InducedSubgraph> al : index)
Collections.sort(al);
}

/**
* find two unlocked overlapping subgraphs, lock them,
* @return new OverlappingPair with two random overlapping subgraphs
* @return new MergeCandidate with two random overlapping subgraphs
*/
public OverlappingPair getRandomPair() {
public MergeCandidate getCandidate() {
synchronized (this) {
while (true) {
ArrayList<InducedSubgraph> overlappingSubgraphs = index[(int) Math.floor(Math.random() * index.length)];

int randIndex1 = (int) Math.floor(Math.random() * overlappingSubgraphs.size());
int randIndex2 = (int) Math.floor(Math.random() * overlappingSubgraphs.size());

if (randIndex1 == randIndex2)
if(overlappingSubgraphs.size() == 0)
continue;

int randIndex1 = (int) Math.floor(Math.random() * overlappingSubgraphs.size());

InducedSubgraph a = overlappingSubgraphs.get(randIndex1);
InducedSubgraph b = overlappingSubgraphs.get(randIndex2);

if (!a.getLock().tryLock()) {
continue;
}
if (!b.getLock().tryLock()) {
a.getLock().unlock();
continue;
}

return new OverlappingPair(a, b);
return new MergeCandidate(a, overlappingSubgraphs);
}
}
}

/**
* remove pair from index, add merged graph in their places
* remove pair from index, add merged graph in their places, sustain sorting
* @param pair
*/
public void update(OverlappingPair pair) {
public void update(MergeCandidate pair) {
synchronized (this) {
for (int i = 0; i < pair.a.getNodeCount(); i++)
index[pair.a.getOriginalNodeID(i)].remove(pair.a);
synchronized (index[pair.a.getOriginalNodeID(i)]) {
index[pair.a.getOriginalNodeID(i)].remove(pair.a);
}
for (int i = 0; i < pair.b.getNodeCount(); i++)
index[pair.b.getOriginalNodeID(i)].remove(pair.b);
for (int i = 0; i < pair.merged.getNodeCount(); i++)
index[pair.merged.getOriginalNodeID(i)].add(pair.merged);
synchronized (index[pair.b.getOriginalNodeID(i)]) {
index[pair.b.getOriginalNodeID(i)].remove(pair.b);
}
for (int i = 0; i < pair.merged.getNodeCount(); i++) {
int originalId = pair.merged.getOriginalNodeID(i);
synchronized (index[originalId]) {
int insertionIndex = 0;
while (insertionIndex < index[originalId].size() && pair.merged.compareTo(index[originalId].get(insertionIndex)) >= 0)
insertionIndex++;
index[originalId].add(insertionIndex, pair.merged);
}
}

source.remove(pair.a);
source.remove(pair.b);
Expand Down
79 changes: 79 additions & 0 deletions src/index/MergeCandidate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package index;

import graph.InducedSubgraph;
import tasks.MergeOverlappingCommunities;

import java.util.ArrayList;

public class MergeCandidate {
public InducedSubgraph a;
public InducedSubgraph b;
public InducedSubgraph merged;

private final ArrayList<InducedSubgraph> source;
private int currentIndex;

// a is already locked
public MergeCandidate(InducedSubgraph a, ArrayList<InducedSubgraph> source) {
currentIndex = 0;
this.a = a;
this.source = source;
}

public boolean nodesOverlapping(double moreThan) {
return a.getNodeOverlapPercent(b) >= moreThan;
}

public boolean edgesOverlapping(double moreThan) {
return a.getEdgeOverlapPercent(b) >= moreThan;
}

public void createMerged() {
merged = a.merge(b);
}

/**
* find next suitable graph, that is, not a and not locked; locks graph, unlocks previous graph
* @return true if suitable next was found, false if end of list has been reached
*/
public boolean next() {
synchronized (source) {
while (++currentIndex < source.size())
if (source.get(currentIndex) != a && source.get(currentIndex).getLock().tryLock()) {
if (b != null)
b.getLock().unlock();
b = source.get(currentIndex);
merged = null;
return true;
}
return false;
}
}

public double getMergedEv() {
if (merged == null)
createMerged();
return merged.getEigenvalue();
}

public double getDelta() {
switch (MergeOverlappingCommunities.evCompareStrategy) {
case 1: // delta := 2 * merged - a - b
return 2 * getMergedEv() - a.getEigenvalue() - b.getEigenvalue();
default: // delta := merged - larger of both
return getMergedEv() - (a.getNodeCount() > b.getNodeCount() ? a.getEigenvalue() : b.getEigenvalue());

}
}

public void unlock() {
assert a.getLock().isLocked() : "attempt to unlock unlocked lock";
a.getLock().unlock();

if (b != null) {
assert b.getLock().isLocked() : "attempt to unlock unlocked lock";
b.getLock().unlock();
}
}

}
42 changes: 0 additions & 42 deletions src/index/OverlappingPair.java

This file was deleted.

63 changes: 63 additions & 0 deletions src/io/GraphWriter.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package io;

import graph.Graph;
import index.MergeCandidate;

import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;

public class GraphWriter {
OutputFormat format;
Expand Down Expand Up @@ -48,6 +50,67 @@ public void checkFormatSet() {
throw new IllegalStateException("cannot read graph: input format is unset");
}

// this method is an abomination
public String toGraphViz(MergeCandidate candidate) {
final String colorA = "cyan3";
final String colorB = "crimson";
final String colorC = "darkgoldenrod";
final String colorEdges = "darkolivegreen";
final String overlap = "prism";
final int penwidth = 3;

HashSet<Integer> a = new HashSet<>(candidate.a.toNodeList());
HashSet<Integer> b = new HashSet<>(candidate.b.toNodeList());
HashSet<Integer> c = new HashSet<>(candidate.b.toNodeList());
a.removeAll(b);
c.removeAll(candidate.a.toNodeList());
b.removeAll(c);
Graph og = candidate.a.getOriginalGraph();

StringBuilder sb = new StringBuilder(String.format("strict graph {\n\tedge [penwidth=%d]\n\tnode [style=filled]\n\toverlap=\"%s\"\n\toutputorder=\"edgesfirst\"\n", penwidth, overlap));

for (int node : b) {
sb.append(String.format("\t%d [color=%s]\n", node, colorB));
for (int neighbor : a)
if (og.hasEdge(node, neighbor))
sb.append(String.format("\t%d -- %d [color=%s]\n", node, neighbor, colorA));
for (int neighbor : b)
if (og.hasEdge(node, neighbor))
sb.append(String.format("\t%d -- %d [color=%s]\n", node, neighbor, colorB));
for (int neighbor : c)
if (og.hasEdge(node, neighbor))
sb.append(String.format("\t%d -- %d [color=%s]\n", node, neighbor, colorC));
}

for (int node : a) {
sb.append(String.format("\t%d [color=%s]\n", node, colorA));
for (int neighbor : a)
if (og.hasEdge(node, neighbor))
sb.append(String.format("\t%d -- %d [color=%s]\n", node, neighbor, colorA));
for (int neighbor : b)
if (og.hasEdge(node, neighbor))
sb.append(String.format("\t%d -- %d [color=%s]\n", node, neighbor, colorA));
for (int neighbor : c)
if (og.hasEdge(node, neighbor))
sb.append(String.format("\t%d -- %d [color=%s]\n", node, neighbor, colorEdges));
}

for (int node : c) {
sb.append(String.format("\t%d [color=%s]\n", node, colorC));
for (int neighbor : a)
if (og.hasEdge(node, neighbor))
sb.append(String.format("\t%d -- %d [color=%s]\n", node, neighbor, colorEdges));
for (int neighbor : b)
if (og.hasEdge(node, neighbor))
sb.append(String.format("\t%d -- %d [color=%s]\n", node, neighbor, colorC));
for (int neighbor : c)
if (og.hasEdge(node, neighbor))
sb.append(String.format("\t%d -- %d [color=%s]\n", node, neighbor, colorC));
}

return sb.append("}").toString();
}

private interface OutputFormat {
/**
* write graph g with specific output format to w
Expand Down
Loading

0 comments on commit 9d7674c

Please sign in to comment.