1

I understand this is more a programming problem but if anyone familiar with the Schellings Segregation problem could help me out with this, I would highly appreciate it.

I have a problem where I am supposed to model the Schelling Segregation problem using pythong. I have been stuck on this for quite a while now but I think my issue is that my neighbours aren't being swapped correctly from an unhappy agent into an empty agent.

**Scope of problem: ** We have a matrix with 0s and 1s and 2s. Os represent empty houses, 1s represent one type of ethnicity, 2s represent another ethnicity. If one ethnicity isn't happy with their fraction of neighbours (defined by self.par) being similar to them, they then become unhappy agents. These unhappy agents need to swapped to empty houses. This needs to reiterated over multiple time steps and the metric (i.e. frac_mean as defined by code below) should decrease as people become "happied"

However, my issue is that the frac mean metric is not showing a consistent patter of decrease.

** Things I have tried: ** The main thing I tried was instead of making the swaps in the original self.array, I made a copy of it and made all swaps on that, then equated it to the original self array as seen by the second last line of the code.

Any help would be appreciated:


class Schelling():
    kernel = [[1,1,1],[1,0,1],[1,1,1]]
    #par = 0.3
def __init__(self, n, par=0.3):
    self.par=par
    probs = [0.1, 0.45, 0.45]
    choices = [0, 1, 2]
    self.array = np.random.choice(choices, (n, n), p=probs)

def count_neighbours(self):
    a = self.array

    empty = a == 0
    red = a == 1
    blue = a == 2

    num_red = correlate2d(red, self.kernel, mode='same', boundary='wrap')
    num_blue = correlate2d(blue, self.kernel, mode='same', boundary='wrap')
    num_neighbours = num_red + num_blue

    frac_red = num_red / num_neighbours
    frac_blue = num_blue / num_neighbours

    frac_red[num_neighbours == 0] = 0
    frac_blue[num_neighbours == 0] = 0

    # Nice way to do a vector if-else application
    frac_same = np.where(red, frac_red, frac_blue)

    # Because only if-else, empty will have frac_blue, so we need to correct this
    frac_same[empty] = np.nan

    return empty, frac_red, frac_blue, frac_same, a

def step(self):
    empty, frac_red, frac_blue, frac_same, count_neighbours_list = self.count_neighbours()
    metric=np.nanmean(frac_same)
    unhappy_address = list(zip(*np.array(np.nonzero(frac_same < self.par))))
    np.random.shuffle(unhappy_address)
    empty_address = list(zip(*np.array(np.nonzero(empty))))


    # Perform swaps until no more swaps are possible
    unhappy_copy=unhappy_address.copy()
    empty_copy=empty_address.copy()

    ind=len(unhappy_copy)

    #ind=min(len(unhappy_address), len(empty_address))
    for i in range(ind):
        #adding a check: 
        #add in a break: for the value of i if its greater than len-1 of empty_address, then break  
        if i == len(empty_address):

            break

        else:

            unhappy_tup_req=unhappy_copy[i]
            emp_tup_req=empty_copy[i]

            #count_neighbours_list[emp_tup_req]=count_neighbours_list[unhappy_tup_req]
            #count_neighbours_list[unhappy_tup_req]==0

            count_neighbours_list[emp_tup_req], count_neighbours_list[unhappy_tup_req] = count_neighbours_list[unhappy_tup_req], count_neighbours_list[emp_tup_req]


    self.array= count_neighbours_list


    return unhappy_address, empty_address, count_neighbours_list, metric

Sl30202
  • 11
  • 1
  • 1
    Do you have a minimal test case for this class? because you are dealing with code, it is best to have a minimal test case + analytical solution to debug (if a problem) – Chinny84 May 19 '23 at 14:02
  • @Chinny84 Hi, thank you for replying! This code is reproducible if you copy it to your own workspace in python. I am new to this platform so not too sure how to provide a minimal test case but if I want to simplify my problem, it would be like this: I have a matrix with 0s, 1s, 2s. In one iteration I swap the 0s with 1s (this doesn't encapsulate the problem but gives you an idea of the main operation. More so I think I've made a problem with swapping them). – Sl30202 May 19 '23 at 23:53
  • I guess the main idea is: I have a matrix with 0s, 1s, 2s. We then analyse the neighbours around each point to see the fraction to be as similar to them (i.e. if I am a zero, then only 30% around me are zeros). If this is below a particular fraction, then the 1s will move to a space with zero. So we need to update a list and loop through and iteratively update the matrix @Chinny84 – Sl30202 May 19 '23 at 23:55

0 Answers0