Пример #1
0
    def test_assign_array(self):
        # Network definition
        g = nx.random_geometric_graph(10, 0.1)
        m = Model(g)

        initial_state = {
            'x': 0,
        }

        def update_x():
            return {'x': np.arange(10)}

        # Model definition
        m.set_states(['x'])
        m.add_update(update_x)
        m.set_initial_state(initial_state)

        output = m.simulate(1)
        self.assertEqual(list(output['states'][0]), list(np.zeros((10, 1))))
        self.assertEqual(list(output['states'][1]), list(np.arange(10)))
Пример #2
0
        I = model.get_state('I')
        R = model.get_state('R')

        dSdt, dIdt, dRdt = deriv(S, I, constants)

        return {
            # 'state': s + (0.01 * (-s + 1))
            'S': S + (dt * dSdt),
            'I': I + (dt * dIdt),
            'R': R + (dt * dRdt)
        }

    # Model definition
    model.set_states(['S', 'I', 'R'])
    model.add_update(update, {'constants': constants})
    model.set_initial_state(initial_state)

    its = model.simulate(10000)
    iterations = list(its['states'].values())

    s = [v[0][0] for v in iterations]
    i = [v[0][1] for v in iterations]
    r = [v[0][2] for v in iterations]

    import matplotlib.pyplot as plt
    x = np.linspace(0, 100, 10001)

    plt.figure()
    plt.plot(x, s, label='S')
    plt.plot(x, i, label='I')
    plt.plot(x, r, label='R')
Пример #3
0
class HIOM(Example):

    def __init__(self):
        n = 400

        g = nx.watts_strogatz_graph(n, 2, 0.02)

        cfg = {
            'utility': False,
        }
        self.model = Model(g, ModelConfiguration(cfg))

        constants = {
            'dt': 0.01,
            'A_min': -0.5,
            'A_star': 1,
            's_O': 0.01,
            's_I': 0,
            'd_A': 0,
            'p': 1,
            'r_min': 0,
            't_O': np.inf,
            'N': n
        }

        def initial_I(constants):
            return np.random.normal(0, 0.3, constants['N'])

        def initial_O(constants):
            return np.random.normal(0, 0.2, constants['N'])

        initial_state = {
            'I': initial_I,
            'O': initial_O,
            'A': 1
        }

        def update_I_A(nodes, constants):
            node = nodes[0]
            nb = np.random.choice(self.model.get_neighbors(node))
            if abs(self.model.get_node_state(node, 'O') - self.model.get_node_state(nb, 'O')) > constants['t_O']:
                return {'I': self.model.get_node_state(node, 'I')}
            else:
                # Update information
                r = constants['r_min'] + (1 - constants['r_min']) / (1 + np.exp(-1 * constants['p'] * (self.model.get_node_state(node, 'O') - self.model.get_node_state(nb, 'O'))))
                inf = r * self.model.get_node_state(node, 'I') + (1-r) * self.model.get_node_state(nb, 'I') + np.random.normal(0, constants['s_I'])

                # Update attention
                node_A = self.model.get_node_state(node, 'A') + constants['d_A'] * (2 * constants['A_star'] - self.model.get_node_state(node, 'A'))
                nb_A = self.model.get_node_state(nb, 'A') + constants['d_A'] * (2 * constants['A_star'] - self.model.get_node_state(nb, 'A'))
                return {'I': [inf], 'A': {node: node_A, nb: nb_A}}

        def update_A(constants):
            return {'A': self.model.get_state('A') - 2 * constants['d_A'] * self.model.get_state('A')/constants['N']}

        def update_O(constants):
            noise = np.random.normal(0, constants['s_O'], constants['N'])
            x = self.model.get_state('O') - constants['dt'] * (self.model.get_state('O')**3 - (self.model.get_state('A') + constants['A_min']) * self.model.get_state('O') - self.model.get_state('I')) + noise
            return {'O': x}

        def shrink_I():
            return {'I': self.model.get_state('I') * 0.999}

        def shrink_A():
            return {'A': self.model.get_state('A') * 0.999}

        def sample_attention_weighted(graph):
            probs = []
            A = self.model.get_state('A')
            factor = 1.0/sum(A)
            for a in A:
                probs.append(a * factor)
            return np.random.choice(graph.nodes, size=1, replace=False, p=probs)

        # Model definition
        self.model.constants = constants
        self.model.set_states(['I', 'A', 'O'])

        update_cfg = UpdateConfiguration({
            'arguments': {'constants': self.model.constants},
            'get_nodes': True
        })
        up_I_A = Update(update_I_A, update_cfg)
        s_I = Update(shrink_I)
        s_A = Update(shrink_A)

        self.model.add_scheme(Scheme(sample_attention_weighted, {'args': {'graph': self.model.graph}, 'updates': [up_I_A]}))
        self.model.add_scheme(Scheme(lambda graph: graph.nodes, {'args': {'graph': self.model.graph}, 'lower_bound': 5000, 'updates': [s_I]}))
        self.model.add_scheme(Scheme(lambda graph: graph.nodes, {'args': {'graph': self.model.graph}, 'lower_bound': 10000, 'updates': [s_A]}))
        self.model.add_update(update_A, {'constants': self.model.constants})
        self.model.add_update(update_O, {'constants': self.model.constants})

        self.model.set_initial_state(initial_state, {'constants': self.model.constants})

    def simulate(self, n):
        return self.model.simulate(n)

    def visualize(self, iterations):
        visualization_config = {
            'layout': 'fr',
            'plot_interval': 100,
            'plot_variable': 'O',
            'variable_limits': {
                'A': [0, 1],
                'O': [-1, 1],
                'I': [-1, 1]
            },
            'cmin': -1,
            'cmax': 1,
            'color_scale': 'RdBu',
            'show_plot': True,
            # 'plot_output': '../animations/HIOM.gif',
            'plot_title': 'HIERARCHICAL ISING OPINION MODEL',
        }

        self.model.configure_visualization(visualization_config, iterations)
        self.model.visualize('animation')
