@@ -20,7 +20,7 @@ kernelspec:
20
20
</div>
21
21
```
22
22
23
- # Racial Segregation
23
+ # Racial Segregation
24
24
25
25
``` {index} single: Schelling Segregation Model
26
26
```
@@ -191,30 +191,30 @@ class Agent:
191
191
b = (self.location[1] - other.location[1])**2
192
192
return sqrt(a + b)
193
193
194
- def happy(self,
194
+ def happy(self,
195
195
agents, # List of other agents
196
196
num_neighbors=10, # No. of agents viewed as neighbors
197
197
require_same_type=5): # How many neighbors must be same type
198
198
"""
199
199
True if a sufficient number of nearest neighbors are of the same
200
- type.
200
+ type.
201
201
"""
202
202
203
203
distances = []
204
-
204
+
205
205
# Distances is a list of pairs (d, agent), where d is distance from
206
206
# agent to self
207
207
for agent in agents:
208
208
if self != agent:
209
209
distance = self.get_distance(agent)
210
210
distances.append((distance, agent))
211
-
211
+
212
212
# Sort from smallest to largest, according to distance
213
213
distances.sort()
214
-
214
+
215
215
# Extract the neighboring agents
216
216
neighbors = [agent for d, agent in distances[:num_neighbors]]
217
-
217
+
218
218
# Count how many neighbors have the same type as self
219
219
num_same_type = sum(self.type == agent.type for agent in neighbors)
220
220
return num_same_type >= require_same_type
@@ -248,9 +248,9 @@ def plot_distribution(agents, cycle_num):
248
248
fig, ax = plt.subplots()
249
249
plot_args = {'markersize': 8, 'alpha': 0.8}
250
250
ax.set_facecolor('azure')
251
- ax.plot(x_values_0, y_values_0,
251
+ ax.plot(x_values_0, y_values_0,
252
252
'o', markerfacecolor='orange', **plot_args)
253
- ax.plot(x_values_1, y_values_1,
253
+ ax.plot(x_values_1, y_values_1,
254
254
'o', markerfacecolor='green', **plot_args)
255
255
ax.set_title(f'Cycle {cycle_num-1}')
256
256
plt.show()
@@ -274,24 +274,24 @@ The real code is below
274
274
``` {code-cell} ipython3
275
275
def run_simulation(num_of_type_0=600,
276
276
num_of_type_1=600,
277
- max_iter=100_000, # Maximum number of iterations
278
- set_seed=1234):
277
+ max_iter=100_000, # Maximum number of iterations
278
+ set_seed=1234):
279
279
280
280
# Set the seed for reproducibility
281
- seed(set_seed)
282
-
281
+ seed(set_seed)
282
+
283
283
# Create a list of agents of type 0
284
284
agents = [Agent(0) for i in range(num_of_type_0)]
285
285
# Append a list of agents of type 1
286
286
agents.extend(Agent(1) for i in range(num_of_type_1))
287
287
288
288
# Initialize a counter
289
289
count = 1
290
-
290
+
291
291
# Plot the initial distribution
292
292
plot_distribution(agents, count)
293
-
294
- # Loop until no agent wishes to move
293
+
294
+ # Loop until no agent wishes to move
295
295
while count < max_iter:
296
296
print('Entering loop ', count)
297
297
count += 1
@@ -303,15 +303,15 @@ def run_simulation(num_of_type_0=600,
303
303
no_one_moved = False
304
304
if no_one_moved:
305
305
break
306
-
306
+
307
307
# Plot final distribution
308
308
plot_distribution(agents, count)
309
309
310
310
if count < max_iter:
311
311
print(f'Converged after {count} iterations.')
312
312
else:
313
313
print('Hit iteration bound and terminated.')
314
-
314
+
315
315
```
316
316
317
317
Let's have a look at the results.
@@ -346,7 +346,7 @@ The object oriented style that we used for coding above is neat but harder to
346
346
optimize than procedural code (i.e., code based around functions rather than
347
347
objects and methods).
348
348
349
- Try writing a new version of the model that stores
349
+ Try writing a new version of the model that stores
350
350
351
351
* the locations of all agents as a 2D NumPy array of floats.
352
352
* the types of all agents as a flat NumPy array of integers.
@@ -375,7 +375,6 @@ solution here
375
375
376
376
``` {code-cell} ipython3
377
377
from numpy.random import uniform, randint
378
- from numba import njit
379
378
380
379
n = 1000 # number of agents (agents = 0, ..., n-1)
381
380
k = 10 # number of agents regarded as neighbors
@@ -386,13 +385,10 @@ def initialize_state():
386
385
types = randint(0, high=2, size=n) # label zero or one
387
386
return locations, types
388
387
389
- @njit # Use Numba to accelerate computation
388
+
390
389
def compute_distances_from_loc(loc, locations):
391
- " Compute distance from location loc to all other points. "
392
- distances = np.empty(n)
393
- for j in range(n):
394
- distances[j] = np.linalg.norm(loc - locations[j, :])
395
- return distances
390
+ """ Compute distance from location loc to all other points. """
391
+ return np.linalg.norm(loc - locations, axis=1)
396
392
397
393
def get_neighbors(loc, locations):
398
394
" Get all neighbors of a given location. "
@@ -417,7 +413,7 @@ def count_happy(locations, types):
417
413
for i in range(n):
418
414
happy_sum += is_happy(i, locations, types)
419
415
return happy_sum
420
-
416
+
421
417
def update_agent(i, locations, types):
422
418
" Move agent if unhappy. "
423
419
moved = False
@@ -432,11 +428,11 @@ def plot_distribution(locations, types, title, savepdf=False):
432
428
colors = 'orange', 'green'
433
429
for agent_type, color in zip((0, 1), colors):
434
430
idx = (types == agent_type)
435
- ax.plot(locations[idx, 0],
436
- locations[idx, 1],
437
- 'o',
431
+ ax.plot(locations[idx, 0],
432
+ locations[idx, 1],
433
+ 'o',
438
434
markersize=8,
439
- markerfacecolor=color,
435
+ markerfacecolor=color,
440
436
alpha=0.8)
441
437
ax.set_title(title)
442
438
plt.show()
@@ -458,15 +454,15 @@ def sim_random_select(max_iter=100_000, flip_prob=0.01, test_freq=10_000):
458
454
i = randint(0, n)
459
455
moved = update_agent(i, locations, types)
460
456
461
- if flip_prob > 0:
457
+ if flip_prob > 0:
462
458
# flip agent i's type with probability epsilon
463
459
U = uniform()
464
460
if U < flip_prob:
465
461
current_type = types[i]
466
462
types[i] = 0 if current_type == 1 else 1
467
463
468
464
# Every so many updates, plot and test for convergence
469
- if current_iter % test_freq == 0:
465
+ if current_iter % test_freq == 0:
470
466
cycle = current_iter / n
471
467
plot_distribution(locations, types, f'iteration {current_iter}')
472
468
if count_happy(locations, types) == n:
0 commit comments