<jupyter_start><jupyter_text>Agent-based modelling Schelling's model in Social Networks *Authors: <NAME>, <NAME>*<jupyter_code>import ipywidgets as widgets
from ipywidgets import interact, interactive
import numpy as np
import random
from random import uniform
from math import sqrt
import matplotlib.pyplot as plt
from IPython.display import display
%matplotlib inline<jupyter_output><empty_output><jupyter_text>Класс модели<jupyter_code>np.random.seed(10)
transitions = []
information_types = ["Politics", "Economy", "Sport", "Art", "Science", "Education", "Cooking", "Religion"]
special_points = [(round(uniform(0, 1),4), round(uniform(0, 1),4)) for i in range(10000)]
special_points2 = [(round(uniform(0, 1),4), round(uniform(0, 1),4)) for i in range(100000)]


def f(x):
    if x:
        friendly_p.disabled = False
        friendly_p.value = 0.75
    else:
        friendly_p.disabled = True
        friendly_p.value = 0

class Agent:

    def __init__(self, a_type, tolerance_p, friendly, friendly_p):
        self.a_type = a_type
        self.change_location()
        self.wish = random.randint(0, 1)
        self.tol = round(uniform(0, 1), 2)
        self.fr = round(uniform(0, 1), 2)
        self.friendly = friendly
        self.popular = ''
        self.sociability = random.choice(["S","US"])
        self.preferences = random.sample(information_types, 2)
        self.access_internet = random.choice([True, False, True])
        self.safety = random.choice([True, True, True, False])

    def change_location(self):
        self.location = round(uniform(0, 1),4), round(uniform(0, 1),4)

    def get_distance(self, other):
        a = (self.location[0] - other.location[0])**2
        b = (self.location[1] - other.location[1])**2
        return sqrt(a + b)
    
    def inform(self, agents):
        if self.a_type == 1:
            self.popular = 'p'
        else:
            self.popular = 'up'
                
    def happy(self, agents):
        distances = []
        for agent in agents:
            if self != agent:
                distance = self.get_distance(agent)
                distances.append((distance, agent))
        distances.sort(key=lambda x: x[0])
        if self.popular == 'up':
            if self.sociability == 'S':
                neighbors = [agent for d, agent in distances[:local_neighbors.value + 4]]
                num_same_type = sum((agent.a_type == 1 and (len(list(set(self.preferences) & set(agent.preferences))) != []))
                                    for agent in neighbors)
                return num_same_type >= require_same_type.value
            else:
                neighbors3 = [agent for d, agent in distances[:local_neighbors.value]]
                num_same_type3 = sum((agent.a_type == 1 and (len(list(set(self.preferences) & set(agent.preferences))) != []))
                                    for agent in neighbors3)
                return num_same_type3 >= require_same_type.value
        else:
            neighbors2 = [agent for d, agent in distances[:local_neighbors.value + 8]]
            num_same_type2 = sum((agent.a_type == 1 and self.safety and (len(list(set(self.preferences) & set(agent.preferences))) != []))
                                    for agent in neighbors2)
            return num_same_type2 >= require_same_type.value
        
    def update(self, agents):
        t2 = False
        count = 0
        for i in special_points:
            if self.location == i:
                self.a_type = 1
                count += 1
        for i in special_points2:        
            if self.location == i:
                t2 = True
        
        
        if t2 and self.friendly:
            self.tol += 0.10 
            self.fr += 0.10
        elif t2 and not self.friendly:
            self.tol += 0.10
        else:
            if self.friendly:
                if self.happy(agents) and self.a_type == 0:
                    if self.fr < friendly_p.value and self.wish == 0 and self.tol < tolerance_p.value:
                        return
                    elif self.fr < friendly_p.value and self.wish == 1 and self.tol < tolerance_p.value:
                        return
                    elif self.fr < friendly_p.value and self.wish == 0 and self.tol > tolerance_p.value:
                        return
                    elif self.fr < friendly_p.value and self.wish == 1 and self.access_internet and self.tol > tolerance_p.value:
                        self.a_type = 1
                        count += 1
                    elif self.fr < friendly_p.value and self.wish == 1 and not self.access_internet and self.tol > tolerance_p.value:
                        return    
                    elif self.fr > friendly_p.value and self.wish == 0 and self.access_internet and self.tol < tolerance_p.value:
                        return
                    elif self.fr > friendly_p.value and self.wish == 1 and self.access_internet and self.tol < tolerance_p.value:
                        self.a_type = 1
                        count += 1
                    elif self.fr > friendly_p.value and self.wish == 1 and not self.access_internet and self.tol < tolerance_p.value:
                        return  
                    elif self.fr > friendly_p.value and self.wish == 0 and self.tol > tolerance_p.value:
                        self.a_type = 1
                        count += 1
                    elif self.fr > friendly_p.value and self.wish == 1 and self.access_internet and self.tol > tolerance_p.value:
                        self.a_type = 1
                        count += 1
                    elif self.fr > friendly_p.value and self.wish == 1 and not self.access_internet and self.tol > tolerance_p.value:
                        return  
                    else:
                        return    
                elif self.happy(agents) and self.a_type == 1:
                    return

                elif not self.happy(agents) and self.a_type == 0:
                    if self.fr < friendly_p.value and self.wish == 0 and self.tol < tolerance_p.value:
                        return
                    elif self.fr < friendly_p.value and self.wish == 1 and self.access_internet and self.tol < tolerance_p.value:
                        while not self.happy(agents):
                            self.change_location()
                            count += 1
                    elif self.fr < friendly_p.value and self.wish == 1 and not self.access_internet and self.tol < tolerance_p.value:
                        return       
                    elif self.fr < friendly_p.value and self.wish == 0 and self.tol > tolerance_p.value:
                        return
                    elif self.fr < friendly_p.value and self.wish == 1 and self.access_internet and self.tol > tolerance_p.value:
                        while not self.happy(agents):
                            self.change_location()
                            count += 1
                    elif self.fr < friendly_p.value and self.wish == 1 and not self.access_internet and self.tol > tolerance_p.value:
                        return       
                    elif self.fr > friendly_p.value and self.wish == 0 and self.tol < tolerance_p.value:
                        return
                    elif self.fr > friendly_p.value and self.wish == 1 and self.access_internet and self.tol < tolerance_p.value:
                        while not self.happy(agents):
                            self.change_location()
                            count += 1
                    elif self.fr > friendly_p.value and self.wish == 1 and self.tol < tolerance_p.value:
                        return        
                    elif self.fr > friendly_p.value and self.wish == 0 and self.access_internet and self.tol > tolerance_p.value:
                        while not self.happy(agents):
                            self.change_location()
                            count += 1
                    elif self.fr > friendly_p.value and self.wish == 0 and not self.access_internet and self.tol > tolerance_p.value:
                        return       
                    elif self.fr > friendly_p.value and self.wish == 1 and self.access_internet and self.tol > tolerance_p.value:
                        while not self.happy(agents):
                            self.change_location()
                            count += 1
                    elif self.fr > friendly_p.value and self.wish == 1 and not self.access_internet and self.tol > tolerance_p.value:
                        return        
                    else:
                        return
                else:
                    return
            else:
                if self.happy(agents) and self.a_type == 0:
                    if self.wish == 0 and self.tol < tolerance_p.value:
                        return
                    elif self.wish == 1 and self.tol < tolerance_p.value:
                        return
                    elif self.wish == 0 and self.tol > tolerance_p.value:
                        return
                    elif self.wish == 1 and self.access_internet and self.tol > tolerance_p.value:
                        self.a_type = 1
                        count += 1
                    elif self.wish == 1 and not self.access_internet and self.tol > tolerance_p.value:
                        return   
                    else:
                        return

                elif self.happy(agents) and self.a_type == 1:
                    return

                elif not self.happy(agents) and self.a_type == 0:
                    if self.wish == 0 and self.tol < tolerence_p.value:
                        return
                    elif self.wish == 1 and self.access_internet and self.tol < tolerence_p.value:
                        while not self.happy(agents):
                            self.change_location()
                            count += 1
                    elif self.wish == 1 and not self.access_internet and self.tol < tolerence_p.value:
                        return        
                    elif self.wish == 0 and self.tol > tolerence_p.value:
                        return
                    elif self.wish == 1 and self.access_internet and self.tol > tolerence_p.value:
                        while not self.happy(agents):
                            self.change_location()
                            count += 1
                    elif self.wish == 1 and not self.access_internet and self.tol > tolerence_p.value:
                        return        
                    else:
                        return
                else:
                    return
        transitions.append(count)
        
                    
