Python实现CBAA算法(二)

一、内容介绍

本节使用机器人任务分配的例子,来加深CBAA算法的理解。与用户购买商品类似,机器人希望分配到相应的距离最近的任务进行工作,假设机器人i的初始位置为(x_{i},y_{i}),任务j的初始位置为(x_{j},y_{j}),那么相应的c_{ij}=-\sqrt{(x_{j}^{2}-x_{i}^{2})^2+(y_{j}^{2}-y_{i}^{2})^2},即越远的地方价值越低。假设机器人和任务目标的位置都已经给出,求出整个过程分配,使整体收获的价值最大。

二、代码解析

为了提高通用性,用类的方式来定义每个机器人,其包含的属性分别为第一节中介绍的x,y,J,c,其余算法与第一节介绍的相同,首先定义该类机器人的属性初始化

class CBAA_agent():
  def __init__(self,state, id=0, task=None):
    """
    c: individual score list
    x: local assignment list
    y: local winning bid list
    state: state of the robot
    """

    self.task_num = task.shape[0]

    # Local Task Assignment List
    self.x = [0 for i in range(self.task_num)]
    # Local Winning Bid List
    self.y = np.array([ -np.inf for _ in range(self.task_num)])
    # This part can be modified depend on the problem
    self.state = np.array([state])
    self.c = -distance_matrix(self.state,task).squeeze() # Score (Euclidean Distance)

    # Agent ID
    self.id = id

在主函数部分,其写法为:

if __name__=="__main__":

  task_num = 5
  robot_num = 5

  task = np.array([[0.4,0.3],[0.7,0.3],[0.4,0.7],[0.2,0.8],[0.1,0.9]])
  state = np.array([[0.1,0.7],[0.4,0.9],[0.35,0.25],[0.33,0.44],[0.22,0.33]])
  fig, ax = plt.subplots()
  ax.set_xlim((-0.1, 1.1))
  ax.set_ylim((-0.1, 1.1))
  ax.plot(task[:, 0], task[:, 1], 'rx')
  ax.plot(state[:,0],state[:,1], 'b^')
  robot_list = [CBAA_agent(state[i],id=i, task=task) for i in range(robot_num)]

然后定义方法,对于每个机器人进行任务筛选方法,写为

  def select_task(self):
    if sum(self.x) == 0:
      # Valid Task List
      h = (self.c > self.y)
      if h.any():
        # Just for euclidean distance score (negative)
        c = copy.deepcopy(self.c)
        c[h==False] = -np.inf

        self.J = np.argmax(c)
        self.x[self.J] = 1
        self.y[self.J] = self.c[self.J]

由于没有和其他机器人共享信息,在完成任务选择后,判断是否竞争成功,在主函数中,和其他机器人共享信息,代码如下:

 def send_message(self):
    """
    Return local winning bid list
    [output]
    y: winning bid list (list:task_num)
    """
    return self.y.tolist()
# 下面为主函数部分
G = np.ones((robot_num, robot_num)) # Fully connected network\
  # Configure network topology manually
  # G[0,1]=0
  # G[1,0]=0

  t = 0 # Iteration number
  assign_plots = []
  while True:
    converged_list = []

    print("==Iteration {}==".format(t))
    ## Phase 1: Auction Process
    print("Auction Process")
    for robot_id , robot in enumerate(robot_list):
      # select task by local information
      robot.select_task()
      # if t==0:
      #   assign_line, = ax.plot([robot.state[0][0],task[robot.J,0]],[robot.state[0][1],task[robot.J,1]],'k-',linewidth=2)
      #   assign_plots.append(assign_line)
      # else:
      #   assign_plots[robot_id].set_data([robot.state[0][0],task[robot.J,0]],[robot.state[0][1],task[robot.J,1]])
      print(robot.x)
    ## Phase 2: Consensus Process
    # plt.pause(0.5)

    print("Consensus Process")
    # Send winning bid list to neighbors (depend on env)
    message_pool = [robot.send_message() for robot in robot_list]

    for robot_id, robot in enumerate(robot_list):
      # Recieve winning bidlist from neighbors
      g = G[robot_id]

      connected, = np.where(g==1)
      connected = list(connected)
      connected.remove(robot_id)

      if len(connected) > 0:
        Y = {neighbor_id:message_pool[neighbor_id] for neighbor_id in connected}
      else:
        Y = None

      # Update local information and decision
      if Y is not None:
        converged = robot.update_task(Y)
        converged_list.append(converged)

      print(robot.x)

在已知其他机器人的竞争信息后,更新任务 

  def update_task(self, Y=None):
    """
    [input]
    Y: winning bid lists from neighbors (dict:{neighbor_id:bid_list})
    [output]
    converged: True or False
    """

    old_x = copy.deepcopy(self.x)

    id_list = list(Y.keys())
    id_list.insert(0, self.id)

    y_list = np.array(list(Y.values()))

    ## Update local winning bid list
    # When recive only one message
    if len(y_list.shape)==1:
      # make shape as (1,task_num)
      y_list = y_list[None,:]

    y_list = np.vstack((self.y[None,:],y_list))

    self.y = y_list.max(0)

    ## Outbid check
    # Winner w.r.t the updated local winning bid list
    max_id = np.argmax(y_list[:,self.J])
    z = id_list[max_id]
    # If the agent is not the winner
    if z != self.id:
        # Release the assignment
        self.x[self.J] = 0

    converged = False
    if old_x == self.x:
      converged = True

    return converged