Пример #4
0
    def update_lambda(constants):
        return {'lambda': model.get_state('lambda') + 0.01}

    def update_A(constants):
        return {'A': constants['q'] * model.get_state('V') + np.minimum((np.random.poisson(model.get_state('lambda'))/7), constants['q']*(1 - model.get_state('V')))}

    # Model definition
    model.constants = constants
    model.set_states(['C', 'S', 'E', 'V', 'lambda', 'A'])
    model.add_update(update_C, {'constants': model.constants})
    model.add_update(update_S, {'constants': model.constants})
    model.add_update(update_E, {'constants': model.constants})
    model.add_update(update_V, {'constants': model.constants})
    model.add_update(update_lambda, {'constants': model.constants})
    model.add_update(update_A, {'constants': model.constants})
    model.set_initial_state(initial_state, {'constants': model.constants})

    its = model.simulate(100)

    iterations = its['states'].values()

    A = [np.mean(it[:, 5]) for it in iterations]
    C = [np.mean(it[:, 0]) for it in iterations]

    E = [np.mean(it[:, 2]) for it in iterations]
    lmd = [np.mean(it[:, 4]) for it in iterations]

    S = [np.mean(it[:, 1]) for it in iterations]
    V = [np.mean(it[:, 3]) for it in iterations]

    x = np.arange(0, len(iterations))