def plot_distribution(agents, cycle_num):
    x_values_0, y_values_0 = [], []
    x_values_1, y_values_1 = [], []
    for agent in agents:
        x, y = agent.location
        if agent.a_type == 0:
            x_values_0.append(x)
            y_values_0.append(y)
        else:
            x_values_1.append(x)
            y_values_1.append(y)
            
    fig, ax = plt.subplots(figsize=(8, 8))
    plot_args = {'markersize': 8, 'alpha': 1}
    ax.set_facecolor('white')
    ax.plot(x_values_0, y_values_0, 'o', markerfacecolor='black', **plot_args)
    ax.plot(x_values_1, y_values_1, 'o', markerfacecolor='yellow', **plot_args)
    ax.set_title(f'Step {cycle_num-1}')
    plt.show()

def function():
    agents = [Agent(0, tolerance_p.value, True, friendly_p.value) for i in range(number_of_type0.value)]
    agents.extend(Agent(1, tolerance_p.value, False, friendly_p.value) for i in range(number_of_type1.value))
    
    agents_old = agents
    old_ag1 = []
    old_ag2 = []
    for agent in agents_old:
        if agent.a_type == 0:
            old_ag1.append(agent.a_type)
        else:
            old_ag2.append(agent.a_type)
            
    labels_old = 'Informed', 'Uninformed'
    explodes = [0, 0.1]
    
    for agent in agents:
            agent.inform(agents)
            
    count2 = 1
    while True:
        plot_distribution(agents, count2)
        count2 += 1
        no_one_moved = True
        for agent in agents:
            old_location = agent.location
            agent.update(agents)
            if agent.location != old_location:
                no_one_moved = False
        if no_one_moved:
            break
            
    ag1 = []
    ag2 = []
    for agent in agents:
        if agent.a_type == 0:
            ag1.append(agent.a_type)
        else:
            ag2.append(agent.a_type)
    labels_new = 'Informed', 'Uninformed'
    
    
    fig1, (ax1, ax2) = plt.subplots(1,2)
    fig1.set_size_inches(12, 12, forward=True)
    
    ax1.pie([len(old_ag2), len(old_ag1)], labels=labels_old, shadow=True, 
            explode=explodes, startangle = 90, autopct='%1.1f%%', colors=['yellow','deepskyblue'])
    ax2.pie([len(ag2), len(ag1)], labels=labels_new, shadow=True, 
            explode=explodes, startangle = 90, autopct='%1.1f%%', colors=['yellow','deepskyblue'])
    
    ax1.set_title("Before")
    ax2.set_title("After")
    
    no_ac_int = 0
    for agent in agents:
        if agent.access_internet == False:
            no_ac_int += 1
    percent_of_no_access = (no_ac_int*100)/(number_of_type0.value +  number_of_type1.value) 
    politics, economy, sport, art, science, education, cooking, religion = 0, 0, 0, 0, 0, 0, 0, 0
    for agent in agents:
        for i in agent.preferences:
            if agent.a_type == 1:
                if i == "Politics":
                    politics += 1
                elif i == "Economy":
                    economy += 1
                elif i == "Sport":
                    sport += 1 
                elif i == "Art":
                    art += 1
                elif i == "Science":
                    science += 1 
                elif i == "Education":
                    education += 1 
                elif i == "Cooking":
                    cooking += 1
                else:
                    religion += 1
            
    fig_new, ax_new = plt.subplots()
    fig_new.set_size_inches(7, 7, forward=True)
    preferences = ('Politics', 'Economy', 'Sport', 'Art', 'Science', 'Education', 'Cooking', 'Religion')
    y_pos = np.arange(len(preferences))
    performance = [politics, economy, sport, art, science, education, cooking, religion]

    ax_new.barh(y_pos, performance, align='center')
    ax_new.set_yticks(y_pos)
    ax_new.set_yticklabels(preferences)
    ax_new.invert_yaxis()  
    ax_new.set_title("Informed agents' preferences")
    
    plt.show()
    #print("Количество популярных:", len(thus1))
    print("\nСреднее число перемещений:", round(np.mean(transitions), 4), "\nОбщее число итераций:", sum(transitions))
    print("Процент агентов, не имеющих доступ к интернету:", percent_of_no_access, "%")<jupyter_output><empty_output><jupyter_text>Интерфейс  взаимодействия<jupyter_code>#количество агентов типа 0
