Swarm-SLAM  1.0.0
C-SLAM Framework
broker.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 from cslam.algebraic_connectivity_maximization import EdgeInterRobot
3 import numpy as np
4 from networkx.algorithms import bipartite
5 import networkx as nx
6 
7 
8 class Broker(object):
9  """The broker decides which vertices in the matching
10  graph are to be shared between the robots.
11  """
12 
13  def __init__(self, edges, robots_involved):
14  """Initialize the broker
15 
16  Args:
17  edges (list(EdgeInterRobot)): _description_
18  robots_involved (list(int)): Robot ids of the
19  robots involved in the exchange
20  """
21  self.edgesedges = edges
22  robots_involved_with_edges = set()
23  for e in self.edgesedges:
24  if e.robot0_id in robots_involved:
25  robots_involved_with_edges.add(e.robot0_id)
26  if e.robot1_id in robots_involved:
27  robots_involved_with_edges.add(e.robot1_id)
28  robots_involved_with_edges = list(robots_involved_with_edges)
29  self.is_multi_robot_graphis_multi_robot_graph = len(robots_involved_with_edges) >= 2
30 
31  if self.is_multi_robot_graphis_multi_robot_graph:
32  if len(robots_involved_with_edges) == 2:
33  self.is_bipartiteis_bipartite = True
34  elif len(robots_involved_with_edges) > 2:
35  self.is_bipartiteis_bipartite = False
36  else:
37  raise Exception(
38  "Broker: The communication brokerage needs to be between at least 2 robots"
39  )
40 
41  # Build graph
42  self.matching_graphmatching_graph = nx.Graph()
43  for e in self.edgesedges:
44  edge_vertices = [(e.robot0_id, e.robot0_keyframe_id),
45  (e.robot1_id, e.robot1_keyframe_id)]
46  # Add vertices (required for bipartite)
47  for vertex in edge_vertices:
48  if vertex not in self.matching_graphmatching_graph:
49  if self.is_bipartiteis_bipartite:
50  if vertex[0] == robots_involved_with_edges[0]:
51  self.matching_graphmatching_graph.add_node(vertex,
52  bipartite=0)
53  elif vertex[0] == robots_involved_with_edges[1]:
54  self.matching_graphmatching_graph.add_node(vertex,
55  bipartite=1)
56  else:
57  if vertex[0] in robots_involved_with_edges:
58  self.matching_graphmatching_graph.add_node(vertex)
59  # Add edges
60  if edge_vertices[0][
61  0] in robots_involved_with_edges and edge_vertices[1][
62  0] in robots_involved_with_edges:
63  self.matching_graphmatching_graph.add_edge(edge_vertices[0],
64  edge_vertices[1])
65 
66  def brokerage(self, use_vertex_cover):
67  """Return the broker selection of vertices to send.
68  Either using vertex cover or simple dialog strategy.
69 
70  Args:
71  use_vertex_cover (bool): use vertex cover stratehy
72 
73  Returns:
74  List(set((int,int)): Vertices to be transmitted
75  """
76  if self.is_multi_robot_graphis_multi_robot_graph:
77  if use_vertex_cover:
78  return self.vertex_coververtex_cover()
79  else:
80  return self.simple_dialogsimple_dialog()
81  else:
82  return []
83 
84  def vertex_cover(self):
85  """Computes the minimum vertex cover over the edges
86  If the graph is bipartite: we compute the maximum matching and
87  recover the minimum vertex cover with Konig's theorem
88 
89  Otherwise, we use an approximate greedy algorithm.
90 
91  Returns:
92  List(set((int,int)): Vertices to be transmitted
93  """
94  vertex_covers = []
95  # Divide into components
96  matching_subgraphs = [
97  self.matching_graphmatching_graph.subgraph(c).copy()
98  for c in nx.connected_components(self.matching_graphmatching_graph)
99  ]
100  # Compute min cover on connected components
101  for graph in matching_subgraphs:
102  if self.is_bipartiteis_bipartite:
103  matching = nx.bipartite.maximum_matching(graph)
104  vertex_covers.append(
105  nx.bipartite.to_vertex_cover(graph, matching))
106  else:
107  vertex_covers.append(
108  nx.algorithms.approximation.vertex_cover.
109  min_weighted_vertex_cover(graph))
110  return vertex_covers
111 
112  def simple_dialog(self):
113  """Simple dialog exchange
114  For each edge, transmit one of the two vertices randomly
115  unless one of the 2 vertices is already transmitted.
116 
117  Returns:
118  List(set((int,int)): Vertices to be transmitted
119  """
120  vertices_dialog = set()
121  for e in self.edgesedges:
122  edge_vertices = [(e.robot0_id, e.robot0_keyframe_id),
123  (e.robot1_id, e.robot1_keyframe_id)]
124  if edge_vertices[0] not in vertices_dialog and edge_vertices[
125  1] not in vertices_dialog:
126  rand_idx = np.random.randint(2)
127  vertices_dialog.add(edge_vertices[rand_idx])
128 
129  return [vertices_dialog]
def __init__(self, edges, robots_involved)
Definition: broker.py:13
def vertex_cover(self)
Definition: broker.py:84
def brokerage(self, use_vertex_cover)
Definition: broker.py:66
def simple_dialog(self)
Definition: broker.py:112