Пример #5
0
class CravingSelfControl(Example):
    def __init__(self):
        # Network definition
        self.g = nx.random_geometric_graph(250, 0.125)
        cfg = {
            'utility': False,
        }
        self.model = Model(self.g, ModelConfiguration(cfg))

        constants = {
            'q': 0.8,
            'b': 0.5,
            'd': 0.2,
            'h': 0.2,
            'k': 0.25,
            'S+': 0.5,
        }
        constants['p'] = 2 * constants['d']

        def initial_v(constants):
            return np.minimum(
                1,
                np.maximum(
                    0,
                    self.model.get_state('C') - self.model.get_state('S') -
                    self.model.get_state('E')))

        def initial_a(constants):
            return constants['q'] * self.model.get_state('V') + (
                np.random.poisson(self.model.get_state('lambda')) / 7)

        initial_state = {
            'C': 0,
            'S': constants['S+'],
            'E': 1,
            'V': initial_v,
            'lambda': 0.5,
            'A': initial_a
        }

        def update_C(constants):
            c = self.model.get_state(
                'C') + constants['b'] * self.model.get_state('A') * np.minimum(
                    1, 1 - self.model.get_state('C')
                ) - constants['d'] * self.model.get_state('C')
            return {'C': c}

        def update_S(constants):
            return {
                'S':
                self.model.get_state('S') + constants['p'] *
                np.maximum(0, constants['S+'] - self.model.get_state('S')) -
                constants['h'] * self.model.get_state('C') -
                constants['k'] * self.model.get_state('A')
            }

        # Naive manner
        # def update_E(constants):
        #     # return {'E': self.model.get_state('E') - 0.015}
        #     e = np.zeros(len(self.model.nodes))
        #     for i, node in enumerate(self.model.nodes):
        #         neighbor_addiction = 0
        #         for neighbor in self.model.get_neighbors(node):
        #             neighbor_addiction += self.model.get_node_state(neighbor, 'A')
        #         e[i] = neighbor_addiction / 50
        #     return {'E': np.maximum(-1.5, self.model.get_state('E') - e)} # Custom calculation

        # Less naive
        # def update_E(constants):
        #     e = np.zeros(len(self.model.nodes))
        #     adj = self.model.get_adjacency()
        #     for i in range(len(self.model.nodes)):
        #         neighbors = adj[i].nonzero()
        #         e[i] = np.sum(self.model.get_nodes_state(neighbors, 'A')) / 50
        #     return {'E': np.maximum(-1.5, self.model.get_state('E') - e)} # Custom calculation

        def update_E(constants):
            adj = self.model.get_adjacency()
            summed = np.matmul(adj, self.model.get_nodes_states())
            e = summed[:, self.model.get_state_index('A')] / 50
            return {'E': np.maximum(-1.5, self.model.get_state('E') - e)}

        def update_V(constants):
            return {
                'V':
                np.minimum(
                    1,
                    np.maximum(
                        0,
                        self.model.get_state('C') - self.model.get_state('S') -
                        self.model.get_state('E')))
            }

        def update_lambda(constants):
            return {'lambda': self.model.get_state('lambda') + 0.01}

        def update_A(constants):
            return {
                'A':
                constants['q'] * self.model.get_state('V') + np.minimum(
                    (np.random.poisson(self.model.get_state('lambda')) / 7),
                    constants['q'] * (1 - self.model.get_state('V')))
            }

        # Model definition
        self.model.constants = constants
        self.model.set_states(['C', 'S', 'E', 'V', 'lambda', 'A'])
        self.model.add_update(update_C, {'constants': self.model.constants})
        self.model.add_update(update_S, {'constants': self.model.constants})
        self.model.add_update(update_E, {'constants': self.model.constants})
        self.model.add_update(update_V, {'constants': self.model.constants})
        self.model.add_update(update_lambda,
                              {'constants': self.model.constants})
        self.model.add_update(update_A, {'constants': self.model.constants})
        self.model.set_initial_state(initial_state,
                                     {'constants': self.model.constants})

    def simulate(self, n):
        return self.model.simulate(n)

    def plot_paper(self, iterations):
        A = [np.mean(it[:, 5]) for it in iterations]
        C = [np.mean(it[:, 0]) for it in iterations]

        E = [np.mean(it[:, 2]) for it in iterations]
        lmd = [np.mean(it[:, 4]) for it in iterations]

        S = [np.mean(it[:, 1]) for it in iterations]
        V = [np.mean(it[:, 3]) for it in iterations]

        x = np.arange(0, len(iterations))
        plt.figure()

        plt.subplot(221)
        plt.plot(x, E, label='E')
        plt.plot(x, lmd, label='lambda')
        plt.legend()

        plt.subplot(222)
        plt.plot(x, A, label='A')
        plt.plot(x, C, label='C')
        plt.legend()

        plt.subplot(223)
        plt.plot(x, S, label='S')
        plt.plot(x, V, label='V')
        plt.legend()

        plt.show()

    def visualize(self, iterations):
        visualization_config = {
            'plot_interval': 2,
            'initial_positions': nx.get_node_attributes(self.g, 'pos'),
            'plot_variable': 'A',
            'color_scale': 'Reds',
            'variable_limits': {
                'A': [0, 0.8],
                'lambda': [0.5, 1.5],
                'C': [-1, 1],
                'V': [-1, 1],
                'E': [-1, 1],
                'S': [-1, 1]
            },
            'show_plot': True,
            # 'plot_output': './animations/c_vs_s.gif',
            'plot_title': 'Self control vs craving simulation',
        }

        self.model.configure_visualization(visualization_config, iterations)
        self.model.visualize('animation')