number_of_type0 = widgets.IntText(
    value = 200,
    description="Informed")
display(number_of_type0)

#количество агентов типа 1
number_of_type1 = widgets.IntText(
    value = 200,
    description="Uninformed")
display(number_of_type1)

#количество соседей
local_neighbors = widgets.IntSlider(
    value=7,
    min=0,
    max=20,
    step=1,
    description='Neighbours',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='d'
)
display(local_neighbors)

#reqires same time
require_same_type = widgets.IntSlider(
    value=5,
    min=0,
    max=10,
    step=1,
    description='Required',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='d'
)
display(require_same_type)

#процент толерантности
tolerance_p = widgets.FloatSlider(
    value=0.7,
    min=0,
    max=1.0,
    step=0.01,
    description='Tolerance',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
)
display(tolerance_p)

#use friendly

interact(f, x=widgets.Checkbox(description='Friendly',disabled=False))

#процент дружелюбности
friendly_p = widgets.FloatSlider(
    value=0,
    min=0,
    max=1.0,
    step=0.01,
    description='Friendly',
    disabled=True,
    continuous_update=False,
    orientation='horizontal',
)
display(friendly_p)

button = widgets.Button(description="Simulate", button_style='info')
output = widgets.Output()

display(button, output)

def on_button_clicked(a):
    function()

button.on_click(on_button_clicked)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09894673487812218, 'fraction_numerical': 0.016370749322900995, 'mean_word_length': 1.6658110059361464, 'pattern_counts': {'":': 7, '<': 42, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '355231', 'license': 'MIT', 'n_tokens_mistral': 5118, 'n_tokens_neox': 4804, 'n_words': 1141, 'path': 'Social Network/The_Social_Network_model.ipynb', 'repo_name': 'kirillzx/Agent-based-modeling', 'size': '16624'}