├── LICENCE.txt ├── README.rst ├── complex_systems ├── __init__.py ├── diffusion.py ├── dygraph.py ├── mobility │ ├── __init__.py │ ├── distance.py │ ├── levy_walk.py │ └── stabrnd.py ├── pgg.py ├── pgg_diffusion.py ├── quasi_unit_disk_graph.py └── spatial │ ├── __init__.py │ └── kernel_density_geo.py ├── doc ├── Makefile ├── complex_systems.mobility.rst ├── complex_systems.rst ├── complex_systems.spatial.rst ├── conf.py ├── examples.rst ├── index.rst ├── install.rst └── modules.rst ├── examples ├── run_diffusion.py ├── run_dygraph_w_PGG.py ├── run_dygraph_w_plot.py ├── run_example_levy_walk_w_plots.py ├── run_kernel_density_geo.py ├── run_pgg.py ├── run_pgg_diffusion.py ├── run_pgg_diffusion_2.py ├── run_quasi_unit_disk_graph.py ├── run_quasi_unit_disk_graph_with_diffusion.py └── run_simple_example_levy_walk.py ├── setup.cfg ├── setup.py ├── simulations └── percolation-mobility-quasiunitdisk-Model │ ├── Data │ └── datafile_test.dat │ ├── defaults.param │ └── run_pgg_2.py └── tests ├── test_distance.py ├── test_dygraph.py ├── test_levy_walk.py ├── test_quasi_unit_disk_graph.py └── test_stabrnd.py /LICENCE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Vincent Gauthier. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ========================================================= 2 | Welcome to Agent Based Model used in the paper entitled : 3 | ========================================================= 4 | 5 | Cooperation Optimized Design for Information Dissemination in Vehicular Networks using Evolutionary Game Theory, 2012. 6 | ====================================================================================================================== 7 | 8 | Abhik Banerjee, Vincent Gauthier, Houda Labiod, Hossam Afifi 9 | ############################################################ 10 | 11 | :Info: See `the site `_ for more information. See `GitHub `_ for the latest source and `Online Documentation `_ for the lastest update on the package documentation. 12 | :Author: Vincent Gauthier 13 | :Maintainer: Vincent Gauthier 14 | 15 | About 16 | ===== 17 | This python package an Agent Based Model used in [BAN12]_ lastest sources could be found at the fllowing repository: `GitHub `_ for the latest source. 18 | 19 | This Toolbox include: 20 | 21 | - Agent based model use in [BAN12]_ in the simulation directory 22 | 23 | - Various simulation examples used in [BAN12]_ could be found in the example directory 24 | 25 | - Human Based Mobility Models in the complex_systems directory 26 | - Truncated Levy Flight Model [Rhee08]_ 27 | 28 | .. [BAN12] Abhik Banerjee, Vincent Gauthier, Houda Labiod, Hossam Afifi, "Cooperation Optimized Design for Information Dissemination in Vehicular Networks using Evolutionary Game Theory", 2012. 29 | 30 | .. [Rhee08] Injong Rhee, Minsu Shin, Seongik Hong, Kyunghan Lee and Song Chong, "On the Levy-walk Nature of Human Mobility", INFOCOM, Arizona, USA, 2008. 31 | 32 | Documentation 33 | ============= 34 | You will need sphinx_ installed to generate the documentation. Documentation 35 | can be generated by running **sphinx-build -b html . build/**. Generated 36 | documentation can be found in the *doc/build/html/* directory. Or consult the `online documentation`_ . 37 | 38 | Testing 39 | ======= 40 | 41 | The easiest way to run the tests is to install `nose 42 | `_ (**easy_install 43 | nose**) and run **nosetests** or **python setup.py test** in the root 44 | of the distribution. Tests are located in the *tests/* directory. 45 | 46 | .. _sphinx: http://sphinx.pocoo.org/ 47 | .. _`online documentation`: https://cooperativenetworking.readthedocs.org 48 | 49 | -------------------------------------------------------------------------------- /complex_systems/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # ------------------------------------------------------------------------------- 4 | # Copyright (c) 2012 Vincent Gauthier. 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining 7 | # a copy of this software and associated documentation files (the 8 | # "Software"), to deal in the Software without restriction, including 9 | # without limitation the rights to use, copy, modify, merge, publish, 10 | # distribute, sublicense, and/or sell copies of the Software, and to 11 | # permit persons to whom the Software is furnished to do so, subject to 12 | # the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included 15 | # in all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------- 25 | -------------------------------------------------------------------------------- /complex_systems/diffusion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | 28 | __author__ = """\n""".join(['Vincent Gauthier']) 29 | 30 | import networkx as nx 31 | import random as RD 32 | import pylab as P 33 | import numpy as N 34 | 35 | class Diffusion(object): 36 | 37 | """docstring for Diffusion""" 38 | 39 | def __init__( 40 | self, 41 | G, 42 | time_step, 43 | nb_simulation_step, 44 | initial_infection_rate=0.0, 45 | initial_time_stamp=0.0, 46 | strategies = None, 47 | ): 48 | 49 | super(Diffusion, self).__init__() 50 | 51 | self._G = G 52 | self._initial_infection_rate = initial_infection_rate 53 | self._initial_time_stamp = initial_time_stamp 54 | self._nb_simulation_step = nb_simulation_step 55 | self._time_step = float(time_step) / nb_simulation_step 56 | self.set_strategies(strategies) 57 | 58 | for node in self._G.nodes(): 59 | if RD.random() < initial_infection_rate: 60 | self._G.node[node]['state'] = 'I' 61 | self._G.node[node]['time_stamp'] = initial_time_stamp 62 | else: 63 | self._G.node[node]['state'] = 'S' 64 | self._G.node[node]['time_stamp'] = initial_time_stamp 65 | 66 | def run_steps(self, infected_node): 67 | self.set_infected(infected_node) 68 | for i in range(self._nb_simulation_step): 69 | self.diffusion_step() 70 | self.set_time_stamp(infected_node, self._initial_time_stamp 71 | + i * self._nb_simulation_step) 72 | 73 | def diffusion_step(self): 74 | H = self._G.copy() 75 | node_list = H.nodes() 76 | RD.shuffle(node_list) 77 | for node in node_list: 78 | if H.node[node]['state'] == 'I' and H.node[node]['strategy'] == 'C': 79 | neighbors = H.neighbors(node) 80 | for neighbor in neighbors: 81 | if RD.random() \ 82 | < H.edge[node][neighbor]['weight']: 83 | if H.node[neighbor]['state'] == 'S': 84 | H.node[neighbor]['state'] = 'I' 85 | H.node[neighbor]['time_stamp'] = \ 86 | H.node[node]['time_stamp'] 87 | else: 88 | max_time_stamp = \ 89 | max(H.node[neighbor]['time_stamp' 90 | ], H.node[node]['time_stamp']) 91 | H.node[neighbor]['time_stamp'] = \ 92 | max_time_stamp 93 | H.node[node]['time_stamp'] = \ 94 | max_time_stamp 95 | self._G = H.copy() 96 | 97 | # 98 | # Set 99 | # 100 | def set_nodes_states(self, nodes_states): 101 | for (key, val) in nodes_states.iteritems(): 102 | self._G.node[key]['state'] = val 103 | 104 | def set_node_time_stamps(self, time_stamps): 105 | for (key, val) in time_stamps.iteritems(): 106 | self._G.node[key]['time_stamp'] = val 107 | 108 | def set_time_stamp(self, node_id, time_stamp): 109 | self._G.node[node_id]['state'] = 'I' 110 | self._G.node[node_id]['time_stamp'] = time_stamp 111 | 112 | def set_weight(self, weights): 113 | for (item, val) in weights.iteritems(): 114 | (node_s, node_d) = item 115 | self._G.edge[node_s][node_d]['weight'] = val 116 | 117 | def set_strategies(self, strategies): 118 | ''' 119 | initialize the strategy of a node in the graph 120 | ''' 121 | if strategies != None: 122 | for node in self._G.nodes(): 123 | self._G.node[node]['strategy'] = strategies[node] 124 | else: 125 | for node in self._G.nodes(): 126 | self._G.node[node]['strategy'] = 'C' 127 | 128 | def set_infected(self, infected_node): 129 | ''' 130 | initialize the infected node in the graph 131 | ''' 132 | time_stamp = self._initial_time_stamp 133 | if type(infected_node) == list: 134 | for node in infected_node.iteritems(): 135 | self._G.node[node]['state'] = 'I' 136 | self._G.node[node]['time_stamp'] = time_stamp 137 | else: 138 | self._G.node[infected_node]['state'] = 'I' 139 | self._G.node[infected_node]['time_stamp'] = time_stamp 140 | 141 | # 142 | # Get 143 | # 144 | def get_number_infected(self): 145 | infected = 0 146 | for node in self._G.nodes(): 147 | if self._G.node[node]['state'] == 'I': 148 | infected += 1 149 | return infected 150 | 151 | def get_time_stamps(self): 152 | time_stamps = {} 153 | for node in self._G.nodes(): 154 | time_stamps[node] = self._G.node[node]['time_stamp'] 155 | return time_stamps 156 | 157 | def get_states(self): 158 | states = {} 159 | for node in self._G.nodes(): 160 | states[node] = self._G.node[node]['state'] 161 | return states -------------------------------------------------------------------------------- /complex_systems/dygraph.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | _author__ = """\n""".join(['Vincent Gauthier']) 28 | 29 | 30 | class DyGraph: 31 | 32 | ''' 33 | DynamicGraph store the time evolution of a graph by saving the snapshot of a graph at a given sampling rate 34 | 35 | :Example: 36 | >>> import networkx as nx 37 | >>> G = DyGraph() 38 | >>> G.add_graph(nx.Graph(), 10.0) 39 | 40 | ''' 41 | 42 | def __init__( 43 | self, 44 | time_stop=None, 45 | time_step=1.0, 46 | timeline=None, 47 | ): 48 | ''' 49 | Constructor 50 | ''' 51 | 52 | import numpy as N 53 | self._slices = {} 54 | self._index = 0 55 | self._slice_time = [] 56 | self._nodes_states = {} 57 | if timeline != None: 58 | self._slice_time = timeline 59 | self._time_stop = max(timeline) 60 | self._time_step = timeline[1] - timeline[0] 61 | self._generate_empty_slices() 62 | elif time_stop != None: 63 | self._time_stop = time_stop 64 | self._time_step = time_step 65 | self._slice_time = N.arange(0, time_stop, time_step) 66 | self._generate_empty_slices() 67 | 68 | def add_graph(self, G, slice_time): 69 | ''' 70 | Add a new slice or update a slice 71 | ''' 72 | 73 | G.graph['slice_time'] = slice_time 74 | 75 | if not slice_time in self._slice_time: 76 | self._slice_time.append(slice_time) 77 | self._time_stop = max(self._slice_time) 78 | self._time_start = min(self._slice_time) 79 | self._slice_time.sort() 80 | 81 | self._slices[int(slice_time)] = {'slice_time': slice_time, 82 | 'graph': G} 83 | 84 | def get_slice(self, time_step=0.0): 85 | ''' 86 | Return the graph slice at time_step=time 87 | ''' 88 | 89 | return self._slices[int(time_step)] 90 | 91 | def get_slice_time(self): 92 | ''' 93 | Return the slice time list 94 | ''' 95 | 96 | return list(self._slice_time) 97 | 98 | def get_graph(self, time_step=0.0): 99 | ''' 100 | Return the graph at time_step=time 101 | ''' 102 | 103 | return self._slices[int(time_step)]['graph'] 104 | 105 | def __iter__(self): 106 | ''' 107 | Iterate through the graph of all the slice in the structure 108 | 109 | :Example: 110 | >>> G = DyGraph() 111 | >>> G.add_graph(nx.Graph(), 10.0) 112 | >>> G.add_graph(nx.Graph(), 10.0) 113 | >>> for g in G: 114 | >>> print g.graph('slice_time') 115 | ''' 116 | 117 | return self 118 | 119 | def next(self): 120 | ''' 121 | Iterate through the graph of all the slice in the structure 122 | 123 | :Example: 124 | >>> G = DyGraph() 125 | >>> G.add_graph(nx.Graph(), 10.0) 126 | >>> G.add_graph(nx.Graph(), 10.0) 127 | >>> for g in G: 128 | >>> print g.graph('slice_time') 129 | ''' 130 | 131 | if self._index > len(self._slice_time) - 1: 132 | self._index = 0 133 | raise StopIteration 134 | else: 135 | self._index += 1 136 | idx = self._slice_time[self._index - 1] 137 | return self._slices[idx]['graph'] 138 | 139 | def set_nodes_states(self, nodes_states): 140 | self._nodes_states = nodes_states 141 | 142 | def get_nodes_states(self): 143 | return self._nodes_states 144 | 145 | def avg_degree(self): 146 | import numpy as np 147 | average_dygraph_degree = [] 148 | for (slice_id, s) in self._slices.iteritems(): 149 | G = s['graph'] 150 | average_dygraph_degree.append(np.mean(G.degree().values())) 151 | return np.mean(average_dygraph_degree) 152 | 153 | def generate_mobility_levy_walk( 154 | self, 155 | alpha, 156 | beta, 157 | size_max, 158 | f_min, 159 | f_max, 160 | s_min, 161 | s_max, 162 | b_c, 163 | radius, 164 | velocity=1.0, 165 | nb_node=1, 166 | ): 167 | ''' 168 | Generate a Levy walk for each node where teh sampling interval are defined as follow : 169 | 170 | - time_interval = [time_stop:time_step:time_stop] 171 | - nb_slices = (time_stop-time_start/time_step) 172 | 173 | :Parameters: 174 | - `alpha` : float 175 | Levy exponent for flight length distribution, 0 < alpha <= 2 176 | - `beta` : float 177 | Levy exponent for pause time distribution, 0 < beta <= 2 178 | - `size_max` : int 179 | size of simulation area 180 | - `velocity` : float 181 | speed in m/s 182 | - `f_min` : int 183 | min flight length 184 | - `f_max` : int 185 | max flight length 186 | - `s_min` : int 187 | min pause time (second) 188 | - `s_max` : int 189 | max pause time (second) 190 | - `b_c` : int 191 | boundary condition: 192 | - wrap-around if b_c=1 193 | - reflection boundary if b_c=2 194 | - `nb_node` : int (default 1) 195 | number of node in the model 196 | ''' 197 | 198 | from mobility.levy_walk import levy_walk 199 | import networkx as nx 200 | 201 | # For each node generate a levy_walk 202 | 203 | for node in range(nb_node): 204 | (un_sampled, A, B, sampled) = levy_walk( 205 | alpha=alpha, 206 | beta=beta, 207 | sample_length=self._time_step, 208 | size_max=size_max, 209 | velocity=velocity, 210 | f_min=f_min, 211 | f_max=f_max, 212 | s_min=s_min, 213 | s_max=s_max, 214 | duration=self._time_stop, 215 | b_c=b_c, 216 | ) 217 | 218 | # Position X,Y at time T of a node in his walk 219 | 220 | (X, Y, T) = zip(*sampled) 221 | 222 | # Foreach time step add a new node with pos=(X,Y) in the graph 223 | 224 | for i in range(len(T)): 225 | self._slices[int(T[i])]['graph'].add_node(node, 226 | pos=(X[i], Y[i])) 227 | 228 | # For each slice generate a the edges of the graph 229 | 230 | for (key, val) in self._slices.iteritems(): 231 | pos = nx.get_node_attributes(val['graph'], 'pos') 232 | G = self._generate_gemetric_graph(nb_node, pos=pos, 233 | radius=radius) 234 | nx.set_node_attributes(G, 'pos', pos) 235 | self.add_graph(G, key) 236 | 237 | def generate_weights( 238 | self, 239 | inner_radius, 240 | outer_radius, 241 | alpha, 242 | ): 243 | '''Generate weigth 244 | ''' 245 | 246 | from quasi_unit_disk_graph import gen_quasi_unit_disk_weight 247 | import networkx as nx 248 | for t in self._slice_time: 249 | pos = nx.get_node_attributes(self._slices[int(t)]['graph'], 250 | 'pos') 251 | G = gen_quasi_unit_disk_weight(self._slices[int(t)]['graph' 252 | ], outer_radius, inner_radius, alpha) 253 | nx.set_node_attributes(G, 'pos', pos) 254 | self.add_graph(G, t) 255 | 256 | def diffusion( 257 | self, 258 | slice_time, 259 | synergy, 260 | states=None, 261 | time_stamps=None, 262 | nb_steps=1, 263 | infected_node=1, 264 | cooperator_ratio=0.0, 265 | strategies=None, 266 | payoffs=None 267 | ): 268 | 269 | from diffusion import Diffusion 270 | from pgg import PublicGoodGames 271 | 272 | G = self._slices[int(slice_time)]['graph'].copy() 273 | 274 | if states == None or time_stamps == None: 275 | # Initialize the Public Good Game 276 | PGG = PublicGoodGames(G=G, 277 | cooperator_ratio=cooperator_ratio, nb_simulation_step=nb_steps, synergy=synergy) 278 | 279 | # Get the startegies list 280 | strategies = PGG.get_strategies() 281 | 282 | # Initialize the disffusion process with the startegies list 283 | D = Diffusion(G=G, nb_simulation_step=nb_steps, 284 | time_step=self._time_step, 285 | initial_time_stamp=slice_time, 286 | strategies=strategies) 287 | 288 | # Run the diffusion Process 289 | D.run_steps(infected_node) 290 | 291 | # Run the Game 292 | PGG.run_game() 293 | 294 | # Return the strategies list, the payoffs list, the timestamps list and the states list 295 | return (D.get_states(), D.get_time_stamps(), PGG.get_strategies(), PGG.get_payoffs()) 296 | elif strategies != None and payoffs != None: 297 | 298 | D = Diffusion(G=G, nb_simulation_step=nb_steps, 299 | time_step=self._time_step, 300 | initial_time_stamp=slice_time, 301 | strategies=strategies) 302 | 303 | PGG = PublicGoodGames(G=G, nb_simulation_step=nb_steps, synergy=synergy) 304 | 305 | PGG.set_strategies(strategies) 306 | PGG.set_payoffs(payoffs) 307 | 308 | D.set_nodes_states(states) 309 | D.set_node_time_stamps(time_stamps) 310 | 311 | # Run the diffusion Process 312 | D.run_steps(infected_node) 313 | # Run the Game 314 | PGG.run_game() 315 | # Return the strategies list, the payoffs list, the timestamps list and the states list 316 | return (D.get_states(), D.get_time_stamps(), PGG.get_strategies(), PGG.get_payoffs()) 317 | 318 | # #################### 319 | # Private Methodes 320 | # #################### 321 | 322 | def _generate_empty_slices(self): 323 | import networkx as nx 324 | for t in self._slice_time: 325 | self.add_graph(nx.Graph(), t) 326 | 327 | def _generate_gemetric_graph( 328 | self, 329 | nb_node, 330 | radius, 331 | pos, 332 | ): 333 | 334 | import networkx as nx 335 | return nx.random_geometric_graph(nb_node, radius, pos=pos) 336 | -------------------------------------------------------------------------------- /complex_systems/mobility/__init__.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------- 2 | # Copyright (c) 2012 Vincent Gauthier. 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining 5 | # a copy of this software and associated documentation files (the 6 | # "Software"), to deal in the Software without restriction, including 7 | # without limitation the rights to use, copy, modify, merge, publish, 8 | # distribute, sublicense, and/or sell copies of the Software, and to 9 | # permit persons to whom the Software is furnished to do so, subject to 10 | # the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | #------------------------------------------------------------------------------- 23 | -------------------------------------------------------------------------------- /complex_systems/mobility/distance.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012 Vincent Gauthier. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining 4 | # a copy of this software and associated documentation files (the 5 | # "Software"), to deal in the Software without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Software, and to 8 | # permit persons to whom the Software is furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | #------------------------------------------------------------------------------- 22 | 23 | __author__ = """\n""".join(['Vincent Gauthier ']) 24 | 25 | __all__ = ['distance'] 26 | 27 | 28 | def distance(X,Y): 29 | ''' 30 | Calculate the Euclidian distance between coordinates at differents step in time 31 | 32 | .. math:: 33 | dist_{i+1} = Distance( (x_i,y_i), (x_{i+1},y_{i+1}) ) \\ \\forall i 34 | 35 | :Example: 36 | >>> from complex_systems.mobility.levy_flight import * 37 | >>> X = [0,0,0] 38 | >>> Y = [1,2,3] 39 | >>> distance(X,Y) 40 | [1.0,1.0] 41 | 42 | :Parameters: 43 | - `X`: list(float) 44 | X coordinates 45 | - `Y`: list(float) 46 | Y coordinates 47 | 48 | :Returns: 49 | - `dist` : list 50 | Euclidian distance 51 | ''' 52 | import numpy as N 53 | dist = [N.sqrt(float((X[t+1] - X[t]) ** 2 + (Y[t+1] - Y[t]) ** 2)) for t in range(len(X)-1)] 54 | return dist -------------------------------------------------------------------------------- /complex_systems/mobility/levy_walk.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | __author__ = """\n""".join(['Vincent Gauthier ']) 28 | 29 | __all__ = ['levy_walk'] 30 | 31 | 32 | def levy_walk( 33 | alpha, 34 | beta, 35 | sample_length, 36 | size_max, 37 | velocity, 38 | f_min, 39 | f_max, 40 | s_min, 41 | s_max, 42 | duration=90000, 43 | b_c=1, 44 | ): 45 | ''' 46 | This code is based on the following paper: 47 | 48 | .. [Rhee08] Injong Rhee, Minsu Shin, Seongik Hong, Kyunghan Lee and Song Chong, "On the Levy-walk Nature of Human Mobility", INFOCOM, Arizona, USA, 2008 49 | 50 | .. note:: 51 | 52 | :Levy Flight or Levy Walk model: 53 | 54 | The Levy Walk generalize the concept of random walker with jump length distribution :math:`p(\\Delta x)` and 55 | and waitting time distribution :math:`p(\\Delta t)` for waitting ting time :math:`\\Delta t_i` and jump length :math:`\\Delta x_i` 56 | at evry steps :math:`i = 1, 2, ..., n` of the walk. 57 | 58 | .. math:: 59 | p(\\Delta x) \\sim \\frac{1}{(\\Delta x)^{1+\\alpha} },\\ \\ \\ p(\\Delta t) \\sim \\frac{1}{(\\Delta t)^{1+\\beta} }, \\ \\alpha , \\beta > 0 60 | 61 | 62 | :Example: 63 | >>> from complex_systems.mobility.levy_walk import * 64 | >>> levy_walk(alpha=0.66, beta=0.99, sample_length=1, size_max=83000, velocity=1.0, f_min=8, f_max=83000, s_min=0.8, s_max=430, duration=500, b_c=2) 65 | 66 | :Parameters: 67 | - `alpha` : float 68 | Levy exponent for flight length distribution, 0 < alpha <= 2 69 | - `beta` : float 70 | Levy exponent for pause time distribution, 0 < beta <= 2 71 | - `sample_length` : int 72 | Sample time in mins 73 | - `size_max` : int 74 | size of simulation area 75 | - `velocity` : float 76 | speed in m/s 77 | - `f_min` : int 78 | min flight length 79 | - `f_max` : int 80 | max flight length 81 | - `s_min` : int 82 | min pause time (second) 83 | - `s_max` : int 84 | max pause time (second) 85 | - `duration` : int 86 | simulation duration (minutes) 87 | - `b_c` : int 88 | boundary condition: 89 | - wrap-around if b_c=1 90 | - reflection boundary if b_c=2 91 | 92 | :Returns: 93 | - `un_sampled` : list(tulpe(X, Y, T)) 94 | - `X` : list(int) 95 | list of X location 96 | - `Y` : list(int) 97 | list of Y location 98 | - `T` : list(float) 99 | time in seconds 100 | - `A` : list(int) 101 | list of jump length 102 | - `B` : list(int) 103 | list of pause time length 104 | - `sampled` : list(tulpe(X_sampled, Y_sampled, T_sampled)) 105 | - `X_sampled` 106 | list of X location at sampled intervals 107 | - `Y_sampled` 108 | list of Y location at sampled intervals 109 | - `T_sampled` 110 | list of sampled intervals 111 | ''' 112 | 113 | import stabrnd as R 114 | import numpy as N 115 | 116 | # Pause Time scale parameter 117 | 118 | pt_scale = 1.0 119 | 120 | # Flight Length scale parameter 121 | 122 | fl_scale = 10.0 123 | 124 | # DEBUG 125 | 126 | DEBUG = False 127 | 128 | delta = 0.0 129 | 130 | # Velocity in meter per mins 131 | 132 | velocity = velocity 133 | if DEBUG: 134 | print 'velocity (m/mins): ', velocity 135 | 136 | num_step = int(N.ceil(float(duration) / sample_length)) 137 | num_step_gen = 10*int(N.ceil(float(duration) / s_min)) 138 | 139 | if DEBUG: 140 | print 'num steps: ', num_step 141 | 142 | # Constant speed 143 | 144 | mu = 0.0 145 | 146 | # Bounds of the simulation area 147 | 148 | max_x = size_max 149 | max_y = size_max 150 | 151 | A = [] 152 | B = [] 153 | x = [0] * (num_step_gen + 1) 154 | y = [0] * (num_step_gen + 1) 155 | t = [0] * (num_step_gen + 1) 156 | x_sampled = [0] * (num_step_gen) 157 | y_sampled = [0] * (num_step_gen) 158 | t_sampled = [0] * (num_step_gen) 159 | dist = [0] * num_step_gen 160 | 161 | if alpha < .1 or alpha > 2: 162 | raise ValueError('Alpha must be in [.1,2] for function stabrnd.' 163 | ) 164 | 165 | if beta < .1 or beta > 2: 166 | raise ValueError('Beta must be in [.1,2] for function stabrnd.') 167 | 168 | # Generate flight length 169 | 170 | while len(A) < num_step_gen: 171 | A_temp = N.abs(R.stabrnd( 172 | alpha, 173 | 0, 174 | fl_scale, 175 | delta, 176 | num_step, 177 | 1, 178 | )) 179 | A_temp = A_temp[A_temp > f_min] 180 | A_temp = A_temp[A_temp < f_max] 181 | A = N.append(A, A_temp) 182 | 183 | A = N.round(A[0:num_step_gen]) 184 | 185 | # Generate pause time 186 | 187 | while len(B) < num_step_gen: 188 | B_temp = N.abs(R.stabrnd( 189 | beta, 190 | 0, 191 | pt_scale, 192 | 0, 193 | num_step, 194 | 1, 195 | )) 196 | B_temp = B_temp[B_temp > s_min] 197 | B_temp = B_temp[B_temp < s_max] 198 | B = N.append(B, B_temp) 199 | 200 | B = N.round(B[0:num_step_gen]) 201 | 202 | # Initial Step 203 | 204 | x[0] = max_x * N.random.rand() 205 | y[0] = max_y * N.random.rand() 206 | if DEBUG: 207 | print x[0], y[0] 208 | t[0] = 0 209 | x_sampled[0] = x[0] 210 | y_sampled[0] = y[0] 211 | j = 1 212 | 213 | for i in N.arange(1, num_step_gen, 2): 214 | theta = 2 * N.pi * N.random.rand() 215 | next_x = N.round(x[i - 1] + A[i] * N.cos(theta)) 216 | next_y = N.round(y[i - 1] + A[i] * N.sin(theta)) 217 | if b_c == 1: 218 | # Boundary of the simulation Area 219 | # Wrap around 220 | if next_x < 0: 221 | x[i] = max_x + next_x 222 | elif next_x > max_x: 223 | x[i] = next_x - max_x 224 | else: 225 | x[i] = next_x 226 | 227 | if next_y < 0: 228 | y[i] = max_y + next_y 229 | elif next_y > max_y: 230 | y[i] = next_y - max_y 231 | else: 232 | y[i] = next_y 233 | elif b_c == 2: 234 | # Boundary of the simulation Area 235 | # Reflection 236 | if next_x < 0: 237 | x[i] = -next_x 238 | elif next_x > max_x: 239 | x[i] = max_x - (next_x - max_x) 240 | else: 241 | x[i] = next_x 242 | 243 | if next_y < 0: 244 | y[i] = -next_y 245 | elif next_y > max_y: 246 | y[i] = max_y - (next_y - max_y) 247 | else: 248 | y[i] = next_y 249 | # end of boundary 250 | 251 | dist[i] = N.sqrt(float((next_x - x[i - 1]) ** 2 + (next_y - y[i 252 | - 1]) ** 2)) 253 | t[i] = t[i - 1] + N.power(float(dist[i]) / velocity, 1 - mu) 254 | t[i + 1] = t[i] + N.abs(B[i]) 255 | x[i + 1] = x[i] 256 | y[i + 1] = y[i] 257 | 258 | while (j * sample_length) < t[i + 1]: 259 | 260 | if j * sample_length < t[i]: 261 | p_ratio = ((j * sample_length)- t[i-1]) / (t[i] - t[i - 1]) 262 | x_sampled[j] = next_x * p_ratio + x[i - 1] * (1 - p_ratio) 263 | y_sampled[j] = next_y * p_ratio + y[i - 1] * (1 - p_ratio) 264 | t_sampled[j] = j * sample_length 265 | if b_c == 1: 266 | # Boundary wrap around 267 | if x_sampled[j] < 0: 268 | x_sampled[j] = max_x + x_sampled[j] 269 | elif x_sampled[j] > max_x: 270 | x_sampled[j] = next_x - max_x 271 | if y_sampled[j] < 0: 272 | y_sampled[j] = max_y + y_sampled[j] 273 | elif y_sampled[j] > max_y: 274 | y_sampled[j] = next_y - max_y 275 | elif b_c == 2: 276 | # Boundary Reflection 277 | if x_sampled[j] < 0: 278 | x_sampled[j] = -x_sampled[j] 279 | elif x_sampled[j] > max_x: 280 | x_sampled[j] = max_x - (x_sampled[j] - max_x) 281 | if y_sampled[j] < 0: 282 | y_sampled[j] = -y_sampled[j] 283 | elif y_sampled[j] > max_y: 284 | y_sampled[j] = max_y - (y_sampled[j] - max_y) 285 | else: 286 | x_sampled[j] = x[i] 287 | y_sampled[j] = y[i] 288 | t_sampled[j] = j * sample_length 289 | 290 | j += 1 291 | 292 | if t[i+1] > duration: 293 | break 294 | 295 | if DEBUG: 296 | print 'Simulation length : ', len(x) 297 | 298 | X = N.round(x[0:i]) 299 | Y = N.round(y[0:i]) 300 | T = t[0:i] 301 | X_sampled = N.round(x_sampled[0:num_step]) 302 | Y_sampled = N.round(y_sampled[0:num_step]) 303 | T_sampled = t_sampled[0:num_step] 304 | un_sampled = zip(X,Y,T) 305 | sampled = zip(X_sampled, Y_sampled, T_sampled) 306 | return (un_sampled, A, B, sampled) 307 | -------------------------------------------------------------------------------- /complex_systems/mobility/stabrnd.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------- 2 | # Copyright (c) 2012 Vincent Gauthier. 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining 5 | # a copy of this software and associated documentation files (the 6 | # "Software"), to deal in the Software without restriction, including 7 | # without limitation the rights to use, copy, modify, merge, publish, 8 | # distribute, sublicense, and/or sell copies of the Software, and to 9 | # permit persons to whom the Software is furnished to do so, subject to 10 | # the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | #------------------------------------------------------------------------------- 23 | 24 | __author__ = """\n""".join(['Vincent Gauthier ']) 25 | 26 | __all__ = ['stabrnd'] 27 | 28 | 29 | def stabrnd(alpha, beta, c, delta, m, n): 30 | ''' 31 | Stable Random Number Generator (McCulloch 12/18/96) based on the paper [Cha71]_ 32 | 33 | Returns m x n matrix of iid stable random numbers with characteristic 34 | exponent alpha in [.1,2], skewness parameter beta in [-1,1], scale c > 0, 35 | and location parameter delta. Based on the method of [Cha71]_ . 36 | 37 | .. [Cha71] J.M. Chambers, C. L. Mallows and B. W.Stuck, "A Method for Simulating Stable Random Variables," JASA 71 (1976): 340-4. 38 | 39 | :History of this Code: 40 | - Encoded in MATLAB by J. Huston McCulloch, Ohio State University Econ. Dept. (mcculloch.2@osu.edu). 41 | - Encoded in Python by V. Gauthier, Telecom SudParis, CNRS Lab (vgauthier@luxbulb.org) 42 | 43 | :Parameters: 44 | - `alpha` : float 45 | Characteristic exponent in [.1,2] 46 | - `beta` : float 47 | Skewness in [-1,1] 48 | - `c` : float 49 | Scale c > 0 50 | - `delta` : float 51 | Location parameter 52 | - `m, n` : int 53 | Dimension of the matrix resultat 54 | 55 | :Returns: 56 | - `x` : matrix 57 | 58 | 59 | .. note:: The CMS method is applied in such a way that x will have the log characteristic function 60 | 61 | .. math:: 62 | \\log E \\cdot e^{(ixt)} = i \\Delta t + \\psi( c \\cdot t ), 63 | 64 | where 65 | 66 | .. math:: 67 | \\psi(t) = -|t|^{\\alpha} \\cdot [ 1 - i\\beta \\cdot sign(t) \\cdot \\tan(\\pi \\alpha/2) ],\\ for\\ \\alpha \\neq 1 68 | 69 | .. math:: 70 | \\psi(t) = -|t| \\cdot [1 + i \\beta (2 \\pi) \\cdot sign(t) \\cdot \\log |t| ],\\ for\\ \\alpha = 1. 71 | 72 | With this parameterization, the stable cdf, see [Mcc96]_ for details. 73 | 74 | .. math:: 75 | S(x; \\alpha, \\beta,c, \\delta) = S((x-\\delta)/c; \\alpha, \\beta, 1, 0). 76 | 77 | When :math:`\\alpha = 2`:, the distribution is Gaussian with mean delta and variance :math:`2 c^2`, and beta has no effect. 78 | 79 | When :math:`\\alpha > 1`, the mean is delta for all :math:`\\beta`. 80 | 81 | When :math:`\\alpha <= 1`, the mean is undefined. 82 | 83 | When :math:`\\beta = 0`, the distribution is symmetrical and delta is the median for all :math:`\\alpha`. 84 | 85 | When :math:`\\alpha = 1` and :math:`\\beta = 0`, the distribution is Cauchy (arctangent) with median :math:`\\delta`. 86 | 87 | When the submitted :math:`\\alpha` is > 2 or < .1, or :math:`\\beta` is outside [-1,1], an 88 | error message is generated and x is returned as a matrix of NaNs. 89 | 90 | :math:`\\alpha < 0.1` is not allowed here because of the non-negligible probability of overflows. 91 | 92 | If you're only interested in the symmetric cases, you may just set :math:`\\beta = 0` 93 | and skip the following considerations: 94 | 95 | When :math:`\\beta > 0, (< 0)`, the distribution is skewed to the right (left). 96 | 97 | When :math:`\\alpha < 1, \\delta`, as defined above, is the unique fractile that is 98 | invariant under averaging of iid contributions. I call such a fractile a 99 | "focus of stability." This, like the mean, is a natural location parameter. 100 | 101 | When :math:`\\alpha = 1`, either every fractile is a focus of stability, as in the 102 | :math:`\\beta = 0` Cauchy case, or else there is no focus of stability at all, as is 103 | the case for :math:`\\beta ~= 0`. In the latter cases, which I call "afocal," delta is 104 | just an arbitrary fractile that has a simple relation to the c.f. 105 | 106 | When :math:`\\alpha > 1 and \\beta > 0`, med(x) must lie very far below the mean as 107 | alpha approaches 1 from above. Furthermore, asalpha approaches 1 from below, 108 | med(x) must lie very far above the focus of stability when :math:`\\beta > 0`. If :math:`\\beta 109 | ~= 0`, there is therefore a discontinuity in the distribution as a function 110 | of alpha as alpha passes 1, when delta is held constant. CMS, following an 111 | insight of Vladimir Zolotarev, remove this discontinuity by subtracting: 112 | 113 | .. math:: 114 | \\beta \\cdot c \\cdot \\tan(\\pi \\cdot \\alpha/2) 115 | 116 | 117 | in their program RSTAB, a.k.a. RNSTA in IMSL (formerly GGSTA). The result is 118 | a random number whose distribution is a continuous function of alpha, but 119 | whose location parameter (which I call zeta) is a shifted version of delta 120 | that has no known interpretation other than computational convenience. 121 | 122 | The present program restores the more meaningful :math:`\\delta` parameterization by 123 | using the CMS (4.1), but with :math:`\\beta \\cdot c \\cdot tan(\\pi \\alpha/2)` added back in (ie with 124 | their initial :math:`tan(\\alpha \\phi_0)` deleted). RNSTA therefore gives different 125 | results than the present program when :math:`\\beta ~= 0`. However, the present beta 126 | is equivalent to the CMS beta' (BPRIME). 127 | 128 | Rather than using the CMS D2 and exp2 functions to compensate for the ill- 129 | condition of the CMS (4.1) when :math:`\\alpha` is very near 1, the present program 130 | merely fudges these cases by computing :math:`x` from their (2.4) and adjusting for 131 | :math:`\\beta \\cdot c \\cdot tan(\\pi \\alpha/2)` when alpha is within 1.e-8 of 1. This should make no 132 | difference for simulation results with samples of size less than 133 | approximately 10^8, and then only when the desired alpha is within 1.e-8 of 134 | 1, but not equal to 1. 135 | 136 | The frequently used Gaussian and symmetric cases are coded 137 | separately so as to speed up execution. 138 | 139 | **References** 140 | .. [Mcc96] J.H. McCulloch, "On the parametrization of the afocal stable distributions," Bull. London Math. Soc. 28 (1996): 651-55, 141 | .. [Zov86] V.M. Zolotarev, "One Dimensional Stable Laws," Amer. Math. Soc., 1986. 142 | .. [Sam94] G. Samorodnitsky and M.S. Taqqu, "Stable Non-Gaussian Random Processes," Chapman & Hill, 1994. 143 | .. [Jan94] A. Janicki and A. Weron, "Simulaton and Chaotic Behavior of Alpha-Stable Stochastic Processes," Dekker, 1994. 144 | .. [Mcc97] J.H. McCulloch, "Financial Applications of Stable Distributons," Handbook of Statistics, Vol. 14, 1997. 145 | ''' 146 | 147 | import numpy as N 148 | import numpy.random as R 149 | 150 | # Error traps 151 | if alpha < .1 or alpha > 2 : 152 | print 'Alpha must be in [.1,2] for function stabrnd.' 153 | x = N.nan * N.zeros((n,m)) 154 | return x 155 | 156 | if N.abs(beta) > 1 : 157 | print 'Beta must be in [-1,1] for function stabrnd.' 158 | x = N.nan * N.zeros((n,m)) 159 | return x 160 | 161 | # Generate exponential w and uniform phi: 162 | w = -N.log(R.rand(m,n)) 163 | phi = (R.rand(m,n) - 0.5) * N.pi 164 | 165 | # Gaussian case (Box-Muller): 166 | if alpha == 2: 167 | x = (2*N.sqrt(w) * N.sin(phi)) 168 | x = delta + c*x 169 | return x 170 | 171 | # Symmetrical cases: 172 | if beta == 0: 173 | if alpha == 1: # Cauchy case 174 | x = N.tan(phi) 175 | else: 176 | x = ((N.cos((1-alpha)*phi) / w) ** (1/alpha - 1) * N.sin(alpha * phi) / N.cos(phi) ** (1/alpha)) 177 | # General cases: 178 | else: 179 | cosphi = N.cos(phi) 180 | if N.abs(alpha-1) > 1.e-8: 181 | zeta = beta * N.tan(N.pi*alpha/2) 182 | aphi = alpha * phi 183 | a1phi = (1 - alpha) * phi 184 | x = ((N.sin(aphi) + zeta * N.cos(aphi)) / cosphi) * ((N.cos(a1phi) + zeta * N.sin(a1phi)) / (w * cosphi)) ** ((1-alpha)/alpha) 185 | else: 186 | bphi = (N.pi/2) + beta * phi 187 | x = (2/N.pi) * (bphi * N.tan(phi) - beta * N.log((N.pi/2) * w * cosphi / bphi)) 188 | if alpha != 1: 189 | x = x + beta * N.tan(N.pi * alpha/2) 190 | 191 | # Finale 192 | x = delta + c * x 193 | return x 194 | -------------------------------------------------------------------------------- /complex_systems/pgg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | __author__ = """\n""".join(['Abhik Banerjee', 'Vincent Gauthier']) 28 | 29 | 30 | class PublicGoodGames: 31 | 32 | def __init__( 33 | self, 34 | G, 35 | synergy, 36 | nb_simulation_step=1, 37 | cooperator_ratio=0.0, 38 | noise_var=0.0, 39 | maxlen_queue=200, 40 | ): 41 | 42 | import random as rd 43 | import collections 44 | self._noise_var = noise_var 45 | self._G = G 46 | self._synergy = synergy 47 | self._nb_simulation_step = int(nb_simulation_step) 48 | self._nb_coop = collections.deque(maxlen=maxlen_queue) 49 | self._nb_def = collections.deque(maxlen=maxlen_queue) 50 | 51 | for nd in self._G.nodes_iter(): 52 | 53 | # Initialize payoff and fitness values of nodes 54 | 55 | self.reset_payoffs() 56 | 57 | # Assign initial strategy 58 | 59 | if rd.random() < cooperator_ratio: 60 | self._G.node[nd]['strategy'] = 'C' 61 | else: 62 | self._G.node[nd]['strategy'] = 'D' 63 | 64 | def compute_payoffs_santos(self, dealer): 65 | ''' 66 | Compute the payoffs 67 | ''' 68 | 69 | #Kx = self.cooperator_in_neighborhood_counter(dealer) 70 | Kx = self._G.degree(dealer) 71 | 72 | dealer_neighborhood = self._G.neighbors(dealer) 73 | dealer_neighborhood.append(dealer) 74 | 75 | cost_i = 0 76 | for i in dealer_neighborhood: 77 | if self._G.node[i]['strategy'] == 'C': 78 | Ki =self._G.degree(i) 79 | cost_i += 1.0 / (Ki + 1) 80 | 81 | for y in dealer_neighborhood: 82 | cost_y = 0 83 | if self._G.node[y]['strategy'] == 'C' : 84 | Ky = self._G.degree(y) 85 | cost_y = 1.0 / (Ky + 1) 86 | self._G.node[y]['payoff'] += (self._synergy/(Kx+1)) * cost_i - cost_y 87 | 88 | def compute_payoffs(self, dealer): 89 | ''' 90 | Compute the payoffs 91 | ''' 92 | import numpy as np 93 | 94 | dealer_neighborhood = self._G.neighbors(dealer) 95 | dealer_neighborhood.append(dealer) 96 | if self._noise_var > 0: 97 | noise = np.random.normal(loc=0.0, scale=self._noise_var, size=1) 98 | else: 99 | noise = 0.0 100 | 101 | if self._G.node[dealer]['strategy'] == 'C': 102 | cost_y = 1.0 103 | else: 104 | cost_y = 0 105 | 106 | cost_i = 0 107 | for i in dealer_neighborhood: 108 | if self._G.node[i]['strategy'] == 'C' : 109 | Ki = self._G.degree(i) 110 | cost_i += 1.0 / (Ki + 1) 111 | self._G.node[dealer]['payoff'] = self._synergy * cost_i - cost_y + noise 112 | 113 | def run_game(self, nb_simulation_step=None): 114 | if nb_simulation_step != None: 115 | nb_step = int(nb_simulation_step) 116 | else: 117 | nb_step = self._nb_simulation_step 118 | for i in xrange(int(nb_step)): 119 | for dealer in self._G.nodes_iter(): 120 | self.compute_payoffs(dealer) 121 | # Update the simuations variable 122 | self.store_cooperator_defector_counter() 123 | self.updateStrategy() 124 | self.reset_payoffs() 125 | 126 | nb_coop = sum(self._nb_coop)/len(self._nb_coop) 127 | return (float(nb_coop)/len(self._G.nodes())) 128 | 129 | 130 | def updateStrategy(self): 131 | import random as rd 132 | import numpy as np 133 | 134 | # We create a copy of the graph so that the transitions in the same time slot 135 | # do not impact each other. 136 | # Since nodes update their strategies based on payoffs in the previous slot 137 | 138 | H = self._G.copy() 139 | 140 | # Update strategies. In this version, the adaptation of PGG is limited 141 | # to the payoffs only, as done above. The strategy update takes place 142 | # irrespective of whether a node has new packets or not. 143 | 144 | for nd in self._G.nodes_iter(): 145 | 146 | # Choose a random neighbor and change strategy with probability 147 | # proportional to the difference 148 | 149 | nd_deg = self._G.degree(nd) 150 | nd_nblist = self._G.neighbors(nd) 151 | 152 | if nd_deg != 0: 153 | comp_nb = nd_nblist[int(np.floor(rd.random() * nd_deg))] 154 | pyoff_diff = self._G.node[nd]['payoff'] \ 155 | - self._G.node[comp_nb]['payoff'] 156 | if rd.random() < 1 / (1 + np.exp(pyoff_diff / 0.1)): 157 | H.node[nd]['strategy'] = \ 158 | self._G.node[comp_nb]['strategy'] 159 | 160 | self._G = H.copy() 161 | 162 | # 163 | # Set 164 | # 165 | 166 | def set_payoffs(self, payoffs): 167 | for node in self._G.nodes_iter(): 168 | self._G.node[node]['payoff'] = payoffs[node] 169 | 170 | def set_strategies(self, strategies): 171 | for node in self._G.nodes_iter(): 172 | self._G.node[node]['strategy'] = strategies[node] 173 | 174 | def set_node_have_packet_to_send(self, packet_to_send): 175 | for node in self._G.nodes_iter(): 176 | self._G.node[node]['packet_to_send'] = packet_to_send[node] 177 | 178 | # 179 | # Get 180 | # 181 | 182 | def get_strategies(self): 183 | strategies = {} 184 | for node in self._G.nodes_iter(): 185 | strategies[node] = self._G.node[node]['strategy'] 186 | return strategies 187 | 188 | def get_payoffs(self): 189 | payoffs = {} 190 | for node in self._G.nodes_iter(): 191 | payoffs[node] = self._G.node[node]['payoff'] 192 | return payoffs 193 | 194 | # 195 | # Reset 196 | # 197 | 198 | def reset_payoffs(self): 199 | for nd in self._G.nodes_iter(): 200 | self._G.node[nd]['payoff'] = 0.0 201 | 202 | def reset_payoffs_selected_player(self, player): 203 | self._G.node[player]['payoff'] = 0.0 204 | 205 | # 206 | # Counter 207 | # 208 | 209 | def compute_avg_payoffs(self): 210 | avg_pay_c = 0 211 | avg_pay_d = 0 212 | avg_pay = 0 213 | for node in self._G.nodes_iter(): 214 | avg_pay += self._G.node[node]['payoff'] 215 | if self._G.node[node]['strategy'] == 'C': 216 | avg_pay_c += self._G.node[node]['payoff'] 217 | else: 218 | avg_pay_d += self._G.node[node]['payoff'] 219 | nbcoop = self.cooperator_counter() 220 | if nbcoop != 0: 221 | avg_pay_c = avg_pay_c / nbcoop 222 | else: 223 | avg_pay_c = 0 224 | nbdef = self.defector_counter() 225 | if nbdef != 0: 226 | avg_pay_d = avg_pay_d / self.defector_counter() 227 | else: 228 | avg_pay_d = 0 229 | avg_pay = avg_pay / len(self._G.nodes()) 230 | return (avg_pay_c, avg_pay_d, avg_pay) 231 | 232 | def cooperator_counter(self): 233 | return [self._G.node[i]['strategy'] for i in 234 | self._G.nodes_iter()].count('C') 235 | 236 | def store_cooperator_defector_counter(self): 237 | self._nb_coop.append(self.cooperator_counter()) 238 | self._nb_def.append(self.defector_counter()) 239 | 240 | def defector_counter(self): 241 | return [self._G.node[i]['strategy'] for i in 242 | self._G.nodes_iter()].count('D') 243 | 244 | def cooperator_in_neighborhood_counter(self, node): 245 | return [self._G.node[neighbor]['strategy'] for neighbor in 246 | self._G.neighbors_iter(node)].count('C') 247 | -------------------------------------------------------------------------------- /complex_systems/pgg_diffusion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | __author__ = """\n""".join(['Abhik Banerjee', 'Vincent Gauthier']) 28 | 29 | import networkx as nx 30 | import numpy.random as RD 31 | import numpy as N 32 | 33 | 34 | class PGG_diffusion: 35 | 36 | def __init__( 37 | self, 38 | G, 39 | synergy, 40 | nb_simulation_step=1, 41 | nb_seeder=1, 42 | cooperator_ratio=0.0, 43 | noise_var=0.0, 44 | maxlen_queue=200, 45 | buffer_size = 100, 46 | ): 47 | 48 | import collections 49 | import numpy as np 50 | self._noise_var = noise_var 51 | self._G = G 52 | self._synergy = synergy 53 | self._nb_node = len(G.nodes()) 54 | self._nb_seeder = nb_seeder 55 | self._nb_simulation_step = int(nb_simulation_step) 56 | self._nb_coop = collections.deque(maxlen=maxlen_queue) 57 | self._nb_def = collections.deque(maxlen=maxlen_queue) 58 | self._infected_node = [RD.randint(0,(self._nb_node-1)) for x in xrange(self._nb_seeder)] 59 | self._simulation_time = 0 60 | self._buffer_size = buffer_size 61 | self.reset_send_update() 62 | 63 | for nd in self._G.nodes_iter(): 64 | 65 | # Initialize payoff and fitness values of nodes 66 | 67 | self.reset_payoffs() 68 | 69 | # Assign initial strategy 70 | if RD.random() < cooperator_ratio: 71 | self._G.node[nd]['strategy'] = 'C' 72 | else: 73 | self._G.node[nd]['strategy'] = 'D' 74 | self._G.node[nd]['state'] = 'S' 75 | self._G.node[nd]['time_stamp'] = [] 76 | 77 | for infected in self._infected_node: 78 | self.set_infected(infected, range(self._buffer_size)) 79 | 80 | 81 | def compute_payoffs(self, dealer): 82 | ''' 83 | Compute the payoffs 84 | ''' 85 | 86 | import numpy as np 87 | 88 | dealer_neighborhood = self._G.neighbors(dealer) 89 | dealer_neighborhood.append(dealer) 90 | if self._noise_var > 0: 91 | noise = np.random.normal(loc=0.0, scale=self._noise_var, 92 | size=1) 93 | else: 94 | noise = 0.0 95 | 96 | if self._G.node[dealer]['strategy'] == 'C' and self._G.node[dealer]['ready_to_sent'] == 1: 97 | #if self._G.node[dealer]['strategy'] == 'C': 98 | Ni = [self._G.node[nd]['strategy'] for nd in self._G.neighbors(dealer)].count('C') 99 | cost_y = 1.0/(Ni+1) 100 | else: 101 | cost_y = 0 102 | 103 | cost_i = 0 104 | for i in dealer_neighborhood: 105 | if self._G.node[i]['strategy'] == 'C' and self._G.node[i]['ready_to_sent'] == 1: 106 | Nj = [self._G.node[nd]['strategy'] for nd in self._G.neighbors(i)].count('C') 107 | cost_i += 1.0 / (Nj+1) 108 | 109 | Nc = [self._G.node[nd]['strategy'] for nd in self._G.neighbors(dealer)].count('C') 110 | self._G.node[dealer]['payoff'] = (float(self._synergy)/(Nc+1)) * cost_i - cost_y + noise 111 | 112 | def diffusion_step(self): 113 | from random import choice 114 | H = self._G.copy() 115 | node_list = H.nodes() 116 | RD.shuffle(node_list) 117 | for node in node_list: 118 | if H.node[node]['state'] == 'I' and H.node[node]['strategy'] == 'C': 119 | neighbors = H.neighbors(node) 120 | pkt = -1 121 | RD.shuffle(neighbors) 122 | for neighbor in neighbors: 123 | if pkt == -1: 124 | ready_to_sent = list(set(H.node[node]['time_stamp']) - set(H.node[neighbor]['time_stamp'])) 125 | if len(ready_to_sent) > 0: 126 | pkt = choice(ready_to_sent) 127 | H.node[neighbor]['time_stamp'].append(pkt) 128 | H.node[neighbor]['state'] = 'I' 129 | H.node[node]['ready_to_sent'] = 1 130 | for nn in neighbors: 131 | if not (pkt in H.node[nn]['time_stamp']): 132 | H.node[nn]['time_stamp'].append(pkt) 133 | H.node[nn]['state'] = 'I' 134 | break 135 | self._G = H.copy() 136 | 137 | def run_game(self, nb_simulation_step=None): 138 | if nb_simulation_step != None: 139 | nb_step = int(nb_simulation_step) 140 | else: 141 | nb_step = self._nb_simulation_step 142 | for i in xrange(int(nb_step)): 143 | self.diffusion_step() 144 | for dealer in self._G.nodes_iter(): 145 | self.compute_payoffs(dealer) 146 | self.store_cooperator_defector_counter() 147 | self.updateStrategy() 148 | self.reset_payoffs() 149 | 150 | ######### 151 | # Print Debug 152 | # 153 | # NbInfected = 0 154 | # NbPacket = 0 155 | # nb_update = 0 156 | # for nd in self._G.nodes(): 157 | # NbPacket += len(self._G.node[nd]['time_stamp']) 158 | # if self._G.node[nd]['ready_to_sent'] == 1: 159 | # nb_update += 1 160 | # if self._G.node[nd]['state'] == 'I': 161 | # NbInfected += 1 162 | # finalState = self._nb_node * self._buffer_size 163 | 164 | # print 'NbPacket', 100*float(NbPacket)/finalState , 'Nb Update: ', nb_update, ' NbInfected ', NbInfected 165 | ######### 166 | # End Print Debug 167 | # 168 | 169 | 170 | self.reset_send_update() 171 | for infected in self._infected_node: 172 | self.set_infected(infected, range(self._buffer_size)) 173 | 174 | nb_coop = sum(self._nb_coop) / len(self._nb_coop) 175 | return float(nb_coop) / len(self._G.nodes()) 176 | 177 | def updateStrategy(self): 178 | import random as rd 179 | import numpy as np 180 | from random import choice 181 | # We create a copy of the graph so that the transitions in the same time slot 182 | # do not impact each other. 183 | # Since nodes update their strategies based on payoffs in the previous slot 184 | 185 | H = self._G.copy() 186 | 187 | # Update strategies. In this version, the adaptation of PGG is limited 188 | # to the payoffs only, as done above. The strategy update takes place 189 | # irrespective of whether a node has new packets or not. 190 | 191 | for nd in self._G.nodes_iter(): 192 | 193 | # Choose a random neighbor and change strategy with probability 194 | # proportional to the difference 195 | 196 | nd_deg = self._G.degree(nd) 197 | nd_nblist = self._G.neighbors(nd) 198 | 199 | if nd_deg != 0: 200 | comp_nb = choice(nd_nblist) 201 | pyoff_diff = self._G.node[nd]['payoff'] \ 202 | - self._G.node[comp_nb]['payoff'] 203 | if rd.random() < 1 / (1 + np.exp(pyoff_diff / 0.1)): 204 | H.node[nd]['strategy'] = \ 205 | self._G.node[comp_nb]['strategy'] 206 | self._G = H.copy() 207 | 208 | # 209 | # Set 210 | # 211 | 212 | def set_payoffs(self, payoffs): 213 | for node in self._G.nodes_iter(): 214 | self._G.node[node]['payoff'] = payoffs[node] 215 | 216 | def set_strategies(self, strategies): 217 | for node in self._G.nodes_iter(): 218 | self._G.node[node]['strategy'] = strategies[node] 219 | 220 | def set_time_stamps(self, time_stamps): 221 | for node in self._G.nodes(): 222 | self._G.node[node]['time_stamp'] = [] 223 | 224 | for (key, val) in time_stamps.iteritems(): 225 | self._G.node[key]['time_stamp'] = val 226 | 227 | def set_seeder(self, seeder): 228 | self._infected_node = seeder 229 | 230 | def set_nodes_states(self, nodes_states): 231 | for (key, val) in nodes_states.iteritems(): 232 | self._G.node[key]['state'] = val 233 | 234 | def set_infected(self, node_id, time_stamp): 235 | self._G.node[node_id]['state'] = 'I' 236 | self._G.node[node_id]['strategy'] = 'C' 237 | self._G.node[node_id]['time_stamp'] = time_stamp 238 | self._G.node[node_id]['ready_to_sent'] = 1 239 | 240 | def set_sent_update(self, sent_update): 241 | for (key, val) in sent_update.iteritems(): 242 | self._G.node[key]['ready_to_sent'] = val 243 | 244 | # 245 | # Get 246 | # 247 | 248 | def get_strategies(self): 249 | strategies = {} 250 | for node in self._G.nodes_iter(): 251 | strategies[node] = self._G.node[node]['strategy'] 252 | return strategies 253 | 254 | def get_payoffs(self): 255 | payoffs = {} 256 | for node in self._G.nodes_iter(): 257 | payoffs[node] = self._G.node[node]['payoff'] 258 | return payoffs 259 | 260 | def get_time_stamps(self): 261 | time_stamps = {} 262 | for node in self._G.nodes_iter(): 263 | time_stamps[node] = self._G.node[node]['time_stamp'] 264 | return time_stamps 265 | 266 | def get_distribution_time_stamps(self): 267 | dist = [] 268 | for node in self._G.nodes(): 269 | ts = self._G.node[node]['time_stamp'] 270 | dist.append(len(ts)) 271 | time_stamps = dict([(x, dist.count(x)) for x in set(dist)]) 272 | return time_stamps 273 | 274 | def get_states(self): 275 | states = {} 276 | for node in self._G.nodes_iter(): 277 | states[node] = self._G.node[node]['state'] 278 | return states 279 | 280 | def get_sent_update(self): 281 | sent_update = {} 282 | for nd in self._G.nodes_iter(): 283 | sent_update[nd] = self._G.node[nd]['ready_to_sent'] 284 | return sent_update 285 | 286 | def get_seeder(self): 287 | #print self._infected_node 288 | return self._infected_node 289 | # 290 | # Reset 291 | # 292 | 293 | def reset_payoffs(self): 294 | for nd in self._G.nodes_iter(): 295 | self._G.node[nd]['payoff'] = 0.0 296 | 297 | def reset_payoffs_selected_player(self, player): 298 | self._G.node[player]['payoff'] = 0.0 299 | 300 | def reset_send_update(self): 301 | for nd in self._G.nodes_iter(): 302 | self._G.node[nd]['ready_to_sent'] = 0 303 | 304 | 305 | # 306 | # Counter 307 | # 308 | 309 | def compute_avg_payoffs(self): 310 | avg_pay_c = 0 311 | avg_pay_d = 0 312 | avg_pay = 0 313 | for node in self._G.nodes_iter(): 314 | avg_pay += self._G.node[node]['payoff'] 315 | if self._G.node[node]['strategy'] == 'C': 316 | avg_pay_c += self._G.node[node]['payoff'] 317 | else: 318 | avg_pay_d += self._G.node[node]['payoff'] 319 | nbcoop = self.cooperator_counter() 320 | if nbcoop != 0: 321 | avg_pay_c = avg_pay_c / nbcoop 322 | else: 323 | avg_pay_c = 0 324 | nbdef = self.defector_counter() 325 | if nbdef != 0: 326 | avg_pay_d = avg_pay_d / self.defector_counter() 327 | else: 328 | avg_pay_d = 0 329 | avg_pay = avg_pay / len(self._G.nodes()) 330 | return (avg_pay_c, avg_pay_d, avg_pay) 331 | 332 | def cooperator_counter(self): 333 | return [self._G.node[i]['strategy'] for i in 334 | self._G.nodes_iter()].count('C') 335 | 336 | def store_cooperator_defector_counter(self): 337 | self._nb_coop.append(self.cooperator_counter()) 338 | self._nb_def.append(self.defector_counter()) 339 | 340 | def defector_counter(self): 341 | return [self._G.node[i]['strategy'] for i in 342 | self._G.nodes_iter()].count('D') 343 | 344 | def cooperator_in_neighborhood_counter(self, node): 345 | return [self._G.node[neighbor]['strategy'] for neighbor in 346 | self._G.neighbors_iter(node)].count('C') 347 | -------------------------------------------------------------------------------- /complex_systems/quasi_unit_disk_graph.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | __author__ = """\n""".join(['Vincent Gauthier']) 28 | 29 | 30 | def gen_quasi_unit_disk_weight( 31 | G, 32 | outer_radius, 33 | inner_radius, 34 | alpha, 35 | ): 36 | 37 | import numpy as N 38 | 39 | for edge in G.edges(): 40 | (node_s, node_d) = edge 41 | (x_s, y_s) = G.node[node_s]['pos'] 42 | (x_d, y_d) = G.node[node_d]['pos'] 43 | D = N.sqrt((x_s - x_d) ** 2 + (y_s - y_d) ** 2) 44 | if D <= inner_radius: 45 | weight = 1 46 | elif D >= outer_radius: 47 | weight = 0 48 | else: 49 | weight = ((outer_radius - D) / (outer_radius 50 | - inner_radius)) ** alpha 51 | G.edge[node_s][node_d]['weight'] = weight 52 | return G 53 | 54 | def remove_edges_from_graph(G): 55 | from random import random 56 | H = G.copy() 57 | for edge in H.edges(): 58 | (node_s, node_d) = edge 59 | if H.edge[node_s][node_d]['weight'] < random(): 60 | H.remove_edge(*edge) 61 | return H -------------------------------------------------------------------------------- /complex_systems/spatial/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # ------------------------------------------------------------------------------- 4 | # Copyright (c) 2012 Vincent Gauthier. 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining 7 | # a copy of this software and associated documentation files (the 8 | # "Software"), to deal in the Software without restriction, including 9 | # without limitation the rights to use, copy, modify, merge, publish, 10 | # distribute, sublicense, and/or sell copies of the Software, and to 11 | # permit persons to whom the Software is furnished to do so, subject to 12 | # the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included 15 | # in all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------- 25 | -------------------------------------------------------------------------------- /complex_systems/spatial/kernel_density_geo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | __author__ = """\n""".join(['Vincent Gauthier']) 28 | 29 | 30 | def kernel_density_geo(X_data, Y_data, bin_size_x=10, bin_size_y=10): 31 | ''' 32 | more information about the `Kernel density estimation `_ 33 | ''' 34 | import scipy.stats as stats 35 | import numpy as N 36 | 37 | #Format teh entry to make sure it is a colum vector 38 | X_data = N.transpose([X_data.ravel()]) 39 | Y_data = N.transpose([Y_data.ravel()]) 40 | pos = N.append(X_data,Y_data,axis=1) 41 | 42 | kde = stats.kde.gaussian_kde(pos.T) 43 | 44 | X_flat = N.linspace(pos[:,0].min(),pos[:,0].max(),bin_size_x) 45 | Y_flat = N.linspace(pos[:,1].min(),pos[:,1].max(),bin_size_y) 46 | 47 | X,Y = N.meshgrid(X_flat,Y_flat) 48 | 49 | grid_coords =N.append(X.reshape(-1,1),Y.reshape(-1,1),axis=1) 50 | Z = kde(grid_coords.T) 51 | Z = Z.reshape(bin_size_x,bin_size_y) 52 | 53 | return grid_coords,Z -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | # the i18n builder cannot share the environment and doctrees with the others 15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 16 | 17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 18 | 19 | help: 20 | @echo "Please use \`make ' where is one of" 21 | @echo " html to make standalone HTML files" 22 | @echo " dirhtml to make HTML files named index.html in directories" 23 | @echo " singlehtml to make a single large HTML file" 24 | @echo " pickle to make pickle files" 25 | @echo " json to make JSON files" 26 | @echo " htmlhelp to make HTML files and a HTML help project" 27 | @echo " qthelp to make HTML files and a qthelp project" 28 | @echo " devhelp to make HTML files and a Devhelp project" 29 | @echo " epub to make an epub" 30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 31 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 32 | @echo " text to make text files" 33 | @echo " man to make manual pages" 34 | @echo " texinfo to make Texinfo files" 35 | @echo " info to make Texinfo files and run them through makeinfo" 36 | @echo " gettext to make PO message catalogs" 37 | @echo " changes to make an overview of all changed/added/deprecated items" 38 | @echo " linkcheck to check all external links for integrity" 39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 40 | 41 | clean: 42 | -rm -rf $(BUILDDIR)/* 43 | 44 | html: 45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 48 | 49 | dirhtml: 50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 51 | @echo 52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 53 | 54 | singlehtml: 55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 56 | @echo 57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 58 | 59 | pickle: 60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 61 | @echo 62 | @echo "Build finished; now you can process the pickle files." 63 | 64 | json: 65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 66 | @echo 67 | @echo "Build finished; now you can process the JSON files." 68 | 69 | htmlhelp: 70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 71 | @echo 72 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 73 | ".hhp project file in $(BUILDDIR)/htmlhelp." 74 | 75 | qthelp: 76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 77 | @echo 78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/AgentBasedModelusedinthepaperentitledCooperationOptimizedDesignforInformationDisseminationinVehicularNetworksusingEvolutionaryGameTheory.qhcp" 81 | @echo "To view the help file:" 82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/AgentBasedModelusedinthepaperentitledCooperationOptimizedDesignforInformationDisseminationinVehicularNetworksusingEvolutionaryGameTheory.qhc" 83 | 84 | devhelp: 85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 86 | @echo 87 | @echo "Build finished." 88 | @echo "To view the help file:" 89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/AgentBasedModelusedinthepaperentitledCooperationOptimizedDesignforInformationDisseminationinVehicularNetworksusingEvolutionaryGameTheory" 90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/AgentBasedModelusedinthepaperentitledCooperationOptimizedDesignforInformationDisseminationinVehicularNetworksusingEvolutionaryGameTheory" 91 | @echo "# devhelp" 92 | 93 | epub: 94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 95 | @echo 96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 97 | 98 | latex: 99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 100 | @echo 101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 103 | "(use \`make latexpdf' here to do that automatically)." 104 | 105 | latexpdf: 106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 107 | @echo "Running LaTeX files through pdflatex..." 108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 110 | 111 | text: 112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 113 | @echo 114 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 115 | 116 | man: 117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 118 | @echo 119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 120 | 121 | texinfo: 122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 123 | @echo 124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 125 | @echo "Run \`make' in that directory to run these through makeinfo" \ 126 | "(use \`make info' here to do that automatically)." 127 | 128 | info: 129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 130 | @echo "Running Texinfo files through makeinfo..." 131 | make -C $(BUILDDIR)/texinfo info 132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 133 | 134 | gettext: 135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 136 | @echo 137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 138 | 139 | changes: 140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 141 | @echo 142 | @echo "The overview file is in $(BUILDDIR)/changes." 143 | 144 | linkcheck: 145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 146 | @echo 147 | @echo "Link check complete; look for any errors in the above output " \ 148 | "or in $(BUILDDIR)/linkcheck/output.txt." 149 | 150 | doctest: 151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 152 | @echo "Testing of doctests in the sources finished, look at the " \ 153 | "results in $(BUILDDIR)/doctest/output.txt." 154 | -------------------------------------------------------------------------------- /doc/complex_systems.mobility.rst: -------------------------------------------------------------------------------- 1 | mobility Package 2 | ================ 3 | 4 | :mod:`mobility` Package 5 | ----------------------- 6 | 7 | .. automodule:: complex_systems.mobility 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | :mod:`distance` Module 13 | ---------------------- 14 | 15 | .. automodule:: complex_systems.mobility.distance 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | :mod:`levy_walk` Module 21 | ----------------------- 22 | 23 | .. automodule:: complex_systems.mobility.levy_walk 24 | :members: 25 | :undoc-members: 26 | :show-inheritance: 27 | 28 | :mod:`stabrnd` Module 29 | --------------------- 30 | 31 | .. automodule:: complex_systems.mobility.stabrnd 32 | :members: 33 | :undoc-members: 34 | :show-inheritance: 35 | 36 | -------------------------------------------------------------------------------- /doc/complex_systems.rst: -------------------------------------------------------------------------------- 1 | complex_systems Package 2 | ======================= 3 | 4 | :mod:`complex_systems` Package 5 | ------------------------------ 6 | 7 | .. automodule:: complex_systems.__init__ 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | :mod:`dygraph` Module 13 | --------------------- 14 | 15 | .. automodule:: complex_systems.dygraph 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | Subpackages 21 | ----------- 22 | 23 | .. toctree:: 24 | 25 | complex_systems.mobility 26 | complex_systems.spatial 27 | 28 | -------------------------------------------------------------------------------- /doc/complex_systems.spatial.rst: -------------------------------------------------------------------------------- 1 | spatial Package 2 | =============== 3 | 4 | :mod:`spatial` Package 5 | ---------------------- 6 | 7 | .. automodule:: complex_systems.spatial 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | :mod:`kernel_density_geo` Module 13 | -------------------------------- 14 | 15 | .. automodule:: complex_systems.spatial.kernel_density_geo 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | -------------------------------------------------------------------------------- /doc/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Agent Based Model used in the paper entitled : Cooperation Optimized Design for Information Dissemination in Vehicular Networks using Evolutionary Game Theory documentation build configuration file, created by 4 | # sphinx-quickstart on Fri Dec 14 11:00:42 2012. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | #sys.path.insert(0, os.path.abspath('.')) 20 | sys.path.insert(0, os.path.abspath('../')) 21 | 22 | # -- General configuration ----------------------------------------------------- 23 | 24 | # If your documentation needs a minimal Sphinx version, state it here. 25 | #needs_sphinx = '1.0' 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be extensions 28 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 29 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.mathjax', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode'] 30 | 31 | # Add any paths that contain templates here, relative to this directory. 32 | templates_path = ['_templates'] 33 | 34 | # The suffix of source filenames. 35 | source_suffix = '.rst' 36 | 37 | # The encoding of source files. 38 | #source_encoding = 'utf-8-sig' 39 | 40 | # The master toctree document. 41 | master_doc = 'index' 42 | 43 | # General information about the project. 44 | project = u'Agent Based Model used in the paper entitled : Cooperation Optimized Design for Information Dissemination in Vehicular Networks using Evolutionary Game Theory' 45 | copyright = u'2012, Vincent Gauthier' 46 | 47 | # The version info for the project you're documenting, acts as replacement for 48 | # |version| and |release|, also used in various other places throughout the 49 | # built documents. 50 | # 51 | # The short X.Y version. 52 | version = '0.2' 53 | # The full version, including alpha/beta/rc tags. 54 | release = '0.2' 55 | 56 | # The language for content autogenerated by Sphinx. Refer to documentation 57 | # for a list of supported languages. 58 | #language = None 59 | 60 | # There are two options for replacing |today|: either, you set today to some 61 | # non-false value, then it is used: 62 | #today = '' 63 | # Else, today_fmt is used as the format for a strftime call. 64 | #today_fmt = '%B %d, %Y' 65 | 66 | # List of patterns, relative to source directory, that match files and 67 | # directories to ignore when looking for source files. 68 | exclude_patterns = ['_build'] 69 | 70 | # The reST default role (used for this markup: `text`) to use for all documents. 71 | #default_role = None 72 | 73 | # If true, '()' will be appended to :func: etc. cross-reference text. 74 | #add_function_parentheses = True 75 | 76 | # If true, the current module name will be prepended to all description 77 | # unit titles (such as .. function::). 78 | #add_module_names = True 79 | 80 | # If true, sectionauthor and moduleauthor directives will be shown in the 81 | # output. They are ignored by default. 82 | #show_authors = False 83 | 84 | # The name of the Pygments (syntax highlighting) style to use. 85 | pygments_style = 'sphinx' 86 | 87 | # A list of ignored prefixes for module index sorting. 88 | #modindex_common_prefix = [] 89 | 90 | 91 | # -- Options for HTML output --------------------------------------------------- 92 | 93 | # The theme to use for HTML and HTML Help pages. See the documentation for 94 | # a list of builtin themes. 95 | html_theme = 'default' 96 | 97 | # Theme options are theme-specific and customize the look and feel of a theme 98 | # further. For a list of options available for each theme, see the 99 | # documentation. 100 | #html_theme_options = {} 101 | 102 | # Add any paths that contain custom themes here, relative to this directory. 103 | #html_theme_path = [] 104 | 105 | # The name for this set of Sphinx documents. If None, it defaults to 106 | # " v documentation". 107 | #html_title = None 108 | 109 | # A shorter title for the navigation bar. Default is the same as html_title. 110 | #html_short_title = None 111 | 112 | # The name of an image file (relative to this directory) to place at the top 113 | # of the sidebar. 114 | #html_logo = None 115 | 116 | # The name of an image file (within the static path) to use as favicon of the 117 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 118 | # pixels large. 119 | #html_favicon = None 120 | 121 | # Add any paths that contain custom static files (such as style sheets) here, 122 | # relative to this directory. They are copied after the builtin static files, 123 | # so a file named "default.css" will overwrite the builtin "default.css". 124 | html_static_path = ['_static'] 125 | 126 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 127 | # using the given strftime format. 128 | #html_last_updated_fmt = '%b %d, %Y' 129 | 130 | # If true, SmartyPants will be used to convert quotes and dashes to 131 | # typographically correct entities. 132 | #html_use_smartypants = True 133 | 134 | # Custom sidebar templates, maps document names to template names. 135 | #html_sidebars = {} 136 | 137 | # Additional templates that should be rendered to pages, maps page names to 138 | # template names. 139 | #html_additional_pages = {} 140 | 141 | # If false, no module index is generated. 142 | #html_domain_indices = True 143 | 144 | # If false, no index is generated. 145 | #html_use_index = True 146 | 147 | # If true, the index is split into individual pages for each letter. 148 | #html_split_index = False 149 | 150 | # If true, links to the reST sources are added to the pages. 151 | #html_show_sourcelink = True 152 | 153 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 154 | #html_show_sphinx = True 155 | 156 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 157 | #html_show_copyright = True 158 | 159 | # If true, an OpenSearch description file will be output, and all pages will 160 | # contain a tag referring to it. The value of this option must be the 161 | # base URL from which the finished HTML is served. 162 | #html_use_opensearch = '' 163 | 164 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 165 | #html_file_suffix = None 166 | 167 | # Output file base name for HTML help builder. 168 | htmlhelp_basename = 'AgentBasedModelusedinthepaperentitledCooperationOptimizedDesignforInformationDisseminationinVehicularNetworksusingEvolutionaryGameTheorydoc' 169 | 170 | 171 | # -- Options for LaTeX output -------------------------------------------------- 172 | 173 | latex_elements = { 174 | # The paper size ('letterpaper' or 'a4paper'). 175 | #'papersize': 'letterpaper', 176 | 177 | # The font size ('10pt', '11pt' or '12pt'). 178 | #'pointsize': '10pt', 179 | 180 | # Additional stuff for the LaTeX preamble. 181 | #'preamble': '', 182 | } 183 | 184 | # Grouping the document tree into LaTeX files. List of tuples 185 | # (source start file, target name, title, author, documentclass [howto/manual]). 186 | latex_documents = [ 187 | ('index', 'AgentBasedModelusedinthepaperentitledCooperationOptimizedDesignforInformationDisseminationinVehicularNetworksusingEvolutionaryGameTheory.tex', u'Agent Based Model used in the paper entitled : Cooperation Optimized Design for Information Dissemination in Vehicular Networks using Evolutionary Game Theory Documentation', 188 | u'Vincent Gauthier', 'manual'), 189 | ] 190 | 191 | # The name of an image file (relative to this directory) to place at the top of 192 | # the title page. 193 | #latex_logo = None 194 | 195 | # For "manual" documents, if this is true, then toplevel headings are parts, 196 | # not chapters. 197 | #latex_use_parts = False 198 | 199 | # If true, show page references after internal links. 200 | #latex_show_pagerefs = False 201 | 202 | # If true, show URL addresses after external links. 203 | #latex_show_urls = False 204 | 205 | # Documents to append as an appendix to all manuals. 206 | #latex_appendices = [] 207 | 208 | # If false, no module index is generated. 209 | #latex_domain_indices = True 210 | 211 | 212 | # -- Options for manual page output -------------------------------------------- 213 | 214 | # One entry per manual page. List of tuples 215 | # (source start file, name, description, authors, manual section). 216 | man_pages = [ 217 | ('index', 'agentbasedmodelusedinthepaperentitledcooperationoptimizeddesignforinformationdisseminationinvehicularnetworksusingevolutionarygametheory', u'Agent Based Model used in the paper entitled : Cooperation Optimized Design for Information Dissemination in Vehicular Networks using Evolutionary Game Theory Documentation', 218 | [u'Vincent Gauthier'], 1) 219 | ] 220 | 221 | # If true, show URL addresses after external links. 222 | #man_show_urls = False 223 | 224 | 225 | # -- Options for Texinfo output ------------------------------------------------ 226 | 227 | # Grouping the document tree into Texinfo files. List of tuples 228 | # (source start file, target name, title, author, 229 | # dir menu entry, description, category) 230 | texinfo_documents = [ 231 | ('index', 'AgentBasedModelusedinthepaperentitledCooperationOptimizedDesignforInformationDisseminationinVehicularNetworksusingEvolutionaryGameTheory', u'Agent Based Model used in the paper entitled : Cooperation Optimized Design for Information Dissemination in Vehicular Networks using Evolutionary Game Theory Documentation', 232 | u'Vincent Gauthier', 'AgentBasedModelusedinthepaperentitledCooperationOptimizedDesignforInformationDisseminationinVehicularNetworksusingEvolutionaryGameTheory', 'One line description of project.', 233 | 'Miscellaneous'), 234 | ] 235 | 236 | # Documents to append as an appendix to all manuals. 237 | #texinfo_appendices = [] 238 | 239 | # If false, no module index is generated. 240 | #texinfo_domain_indices = True 241 | 242 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 243 | #texinfo_show_urls = 'footnote' 244 | 245 | 246 | # Example configuration for intersphinx: refer to the Python standard library. 247 | intersphinx_mapping = {'http://docs.python.org/': None} 248 | -------------------------------------------------------------------------------- /doc/examples.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Example 3 | ======= 4 | 5 | Generate a Levy-Walk 6 | ==================== 7 | 8 | .. code-block:: python 9 | 10 | import pylab as plt 11 | from complex_systems.mobility.levy_flight import levy_flight 12 | 13 | LF = levy_flight(alpha=0.66,beta=0.99,sample_length=10,size_max=10000,velocity=1.0,f_min=8,f_max=10000,s_min=0.8,s_max=430,duration=500,b_c=1) 14 | 15 | plt.figure() 16 | plt.plot(LF[0], LF[1], 'o-') 17 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | 2 | .. include:: ../README.rst 3 | 4 | Contents 5 | ======== 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | install 11 | examples 12 | modules 13 | 14 | 15 | Indices and tables 16 | ================== 17 | 18 | * :ref:`genindex` 19 | * :ref:`modindex` 20 | * :ref:`search` 21 | 22 | -------------------------------------------------------------------------------- /doc/install.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | Obtaining and Installing 3 | ======================== 4 | 5 | Requirements 6 | ============ 7 | 8 | Python 2.7 is required, Complex Systems relies on a number of different packages. However, the only compulsory package is NumPy_. All other requirements are optional - if they are not present, the relevant read/write methods will be disabled but will not otherwise prevent Complex Systems from functioning. 9 | 10 | Below is a list of the optional packages that Complex Systems depends on: 11 | 12 | - Matplotlib_ 13 | - Scikits_ 14 | 15 | Stable version 16 | ============== 17 | The latest stable release of Complex Systems can be downloaded from Bitbucket_. To install Complex Systems, use the standard installation procedure: 18 | 19 | .. code-block:: bash 20 | 21 | tar zxvf ComplexSystems-x.x.x.x.tar.gz 22 | cd ComplexSystems-x.x.x.x/ 23 | python setup.py install 24 | 25 | 26 | Developer version 27 | ================= 28 | 29 | Advanced users wishing to use the latest development (“unstable”) version can check it out with: 30 | 31 | .. code-block:: bash 32 | 33 | git clone https://bitbucket.org/vgauthier/complex-systems.git 34 | 35 | which can then be installed with: 36 | 37 | .. code-block:: bash 38 | 39 | cd ComplexSystems 40 | python setup.py install 41 | 42 | .. _Bitbucket: https://bitbucket.org/ 43 | .. _NumPy: http://numpy.scipy.org/ 44 | .. _Matplotlib: http://matplotlib.sourceforge.net/ 45 | .. _Scikits: http://scikits.appspot.com/ -------------------------------------------------------------------------------- /doc/modules.rst: -------------------------------------------------------------------------------- 1 | complex_systems 2 | =============== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | complex_systems 8 | -------------------------------------------------------------------------------- /examples/run_diffusion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # ------------------------------------------------------------------------------- 4 | # Copyright (c) 2012 Vincent Gauthier. 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining 7 | # a copy of this software and associated documentation files (the 8 | # "Software"), to deal in the Software without restriction, including 9 | # without limitation the rights to use, copy, modify, merge, publish, 10 | # distribute, sublicense, and/or sell copies of the Software, and to 11 | # permit persons to whom the Software is furnished to do so, subject to 12 | # the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included 15 | # in all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------- 25 | 26 | __author__ = """\n""".join(['Vincent Gauthier']) 27 | 28 | import networkx as nx 29 | import random as RD 30 | import pylab as P 31 | import numpy as N 32 | from complex_systems.diffusion import Diffusion 33 | 34 | def main(): 35 | nb_node = 1000 36 | Pb_edge = 3.0 / nb_node 37 | weights = 0.1 38 | edges_weights = {} 39 | 40 | # Define the Graph 41 | 42 | G = nx.fast_gnp_random_graph(nb_node, Pb_edge) 43 | 44 | # Instantiate the diffusion Process 45 | 46 | D = Diffusion(G) 47 | 48 | # define the weights on the edges 49 | 50 | for edges in G.edges(): 51 | edges_weights[edges] = weights 52 | 53 | # Set the weights on the edge of the graph 54 | 55 | D.set_weight(edges_weights) 56 | 57 | # Run the diffusion Process 58 | 59 | D.run_steps(1000, 1) 60 | 61 | # Stats 62 | 63 | print D.get_number_infected() 64 | time_stamps = D.get_time_stamps() 65 | print time_stamps 66 | 67 | 68 | time_stamps_list = [vals for key,vals in time_stamps.iteritems()] 69 | 70 | nx.draw(G, pos=nx.spring_layout(G), node_size=20, with_labels=False) 71 | 72 | # the histogram of the data with histtype='step' 73 | 74 | P.figure() 75 | (n, bins, patches) = P.hist(time_stamps_list, 50, normed=1, 76 | histtype='bar', rwidth=0.8) 77 | 78 | # l = P.plot(bins,'k--', linewidth=1.5) 79 | 80 | P.show() 81 | 82 | 83 | if __name__ == '__main__': 84 | main() 85 | -------------------------------------------------------------------------------- /examples/run_dygraph_w_PGG.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | _author__ = """\n""".join(['Vincent Gauthier']) 28 | 29 | 30 | def main(): 31 | from complex_systems.dygraph import DyGraph 32 | from complex_systems.pgg import PublicGoodGames 33 | from complex_systems.quasi_unit_disk_graph import gen_quasi_unit_disk_weight 34 | from complex_systems.quasi_unit_disk_graph import remove_edges_from_graph 35 | import networkx as nx 36 | import pylab as plt 37 | 38 | outer_radius = 75 39 | inner_radius = 40 40 | alpha_quasi_unit_disk = 0.9 41 | synergy = 8 42 | coop_ratio = 0.5 43 | noise_var = 1 44 | nb_node = 400 45 | time_step = 5.0 46 | G = DyGraph(time_stop=2000.0, time_step=time_step) 47 | G.generate_mobility_levy_walk( 48 | alpha=0.9, 49 | beta=0.9, 50 | size_max=1000, 51 | f_min=10, 52 | f_max=1000, 53 | s_min=5, 54 | s_max=1000.0, 55 | b_c=2, 56 | radius=200.0, 57 | nb_node=nb_node, 58 | ) 59 | first_run = True 60 | resultats = [] 61 | for g in G: 62 | g = gen_quasi_unit_disk_weight(G=g, outer_radius=outer_radius, 63 | inner_radius=inner_radius, alpha=alpha_quasi_unit_disk) 64 | g = remove_edges_from_graph(g) 65 | if first_run == True: 66 | PGG = PublicGoodGames(G=g, synergy=synergy, 67 | cooperator_ratio=coop_ratio, 68 | noise_var=noise_var) 69 | nb_coop = PGG.run_game(time_step) 70 | resultats.append(nb_coop) 71 | strategies = PGG.get_strategies() 72 | first_run = False 73 | else: 74 | PGG = PublicGoodGames(G=g, synergy=synergy, 75 | cooperator_ratio=coop_ratio, 76 | noise_var=noise_var) 77 | PGG.set_strategies(strategies) 78 | nb_coop = PGG.run_game(time_step) 79 | strategies = PGG.get_strategies() 80 | resultats.append(nb_coop) 81 | plt.figure() 82 | plt.plot(resultats, '-o') 83 | plt.show() 84 | 85 | if __name__ == '__main__': 86 | main() 87 | -------------------------------------------------------------------------------- /examples/run_dygraph_w_plot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | _author__ = """\n""".join(['Vincent Gauthier']) 28 | 29 | 30 | def main(): 31 | from complex_systems.dygraph import DyGraph 32 | import networkx as nx 33 | import pylab as plt 34 | 35 | G = DyGraph(time_stop=400.0, time_step=5.0) 36 | G.generate_mobility_levy_walk( 37 | alpha=0.9, 38 | beta=0.9, 39 | size_max=1000, 40 | f_min=1, 41 | f_max=100, 42 | s_min=1, 43 | s_max=100.0, 44 | b_c=2, 45 | radius=200.0, 46 | nb_node=2, 47 | velocity=float(1.0/60), 48 | ) 49 | time_step = 10.0 50 | graph = G.get_graph(time_step) 51 | i = 1 52 | for g in G: 53 | print "print graph of the slice ", g.graph['slice_time'] 54 | pos = nx.get_node_attributes(g, 'pos') 55 | plt.figure() 56 | plt.title('Time = ' + str(g.graph['slice_time']*5.0) + ' seconds') 57 | limits=plt.axis('off') 58 | plt.draw() 59 | nx.draw(g, pos=pos,with_labels=False, node_size=20) 60 | filename = 'graph_' + str("%04d" % i) + '.jpg' 61 | plt.savefig(filename) 62 | i += 1 63 | 64 | 65 | if __name__ == '__main__': 66 | main() 67 | -------------------------------------------------------------------------------- /examples/run_example_levy_walk_w_plots.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # ------------------------------------------------------------------------------- 4 | # Copyright (c) 2012 Vincent Gauthier. 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining 7 | # a copy of this software and associated documentation files (the 8 | # "Software"), to deal in the Software without restriction, including 9 | # without limitation the rights to use, copy, modify, merge, publish, 10 | # distribute, sublicense, and/or sell copies of the Software, and to 11 | # permit persons to whom the Software is furnished to do so, subject to 12 | # the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included 15 | # in all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------- 25 | 26 | __author__ = """\n""".join(['Vincent Gauthier ']) 27 | 28 | __all__ = ['test_levy_walk_w_plots'] 29 | 30 | 31 | def run_example_levy_walk_w_plots(): 32 | import numpy as N 33 | import pylab as plt 34 | from scikits.statsmodels.tools.tools import ECDF 35 | 36 | from complex_systems.mobility.levy_walk import levy_walk 37 | from complex_systems.mobility.distance import distance 38 | 39 | alpha = 0.9 40 | beta = 0.9 41 | f_min = 1.0 42 | f_max = 100.0 43 | s_min = 1.0 44 | s_max = 100.0 45 | velocity = 5.0 46 | 47 | (un_sampled, A, B, sampled) = levy_walk( 48 | alpha=alpha, 49 | beta=beta, 50 | sample_length=10.0, 51 | size_max=10000, 52 | velocity=velocity, 53 | f_min=f_min, 54 | f_max=f_max, 55 | s_min=s_min, 56 | s_max=s_max, 57 | duration=1000, 58 | b_c=2, 59 | ) 60 | 61 | (X, Y, T) = zip(*un_sampled) 62 | (X_sampled, Y_sampled, T_sampled) = zip(*sampled) 63 | print T_sampled, X_sampled, Y_sampled 64 | 65 | plt.figure() 66 | plt.plot(X_sampled, Y_sampled, 'ro-') 67 | plt.plot(X, Y, 'o-') 68 | 69 | ecdf = ECDF(A) 70 | x = N.linspace(min(A), max(A)) 71 | y = 1 - ecdf(x) 72 | 73 | ax1 = plt.subplot(121) 74 | plt.loglog(x, y, 'r', linewidth=2.0) 75 | plt.xlim(1, max(A)) 76 | plt.ylim(min(y), max(y)) 77 | plt.grid(True, which='both') 78 | plt.xlabel('Distance [m]') 79 | plt.ylabel('P(X > x)') 80 | 81 | ecdf = ECDF(B) 82 | x = N.linspace(min(B), max(B)) 83 | y = 1 - ecdf(x) 84 | ax2 = plt.subplot(122, sharey=ax1) 85 | plt.setp( ax2.get_yticklabels(), visible=False) 86 | plt.loglog(x, y, 'r', linewidth=2.0) 87 | plt.xlim(1, max(B)) 88 | plt.ylim(min(y), max(y)) 89 | plt.grid(True, which='both') 90 | plt.xlabel('Pause Time [mins]') 91 | plt.savefig('levywalk.pdf') 92 | plt.savefig('levywalk.eps') 93 | #plt.ylabel('P(X > x)') 94 | 95 | D = distance(X, Y) 96 | D_sampled = distance(X_sampled, Y_sampled) 97 | Dcumsum = N.cumsum(D) 98 | Dcumsum_sampled = N.cumsum(D_sampled) 99 | 100 | plt.figure() 101 | plt.plot(T[0:len(D)], Dcumsum, 'o-r', linewidth=2.0) 102 | plt.plot(T_sampled[0:len(Dcumsum_sampled)], Dcumsum_sampled, 'o-', 103 | linewidth=2.0) 104 | plt.ylabel('Cumulative distance traveled by the random walker (meters)' 105 | ) 106 | plt.xlabel('Time (mins)') 107 | plt.show() 108 | 109 | 110 | if __name__ == '__main__': 111 | run_example_levy_walk_w_plots() 112 | -------------------------------------------------------------------------------- /examples/run_kernel_density_geo.py: -------------------------------------------------------------------------------- 1 | 2 | def main(): 3 | from complex_systems.spatial.kernel_density_geo import kernel_density_geo 4 | import scipy.stats as stats 5 | import pylab as plt 6 | from matplotlib.pyplot import imshow 7 | import numpy as np 8 | 9 | X_data = stats.norm.rvs(loc=3,scale=1,size=(2000,1)) 10 | Y_data = stats.norm.rvs(loc=2,scale=1,size=(2000,1)) 11 | 12 | coor,Z = kernel_density_geo(X_data, Y_data,bin_size_x=100, bin_size_y=100) 13 | plt.figure() 14 | plt.imshow(Z, interpolation="nearest") 15 | plt.show() 16 | 17 | if __name__ == '__main__': 18 | main() -------------------------------------------------------------------------------- /examples/run_pgg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # ------------------------------------------------------------------------------- 4 | # Copyright (c) 2012 Vincent Gauthier. 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining 7 | # a copy of this software and associated documentation files (the 8 | # "Software"), to deal in the Software without restriction, including 9 | # without limitation the rights to use, copy, modify, merge, publish, 10 | # distribute, sublicense, and/or sell copies of the Software, and to 11 | # permit persons to whom the Software is furnished to do so, subject to 12 | # the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included 15 | # in all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------- 25 | 26 | __author__ = """\n""".join(['Vincent Gauthier']) 27 | 28 | 29 | 30 | def main(): 31 | import networkx as nx 32 | from complex_systems.pgg import PublicGoodGames 33 | import pylab as plt 34 | import numpy as np 35 | 36 | nb_node = 1000 37 | edge_prob = 10.0/nb_node 38 | coop_ratio = 0.5 39 | synergy = 8 40 | nb_round = 100 41 | nb_game_per_round = 10 42 | nb_def = [] 43 | nb_coop = [] 44 | 45 | # Generate a Random Graph 46 | G = nx.fast_gnp_random_graph(nb_node, edge_prob) 47 | # initialize the game 48 | PGG = PublicGoodGames(G=G, synergy=synergy,nb_simulation_step=nb_game_per_round, cooperator_ratio=coop_ratio) 49 | for i in range(nb_round): 50 | PGG.run_game() 51 | nb_def.append(PGG.defector_counter()) 52 | nb_coop.append(PGG.cooperator_counter()) 53 | #print nb_coop, nb_def 54 | plt.figure() 55 | plt.plot(nb_def,'b-*') 56 | plt.plot(nb_coop,'r-*') 57 | plt.figure() 58 | print np.mean([val for key, val in G.degree().iteritems()]) 59 | nx.draw_networkx(G, node_size=20, with_labels = False) 60 | plt.show() 61 | 62 | if __name__ == '__main__': 63 | main() -------------------------------------------------------------------------------- /examples/run_pgg_diffusion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # ------------------------------------------------------------------------------- 4 | # Copyright (c) 2012 Vincent Gauthier. 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining 7 | # a copy of this software and associated documentation files (the 8 | # "Software"), to deal in the Software without restriction, including 9 | # without limitation the rights to use, copy, modify, merge, publish, 10 | # distribute, sublicense, and/or sell copies of the Software, and to 11 | # permit persons to whom the Software is furnished to do so, subject to 12 | # the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included 15 | # in all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------- 25 | 26 | __author__ = """\n""".join(['Vincent Gauthier']) 27 | 28 | 29 | 30 | def main(): 31 | import networkx as nx 32 | from complex_systems.pgg_diffusion import PGG_diffusion 33 | from complex_systems.quasi_unit_disk_graph import gen_quasi_unit_disk_weight 34 | from complex_systems.quasi_unit_disk_graph import remove_edges_from_graph 35 | import pylab as plt 36 | import numpy as np 37 | 38 | nb_node = 400 39 | xmax = 1000 40 | ymax = 1000 41 | coop_ratio = 0.5 42 | synergy = 2 43 | nb_round = 100 44 | nb_game_per_round = 1 45 | nb_def = [] 46 | nb_coop = [] 47 | inner_radius = 45 48 | outer_radius = 75 49 | alpha = 0.3 50 | nb_seeder = 40 51 | 52 | # Generate a Random Graph 53 | p = dict((i,(np.random.uniform(low=0.0, high=xmax),np.random.uniform(low=0.0, high=ymax))) for i in range(nb_node)) 54 | G = nx.random_geometric_graph(nb_node,outer_radius,pos=p) 55 | G = gen_quasi_unit_disk_weight(G=G, outer_radius=outer_radius, inner_radius=inner_radius, alpha=alpha) 56 | G = remove_edges_from_graph(G) 57 | # initialize the game 58 | PGG = PGG_diffusion(G=G, synergy=synergy,nb_simulation_step=nb_game_per_round, nb_seeder=nb_seeder, buffer_size = 100, cooperator_ratio=coop_ratio, noise_var=0.0) 59 | for i in range(nb_round): 60 | PGG.run_game() 61 | nb_def.append(PGG.defector_counter()) 62 | nb_coop.append(PGG.cooperator_counter()) 63 | 64 | plt.figure() 65 | plt.plot(nb_def,'b-*') 66 | plt.plot(nb_coop,'r-*') 67 | 68 | plt.figure() 69 | nx.draw_networkx(G, node_size=20, pos=p, with_labels = False) 70 | 71 | time_stamps_dist = PGG.get_distribution_time_stamps() 72 | x = [] 73 | y = [] 74 | for key,val in time_stamps_dist.iteritems(): 75 | x.append(key) 76 | y.append(val) 77 | 78 | plt.figure() 79 | plt.bar(x,y) 80 | plt.show() 81 | 82 | if __name__ == '__main__': 83 | main() -------------------------------------------------------------------------------- /examples/run_pgg_diffusion_2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # ------------------------------------------------------------------------------- 4 | # Copyright (c) 2012 Vincent Gauthier. 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining 7 | # a copy of this software and associated documentation files (the 8 | # "Software"), to deal in the Software without restriction, including 9 | # without limitation the rights to use, copy, modify, merge, publish, 10 | # distribute, sublicense, and/or sell copies of the Software, and to 11 | # permit persons to whom the Software is furnished to do so, subject to 12 | # the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included 15 | # in all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------- 25 | 26 | __author__ = """\n""".join(['Vincent Gauthier']) 27 | 28 | 29 | 30 | def main(parameters): 31 | import networkx as nx 32 | from complex_systems.dygraph import DyGraph 33 | from complex_systems.pgg_diffusion import PGG_diffusion 34 | from complex_systems.quasi_unit_disk_graph import gen_quasi_unit_disk_weight 35 | from complex_systems.quasi_unit_disk_graph import remove_edges_from_graph 36 | import pylab as plt 37 | import numpy as np 38 | 39 | nb_node = 400 40 | xmax = 1000 41 | ymax = 1000 42 | coop_ratio = 0.5 43 | synergy = 9 44 | nb_game_per_round = 1 45 | nb_def = [] 46 | nb_coop = [] 47 | number_of_node = parameters['number_of_node'] 48 | nb_seeder = parameters['number_of_seeder'] 49 | size_of_simulation_area = parameters['size_of_simulation_area'] 50 | buffer_size = parameters['buffer_size'] 51 | outer_radius = parameters['outer_radius'] 52 | inner_radius = parameters['inner_radius'] 53 | alpha_quasi_unit_disk = parameters['alpha_quasi_unit_disk'] 54 | coop_ratio = parameters['initial_cooperator_ratio'] 55 | simulation_length = parameters['simulation_length'] 56 | sampling_interval = parameters['sampling_interval'] 57 | alpha_levy = parameters['alpha_levy'] 58 | #noise_var = parameters['noise_variance'] 59 | noise_var = 0.1 60 | beta = parameters['beta'] 61 | f_min = parameters['f_min'] 62 | f_max = parameters['f_max'] 63 | s_min = parameters['s_min'] 64 | s_max = parameters['s_max'] 65 | velocity = parameters['velocity'] 66 | 67 | 68 | G = DyGraph(time_stop=simulation_length, 69 | time_step=sampling_interval) 70 | G.generate_mobility_levy_walk( 71 | alpha=alpha_levy, 72 | beta=beta, 73 | size_max=xmax, 74 | f_min=f_min, 75 | f_max=f_max, 76 | s_min=s_min, 77 | s_max=s_max, 78 | b_c=2, 79 | radius=outer_radius, 80 | nb_node=nb_node, 81 | velocity=velocity, 82 | ) 83 | 84 | first_run = True 85 | for g in G: 86 | g = gen_quasi_unit_disk_weight(G=g, outer_radius=outer_radius, 87 | inner_radius=inner_radius, alpha=alpha_quasi_unit_disk) 88 | g = remove_edges_from_graph(g) 89 | if first_run == True: 90 | 91 | PGG = PGG_diffusion(G=g, synergy=synergy, 92 | cooperator_ratio=coop_ratio, 93 | noise_var=noise_var, 94 | buffer_size=buffer_size, 95 | nb_seeder=int(nb_seeder)) 96 | 97 | PGG.run_game() 98 | nb_def.append(PGG.defector_counter()) 99 | nb_coop.append(PGG.cooperator_counter()) 100 | strategies = PGG.get_strategies() 101 | time_stamps = PGG.get_time_stamps() 102 | states = PGG.get_states() 103 | #sent_update = PGG.get_sent_update() 104 | seeder = PGG.get_seeder() 105 | #print time_stamps[0] 106 | #print sent_update 107 | #print strategies 108 | #print states 109 | first_run = False 110 | else: 111 | PGG = PGG_diffusion(G=g, synergy=synergy, 112 | cooperator_ratio=coop_ratio, 113 | buffer_size=buffer_size, 114 | noise_var=noise_var) 115 | PGG.set_strategies(strategies) 116 | PGG.set_time_stamps(time_stamps) 117 | PGG.set_nodes_states(states) 118 | #PGG.set_sent_update(sent_update) 119 | PGG.set_seeder(seeder) 120 | res = PGG.run_game() 121 | nb_def.append(PGG.defector_counter()) 122 | nb_coop.append(PGG.cooperator_counter()) 123 | strategies = PGG.get_strategies() 124 | time_stamps = PGG.get_time_stamps() 125 | states = PGG.get_states() 126 | #print states 127 | #print strategies 128 | #print time_stamps[0] 129 | #sent_update = PGG.get_sent_update() 130 | #seeder = PGG.get_seeder() 131 | #print seeder 132 | print synergy, res, np.mean(G.avg_degree()) 133 | plt.figure() 134 | plt.plot(nb_def,'b-*') 135 | plt.plot(nb_coop,'r-*') 136 | 137 | #plt.figure() 138 | #print np.mean([val for key, val in G.degree().iteritems()]) 139 | #nx.draw_networkx(G, node_size=20, pos=p, with_labels = False) 140 | 141 | time_stamps_dist = PGG.get_distribution_time_stamps() 142 | x = [] 143 | y = [] 144 | for key,val in time_stamps_dist.iteritems(): 145 | x.append(key) 146 | y.append(val) 147 | 148 | plt.figure() 149 | plt.bar(x,y) 150 | plt.show() 151 | 152 | if __name__ == '__main__': 153 | import sys 154 | from sumatra.parameters import build_parameters 155 | parameter_file = sys.argv[1] 156 | parameters = build_parameters(parameter_file) 157 | main(parameters) -------------------------------------------------------------------------------- /examples/run_quasi_unit_disk_graph.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------- 2 | # Copyright (c) 2012 Vincent Gauthier. 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining 5 | # a copy of this software and associated documentation files (the 6 | # "Software"), to deal in the Software without restriction, including 7 | # without limitation the rights to use, copy, modify, merge, publish, 8 | # distribute, sublicense, and/or sell copies of the Software, and to 9 | # permit persons to whom the Software is furnished to do so, subject to 10 | # the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | # ------------------------------------------------------------------------------- 23 | __author__ = """\n""".join(['Vincent Gauthier']) 24 | 25 | import networkx as nx 26 | from complex_systems.quasi_unit_disk_graph import gen_quasi_unit_disk_weight 27 | 28 | def main(): 29 | G = nx.Graph() 30 | G.add_node(1, pos=(1,1)) 31 | G.add_node(2, pos=(1,2)) 32 | G.add_node(3, pos=(1,3)) 33 | G.add_edge(1,2) 34 | G.add_edge(1,3) 35 | G.add_edge(2,3) 36 | G1 = gen_quasi_unit_disk_weight(G, inner_radius=1, outer_radius=3, alpha=1) 37 | print [d['weight'] for u,v,d in G1.edges(data=True)] 38 | 39 | if __name__ == '__main__': 40 | main() -------------------------------------------------------------------------------- /examples/run_quasi_unit_disk_graph_with_diffusion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | __author__ = """\n""".join(['Vincent Gauthier']) 28 | 29 | 30 | def main(): 31 | from complex_systems.dygraph import DyGraph 32 | from complex_systems.quasi_unit_disk_graph import gen_quasi_unit_disk_weight 33 | from complex_systems.diffusion import Diffusion 34 | import networkx as nx 35 | import pylab as plt 36 | 37 | # Variables 38 | 39 | size_of_simulation_area = 1000.0 40 | inner_radius = 10 41 | outer_radius = 50 42 | number_of_node = 100 43 | simulation_length = 1000.0 44 | sample_interval = 10.0 45 | alpha = 0.8 46 | 47 | # Generate a Graph with position 48 | 49 | G = DyGraph(time_stop=simulation_length, time_step=sample_interval) 50 | G.generate_mobility_levy_walk( 51 | alpha=0.9, 52 | beta=0.9, 53 | size_max=size_of_simulation_area, 54 | f_min=10, 55 | f_max=1000, 56 | s_min=5, 57 | s_max=1000.0, 58 | b_c=2, 59 | radius=outer_radius, 60 | nb_node=number_of_node, 61 | ) 62 | 63 | G.generate_weights(inner_radius=inner_radius, 64 | outer_radius=outer_radius, alpha=alpha) 65 | 66 | slice_time_list = G.get_slice_time() 67 | i = 1 68 | for t in slice_time_list: 69 | if t == 0.0: 70 | [states, time_stamps, strategies, payoffs] = G.diffusion(t, 71 | nb_steps=10, synergy=8.0, 72 | cooperator_ratio=0.5) 73 | else: 74 | Gslice = G.get_graph(t) 75 | pos = nx.get_node_attributes(Gslice, 'pos') 76 | 77 | [states, time_stamps, strategies, payoffs] = G.diffusion( 78 | t, 79 | nb_steps=10, 80 | synergy=8.0, 81 | states=states, 82 | time_stamps=time_stamps, 83 | strategies=strategies, 84 | payoffs=payoffs, 85 | ) 86 | nbcoops = [strategy for strategy in strategies if strategy == 'C'].count() 87 | 88 | 89 | Gslice = G.get_graph(t) 90 | 91 | pos = nx.get_node_attributes(Gslice, 'pos') 92 | nodelist_infected = [key for (key, val) in states.iteritems() 93 | if val == 'I'] 94 | nodelist_not_infected = [key for (key, val) in 95 | states.iteritems() if val == 'S'] 96 | 97 | plt.figure() 98 | nx.draw_networkx(Gslice, nodelist=nodelist_infected, pos=pos, with_labels=False, node_size=20) 99 | nx.draw_networkx(Gslice, nodelist=nodelist_not_infected, pos=pos, with_labels=False, node_size=20, node_color='g') 100 | filename = 'diffusion_' + str("%04d" % i) + '.jpg' 101 | plt.savefig(filename) 102 | 103 | i += 1 104 | 105 | time_stamps_list = [vals for (key, vals) in time_stamps.iteritems()] 106 | 107 | plt.figure() 108 | (n, bins, patches) = plt.hist(time_stamps_list, 50, normed=1, 109 | histtype='bar', rwidth=0.8) 110 | plt.show() 111 | 112 | 113 | if __name__ == '__main__': 114 | main() 115 | -------------------------------------------------------------------------------- /examples/run_simple_example_levy_walk.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | def main(): 28 | from complex_systems.mobility.levy_flight import levy_flight 29 | 30 | for i in range(100): 31 | (un_s, A, B, sampled) = levy_flight( 32 | alpha=0.66, 33 | beta=0.99, 34 | sample_length=50.0, 35 | size_max=10000, 36 | velocity=0.1, 37 | f_min=8, 38 | f_max=10000, 39 | s_min=0.8, 40 | s_max=50, 41 | duration=1000, 42 | b_c=1, 43 | ) 44 | (X, Y, T) = zip(*sampled) 45 | print len(sampled), T 46 | 47 | 48 | if __name__ == '__main__': 49 | main() -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [build_sphinx] 2 | source-dir = doc/ 3 | build-dir = doc/build 4 | all_files = 1 5 | 6 | [upload_sphinx] 7 | upload-dir = doc/build/html 8 | 9 | [metadata] 10 | description-file = README.rst -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | import os 3 | 4 | version = '0.3.2' 5 | README = os.path.join(os.path.dirname(__file__), 'README.txt') 6 | long_description = open(README).read() + 'nn' 7 | 8 | setup( 9 | name='ComplexSystems', 10 | packages=find_packages(), 11 | version=version, 12 | description='Toolbox for Complex Sytems including : Public Good Game, Human Based Mobility Models', 13 | long_description=long_description, 14 | author='Vincent Gauthier', 15 | author_email='vgauthier@luxbulb.org', 16 | url='http://bitbucket.org/vgauthier/complex-systems/', 17 | keywords=["complex systems", "Levy flight", "human mobility"], 18 | requires=['numpy','pylab'], 19 | license='MIT', 20 | tests_require=['nose'], 21 | test_suite = 'nose.collector', 22 | platforms=['any'], 23 | classifiers=[ 24 | 'License :: OSI Approved :: MIT License', 25 | 'Programming Language :: Python', 26 | 'Programming Language :: Python :: 2.7', 27 | 'Operating System :: OS Independent', 28 | 'Topic :: Scientific/Engineering :: Mathematics', 29 | 'Development Status :: 4 - Beta', 30 | 'Intended Audience :: Science/Research' 31 | ], 32 | install_requires=[ 33 | "numpy >= 1.4.0" 34 | ] 35 | ) 36 | -------------------------------------------------------------------------------- /simulations/percolation-mobility-quasiunitdisk-Model/Data/datafile_test.dat: -------------------------------------------------------------------------------- 1 | "1","0.30800000000000011","0.67439999999999989" 2 | "2","0.32400000000000001","0.70960000000000012" 3 | "3","0.33200000000000002","0.80800000000000005" 4 | "4","0.314","0.91199999999999992" 5 | "5","0.39600000000000002","0.87520000000000009" 6 | "6","0.374","0.77120000000000011" 7 | "7","0.43200000000000005","0.74960000000000004" 8 | "8","0.43200000000000005","0.91279999999999983" 9 | "9","0.35800000000000004","0.85600000000000009" 10 | -------------------------------------------------------------------------------- /simulations/percolation-mobility-quasiunitdisk-Model/defaults.param: -------------------------------------------------------------------------------- 1 | # Simulation Model Parameters 2 | size_of_simulation_area = 1000.0 3 | number_of_node = 50 4 | simulation_length = 100.0 5 | sampling_interval = 10.0 6 | 7 | # PGG Parameters 8 | initial_cooperator_ratio = 0.5 9 | noise_variance = 1 10 | 11 | # Parameters for the main simulation loop 12 | synergy_step = 1 13 | synergy_min = 1 14 | synergy_max = 10 15 | ## Nb Simulation Batch 16 | nb_batch = 10 17 | ## File Label 18 | label = 'test' 19 | 20 | # Parameters Levy Walks 21 | alpha_levy = 0.9 22 | beta = 0.9 23 | f_min = 1.0 24 | f_max = 100.0 25 | s_min = 1.0 26 | s_max = 100.0 27 | velocity = 8.0 28 | 29 | # Parameters Quasi Unit Disk Model 30 | alpha_quasi_unit_disk = 0.3 31 | inner_radius = 40.0 32 | outer_radius = 75.0 33 | 34 | # Data Output 35 | filename = 'Data/datafile' 36 | 37 | -------------------------------------------------------------------------------- /simulations/percolation-mobility-quasiunitdisk-Model/run_pgg_2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | __author__ = """\n""".join(['Vincent Gauthier']) 28 | 29 | def parameters_sweep(parameters): 30 | import networkx as nx 31 | from complex_systems.pgg import PublicGoodGames 32 | import numpy as np 33 | import csv 34 | import itertools 35 | from multiprocessing import Pool 36 | 37 | ####### Init the variables ####### 38 | synergy_step = parameters['synergy_step'] 39 | synergy_max = parameters['synergy_max'] 40 | synergy_min = parameters['synergy_min'] 41 | filename_txt = parameters['filename'] + '_%s.dat' \ 42 | % parameters['label'] 43 | filename_jpg = parameters['filename'] + '_%s.jpg' \ 44 | % parameters['label'] 45 | nb_batch = parameters['nb_batch'] 46 | synergy_range = np.arange(synergy_min, synergy_max, synergy_step) 47 | job_id_list = [] 48 | resultats_raw = dict() 49 | X = [] 50 | Y = [] 51 | Z = [] 52 | 53 | # Init Dictionary 54 | for entry in synergy_range: 55 | resultats_raw[entry] = [] 56 | 57 | ####### Init the Multiprocessing Pool ####### 58 | pool = Pool() 59 | 60 | ####### Start the Batch of simualtion ####### 61 | for synergy in synergy_range: 62 | # Run the Game 63 | jobid = [pool.apply_async(run_simu, (parameters, synergy,)) for i in range(nb_batch)] 64 | job_id_list.append(jobid) 65 | print 'Job list submited to the scheduler' 66 | 67 | ####### Gather the simulations results ####### 68 | for batch in job_id_list: 69 | for job in batch: 70 | resultat = job.get() 71 | map_id, val1, val2 = resultat 72 | resultats_raw[map_id].append((val1,val2)) 73 | print 'Finish the batch of simulation for synergy =', map_id 74 | items = resultats_raw.items() 75 | items.sort() 76 | ####### Reduce the results ####### 77 | for key,val in items: 78 | x, y, z = reduceR(key, val) 79 | X.append(x) 80 | Y.append(y) 81 | Z.append(z) 82 | 83 | ####### Save the Result in csv file ####### 84 | with open(filename_txt, 'wb') as f: 85 | writer = csv.writer(f, delimiter=',', quoting=csv.QUOTE_ALL) 86 | for row_id in xrange(len(X)): 87 | row = [X[row_id], Y[row_id], Z[row_id]] 88 | writer.writerow(row) 89 | 90 | def reduceR(key, val): 91 | import numpy as np 92 | val1, val2 = zip(*val) 93 | print 'Reducer:', val1 94 | return key, np.mean(val1), np.mean(val2) 95 | 96 | def run_simu(parameters, synergy): 97 | import numpy as np 98 | import networkx as nx 99 | from complex_systems.dygraph import DyGraph 100 | from complex_systems.pgg import PublicGoodGames 101 | from complex_systems.quasi_unit_disk_graph import gen_quasi_unit_disk_weight 102 | from complex_systems.quasi_unit_disk_graph import remove_edges_from_graph 103 | 104 | 105 | number_of_node = parameters['number_of_node'] 106 | size_of_simulation_area = parameters['size_of_simulation_area'] 107 | outer_radius = parameters['outer_radius'] 108 | inner_radius = parameters['inner_radius'] 109 | alpha_quasi_unit_disk = parameters['alpha_quasi_unit_disk'] 110 | coop_ratio = parameters['initial_cooperator_ratio'] 111 | simulation_length = parameters['simulation_length'] 112 | sampling_interval = parameters['sampling_interval'] 113 | alpha_levy = parameters['alpha_levy'] 114 | noise_var = parameters['noise_variance'] 115 | beta = parameters['beta'] 116 | f_min = parameters['f_min'] 117 | f_max = parameters['f_max'] 118 | s_min = parameters['s_min'] 119 | s_max = parameters['s_max'] 120 | velocity = parameters['velocity'] 121 | 122 | G = DyGraph(time_stop=simulation_length, time_step=sampling_interval) 123 | G.generate_mobility_levy_walk( 124 | alpha=alpha_levy, 125 | beta=beta, 126 | size_max=size_of_simulation_area, 127 | f_min=f_min, 128 | f_max=f_max, 129 | s_min=s_min, 130 | s_max=s_max, 131 | b_c=2, 132 | radius=outer_radius, 133 | nb_node=number_of_node, 134 | velocity=velocity, 135 | ) 136 | 137 | first_run = True 138 | resultats = [] 139 | for g in G: 140 | g = gen_quasi_unit_disk_weight(G=g, outer_radius=outer_radius, 141 | inner_radius=inner_radius, alpha=alpha_quasi_unit_disk) 142 | g = remove_edges_from_graph(g) 143 | if first_run == True: 144 | PGG = PublicGoodGames(G=g, synergy=synergy, 145 | cooperator_ratio=coop_ratio, 146 | noise_var=noise_var) 147 | nb_coop = PGG.run_game(sampling_interval) 148 | resultats.append(nb_coop) 149 | strategies = PGG.get_strategies() 150 | first_run = False 151 | else: 152 | PGG = PublicGoodGames(G=g, synergy=synergy, 153 | cooperator_ratio=coop_ratio, 154 | noise_var=noise_var) 155 | PGG.set_strategies(strategies) 156 | nb_coop = PGG.run_game(sampling_interval) 157 | strategies = PGG.get_strategies() 158 | resultats.append(nb_coop) 159 | 160 | return (synergy, nb_coop, np.mean(G.avg_degree())) 161 | 162 | if __name__ == '__main__': 163 | import sys 164 | from sumatra.parameters import build_parameters 165 | 166 | sys.path.append('../..') 167 | 168 | parameter_file = sys.argv[1] 169 | parameters = build_parameters(parameter_file) 170 | parameters_sweep(parameters) 171 | -------------------------------------------------------------------------------- /tests/test_distance.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------- 2 | # Copyright (c) 2012 Vincent Gauthier. 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining 5 | # a copy of this software and associated documentation files (the 6 | # "Software"), to deal in the Software without restriction, including 7 | # without limitation the rights to use, copy, modify, merge, publish, 8 | # distribute, sublicense, and/or sell copies of the Software, and to 9 | # permit persons to whom the Software is furnished to do so, subject to 10 | # the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | #------------------------------------------------------------------------------- 23 | 24 | __author__ = """\n""".join(['Vincent Gauthier ']) 25 | 26 | __all__ = ['distance'] 27 | 28 | 29 | from complex_systems.mobility.distance import distance 30 | import unittest 31 | 32 | class test_distance(unittest.TestCase): 33 | 34 | def setUp(self): 35 | pass 36 | 37 | def test_distance(self): 38 | X = [0, 0, 0] 39 | Y = [1, 2, 3] 40 | result = [1.0, 1.0] 41 | self.assertEqual(result, distance(X, Y)) 42 | 43 | if __name__ == '__main__': 44 | unittest.main() 45 | -------------------------------------------------------------------------------- /tests/test_dygraph.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | from complex_systems.dygraph import DyGraph 28 | import unittest 29 | 30 | 31 | class test_DyGraph(unittest.TestCase): 32 | 33 | def setUp(self): 34 | self.dygraph = DyGraph() 35 | 36 | def test_add_graph(self): 37 | import networkx as nx 38 | self.dygraph = DyGraph() 39 | timeStep = 10.0 40 | G = nx.Graph() 41 | G.add_node(1) 42 | G.add_node(2) 43 | self.dygraph.add_graph(G, timeStep) 44 | self.assertDictEqual(G.node, 45 | self.dygraph._slices[timeStep]['graph' 46 | ].node) 47 | self.assertEqual(timeStep, 48 | self.dygraph._slices[timeStep]['graph' 49 | ].graph['slice_time']) 50 | 51 | def test_dygraph(self): 52 | import numpy as N 53 | self.dygraph = DyGraph(time_stop=100.0, time_step=10.0) 54 | self.assertEqual(N.ceil(100.0 / 10.0), 55 | len(self.dygraph._slices)) 56 | 57 | def test_dygraph_with_timeline(self): 58 | import numpy as N 59 | self.dygraph = DyGraph(timeline=N.arange(0,100,10)) 60 | self.assertEqual(N.ceil(100.0 / 10.0), 61 | len(self.dygraph._slices)) 62 | 63 | def test_iter(self): 64 | import networkx as nx 65 | self.dygraph = DyGraph() 66 | self.dygraph.add_graph(nx.Graph(),10.0) 67 | self.dygraph.add_graph(nx.Graph(),20.0) 68 | self.dygraph.add_graph(nx.Graph(),30.0) 69 | for g in self.dygraph: 70 | print g.graph['slice_time'] 71 | self.assertEqual([10.0, 20.0, 30], self.dygraph._slice_time) 72 | 73 | def test_gen_mobility(self): 74 | import numpy as N 75 | self.dygraph = DyGraph(time_stop=100.0, time_step=10.0) 76 | self.dygraph.generate_mobility_levy_walk( 77 | alpha=0.9, 78 | beta=0.9, 79 | size_max=100, 80 | f_min=10, 81 | f_max=100, 82 | s_min=1, 83 | s_max=100, 84 | b_c=2, 85 | radius=20.0, 86 | nb_node=10, 87 | ) 88 | self.assertEqual(N.ceil(100.0 / 10.0), 89 | len(self.dygraph._slices)) 90 | 91 | if __name__ == '__main__': 92 | unittest.main() -------------------------------------------------------------------------------- /tests/test_levy_walk.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------- 2 | # Copyright (c) 2012 Vincent Gauthier. 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining 5 | # a copy of this software and associated documentation files (the 6 | # "Software"), to deal in the Software without restriction, including 7 | # without limitation the rights to use, copy, modify, merge, publish, 8 | # distribute, sublicense, and/or sell copies of the Software, and to 9 | # permit persons to whom the Software is furnished to do so, subject to 10 | # the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | # ------------------------------------------------------------------------------- 23 | 24 | __author__ = """\n""".join(['Vincent Gauthier ']) 25 | 26 | __all__ = ['test_levy_walk'] 27 | 28 | from complex_systems.mobility.levy_walk import levy_walk 29 | import unittest 30 | import logging 31 | import sys 32 | 33 | 34 | class test_levy_walk(unittest.TestCase): 35 | 36 | def setUp(self): 37 | pass 38 | 39 | def test_levy_walk(self): 40 | (un_sample, A, B, sample) = levy_walk( 41 | alpha=0.66, 42 | beta=0.99, 43 | sample_length=10, 44 | size_max=83000, 45 | velocity=1.0, 46 | f_min=8, 47 | f_max=83000, 48 | s_min=0.8, 49 | s_max=430, 50 | duration=1000, 51 | b_c=2, 52 | ) 53 | 54 | (un_sample, A, B, sample) = levy_walk( 55 | alpha=0.66, 56 | beta=0.99, 57 | sample_length=10, 58 | size_max=83000, 59 | velocity=1.0, 60 | f_min=8, 61 | f_max=83000, 62 | s_min=0.8, 63 | s_max=430, 64 | duration=1000, 65 | b_c=1, 66 | ) 67 | 68 | def test_levy_walk_bad_parameter_alpha(self): 69 | self.assertRaises( 70 | ValueError, 71 | levy_walk, 72 | alpha=-1, 73 | beta=0.99, 74 | sample_length=1, 75 | size_max=83000, 76 | velocity=1.0, 77 | f_min=8, 78 | f_max=83000, 79 | s_min=0.8, 80 | s_max=430, 81 | duration=500, 82 | b_c=2, 83 | ) 84 | 85 | self.assertRaises( 86 | ValueError, 87 | levy_walk, 88 | alpha=3, 89 | beta=0.99, 90 | sample_length=1, 91 | size_max=83000, 92 | velocity=1.0, 93 | f_min=8, 94 | f_max=83000, 95 | s_min=0.8, 96 | s_max=430, 97 | duration=500, 98 | b_c=2, 99 | ) 100 | 101 | def test_levy_walk_bad_parameter_beta(self): 102 | self.assertRaises( 103 | ValueError, 104 | levy_walk, 105 | alpha=1, 106 | beta=-1, 107 | sample_length=1, 108 | size_max=83000, 109 | velocity=1.0, 110 | f_min=8, 111 | f_max=83000, 112 | s_min=0.8, 113 | s_max=430, 114 | duration=500, 115 | b_c=2, 116 | ) 117 | 118 | self.assertRaises( 119 | ValueError, 120 | levy_walk, 121 | alpha=1, 122 | beta=3, 123 | sample_length=1, 124 | size_max=83000, 125 | velocity=1.0, 126 | f_min=8, 127 | f_max=83000, 128 | s_min=0.8, 129 | s_max=430, 130 | duration=500, 131 | b_c=2, 132 | ) 133 | 134 | def test_levy_walk_return_sample_length(self): 135 | import numpy as N 136 | duration = 1000.0 137 | sample_length = 10.0 138 | test_len = 10 139 | for i in range(test_len): 140 | (un_sample, A, B, sample) = levy_walk( 141 | alpha=0.66, 142 | beta=0.99, 143 | sample_length=sample_length, 144 | size_max=83000, 145 | velocity=1.0, 146 | f_min=8, 147 | f_max=83000, 148 | s_min=0.8, 149 | s_max=430, 150 | duration=duration, 151 | b_c=2, 152 | ) 153 | (X,Y,T) = zip(*sample) 154 | print 'NB SAMPLE', int(N.ceil(duration/sample_length)), len(set(T)) 155 | self.assertEqual(N.ceil(duration/sample_length), len(list(set(T)))) 156 | 157 | 158 | 159 | if __name__ == '__main__': 160 | unittest.main() 161 | -------------------------------------------------------------------------------- /tests/test_quasi_unit_disk_graph.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ------------------------------------------------------------------------------- 5 | # Copyright (c) 2012 Vincent Gauthier. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | # ------------------------------------------------------------------------------- 26 | 27 | from complex_systems.quasi_unit_disk_graph import gen_quasi_unit_disk_weight 28 | import unittest 29 | 30 | 31 | class test_QuasiUnitDiskGraph(unittest.TestCase): 32 | 33 | def setUp(self): 34 | import networkx as nx 35 | 36 | self.G = nx.Graph() 37 | self.G.add_node(1, pos=(1, 1)) 38 | self.G.add_node(2, pos=(1, 2)) 39 | self.G.add_node(3, pos=(1, 3)) 40 | self.G.add_edge(1, 2) 41 | self.G.add_edge(1, 3) 42 | self.G.add_edge(2, 3) 43 | 44 | def test_gen_weight(self): 45 | G1 = gen_quasi_unit_disk_weight(self.G, inner_radius=1, 46 | outer_radius=3, alpha=1) 47 | val = [d['weight'] for (u, v, d) in G1.edges(data=True)] 48 | self.assertEqual(val, [1, 0.5, 1]) 49 | 50 | 51 | if __name__ == '__main__': 52 | unittest.main() 53 | -------------------------------------------------------------------------------- /tests/test_stabrnd.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------- 2 | # Copyright (c) 2012 Vincent Gauthier. 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining 5 | # a copy of this software and associated documentation files (the 6 | # "Software"), to deal in the Software without restriction, including 7 | # without limitation the rights to use, copy, modify, merge, publish, 8 | # distribute, sublicense, and/or sell copies of the Software, and to 9 | # permit persons to whom the Software is furnished to do so, subject to 10 | # the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | #------------------------------------------------------------------------------- 23 | 24 | __author__ = """\n""".join(['Vincent Gauthier ']) 25 | 26 | __all__ = ['test_stabrnd'] 27 | 28 | 29 | from complex_systems.mobility.stabrnd import stabrnd 30 | import numpy as N 31 | import unittest 32 | 33 | class test_stabrnd(unittest.TestCase): 34 | 35 | def setUp(self): 36 | pass 37 | 38 | def test_stabrnd(self): 39 | result = N.array([[2.92229997],[-0.78181396],[-0.44122327]]) 40 | N.random.seed(123456) 41 | test = stabrnd(0.8, 0, 1, 0, 3, 1) 42 | self.assertEqual(result.all(), test.all()) 43 | 44 | if __name__ == '__main__': 45 | unittest.main() 46 | --------------------------------------------------------------------------------