Skip to content

Commit

Permalink
TrackerHub emits nodes and edges now.
Browse files Browse the repository at this point in the history
* Added simple calls to TrackerHub and Tracker which (by default)
connect and stream data to Gephi.
* Error handling is non-existent -- will crash if Gephi not configured
properly during runtime.
* Lots of features to be added!
  • Loading branch information
oyeb committed Oct 25, 2016
1 parent a12f816 commit 08444a1
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 11 deletions.
6 changes: 3 additions & 3 deletions onemax.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def breed(algorithm, parents):
return algorithm(*parents)

# add any other default args to the tracker here:
deap.creator.create("tracker", peaviz.Tracker, hub=trackerHub)
deap.creator.create("tracker", peaviz.Tracker, hub=trackerHub, size=20)

# a normal (deap) fitness vector
deap.creator.create("maximize", deap.base.Fitness, weights=(1.0,))
Expand All @@ -42,7 +42,7 @@ def breed(algorithm, parents):
toolbox.register("attr", random.randint, 0, 1)

# `maker` takes responsibility to properly configure the tracker
toolbox.register("individual", maker, deap.creator.Individual, toolbox.attr, 4)
toolbox.register("individual", maker, deap.creator.Individual, toolbox.attr, 40)
toolbox.register("population", deap.tools.initRepeat, list, toolbox.individual)

# `myFitness` is a simple function, which additionall keeps the tracker updated
Expand All @@ -57,7 +57,7 @@ def breed(algorithm, parents):

def main():
random.seed(time.time())
pop = toolbox.population(n=20)
pop = toolbox.population(n=80)

fitnesses = list(toolbox.map(toolbox.evaluate, pop))
for ind, fit in zip(pop, fitnesses):
Expand Down
70 changes: 62 additions & 8 deletions peaviz/tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,46 @@
Track evolution dynamics like individual interactions, fitness statistics. This
information is used to create the Complex Network.
"""
import random
import gephistreamer.graph as graph
import gephistreamer.streamer as streamer

def compact_str(container):
if type(container) in [list, tuple, set]:
return "["+",".join(str(item) for item in container)+"]"
else:
return container # because it might not be a container...

class TrackerHub:
"""
@brief Coordinates all trackers for a (sub) population.
"""
@property
def bucket(self):
return self._bucket

"""
def __init__(self, streamer=streamer.Streamer(streamer.GephiREST())):
self.streamer = streamer
self._bucket = {}

@property
def bucket(self):
return self._bucket

def register(self, tracker):
try:
self._bucket[tracker.index] = tracker
except:
raise RuntimeError("Tracker cannot be registered, it has no `identity`!")

def emitNode(self, node):
response = self.streamer.add_node(node)
if response.status_code != 200:
print("Gephi GraphStream error. [status=%d]" % response.status)
return response

def emitEdge(self, edge):
response = self.streamer.add_edge(edge)
if response.status_code != 200:
print("Gephi GraphStream error. [status=%d]" % response.status)
return response

def __getitem__(self, tracker_index):
return self.bucket.get(tracker_index, None)

Expand All @@ -45,7 +64,7 @@ def hub(self, newHub):
def index(self):
return self._index

def __init__(self, hub=None, parents=None, gen=0, fitness=None, **kwargs):
def __init__(self, hub=None, parents=tuple(), gen=0, fitness=tuple(), **kwargs):
self._hub = hub
self._index = None
self.preset(parents, gen, fitness, **kwargs)
Expand All @@ -56,20 +75,55 @@ def preset(self, parents=None, gen=0, fitness=None, **kwargs):
self.fitness = fitness
self.attributes = kwargs

def setParents(self, parents, gen=None):
def setParents(self, parents, gen=None, transmit=True):
assert(isinstance(parents[0], int))
self.parents = parents
if gen:
self.gen = gen
else:
self.gen += 1
if transmit:
self.insertEdge()

def insertNode(self, location=None, pop_size=500):
x_extent = y_extent = pop_size
attributes = {'gen' : self.gen,
'fitness' : compact_str(self.fitness),
'parents' : compact_str(self.parents),
'x' : random.randint(-x_extent, x_extent),
'y' : random.randint(-y_extent, y_extent)
}
if location is not None:
if (type(location) in [tuple, list] and len(location) == 2):
attributes['x'], attributes['y'] = location
# else, the randomized coordinates which have been set already

if self.attributes:
# need to flatten attributes, GraphStream API rejects `actions` if
# Node attribute-values are compound JSON types (like [] or {})
for k in self.attributes:
# this will (correctly) overwrite
attributes.update(k, compact_str(self.attributes[k]))

node = graph.Node(str(self.index), **attributes)
response = self.hub.emitNode(node)
#print(response.content)

def insertEdge(self, directed=True, **kwargs):
for parent in self.parents:
assert(isinstance(parent, int))
eid = str(self.index) + '>' + str(parent)
edge = graph.Edge(str(self.index), str(parent), eid=eid, directed=directed, **kwargs)
self.hub.emitEdge(edge)

def setFitness(self, fitness, **kwargs):
self.fitness = fitness
self.attributes.update(kwargs)

def deploy(self, ind=None):
def deploy(self, ind=None, transmit=True):
self._index = ind if ind else Tracker._IND_COUNT
Tracker._IND_COUNT += 1
self.hub.register(self)
if transmit:
self.insertNode()
return self._index

0 comments on commit 08444a1

Please sign in to comment.