Skip to content

Commit

Permalink
Work on MCMC algorithm, transition probabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
Manuel Zander authored and Manuel Zander committed Jun 20, 2018
1 parent 3b2964e commit 35dced6
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 35 deletions.
92 changes: 92 additions & 0 deletions MCMC_profile.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
Name:
Type: DiGraph
Number of nodes: 2001
Number of edges: 3932
Average in degree: 1.9650
Average out degree: 1.9650
9019172280 function calls (9019159907 primitive calls) in 4591.231 seconds

Ordered by: cumulative time

ncalls tottime percall cumtime percall filename:lineno(function)
2 0.000 0.000 4591.252 2295.626 core.py:1(<module>)
1052/1 0.017 0.000 4591.233 4591.233 {built-in method builtins.exec}
1 0.026 0.026 4547.025 4547.025 simulation.py:68(run)
2000 0.004 0.000 4546.924 2.273 simulation.py:100(tip_selection)
2000 0.040 0.000 4546.920 2.273 simulation.py:218(weighted_MCMC)
2000 24.496 0.012 4515.675 2.258 simulation.py:234(calc_weights)
2003000 112.210 0.000 4490.570 0.002 dag.py:74(ancestors)
2003000 9.370 0.000 4294.554 0.002 generic.py:149(shortest_path_length)
2003000 165.348 0.000 4265.964 0.002 unweighted.py:25(single_source_shortest_path_length)
668813765 654.194 0.000 4097.642 0.000 unweighted.py:69(_single_shortest_path_length)
666816845 1432.373 0.000 2899.202 0.000 {method 'update' of 'dict' objects}
1796600942 506.662 0.000 813.392 0.000 _collections_abc.py:719(__iter__)
666810765 436.412 0.000 544.249 0.000 coreviews.py:81(__getitem__)
666810765 324.471 0.000 434.178 0.000 _collections_abc.py:672(keys)
666810765 197.035 0.000 306.731 0.000 coreviews.py:51(__iter__)
1129790177 219.260 0.000 219.260 0.000 coreviews.py:54(__getitem__)
680028033 111.715 0.000 111.715 0.000 {built-in method builtins.iter}
666810765 109.707 0.000 109.707 0.000 _collections_abc.py:698(__init__)
668813765 108.416 0.000 108.416 0.000 coreviews.py:45(__init__)
668813765 82.347 0.000 82.347 0.000 dag.py:90(<genexpr>)
1 0.001 0.001 43.328 43.328 simulation.py:82(print_graph)
1 0.000 0.000 43.239 43.239 pyplot.py:236(show)
1 0.000 0.000 43.239 43.239 backend_bases.py:178(show)
1 0.000 0.000 43.110 43.110 backend_macosx.py:208(mainloop)
1 37.035 37.035 43.110 43.110 {built-in method matplotlib.backends._macosx.show}
4000 0.262 0.000 28.158 0.007 simulation.py:240(weighted_random_walk)
4000 8.186 0.002 24.058 0.006 simulation.py:153(get_valid_tips)
3671332 9.170 0.000 11.382 0.000 simulation.py:171(all_approvers_not_visible)
2003050 3.923 0.000 7.215 0.000 contextlib.py:85(__exit__)
4006592 2.002 0.000 7.171 0.000 {built-in method builtins.next}
2003050 2.174 0.000 7.169 0.000 contextlib.py:157(helper)
13207612 4.441 0.000 6.458 0.000 digraph.py:788(predecessors)
1 0.000 0.000 5.953 5.953 backend_macosx.py:170(save_figure)
1 5.682 5.682 5.682 5.682 {built-in method matplotlib.backends._macosx.choose_save_file}
4006000 4.763 0.000 5.162 0.000 contextmanagers.py:10(reversed)
2003050 4.107 0.000 4.994 0.000 contextlib.py:59(__init__)
2003050 0.964 0.000 4.841 0.000 contextlib.py:79(__enter__)
4000 2.703 0.001 3.058 0.001 simulation.py:134(get_visible_transactions)
2000 1.848 0.001 3.031 0.002 simulation.py:284(get_tips)
2003000 1.719 0.000 2.297 0.000 digraph.py:319(adj)
11569771/11569178 1.509 0.000 1.509 0.000 {built-in method builtins.len}
2003000 1.047 0.000 1.047 0.000 graph.py:797(has_node)
2020984 0.898 0.000 0.899 0.000 {built-in method builtins.getattr}
632/4 0.005 0.000 0.866 0.216 <frozen importlib._bootstrap>:966(_find_and_load)
632/4 0.003 0.000 0.866 0.216 <frozen importlib._bootstrap>:936(_find_and_load_unlocked)
596/4 0.004 0.000 0.865 0.216 <frozen importlib._bootstrap>:651(_load_unlocked)
535/4 0.002 0.000 0.865 0.216 <frozen importlib._bootstrap_external>:672(exec_module)
731/4 0.001 0.000 0.864 0.216 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
2003000 0.677 0.000 0.677 0.000 graph.py:385(__contains__)
32 0.001 0.000 0.619 0.019 __init__.py:1(<module>)
1 0.000 0.000 0.548 0.548 __init__.py:54(<module>)
3671332 0.496 0.000 0.496 0.000 {method 'issubset' of 'set' objects}
407/50 0.001 0.000 0.495 0.010 {built-in method builtins.__import__}
2004276 0.412 0.000 0.412 0.000 {method 'items' of 'dict' objects}
51263 0.084 0.000 0.407 0.000 simulation.py:261(<listcomp>)
2227/1400 0.002 0.000 0.400 0.000 <frozen importlib._bootstrap>:997(_handle_fromlist)
2003001 0.399 0.000 0.399 0.000 digraph.py:1062(is_directed)
4497465 0.397 0.000 0.397 0.000 {method 'append' of 'list' objects}
309501 0.324 0.000 0.324 0.000 {built-in method builtins.max}
1 0.000 0.000 0.317 0.317 simulation.py:1(<module>)
1 0.000 0.000 0.270 0.270 figure.py:1929(savefig)
1 0.000 0.000 0.269 0.269 backend_bases.py:2107(print_figure)
1 0.000 0.000 0.268 0.268 backend_agg.py:512(print_png)
1 0.238 0.238 0.238 0.238 {built-in method matplotlib._png.write_png}
1 0.000 0.000 0.234 0.234 pyplot.py:19(<module>)
3 0.000 0.000 0.184 0.061 __init__.py:4(<module>)
4 0.000 0.000 0.181 0.045 __init__.py:3(<module>)
1 0.000 0.000 0.168 0.168 nx_pydot.py:15(<module>)
1 0.000 0.000 0.166 0.166 __init__.py:16(<module>)
535 0.005 0.000 0.156 0.000 <frozen importlib._bootstrap_external>:743(get_code)
51263 0.101 0.000 0.146 0.000 simulation.py:262(<listcomp>)
51263 0.102 0.000 0.138 0.000 simulation.py:269(weigthed_choice)
1 0.000 0.000 0.135 0.135 intersection.py:4(<module>)
1 0.064 0.064 0.129 0.129 {method 'show' of '_macosx.FigureManager' objects}
1 0.000 0.000 0.123 0.123 algebraicconnectivity.py:9(<module>)
1 0.000 0.000 0.120 0.120 __init__.py:106(<module>)
583/581 0.002 0.000 0.120 0.000 <frozen importlib._bootstrap>:564(module_from_spec)
1449/1388 0.035 0.000 0.117 0.000 {built-in method builtins.__build_class__}
131 0.002 0.000 0.113 0.001 backend_bases.py:1955(motion_notify_event)
43/42 0.000 0.000 0.100 0.002 <frozen importlib._bootstrap_external>:919(create_module)
43/42 0.097 0.002 0.100 0.002 {built-in method _imp.create_dynamic}
37 changes: 37 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,27 +1,64 @@
appnope==0.1.0
atomicwrites==1.1.5
attrs==18.1.0
bleach==2.1.3
coverage==4.5.1
cycler==0.10.0
decorator==4.3.0
entrypoints==0.2.3
flake8==2.6.2
hacking==1.1.0
html5lib==1.0.1
hypothesis==3.57.0
ipykernel==4.8.2
ipython==5.0.0
ipython-genutils==0.2.0
ipywidgets==7.2.1
Jinja2==2.10
jsonschema==2.6.0
jupyter==1.0.0
jupyter-client==5.2.3
jupyter-console==5.2.0
jupyter-core==4.4.0
kiwisolver==1.0.1
MarkupSafe==1.0
matplotlib==2.2.2
mccabe==0.5.3
mistune==0.8.3
more-itertools==4.2.0
nbconvert==5.3.1
nbformat==4.4.0
networkx==2.1
nose==1.3.7
notebook==5.5.0
numpy==1.14.3
pandocfilters==1.4.2
pbr==4.0.3
pexpect==4.6.0
pickleshare==0.7.4
pluggy==0.6.0
prompt-toolkit==1.0.15
ptyprocess==0.5.2
py==1.5.3
pycodestyle==2.0.0
pyflakes==1.2.3
Pygments==2.2.0
pyparsing==2.2.0
pyprof2calltree==1.4.3
pysha3==1.0.2
pytest==3.6.0
python-dateutil==2.7.3
pytz==2018.4
pyzmq==17.0.0
qtconsole==4.3.1
Send2Trash==1.5.0
simplegeneric==0.8.1
six==1.11.0
terminado==0.8.1
testpath==0.3.1
tornado==5.0.2
traitlets==4.3.2
utils==0.9.0
wcwidth==0.1.7
webencodings==0.5.1
widgetsnbextension==3.2.1
7 changes: 4 additions & 3 deletions simulation/core.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import helpers
import constants
import networkx as nx
from simulation import Simulation

