Skip to content

Commit eb1574f

Browse files
author
debsankha manik
committed
added hierarchical design approach in specs
1 parent 8e1806b commit eb1574f

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed

spec/hierarchical.md

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Hierarchichal Design Overview
2+
3+
# User Story 1: Scaling of Basin of attraction volumes for Kuramoto Networks
4+
## Setting:
5+
A Kuramoto network $$F$$ is completely specified by it's graph topology $$G(V, E)$$ and its set of natural frequencies $$\vec{\omega})$$ for all the nodes. Here we are only intersted in ring topology. All fixed points of a Kuramoto ring are uniquely identified by an integer called the **winding number** $$k$$.
6+
7+
## Study:
8+
We are interested in the probability that a random initial condition evolves to the steady state with $$k = k'$$, i.e. $$V_{k, N} = P(k | len(V) = N)$$. And we want this over all possible distributions of natural frequencies $\vec{\omega}$ (subject to some constraints, that make it a finite space).
9+
10+
## Sequential pseudocode would be:
11+
```python
12+
N_range = np.arange(10,100)
13+
V = []
14+
15+
# Outermost loop: obver many ring sizes
16+
for N in N_range:
17+
V_N = 0
18+
# loop over all omega combinations
19+
V_array = []
20+
for idx, omega in enumerate(all_omegas(N)):
21+
# loop over many initial conditions
22+
k_list = []
23+
for initcond in get_initconds(num_initconds):
24+
k = find_k(N, omega, initcond)
25+
k_list.append(k)
26+
# Now bin the data to find the frequencies
27+
V_omega = scipy.stats.itemfreq(k_list)
28+
V_array.append(V_omega)
29+
# Do the averaging over all omegas
30+
V_N = np.average(V_array, axis = 2)
31+
V.append(V_N)
32+
```
33+
34+
## Can we transform this to this?
35+
```python
36+
basin_singlering = Experiment(find_k, initcond_range = initcond_iter(...), aggregator =\
37+
<#something that counts final states and computes probabilities>)
38+
# outout is of the form: {0: 0.78, 1: 0.11, -1: 0.14}
39+
basin_all_omegas_for_single_size = Experiment(basin_singlering, omega_range = omega_iter(100),\
40+
aggregator = <#averages over all omega distributions,\
41+
computes some sort of central tendency>)
42+
# outout is of the form: {'averages': {0: 0.78, 1: 0.11, -1: 0.14}, 'variances': {0: 0.1, 1: 0.2, -1:0.3}
43+
basin_scaling_with_size = Experiment(basin_all_omegas_for_single_size, n_range \=
44+
np.arange(1, 100, 10), aggregator = <# concatenates results for all n>)
45+
# outout is of the form: {n0: {'averages': {}, 'variances': {}}, n1: {'averages': {}, 'variances': {}}, ....}
46+
```
47+
48+
### Advantages:
49+
- Completely Hierarchichal
50+
### Disadvantages:
51+
- Fill it in!
52+
53+
## Design idea:
54+
Here I outline how to acheive the user interface that I outlined in the last subsection.
55+
So here I present a code snippet.
56+
57+
### Disclaimer:
58+
#### What these code snippets are:
59+
1. A *minimum working example (MWA)* that is capable of supporting a hierarchichal user interface.
60+
2. I do this by writing some classes and their attributes and methods.
61+
3. Everything apart from the object structures (classes) and call signature (functions) are demonstrative only.
62+
63+
#### What they are NOT:
64+
1. Taking into account the whole problem of scheduling.
65+
2. The aspect of chunking and parallelizing.
66+
67+
```python
68+
class Experiment(object):
69+
"""
70+
Experiment
71+
=========
72+
An object that specifies how to compute a function *func* on a range of *arguments* and process
73+
all the outputs from single runs to compute an *output*.
74+
75+
Parameters
76+
----------
77+
func : a function/callable
78+
func must take a single argument that we call *input*
79+
param : a parameter that, along with the function, completely specifies what the *output*
80+
should be.
81+
input_generator :
82+
a callable taking a mandatoryargument, *parameter*, that generates the range of *inputs*
83+
to *func*. it can also take optional parameters. See draft implementation of *run* below.
84+
"""
85+
def __init__(self, func, input_generator, input_generator_args = None):
86+
"""
87+
"""
88+
pass
89+
def run(self, param):
90+
"""
91+
"""
92+
return [func(input) for input in input_generator(param, *input_generator_args)]
93+
```
94+
95+
## Design used in test case: basin volume of Kuramoto rings
96+
Let me try to make it clearer by giving an example use case, our very own problem of Kuramoto networks.
97+
```python
98+
def compute_k((omega, initcond)):
99+
"""Evolves a ring network with frequencies *omega* from initial condition
100+
*initcond*
101+
Returns winding number of final state k
102+
"""
103+
pass
104+
105+
def generate_initconds(omega, nrepeat):
106+
"""generates nrepeat vectors of random phase angles, each same size as omega"""
107+
for initcond in np.random.uniform(0, 2*np.pi, size = (nrepeat, len(omega))):
108+
yield omega, initcond
109+
110+
def gen_all_vectors_with_len(len):
111+
"""
112+
Generates all vectors with elements ±1 and length len
113+
"""
114+
pass
115+
116+
# Experiment that computes the basin volumes of a single ring. Note how teh number of initial conditions is specified as input_generator_args.
117+
E_onering = Experiment(compute_k, input_generator=\
118+
generate_initconds, input_generator_args = (1000,))
119+
120+
# Experiment that computes the basin volumes of all rings of a given size
121+
E_onesize = Experiment(E_onering.run, input_generator=\
122+
gen_allvectors_with_len, input_generator_args = None)
123+
124+
# Experiment that computes the basin volumes of rings of size in certain range
125+
E_basin_scaling = Experiment(E_onesize.run, input_generator = lambda x:x)
126+
# Finally, call the run function of E_basin_scaling causes all child experiments to run recursively.
127+
E_basin_scaling.run(param = np.arange(min_size, max_size, 10))
128+
```
129+
OK. So this design can do hierarchical experiments. But let's see how it works in some other scenario, for sake of being thorough:
130+
## Design used in another test case: find out the critical coupling of a kuramoto network
131+
```python
132+
def order_param(Network, initcond):
133+
"""Computes the order parameter by simulating the network from given initial condition"""
134+
pass
135+
def generate_initconds(nrepeat):
136+
"""
137+
generates args for func:`order_param`
138+
"""
139+
<a name="ugly"></a>
140+
G = nx.Graph()
141+
# code to set up your graph here
142+
for thetas in np.random.uniform(0, 2*pi, size = nrepeat):
143+
yield G, thetas
144+
E_one_k = Experiment(order_param, input_generator = generate_initconds, input_generator_args = (1000,))
145+
E_orderparam_scaling = Experiment(E_one_k.run, input_generator =\
146+
lambda mink, maxk: np.arange(mink, maxk, (maxk - mink)/100))
147+
E_orderparam_scaling.run((0, 1))
148+
```
149+
150+
## Problems:
151+
1. It is plain ugly how we [link text](#ugly).
152+
153+

0 commit comments

Comments
 (0)