Skip to content

Commit

Permalink
Updated hSync algorithm; Added unit-tests for hSync; Added examples f…
Browse files Browse the repository at this point in the history
…or hSync
  • Loading branch information
annoviko committed Mar 15, 2014
1 parent 05d1dea commit f802583
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 19 deletions.
63 changes: 50 additions & 13 deletions hsyncnet/__init__.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,70 @@
from nnet.sync import *;

from syncnet import syncnet;
from support import average_neighbor_distance, read_sample, draw_clusters;
from support import average_neighbor_distance, read_sample;

class hsyncnet(syncnet):
def __init__(self, source_data):
"Costructor of the oscillatory network hSync"

"(in) source_data - input data set defines structure of the network"

super().__init__(source_data);

def process(self, number_clusters, order = 0.998, solution = solve_type.FAST, collect_dynamic = False):
"Perform clustering of input data set in line with input parameters"

"(in) number_clusters - number of clusters that should be allocated"
"(in) order - level of local synchronization between oscillator that defines end of process of synchronization, range [0..1]"
"(in) solution - type of solving differential equation: ode45, usual diff, etc."
"(in) collect_dynamic - if True - return whole history of process synchronization otherwise - final state (when process of clustering is over)"

"Returns dynamic of the network as tuple (time, oscillator_phases) that depends on collect_dynamic parameters"

number_neighbors = 3;
current_number_clusters = numpy.Inf;

while(current_number_clusters > number_clusters):
radius = average_neighbor_distance(self._osc_loc, number_neighbors);
dyn_phase = [];
dyn_time = [];

radius = average_neighbor_distance(self._osc_loc, number_neighbors);

while(current_number_clusters > number_clusters):
self._create_connections(radius);

self.simulate_dynamic(order, solution, collect_dynamic);
clusters = self.get_clusters();
(t, dyn) = self.simulate_dynamic(order, solution, collect_dynamic);
if (collect_dynamic == True):
dyn_phase += dyn;

if (len(dyn_time) > 0):
point_time_last = dyn_time[len(dyn_time) - 1];
dyn_time += [time_point + point_time_last for time_point in t];
else:
dyn_time += t;

clusters = self.get_clusters(0.05);

# Get current number of allocated clusters
current_number_clusters = len(clusters);

# Increase number of neighbors that should be used
number_neighbors += 1;

# Update connectivity radius and check if average function can be used anymore
if (number_neighbors >= len(self._osc_loc)):
radius = radius * 0.1 + radius;
else:
radius = average_neighbor_distance(self._osc_loc, number_neighbors);


return (dyn_time, dyn_phase);

sample = read_sample('../Samples/SampleSimple1.txt');
network = hsyncnet(sample);

network.process(2);

# sample = read_sample('../Samples/SampleSimple1.txt');
# network = hsyncnet(sample);
#
# (dyn_time, dyn_phase) = network.process(2, collect_dynamic = True);
#
# draw_dynamics(dyn_time, dyn_phase);

clusters = network.get_clusters();
draw_clusters(sample, clusters);
#
# clusters = network.get_clusters();
# draw_clusters(sample, clusters);
78 changes: 78 additions & 0 deletions hsyncnet/examples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from nnet.sync import draw_dynamics;

from support import read_sample, draw_clusters;
from hsyncnet import hsyncnet;

def template_clustering(file, number_clusters, arg_collect_dynamic = True, show_network_structure = False, arg_order = 0.999, arg_eps = 0.1):
sample = read_sample(file);
network = hsyncnet(sample);

(time, dynamic) = network.process(number_clusters, order = arg_order, collect_dynamic = arg_collect_dynamic);
clusters = network.get_clusters();

if (show_network_structure == True):
network.show_network();

if (arg_collect_dynamic == True):
draw_dynamics(time, dynamic);

draw_clusters(sample, clusters);


def cluster_sample1():
template_clustering('../Samples/SampleSimple1.txt', 2);

def cluster_sample2():
template_clustering('../Samples/SampleSimple2.txt', 3);

def cluster_sample3():
template_clustering('../Samples/SampleSimple3.txt', 4);

def cluster_simple4():
template_clustering('../Samples/SampleSimple4.txt', 5);

def cluster_simple5():
template_clustering('../Samples/SampleSimple5.txt', 4);

def cluster_elongate():
template_clustering('../Samples/SampleElongate.txt', 2, arg_collect_dynamic = False);

def cluster_lsun():
"NOTE: Too slow"
template_clustering('../Samples/SampleLsun.txt', 3, arg_collect_dynamic = False);

def cluster_hepta():
template_clustering('../Samples/SampleHepta.txt', 7, arg_collect_dynamic = False);

def cluster_tetra():
"NOTE: Too slow"
template_clustering('../Samples/SampleTetra.txt', 4, arg_collect_dynamic = False);

