Source code for mapof.marriages.cultures.euclidean

import math

import numpy as np
from numpy import linalg

from mapof.marriages.cultures.mallows import mallows_votes


def weighted_l1(a1, a2, w):
    total = 0
    for i in range(len(a1)):
        total += abs(a1[i] - a2[i]) * w[i]
    return total


[docs] def generate_euclidean_votes( num_agents: int = None, dim=2, space='uniform', **_kwargs ): """ Generates the votes based on the Euclidean model. """ name = f'{dim}d_{space}' left = np.array([get_rand(name, i=i, num_agents=num_agents) for i in range(num_agents)]) right = np.array([get_rand(name, i=i, num_agents=num_agents) for i in range(num_agents)]) left_votes = np.zeros([num_agents, num_agents], dtype=int) right_votes = np.zeros([num_agents, num_agents], dtype=int) distances = np.zeros([num_agents, num_agents], dtype=float) for v in range(num_agents): for c in range(num_agents): left_votes[v][c] = c distances[v][c] = np.linalg.norm(left[v] - right[c]) left_votes[v] = [x for _, x in sorted(zip(distances[v], left_votes[v]))] for v in range(num_agents): for c in range(num_agents): right_votes[v][c] = c distances[v][c] = np.linalg.norm(right[v] - left[c]) right_votes[v] = [x for _, x in sorted(zip(distances[v], right_votes[v]))] return [left_votes, right_votes]
[docs] def generate_mallows_euclidean_votes(num_agents: int = None, dim=2, space='uniform', phi=0.5, **kwargs): """ Generates the votes based on the Mallows on top of the Euclidean model. """ name = f'{dim}d_{space}' left = np.array([get_rand(name, i=i, num_agents=num_agents) for i in range(num_agents)]) right = np.array([get_rand(name, i=i, num_agents=num_agents) for i in range(num_agents)]) left_votes = np.zeros([num_agents, num_agents], dtype=int) right_votes = np.zeros([num_agents, num_agents], dtype=int) distances = np.zeros([num_agents, num_agents], dtype=float) for v in range(num_agents): for c in range(num_agents): left_votes[v][c] = c distances[v][c] = np.linalg.norm(left[v] - right[c]) left_votes[v] = [x for _, x in sorted(zip(distances[v], left_votes[v]))] for v in range(num_agents): for c in range(num_agents): right_votes[v][c] = c distances[v][c] = np.linalg.norm(right[v] - left[c]) right_votes[v] = [x for _, x in sorted(zip(distances[v], right_votes[v]))] left_votes = mallows_votes(left_votes, phi) right_votes = mallows_votes(right_votes, phi) return [left_votes, right_votes]
[docs] def generate_reverse_euclidean_votes( num_agents: int = None, dim=2, space='uniform', phi=0.5, proportion: float = 0.5, **_kwargs ): """ Generates the votes based on the Reverse Euclidean model. """ name = f'{dim}d_{space}' left = np.array([get_rand(name, i=i, num_agents=num_agents) for i in range(num_agents)]) right = np.array([get_rand(name, i=i, num_agents=num_agents) for i in range(num_agents)]) left_votes = np.zeros([num_agents, num_agents], dtype=int) right_votes = np.zeros([num_agents, num_agents], dtype=int) distances = np.zeros([num_agents, num_agents], dtype=float) for v in range(num_agents): for c in range(num_agents): left_votes[v][c] = c distances[v][c] = np.linalg.norm(left[v] - right[c]) left_votes[v] = [x for _, x in sorted(zip(distances[v], left_votes[v]))] for v in range(num_agents): for c in range(num_agents): right_votes[v][c] = c distances[v][c] = np.linalg.norm(right[v] - left[c]) right_votes[v] = [x for _, x in sorted(zip(distances[v], right_votes[v]))] p = proportion for i in range(int(num_agents * (1. - p))): tmp = list(left_votes[i]) tmp.reverse() left_votes[i] = tmp tmp = list(right_votes[i]) tmp.reverse() right_votes[i] = tmp return [left_votes, right_votes]
[docs] def generate_expectation_votes(num_agents: int = None, dim=2, space='uniform', std=0.1, phi=0.5, **_kwargs): """ Generates the votes based on the Expectation model. """ name = f'{dim}d_{space}' left_agents_reality = np.array([get_rand(name) for _ in range(num_agents)]) left_agents_wishes = np.zeros([num_agents, 2]) right_agents_reality = np.array([get_rand(name) for _ in range(num_agents)]) right_agents_wishes = np.zeros([num_agents, 2]) for v in range(num_agents): # while agents_wishes[v][0] <= 0 or agents_wishes[v][0] >= 1: left_agents_wishes[v][0] = np.random.normal(left_agents_reality[v][0], std) # while agents_wishes[v][1] <= 0 or agents_wishes[v][1] >= 1: left_agents_wishes[v][1] = np.random.normal(left_agents_reality[v][1], std) # while agents_wishes[v][0] <= 0 or agents_wishes[v][0] >= 1: right_agents_wishes[v][0] = np.random.normal(right_agents_reality[v][0], std) # while agents_wishes[v][1] <= 0 or agents_wishes[v][1] >= 1: right_agents_wishes[v][1] = np.random.normal(right_agents_reality[v][1], std) left_votes = np.zeros([num_agents, num_agents], dtype=int) right_votes = np.zeros([num_agents, num_agents], dtype=int) distances = np.zeros([num_agents, num_agents], dtype=float) for v in range(num_agents): for c in range(num_agents): left_votes[v][c] = c distances[v][c] = np.linalg.norm(right_agents_reality[c] - left_agents_wishes[v]) left_votes[v] = [x for _, x in sorted(zip(distances[v], left_votes[v]))] for v in range(num_agents): for c in range(num_agents): right_votes[v][c] = c distances[v][c] = np.linalg.norm(left_agents_reality[c] - right_agents_wishes[v]) right_votes[v] = [x for _, x in sorted(zip(distances[v], right_votes[v]))] return [left_votes, right_votes]
[docs] def generate_fame_votes(num_agents: int = None, dim=2, space='uniform', radius=0.1, **_kwargs): """ Generates the votes based on the Fame model. """ name = f'{dim}d_{space}' left = np.array([get_rand(name, i=i, num_agents=num_agents) for i in range(num_agents)]) right = np.array([get_rand(name, i=i, num_agents=num_agents) for i in range(num_agents)]) left_rays = np.array([np.random.uniform(0, radius) for _ in range(num_agents)]) right_rays = np.array([np.random.uniform(0, radius) for _ in range(num_agents)]) left_votes = np.zeros([num_agents, num_agents], dtype=int) right_votes = np.zeros([num_agents, num_agents], dtype=int) distances = np.zeros([num_agents, num_agents], dtype=float) for v in range(num_agents): for c in range(num_agents): left_votes[v][c] = c distances[v][c] = np.linalg.norm(left[v] - right[c]) distances[v][c] = distances[v][c] - right_rays[c] left_votes[v] = [x for _, x in sorted(zip(distances[v], left_votes[v]))] for v in range(num_agents): for c in range(num_agents): right_votes[v][c] = c distances[v][c] = np.linalg.norm(right[v] - left[c]) distances[v][c] = distances[v][c] - left_rays[c] right_votes[v] = [x for _, x in sorted(zip(distances[v], right_votes[v]))] return [left_votes, right_votes]
[docs] def generate_attributes_votes(num_agents: int = None, dim: int = 2, space: str = 'uniform', **_kwargs): """ Generates the votes based on the Attributes model. """ name = f'{dim}d_{space}' left_agents_skills = np.array([get_rand(name) for _ in range(num_agents)]) left_agents_weights = np.array([get_rand(name) for _ in range(num_agents)]) right_agents_skills = np.array([get_rand(name) for _ in range(num_agents)]) right_agents_weights = np.array([get_rand(name) for _ in range(num_agents)]) votes = np.zeros([num_agents, num_agents], dtype=int) left_votes = np.zeros([num_agents, num_agents], dtype=int) right_votes = np.zeros([num_agents, num_agents], dtype=int) distances = np.zeros([num_agents, num_agents], dtype=float) ones = np.ones([dim], dtype=float) for v in range(num_agents): for c in range(num_agents): left_votes[v][c] = c if dim == 1: distances[v][c] = (1. - right_agents_skills[c]) * left_agents_weights[v] else: distances[v][c] = weighted_l1(ones, right_agents_skills[c], left_agents_weights[v]) left_votes[v] = [x for _, x in sorted(zip(distances[v], left_votes[v]))] for v in range(num_agents): for c in range(num_agents): right_votes[v][c] = c if dim == 1: distances[v][c] = (1. - left_agents_skills[c]) * right_agents_weights[v] else: distances[v][c] = weighted_l1(ones, left_agents_skills[c], right_agents_weights[v]) right_votes[v] = [x for _, x in sorted(zip(distances[v], right_votes[v]))] return [left_votes, right_votes]
#################################################### ### UPDATE THIS TO MATCH THE RESAMPLING APPROACH ###
[docs] def get_rand(model: str, i: int = 0, num_agents: int = 0) -> list: """ generate random values""" point = [0] if model in {"1d_uniform", "1d_interval"}: return np.random.rand() elif model in {'1d_asymmetric'}: if np.random.rand() < 0.3: return np.random.normal(loc=0.25, scale=0.15, size=1) else: return np.random.normal(loc=0.75, scale=0.15, size=1) elif model in {"1d_gaussian"}: point = np.random.normal(0.5, 0.15) while point > 1 or point < 0: point = np.random.normal(0.5, 0.15) # elif model == "1d_one_sided_triangle": # point = np.random.uniform(0, 1) ** 0.5 # elif model == "1d_full_triangle": # point = np.random.choice( # [np.random.uniform(0, 1) ** 0.5, 2 - np.random.uniform(0, 1) ** 0.5]) # elif model == "1d_two_party": # point = np.random.choice([np.random.uniform(0, 1), np.random.uniform(2, 3)]) elif model in {"2d_disc"}: phi = 2.0 * 180.0 * np.random.random() radius = math.sqrt(np.random.random()) * 0.5 point = [0.5 + radius * math.cos(phi), 0.5 + radius * math.sin(phi)] elif model in {"2d_square", "2d_uniform"}: point = [np.random.random(), np.random.random()] # elif model in {'2d_asymmetric'}: # if np.random.rand() < 0.3: # return np.random.normal(loc=0.25, scale=0.15, size=2) # else: # return np.random.normal(loc=0.75, scale=0.15, size=2) # elif model == "2d_sphere": # alpha = 2 * math.pi * np.random.random() # x = 1. * math.cos(alpha) # y = 1. * math.sin(alpha) # point = [x, y] # elif model in ["2d_gaussian"]: # point = [np.random.normal(0.5, 0.15), np.random.normal(0.5, 0.15)] # while np.linalg.norm(point - np.array([0.5, 0.5])) > 0.5: # point = [np.random.normal(0.5, 0.15), np.random.normal(0.5, 0.15)] # elif model in ["3d_cube", "3d_uniform"]: # point = [np.random.random(), np.random.random(), np.random.random()] # elif model in ["5d_uniform"]: # dim = 5 # point = [np.random.random() for _ in range(dim)] # elif model in ["10d_uniform"]: # dim = 10 # point = [np.random.random() for _ in range(dim)] # elif model in {'3d_asymmetric'}: # if np.random.rand() < 0.3: # return np.random.normal(loc=0.25, scale=0.15, size=3) # else: # return np.random.normal(loc=0.75, scale=0.15, size=3) # elif model in ['3d_gaussian']: # point = [np.random.normal(0.5, 0.15), # np.random.normal(0.5, 0.15), # np.random.normal(0.5, 0.15)] # while np.linalg.norm(point - np.array([0.5, 0.5, 0.5])) > 0.5: # point = [np.random.normal(0.5, 0.15), # np.random.normal(0.5, 0.15), # np.random.normal(0.5, 0.15)] # elif model == "4d_cube": # dim = 4 # point = [np.random.random() for _ in range(dim)] # elif model == "5d_cube": # dim = 5 # point = [np.random.random() for _ in range(dim)] else: print('unknown culture_id', model) point = [0, 0] return point