整个任务的代码如图所示,结果给出

import numpy
import numpy as np
import copy
from scipy.spatial import distance_matrix
import matplotlib.pyplot as plt

class CBAA_agent():
  def __init__(self,state, id=0, task=None):
    """
    c: individual score list
    x: local assignment list
    y: local winning bid list
    state: state of the robot
    """

    self.task_num = task.shape[0]

    # Local Task Assignment List
    self.x = [0 for i in range(self.task_num)]
    # Local Winning Bid List
    self.y = np.array([ -np.inf for _ in range(self.task_num)])
    # This part can be modified depend on the problem
    self.state = np.array([state])
    self.c = -distance_matrix(self.state,task).squeeze() # Score (Euclidean Distance)

    # Agent ID
    self.id = id

  def select_task(self):
    if sum(self.x) == 0:
      # Valid Task List
      h = (self.c > self.y)
      if h.any():
        # Just for euclidean distance score (negative)
        c = copy.deepcopy(self.c)
        c[h==False] = -np.inf

        self.J = np.argmax(c)
        self.x[self.J] = 1
        self.y[self.J] = self.c[self.J]

  def update_task(self, Y=None):
    """
    [input]
    Y: winning bid lists from neighbors (dict:{neighbor_id:bid_list})
    [output]
    converged: True or False
    """

    old_x = copy.deepcopy(self.x)

    id_list = list(Y.keys())
    id_list.insert(0, self.id)

    y_list = np.array(list(Y.values()))

    ## Update local winning bid list
    # When recive only one message
    if len(y_list.shape)==1:
      # make shape as (1,task_num)
      y_list = y_list[None,:]

    y_list = np.vstack((self.y[None,:],y_list))

    self.y = y_list.max(0)

    ## Outbid check
    # Winner w.r.t the updated local winning bid list
    max_id = np.argmax(y_list[:,self.J])
    z = id_list[max_id]
    # If the agent is not the winner
    if z != self.id:
        # Release the assignment
        self.x[self.J] = 0

    converged = False
    if old_x == self.x:
      converged = True

    return converged

  def send_message(self):
    """
    Return local winning bid list
    [output]
    y: winning bid list (list:task_num)
    """
    return self.y.tolist()

if __name__=="__main__":

  task_num = 5
  robot_num = 5

  task = np.array([[0.4,0.3],[0.7,0.3],[0.4,0.7],[0.2,0.8],[0.1,0.9]])
  state = np.array([[0.1,0.7],[0.4,0.9],[0.35,0.25],[0.33,0.44],[0.22,0.33]])
  fig, ax = plt.subplots()
  ax.set_xlim((-0.1, 1.1))
  ax.set_ylim((-0.1, 1.1))
  ax.plot(task[:, 0], task[:, 1], 'rx')
  ax.plot(state[:,0],state[:,1], 'b^')
  robot_list = [CBAA_agent(state[i],id=i, task=task) for i in range(robot_num)]

  # Network Initialize
  G = np.ones((robot_num, robot_num)) # Fully connected network\
  # Configure network topology manually
  # G[0,1]=0
  # G[1,0]=0

  t = 0 # Iteration number
  assign_plots = []
  while True:
    converged_list = []

    print("==Iteration {}==".format(t))
    ## Phase 1: Auction Process
    print("Auction Process")
    for robot_id , robot in enumerate(robot_list):
      # select task by local information
      robot.select_task()
      # if t==0:
      #   assign_line, = ax.plot([robot.state[0][0],task[robot.J,0]],[robot.state[0][1],task[robot.J,1]],'k-',linewidth=2)
      #   assign_plots.append(assign_line)
      # else:
      #   assign_plots[robot_id].set_data([robot.state[0][0],task[robot.J,0]],[robot.state[0][1],task[robot.J,1]])
      print(robot.x)
    ## Phase 2: Consensus Process
    # plt.pause(0.5)

    print("Consensus Process")
    # Send winning bid list to neighbors (depend on env)
    message_pool = [robot.send_message() for robot in robot_list]

    for robot_id, robot in enumerate(robot_list):
      # Recieve winning bidlist from neighbors
      g = G[robot_id]

      connected, = np.where(g==1)
      connected = list(connected)
      connected.remove(robot_id)

      if len(connected) > 0:
        Y = {neighbor_id:message_pool[neighbor_id] for neighbor_id in connected}
      else:
        Y = None

      # Update local information and decision
      if Y is not None:
        converged = robot.update_task(Y)
        converged_list.append(converged)

      print(robot.x)


    t += 1

    if sum(converged_list)==robot_num:
      for robot_id, robot in enumerate(robot_list):
          assign_line, = ax.plot([robot.state[0][0],task[robot.J,0]],[robot.state[0][1],task[robot.J,1]],'k-',linewidth=2)
          assign_plots.append(assign_line)

      dpi = 500
      figure_size = (8,6)
      plt.savefig('Solution.png',dpi=dpi,bbox_inches='tight')
      plt.show()
      break

  print("CONVERGED")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值