#Parameters: no_of_transactions, lambda, no_of_agents, alpha, latency, distance, tip_selection_algo
#Tip selection algorithms are "random", "weighted", "unweighted"

simu = Simulation(10000, 50, 1, 0.05, 1, 0, "weighted")
simu = Simulation(20, 2, 1, 0, 1, 0, "weighted")

simu.setup()

simu.run()

simu.print_graph()

print(nx.info(simu.DG))

simu.print_graph()
80 changes: 48 additions & 32 deletions simulation/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,18 @@ def run(self):

def print_graph(self):

# Plotting number of tips
lens = []
for i in self.record_tips:
lens.append(len(i))
plt.plot(self.arrival_times, lens)
plt.show()
#Plotting number of tips
# lens = []
# for i in self.record_tips:
# lens.append(len(i))
# plt.plot(self.arrival_times, lens)
# plt.show()

#Plot the graph
# pos = nx.get_node_attributes(self.DG, 'pos')
# nx.draw_networkx(self.DG, pos, with_labels=True)
# plt.title("Transactions = " + str(self.no_of_transactions) + ", " + r'$\lambda$' + " = " + str(self.lam))
# plt.show()
pos = nx.get_node_attributes(self.DG, 'pos')
nx.draw_networkx(self.DG, pos, with_labels=True)
plt.title("Transactions = " + str(self.no_of_transactions) + ", " + r'$\lambda$' + " = " + str(self.lam))
plt.show()

