ASYMM

This is an example on how to use the ASYMM class. See also the reference [FaGa19b].

examples/setups/asymm/launcher.py
import numpy as np
import networkx as nx
import dill as pickle
from mpi4py import MPI
from disropt.agents import Agent
from disropt.algorithms.asymm import ASYMM
from disropt.utils.graph_constructor import binomial_random_graph, metropolis_hastings
from disropt.functions import SquaredNorm, Norm, Variable
from disropt.problems import Problem

# get MPI info
comm = MPI.COMM_WORLD
nproc = comm.Get_size()
local_rank = comm.Get_rank()

# Generate a common graph (everyone use the same seed)
Adj = binomial_random_graph(nproc, p=1, seed=1)
W = metropolis_hastings(Adj)
graph = nx.DiGraph(Adj)
graph_diameter = nx.diameter(graph)

if local_rank == 0:
    print(Adj)

# create local agent
agent = Agent(in_neighbors=np.nonzero(Adj[local_rank, :])[0].tolist(),
              out_neighbors=np.nonzero(Adj[:, local_rank])[0].tolist(),
              in_weights=W[local_rank, :].tolist())

# problem set-up
n = 2

# target point
x_true = np.random.randn(n, 1)

if local_rank == 0:
    print(x_true)

# reset local seed
np.random.seed(10 * local_rank)

# local position
c = np.random.randn(n, 1)

# true distance
distance = np.linalg.norm(x_true-c, ord=2)

# declare a variable
x = Variable(n)

# define the local objective function
objective = (x -c) @ (x - c)

# local constraint
upper_bound = (x-c) @ (x-c) <= (distance**2 + 0.00001*np.random.rand())
lower_bound = (x-c) @ (x-c) >= (distance**2 - 0.00001*np.random.rand())

constraints = [upper_bound, lower_bound]
# define local problem
pb = Problem(objective_function=objective, constraints=constraints)
agent.set_problem(pb)

####
x0 = np.random.randn(n, 1)
algorithm = ASYMM(agent=agent,
                  graph_diameter=graph_diameter,
                  initial_condition=x0,
                  enable_log=True)

timestamp_sequence_awake, timestamp_sequence_sleep, sequence = algorithm.run(running_time=30.0)

# print solution
print("Agent {}:\n value: {}\n".format(agent.id, algorithm.get_result()))

# save data
with open('agent_{}_constraints.pkl'.format(agent.id), 'wb') as output:
    pickle.dump(agent.problem.constraints, output, pickle.HIGHEST_PROTOCOL)
np.save("agents.npy", nproc)
np.save("agent_{}_sequence.npy".format(agent.id), sequence)
np.save("agent_{}_timestamp_sequence_awake.npy".format(agent.id), timestamp_sequence_awake)
np.save("agent_{}_timestamp_sequence_sleep.npy".format(agent.id), timestamp_sequence_sleep)
examples/setups/asymm/results.py
import numpy as np
import dill as pickle
import matplotlib.pyplot as plt


# number of agents
N = np.load("agents.npy")

# retrieve local sequences
sequence = {}
constraints = {}
timestamp_sequence_awake = {}
timestamp_sequence_sleep = {}
colors = {}
t_init = None
for i in range(N):
    colors[i] = np.random.rand(3, 1).flatten()
    filename = "agent_{}_sequence.npy".format(i)
    sequence[i] = np.load(filename, allow_pickle=True)

    filename = "agent_{}_timestamp_sequence_awake.npy".format(i)
    timestamp_sequence_awake[i] = np.load(filename, allow_pickle=True)

    filename = "agent_{}_timestamp_sequence_sleep.npy".format(i)
    timestamp_sequence_sleep[i] = np.load(filename, allow_pickle=True)

    if t_init is not None:
        m = min(timestamp_sequence_awake[i])
        t_init = min(t_init, m)
    else:
        t_init = min(timestamp_sequence_awake[i])

    with open('agent_{}_constraints.pkl'.format(i), 'rb') as input:
        constraints[i] = pickle.load(input)

for i in range(N):
    timestamp_sequence_awake[i] = timestamp_sequence_awake[i] - t_init
    timestamp_sequence_sleep[i] = timestamp_sequence_sleep[i] - t_init

# plot
plt.figure()
for i in range(N):
    dims = sequence[i].shape
    for j in range(dims[1]):
        for m in range(dims[2]):
            plt.plot(timestamp_sequence_sleep[i], sequence[i][:, j, m])
plt.ylim([-5, 5])

# # plt
plt.figure()
for i in range(N):
    dims = sequence[i].shape
    iterations = dims[0]
    print("Agent {}, iterations {}".format(i, iterations))
    feasibility = np.zeros([iterations, 2])
    for k in range(iterations):
        for idx, constr in enumerate(constraints[i]):
            flag = constr.eval((sequence[i][k, :, :]).reshape(2,1))
            if flag == False:
                feasibility[k, idx] += abs(constr.function.eval((sequence[i][k, :, :]).reshape(2,1)).flatten())
    plt.semilogy(timestamp_sequence_sleep[i], feasibility)
# plt.lim([-1, 15])

plt.show()

The two files can be executed by issuing the following commands in the example folder:

> mpirun -np 30 --oversubscribe python launcher.py
> python results.py