def cluster_target():
"NOTE: Too slow"
template_clustering('../Samples/SampleTarget.txt', 6, arg_collect_dynamic = False);

def cluster_chainlink():
"NOTE: Too slow"
template_clustering('../Samples/SampleChainlink.txt', 2, arg_collect_dynamic = False);

def cluster_wing_nut():
"NOTE: Too slow"
template_clustering('../Samples/SampleWingNut.txt', 2, arg_collect_dynamic = False);

def cluster_two_diamonds():
"NOTE: Too slow"
template_clustering('../Samples/SampleTwoDiamonds.txt', 2, arg_collect_dynamic = False);

# cluster_sample1();
# cluster_sample2();
# cluster_sample3();
# cluster_simple4();
# cluster_elongate();
# cluster_lsun();
# cluster_hepta();
# cluster_tetra();
# cluster_target();
# cluster_chainlink();
# cluster_wing_nut();
# cluster_two_diamonds();
47 changes: 47 additions & 0 deletions hsyncnet/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import unittest;

from support import read_sample;
from hsyncnet import hsyncnet;

class Test(unittest.TestCase):
def templateClusteringResults(self, path, number_clusters, expected_length_clusters):
sample = read_sample(path);
network = hsyncnet(sample);

(t, d) = network.process(number_clusters, order = 0.999, collect_dynamic = True);
clusters = network.get_clusters();

assert sum([len(cluster) for cluster in clusters]) == sum(expected_length_clusters);

if (sorted([len(cluster) for cluster in clusters]) != expected_length_clusters):
# print("Result: ", sorted([len(cluster) for cluster in clusters]), "Expect: ", expected_length_clusters);
# network.show_network();
# draw_dynamics(t, d);
# draw_clusters(sample, clusters);

assert sorted([len(cluster) for cluster in clusters]) == expected_length_clusters;


def testClusteringSampleSimple1(self):
self.templateClusteringResults("../Samples/SampleSimple1.txt", 2, [5, 5]);
self.templateClusteringResults("../Samples/SampleSimple1.txt", 1, [10]);

def testClusteringSampleSimple2(self):
self.templateClusteringResults("../Samples/SampleSimple2.txt", 3, [5, 8, 10]);
self.templateClusteringResults("../Samples/SampleSimple2.txt", 1, [23]);

def testClusteringSampleSimple3(self):
self.templateClusteringResults("../Samples/SampleSimple3.txt", 4, [10, 10, 10, 30]);
self.templateClusteringResults("../Samples/SampleSimple3.txt", 1, [60]);

def testClusteringSampleSimple4(self):
self.templateClusteringResults("../Samples/SampleSimple4.txt", 5, [15, 15, 15, 15, 15]);
self.templateClusteringResults("../Samples/SampleSimple4.txt", 1, [75]);

def testClusteringSampleSimple5(self):
self.templateClusteringResults("../Samples/SampleSimple5.txt", 4, [15, 15, 15, 15]);
self.templateClusteringResults("../Samples/SampleSimple5.txt", 1, [60]);


if __name__ == "__main__":
unittest.main()
9 changes: 4 additions & 5 deletions nnet/sync/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from scipy.integrate import odeint;
from scipy.integrate import ode;
from scipy.spatial import distance;

from support import euclidean_distance;
from hierarchical import hierarchical;


class solve_type:
Expand Down Expand Up @@ -301,12 +303,9 @@ def simulate_dynamic(self, order = 0.998, solution = solve_type.FAST, collect_dy
current_order = self.sync_local_order();

# If requested input dynamics
dyn_phase = None;
dyn_time = None;
dyn_phase = [];
dyn_time = [];
if (collect_dynamic == True):
dyn_phase = list();
dyn_time = list();

dyn_phase.append(self._phases);
dyn_time.append(0);

Expand Down
12 changes: 11 additions & 1 deletion syncnet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ def get_neighbors(self, index):

def phase_kuramoto(self, teta, t, argv):
"Overrided method for calculation of oscillator phase"

"(in) teta - current value of phase"
"(in) t - time (can be ignored)"
"(in) argv - index of oscillator whose phase represented by argument teta"

"Return new value of phase of oscillator with index 'argv'"
index = argv; # index of oscillator
phase = 0; # phase of a specified oscillator that will calculated in line with current env. states.

Expand All @@ -88,7 +94,11 @@ def phase_kuramoto(self, teta, t, argv):


def get_clusters(self, eps = 0.1):
"Return clusters"
"Return list of clusters in line with state of ocillators (phases)."

"(in) eps - tolerance level that define maximal difference between phases of oscillators in one cluster"

"Return list of clusters, for example [ [cluster1], [cluster2], ... ]"
return self.allocate_sync_ensembles(eps);


Expand Down

0 comments on commit f802583

Please sign in to comment.