#Save the graph
#plt.savefig('graph.png')
Expand Down Expand Up @@ -187,7 +187,7 @@ def unweighted_MCMC(self, transaction):
if(tip1 != tip2):
self.DG.add_edge(transaction,tip2)

#self.record_tips.append(self.get_tips())
self.record_tips.append(self.get_tips())

def random_walk(self, start, transaction):

Expand Down Expand Up @@ -220,7 +220,7 @@ def weighted_MCMC(self, transaction):
#Start at genesis
start = self.transactions[0]

self.calc_weights()
#self.calc_weights(list(self.DX.nodes))

tip1 = self.weighted_random_walk(start, transaction)
tip2 = self.weighted_random_walk(start, transaction)
Expand All @@ -231,21 +231,32 @@ def weighted_MCMC(self, transaction):

self.record_tips.append(self.get_tips())

def calc_weights(self):
def calc_weights(self, transactions):

for transaction in self.DG.nodes:
for transaction in transactions:
transaction.cum_weight = len(list(nx.ancestors(self.DG, transaction))) + 1
#print("Transaction " + str(transaction) + " has cum_weight " + str(transaction.cum_weight))

# sorted = nx.topological_sort(self.DG)
#
# for transaction in sorted:
# children = self.DG.successors(transaction)
#
# for child in children:
# child.ancestors = child.ancestors.union(transaction.ancestors)
# set1 = set()
# set1.add(transaction)
# child.ancestors = child.ancestors.union(set1)
#
# transaction.cum_weight = len(transaction.ancestors) + 1

def weighted_random_walk(self, start, transaction):

walker_on = start
visible_transactions, not_visible_transactions = self.get_visible_transactions(transaction)
valid_tips = self.get_valid_tips(visible_transactions, not_visible_transactions)

#print("Valid tips: " + str(valid_tips))

# If only genesis a valid tip, approve genesis
#If only genesis a valid tip, approve genesis
if (valid_tips == [walker_on]):
#print("Return early: " + str(walker_on))
return walker_on
Expand All @@ -255,30 +266,35 @@ def weighted_random_walk(self, start, transaction):
approvers = list(self.DG.predecessors(walker_on))
if approvers == []:
return walker_on
#print("Approvers: " + str(approvers))

self.calc_weights(approvers)

#Calculate transition probabilities
weights = [approver.cum_weight for approver in approvers]
normalized_weights = [weight - max(weights) for weight in weights]
weights = [math.exp(self.alpha * weight) for weight in normalized_weights]
sum_of_weights = sum(weights)
transition_probabilities = [math.exp(self.alpha * approver.cum_weight)/sum_of_weights for approver in approvers]

walker_on = self.weigthed_choice(approvers, weights)
walker_on = np.random.choice(approvers, p=transition_probabilities)
#walker_on = self.weigthed_choice(approvers, weights)

#print("Return after loop: " + str(walker_on))
return walker_on

def weigthed_choice(self, approvers, weights):

sum_of_weights = sum(weights)
rand = random.random() * sum_of_weights

cum_sum = weights[0]

for i in range(1, len(weights)):
if rand < cum_sum:
return approvers[i-1]
cum_sum += weights[i]

return approvers[-1]
# def weigthed_choice(self, approvers, weights):
#
# sum_of_weights = sum(weights)
# rand = random.random() * sum_of_weights
#
# cum_sum = weights[0]
#
# for i in range(1, len(weights)):
# if rand < cum_sum:
# return approvers[i-1]
# cum_sum += weights[i]
#
# return approvers[-1]

#For printing number of tips as function of time
def get_tips(self):
Expand Down
1 change: 1 addition & 0 deletions simulation/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ def __init__(self, _arrival_time, counter):
self.arrival_time = _arrival_time
self.agent, self.tip1, self.tip2 = None, None, None
self.cum_weight = 0
self.ancestors = set()

#Give transaction a random hash as identifier? For now just using numbers
self.id = counter
Expand Down

0 comments on commit 35dced6

Please sign in to comment.