Advertisement
AmCholadawan

multi_agent_island_map_v1

Apr 1st, 2018
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 51.98 KB | None | 0 0
  1. from collections import namedtuple
  2. from collections import OrderedDict
  3. from enum import Enum
  4. from matplotlib import pyplot as plt
  5. import os
  6. import csv
  7. import numpy as np
  8. import copy
  9. import random
  10. import time
  11. from datetime import datetime
  12. import struct
  13. import pickle
  14. import sys
  15. from scipy.ndimage.interpolation import zoom
  16.  
  17. #import levyrandom2
  18. #import levywalklike
  19.  
  20. # test merge
  21.  
  22.  
  23. class slicee:
  24.     """
  25.     Creates an array of start and stop value pairs (with optional step
  26.     values)
  27.  
  28.      Examples
  29.     --------
  30.     >>> slicee()[0, 1:2, ::5, ...]
  31.     # '(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'
  32.  
  33.     References
  34.     ----------
  35.     .. [#] Python's slice notation. StackOverflow.
  36.        http://stackoverflow.com/questions/509211/explain-pythons-slice-notation
  37.  
  38.  
  39.     """
  40.     def __getitem__(self, item):
  41.         return item
  42.  
  43. dateStr = time.strftime('%Y-%m-%d')
  44. #timeStr = time.strftime('%Y-%m-%d_%H_%M_%S')
  45. timeStr = datetime.utcnow().strftime('%Y-%m-%d%H%M%S%f')[:-3]
  46. #timeStr1 = datetime.utcnow()
  47. #timeStr = timeStr1.strftime('%Y-%m-%d%H%M%S%f')[:-3]
  48.  
  49. # set model parameters
  50. # give your data set directory a name
  51. dataSetName = "Finitefood" #+ dateStr
  52. #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  53. n_cells = 10000 #400                         # must be square number
  54.  
  55. if len(sys.argv) > 2:
  56.     n_bots =  int(sys.argv[2]) #169
  57. else:
  58.     n_bots = 1
  59.  
  60. print(type(n_bots))
  61.  
  62. #max_food_per_cell = 100
  63. if len(sys.argv) > 1:
  64.     max_food_per_cell = int(sys.argv[3]) #1
  65. else:
  66.     max_food_per_cell = 100
  67.  
  68.  
  69. food_cell_value = "max_food_per_cell"   # "random", "max_food_per_cell"
  70. plot_output = False                    #  plots and saves output data
  71. show_plot = True                      #  displays data during simulation
  72. #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  73. trophallaxis = True
  74. FiniteFood = True
  75. #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  76. scavenge = True
  77. food_map_style = "island_map"          # "existing_map", "new_map", "central_map", "density_map", "island_map"
  78. bot_map_style = "central_map"           # "existing_map", "new_map", "random_map", "central_map"
  79. maxTimesteps = 1
  80.  
  81. food_tick = 3
  82.  
  83. if food_map_style == "density_map":     # specify the density and the number of blocks
  84.     food_map_density = 10               # % of density in each block
  85.     blocks = 1                          # number of block in n_cells
  86.  
  87. if food_map_style == "island_map":      # specify the parameters for island_map mode
  88.     is_binary_island = 1                # 1 to generate a binary island to fill with populate_food_cells
  89.                                         # 0 to generate a smooth gradient map
  90.     noise_size = 5                     # size of the uniform noise kernel before zoom op
  91.     noise_threshold = 0.3               # % of area covered by land
  92.  
  93. if food_map_style == "central_map":     # set dimensions of food patches:
  94.     if len(sys.argv) > 1:
  95.         n_food_cells = int(sys.argv[1]) #1
  96.     else:
  97.         n_food_cells = 100
  98.  
  99. if food_map_style == "new_map":         # set dimensions of food patches:
  100.     if len(sys.argv) > 1:
  101.         food_offset = int(sys.argv[1]) #1
  102.     else:
  103.         food_offset = 5
  104.  
  105.     bot_length = n_bots ** (1/2)
  106.     half_bot_length = bot_length/2
  107.     n_cells_length = n_cells ** (1/2)
  108.     mid_n_cells = n_cells_length/2
  109.     bot_edge_plus = mid_n_cells + half_bot_length
  110.     bot_edge_neg = mid_n_cells - half_bot_length
  111.     food_in_edge_plus = bot_edge_plus + food_offset
  112.     food_in_edge_neg = bot_edge_neg - food_offset
  113.     food_out_edge_plus = food_in_edge_plus + food_tick
  114.     food_out_edge_neg = food_in_edge_neg - food_tick        
  115.        
  116.     food_y_range = slicee()[food_out_edge_neg:food_in_edge_plus,
  117.                             food_in_edge_plus:food_out_edge_plus,
  118.                             food_in_edge_neg:food_out_edge_plus,
  119.                             food_out_edge_neg:food_in_edge_neg,]
  120.     food_x_range = slicee()[food_out_edge_neg:food_in_edge_neg,
  121.                             food_out_edge_neg:food_in_edge_plus,
  122.                             food_in_edge_plus:food_out_edge_plus,
  123.                             food_in_edge_neg:food_out_edge_plus,]  
  124.    
  125.     # food_y_range = slicee()[1:2, 4:6,]
  126.     # food_x_range = slicee()[1:2, 4:6,]
  127. #    food_y_range = slicee()[3:7, ]
  128. #    food_x_range = slicee()[3:7, ]
  129.  
  130. if bot_map_style == "new_map":  # set dimensions of bot groups:
  131.     bot_y_range = slicee()[3:7, ]
  132.     bot_x_range = slicee()[3:7, ]
  133.  
  134. if bot_map_style == "random":
  135.     set_number_agents_on_food = True
  136.     n_agents_on_food = 2
  137.  
  138. if bot_map_style == "existing_map":  # input names of previous data
  139.     bot_map_dir = "Data.07-02-2016_00_25_05_JST"
  140.     bot_map_name = "Data.07-02-2016_00_25_05_JST"
  141.  
  142. if food_map_style == "existing_map": # input names of previous data
  143.     food_map_dir = "Data.07-02-2016_00_25_05_JST"
  144.     food_map_name = "Data.07-02-2016_00_25_05_JST"
  145.  
  146.  
  147. BOT_DEFAULTS = OrderedDict([
  148.     ("base_metabolism", 0),
  149.     ("EinPerFeed", 10),
  150.     ("eff_E_conversion", 1),
  151.     ("t_steps_to_charge", 5),
  152.     ("Estored_init", 50),
  153.     ("Estored_max", 100),
  154.     ("Eth_battFull", 0),
  155.     ("Ecost_perStep", 1),
  156.     #("Ecost_perFeed", 1),
  157.     ("senseRange", 1),
  158.     ("scavenge", scavenge),
  159.     ("trophallaxis", trophallaxis),
  160.     ("trophMode", "cautious"),  # "equalise", "cautious", "selfless"
  161. ])
  162.  
  163. """dict: Default values for bot construction."""
  164.  
  165. SENSING_TARGETS = {
  166.     "neighbour_on_food": 2,
  167.     "neighbour_not_on_food": 1,
  168.     "neighbouring_recruits" : 1,
  169.     "neighbouring_bot" : 1,
  170.     "neighbouring_space": 0,
  171. }
  172. """dict: Potential targets that can be sensed."""
  173.  
  174. # random seed is random choice.
  175. # replace with set values for repeated output
  176. seed_np = np.random.randint(0, 2**32 - 1)
  177. seed_random = np.random.randint(0, 2**32 - 1)
  178. np.random.seed(seed_np)
  179. random.seed(seed_random)
  180.  
  181. # the path to where you want to save the data
  182. dirname = os.path.abspath(os.path.join(
  183.     os.path.dirname( __file__ ),
  184.     '../../..',
  185.     "simulation_results"
  186.     + "/" + "self_energy_robot"
  187.     + "/" + "test11"
  188.     + "/" + "island_map"
  189.     ))
  190.  
  191. path =  dirname + "/" + dataSetName
  192.  
  193. # give each run in the data set a unique name
  194. dataName = "Bots" + str(n_bots) + "Island" + "Maxfood" + str(max_food_per_cell) + "_" + timeStr   #Maxfood = initial max_food_per_cells
  195. #print("current data", dataName)
  196.  
  197. # directory to store plot data
  198. os.makedirs(path
  199.             + "/" + dataName
  200.             + "/" + "plot_data")
  201.  
  202. # os.makedirs(path + "/"
  203. #             + dataName
  204. #             + "/figures")
  205.  
  206. dataTimestep = path \
  207.                + "/" + dataName  \
  208.                + "/" + dataName + '_dataTimestep.csv'
  209.  
  210. dataSummary = path \
  211.               + "/" + dataName  \
  212.               + "/" + dataName + '_dataSummary.csv'
  213.  
  214. data_per_timestep = ["count",
  215.                      "total_food",
  216.                      "food_patches",
  217.                      "bots_with_Estored",
  218.                      "area_covered",
  219.                      "total_steps_taken",
  220.                      "max_energy_stored",
  221.                      "trophallaxis",
  222.                      ]
  223. count = 1
  224. trophallaxis_value = 0
  225. start_time = time.time()
  226.  
  227. Location = namedtuple("Location", ("x", "y"))
  228.  
  229. class Food(object):
  230.     """
  231.  Maps the distribution of food over the grid space.
  232.  
  233.  Parameters
  234.  ----------
  235.  food_map_style :
  236.      The name of the method used to construct the food map.
  237.  n_cells : int
  238.     The number of cells with individual values that the food map is
  239.     discretised into.
  240.  max_food_per_cell : int
  241.     The maximum value of a food cell.
  242.  
  243.  Attributes
  244.  ----------
  245.  n_cells : int
  246.     The number of cells with individual values that the food map is
  247.     discretised into.
  248.  map_size : int
  249.      The length of each side of the food map in grid cells.
  250.  max_food_per_cell : int
  251.     The maximum value of a food cell.
  252.  food_map : array
  253.     The distribution of food across the grid space, food cell discretisation.
  254.  
  255.  """
  256.     def __init__(self):
  257.  
  258.         self.food_map_style = food_map_style
  259.         self.n_cells = n_cells
  260.         self.map_size = int(np.sqrt(self.n_cells))
  261.         self.max_food_per_cell = max_food_per_cell
  262.         self.food_map = np.zeros(self.n_cells)
  263.  
  264.         if food_map_style == "existing_map":
  265.  
  266.             self.food_map = np.load(food_map_dir
  267.                                     + "/" + food_map_name
  268.                                     + "/" + food_map_name
  269.                                     + "_food.npy")
  270.             map_name = food_map_name
  271.  
  272.         elif food_map_style == "new_map":
  273.             self._new_map()
  274.             map_name = dataName
  275.  
  276.         elif food_map_style == "central_map":
  277.             self._central_map()
  278.             map_name = dataName
  279.            
  280.         elif food_map_style == "density_map":
  281.             self._density_map(food_map_density, blocks)
  282.             map_name = dataName
  283.  
  284.         elif food_map_style == "island_map":
  285.             self._island_map(is_binary_island, noise_size, noise_threshold)
  286.             map_name = dataName
  287.  
  288.         food_map_name = path \
  289.                         + "/" + dataName \
  290.                         + "/" + map_name
  291.  
  292.         np.save(food_map_name + "_food", self.food_map)
  293.         self.total_food_initial = np.sum(self.food_map)
  294.         self.total_food_cells_initial = len(np.argwhere(self.food_map))
  295.  
  296.     def _new_map(self):
  297.         self.food_map = np.reshape(self.food_map,
  298.                                    (self.map_size,self.map_size))
  299.  
  300.         for y, x in zip(food_y_range, food_x_range):
  301.             self.food_map[y, x] = 1
  302.  
  303.         self.populate_food_cells()
  304.  
  305.     def _central_map(self):
  306.         self.food_map = np.reshape(self.food_map,
  307.                                    (self.map_size, self.map_size))
  308.  
  309.         _midpoint = int(self.map_size / 2)
  310.         _sideLength = int(np.sqrt(n_food_cells))
  311.         _lower = int(_midpoint - (_sideLength / 2))
  312.         _upper = int(_lower + _sideLength)
  313.         _range = np.arange(_lower, _upper, 1)
  314.  
  315.         for y in _range:
  316.             for x in _range:
  317.                 self.food_map[y, x] = 1
  318.  
  319.         self.populate_food_cells()
  320.    
  321.     def _density_map(self, food_map_density, blocks):
  322.         self.food_map = np.reshape(self.food_map,
  323.                                    (self.map_size, self.map_size))
  324.        
  325.         self.cells_per_block = int(n_cells / blocks)
  326.         self.blocks_per_side = int(np.sqrt(blocks))
  327.         self.block_size = int(self.map_size / self.blocks_per_side)
  328.         self.n_food_cells = int(self.cells_per_block * food_map_density / 100)
  329.        
  330.         for col in range(self.blocks_per_side):
  331.             for row in range(self.blocks_per_side):
  332.                 self.food_cells = np.random.choice(self.cells_per_block, self.n_food_cells, replace=False)
  333.                 for cell in self.food_cells:
  334.                     self.food_map[(col * self.block_size) + (cell % self.block_size),
  335.                                   (row * self.block_size) + (cell // self.block_size)] = 1
  336.                          
  337.         #self.populate_food_cells()
  338.         for x, y in np.argwhere(self.food_map):
  339.             self.food_map[x, y] = self.max_food_per_cell
  340.  
  341.     def _island_map(self, is_binary_island, noise_size, noise_threshold):
  342.         self.food_map = np.reshape(self.food_map,
  343.                                    (self.map_size, self.map_size))
  344.        
  345.         noise_map = np.random.uniform(size=(noise_size,noise_size))
  346.  
  347.         if is_binary_island == 1:
  348.             noise_map = zoom(noise_map, self.map_size / noise_size)
  349.             noise_map = noise_map > noise_threshold
  350.             noise_map = np.where(noise_map, 0, 1)
  351.             self.food_map = noise_map
  352.             self.populate_food_cells()
  353.        
  354.         elif is_binary_island == 0:
  355.             #noise_map = [[int(10 * element) for element in line] for line in noise_map]
  356.             noise_map = zoom(noise_map, self.map_size / noise_size)
  357.             self.food_map = noise_map
  358.            
  359.             for x, y in np.argwhere(self.food_map):
  360.                 factor = self.food_map[x, y]
  361.                 if factor >= 0:
  362.                     self.food_map[x, y] = self.max_food_per_cell * factor
  363.                 else:
  364.                     self.food_map[x, y] = 0
  365.  
  366.     def populate_food_cells(self):
  367.         # food on each cell
  368.         y, x = np.nonzero(self.food_map)
  369.         for X, Y in zip(x, y):
  370.  
  371.             if food_cell_value == "max_food_per_cell":
  372.                 self.food_map[X, Y] = self.max_food_per_cell
  373.  
  374.             if food_cell_value == "random":
  375.                 # set limits
  376.                 food_cell_values = range(BOT_DEFAULTS['Ein_perFeed'],
  377.                                          self.max_food_per_cell + 1,
  378.                                          BOT_DEFAULTS['Ein_perFeed'])
  379.                 self.food_map[X, Y] = random.choice(food_cell_values)
  380.  
  381.     def __repr__(self):
  382.         return "Food({}, {}, {})".format(
  383.             self.n_cells,
  384.             self.map_size,
  385.             self.max_food_per_cell,)
  386.  
  387.     def __str__(self):
  388.         return str(self.food_map)
  389.  
  390. class Bot(object):
  391.     """
  392.  Robot agents that travel around the grid space, eating the food.
  393.  
  394.  Parameters
  395.  ----------
  396.  base_metabolism : int
  397.      The base energy consumption per simulation step of each bot
  398.  Eremoved_perFeed : int
  399.      The amount of energy removed from the cell on the food map on which a
  400.      bot is located every time athe bot feeds.
  401.  Estored_init : float
  402.      The amount of stored energy the bots are initialised with.
  403.  Ecost_perStep : int
  404.      The energy consumed by the bot for each step of size = one grid space.
  405.  Eth_explore : int
  406.      The stored energy threshold that prompts bots to change their task from
  407.      storing energy to exploring.
  408.  Eth_store : int
  409.      The stored energy threshold that prompts bots to change their task from
  410.      exploring to storing energy and aggregating bots around the
  411.      source of energy.
  412.  Eth_troph : int
  413.      The stored energy threshold at which the bot begins sharing energy with
  414.      others.
  415.  Eth_battFull : int
  416.      The stored energy threshold at which a bot stops receiving energy during
  417.      trophallaxis.
  418.  Estored_max : int.
  419.      The value of stored energy above which feeding does not increase the
  420.  senseRange, : int
  421.      The thickness of the border around the bot location within which
  422.      cells are considered in sensing operations.
  423.  troph : logical
  424.      Boolean value for whether bots feed each other or not.
  425.  trophMode : string
  426.      The name of the method the bot uses when feeding bots.
  427.  eff_E_conversion : int
  428.      The efficency (maximum = 1) with which energy removed from the food
  429.      map is converted to stored energy.
  430.  t_steps_to_charge : int
  431.      The number of time steps the bot takes for the converted energy to be
  432.      stored.
  433.  
  434.  Attributes
  435.  ----------
  436.  base_metabolism : int
  437.      The base energy consumption per simulation step of each bot
  438.  Eremoved_perFeed : int
  439.      The amount of energy removed from the cell on the food map on which a
  440.      bot is located every time athe bot feeds.
  441.  Estored_init : float
  442.      The amount of stored energy the bots are initialised with.
  443.  Ecost_perStep : int
  444.      The energy consumed by the bot for each step of size = one grid space.
  445.  Eth_explore : int
  446.      The stored energy threshold that prompts bots to change their task from
  447.      storing energy to exploring.
  448.  Eth_store : int
  449.      The stored energy threshold that prompts bots to change their task from
  450.      exploring to storing energy and aggregating bots around the
  451.      source of energy.
  452.  Eth_troph : int
  453.      The stored energy threshold at which the bot begins sharing energy with
  454.      others.
  455.  Eth_battFull : int
  456.      The stored energy threshold at which a bot stops receiving energy during
  457.      trophallaxis.
  458.  Estored_max : int.
  459.      The value of stored energy above which feeding does not increase the
  460.  senseRange, : int
  461.      The thickness of the border around the bot location within which
  462.      cells are considered in sensing operations.
  463.  troph : logical
  464.      Boolean value for whether bots feed each other or not.
  465.  trophMode : string
  466.      The name of the method the bot uses when feeding bots.
  467.  eff_E_conversion : int
  468.      The efficency (maximum = 1) with which energy removed from the food
  469.      map is converted to stored energy.
  470.  t_steps_to_charge : int
  471.      The number of time steps the bot takes for the converted energy to be
  472.      stored.
  473.  E_stored : float
  474.      The cumulative energy from feeding less the energy consumed.
  475.  location : tuple
  476.      The x, y coordinates of the bot location on the bot map.
  477.  new_location_generator : string
  478.      The name of the method the bot uses to choose a new location on the bot
  479.      map to attempt to move to.
  480.  new_location_generators : dictionary
  481.      The possible new location generators used by the bot.
  482.  target_location : tuple
  483.      The x, y coordinates of the location on the bot map that the bot will
  484.      attempt to move to.
  485.  
  486.  
  487.  
  488.  
  489.  bots : list
  490.      A list of all the bots that exist.
  491.  sense_kernel : array
  492.      A kernel of values used in bot operations that "sense" the cells
  493.      surrounding the bot, with the footprint of the sensed cells equal to the
  494.      dimensions of the kernel.
  495.  
  496.  """
  497.     bots = []
  498.  
  499.     sense_kernel = np.zeros((2 * BOT_DEFAULTS["senseRange"]+ 1) ** 2)
  500.     sense_kernel[(len(sense_kernel) // 2)] = 1
  501.     kernel_size = np.sqrt(len(sense_kernel))
  502.     sense_kernel = np.reshape(sense_kernel, (kernel_size, kernel_size))
  503.  
  504.     def __init__(self, world, *,
  505.                  base_metabolism,
  506.                  EinPerFeed,
  507.                  eff_E_conversion,
  508.                  t_steps_to_charge,
  509.                  Estored_init,
  510.                  Estored_max,
  511.                  Eth_battFull,
  512.                  Ecost_perStep,
  513.                  #Ecost_perFeed,
  514.                  senseRange,
  515.                  trophallaxis,
  516.                  scavenge,
  517.                  trophMode):
  518.  
  519.         self.base_metabolism = base_metabolism
  520.         self.EinPerFeed = EinPerFeed
  521.         self.Estored_init = Estored_init
  522.         self.Ecost_perStep = Ecost_perStep
  523.         self.Eth_battFull = Eth_battFull
  524.         self.Estored_max = Estored_max
  525.         self.senseRange = senseRange
  526.         self.troph = trophallaxis
  527.         self.scavenge = scavenge
  528.         self.trophMode = trophMode
  529.         self.eff_E_conversion = eff_E_conversion
  530.         self.t_steps_to_charge = t_steps_to_charge
  531.         self.Estored = Estored_init
  532.         self.location = None
  533.         self.new_location_generator = "random"
  534.         self.target_location = None
  535.         self.bots.append(self)
  536.  
  537.         self.new_location_generators = {
  538.             "random": self.new_location_random,
  539.             "levy": self.new_location_levy,
  540.             "levy_jump": self.new_location_levy_jump,
  541.             "levywalklike": self.new_location_levywalklike,
  542.         }
  543.  
  544.         self.levylastdirection = [0, 0]
  545.         self.levystepsleft = 0
  546.  
  547.     def sense(self, map, sensing_target):
  548.         """
  549.      Checks if bot has any neighbouring bots/ spaces/ recruits
  550.      Parameters
  551.      ----------
  552.      map : array
  553.          The map whose contents are being sensed.
  554.      sensing_target : string
  555.          The item to search for.
  556.  
  557.      Returns
  558.      -------
  559.      list[Location]
  560.          The location of all neighbours of the target type.
  561.  
  562.      """
  563.         # top left hand corner of kernel = i, j
  564.         i = self.location.y - BOT_DEFAULTS["senseRange"]
  565.         j = self.location.x - BOT_DEFAULTS["senseRange"]
  566.         k = np.shape(Bot.sense_kernel)[0]
  567.  
  568.         neighbours = np.argwhere(map[i:i + k, j:j + k]
  569.                                  - Bot.sense_kernel ==
  570.                                  SENSING_TARGETS[sensing_target])
  571.  
  572.         return [Location(x + j, y + i) for y, x in neighbours]
  573.  
  574.     def evaluate_neighbours(self, world):
  575.         """
  576.  
  577.      Parameters
  578.      ----------
  579.      world : object
  580.          The world in which the bots live
  581.  
  582.      Returns
  583.      -------
  584.  
  585.      """
  586.         location = self.location
  587.         #print(self.location)
  588.  
  589.         neighbours = self.sense(np.ma.make_mask(world.bot_map) * 1,
  590.                                 "neighbouring_bot")
  591.  
  592.         # print("neighbours", neighbours)
  593.         #
  594.         # print(world.food_map)
  595.         #
  596.         # bot_on_food = bool((np.ma.make_mask(world.food_map) * 1))
  597.         #                    [location[::-1]])
  598.         #
  599.         # print(bot_on_food)
  600.         #
  601.         # print("on food", bot_on_food)
  602.  
  603.         if neighbours == []:
  604.             pass
  605.  
  606.         else:
  607.             return neighbours  # neighbours_food
  608.             # CATAGORISES NEIGHOURS BY FOOD VALUE OF CURRENT LOCATION
  609.             # neighbours = {}
  610.             #
  611.             # bot_not_on_food_map = np.ma.make_mask(world.bot_map) * 1 - \
  612.             #                   np.ma.make_mask(world.food_map) * 1
  613.             #
  614.             # bot_on_food_map = np.ma.make_mask(world.bot_map) * 1 + \
  615.             #               np.ma.make_mask(world.food_map) * 1
  616.             #
  617.             # if bot_on_food:
  618.             #     neighbours["bot1_neighbour0"] = \
  619.             #         self.sense(bot_not_on_food_map, "neighbour_not_on_food")
  620.             #
  621.             #     neighbours["bot1_neighbour1"] = \
  622.             #         self.sense(bot_on_food_map, "neighbour_on_food")
  623.             #
  624.             # else:  # if food cell empty
  625.             #
  626.             #     neighbours["bot0_neighbour0"] = \
  627.             #         self.sense(bot_not_on_food_map,"neighbour_not_on_food")
  628.             #
  629.             #     neighbours["bot0_neighbour1"] = \
  630.             #         self.sense(bot_on_food_map, "neighbour_on_food")
  631.  
  632.  
  633.  
  634.     def new_location_random(self, location, world):
  635.         """
  636.      Determines the next space the bot will attempt to move to.
  637.  
  638.      Parameters
  639.      ----------
  640.      initial_location: named tuple
  641.          The x,y coordinates of position the bot will attempt to move from.
  642.  
  643.      Returns
  644.      -------
  645.      new_location : name tuple
  646.          The x,y coordinates of next position the bot will attempt to move to.
  647.      """
  648.  
  649.         new_location = Location(
  650.             np.clip(location.x + random.randint(-1, 1),
  651.                     BOT_DEFAULTS["senseRange"],
  652.                     world.bot_map_size - 1
  653.                     - BOT_DEFAULTS["senseRange"]),
  654.             np.clip(location.y + random.randint(-1, 1),
  655.                     BOT_DEFAULTS["senseRange"],
  656.                     world.bot_map_size - 1
  657.                     - BOT_DEFAULTS["senseRange"]))
  658.  
  659.         return new_location
  660.  
  661.     """Levy related functions"""
  662.     def new_location_levy(self, location, world):
  663.         """
  664.       Determines the next space the bot will attempt to move to.
  665.  
  666.       Parameters
  667.       ----------
  668.       initial_location: named tuple
  669.           The x,y coordinates of position the bot will attempt to move from.
  670.  
  671.       Returns
  672.       -------
  673.       new_location : name tuple
  674.           The x,y coordinates of next position the bot will attempt to move to.
  675.       """
  676.  
  677.         if self.levystepsleft == 0:
  678.             levystep = levyrandom2.direction()
  679.             new_direction = levystep[0]
  680.             self.levylastdirection = new_direction
  681.             self.levystepsleft = levystep[1] -1
  682.         else:
  683.             new_direction = self.levylastdirection
  684.             self.levystepsleft -= 1
  685.  
  686.         new_location = Location(
  687.             np.clip(location.x + new_direction[0],
  688.                     BOT_DEFAULTS["senseRange"],
  689.                     world.bot_map_size - 1
  690.                     - BOT_DEFAULTS["senseRange"]),
  691.             np.clip(location.y + new_direction[1],
  692.                     BOT_DEFAULTS["senseRange"],
  693.                     world.bot_map_size - 1
  694.                     - BOT_DEFAULTS["senseRange"]))
  695.  
  696.         return new_location
  697.  
  698.     def new_location_levy_jump(self, location, world):
  699.         """
  700.       Determines the next space the bot will attempt to move to.
  701.  
  702.       Parameters
  703.       ----------
  704.       initial_location: named tuple
  705.           The x,y coordinates of position the bot will attempt to move from.
  706.  
  707.       Returns
  708.       -------
  709.       new_location : name tuple
  710.           The x,y coordinates of next position the bot will attempt to move to.
  711.       """
  712.  
  713.         levystep = levyrandom2.direction()
  714.         new_direction = [levystep[0][0] * levystep[1], levystep[0][1] * levystep[1]]
  715.  
  716.         new_location = Location(
  717.             np.clip(location.x + new_direction[0],
  718.                     BOT_DEFAULTS["senseRange"],
  719.                     world.bot_map_size - 1
  720.                     - BOT_DEFAULTS["senseRange"]),
  721.             np.clip(location.y + new_direction[1],
  722.                     BOT_DEFAULTS["senseRange"],
  723.                     world.bot_map_size - 1
  724.                     - BOT_DEFAULTS["senseRange"]))
  725.  
  726.         return new_location
  727.  
  728.     def new_location_levywalklike(self, location, world):
  729.         """
  730.       Determines the next space the bot will attempt to move to.
  731.  
  732.       Parameters
  733.       ----------
  734.       initial_location: named tuple
  735.           The x,y coordinates of position the bot will attempt to move from.
  736.  
  737.       Returns
  738.       -------
  739.       new_location : name tuple
  740.           The x,y coordinates of next position the bot will attempt to move to.
  741.       """
  742.        
  743.         probability = 80 # in range [0, 100]
  744.  
  745.         new_direction = levywalklike.direction(probability, self.levylastdirection)
  746.         self.levylastdirection = new_direction
  747.  
  748.         new_location = Location(
  749.             np.clip(location.x + new_direction[0],
  750.                     BOT_DEFAULTS["senseRange"],
  751.                     world.bot_map_size - 1
  752.                     - BOT_DEFAULTS["senseRange"]),
  753.             np.clip(location.y + new_direction[1],
  754.                     BOT_DEFAULTS["senseRange"],
  755.                     world.bot_map_size - 1
  756.                     - BOT_DEFAULTS["senseRange"]))
  757.  
  758.         return new_location
  759.     """/Levy related functions"""
  760.  
  761.     def move(self, world, location):
  762.         """
  763.      Moves the bot and updates the stroed energy accordingly.
  764.  
  765.      Parameters
  766.      ----------
  767.      new_location : Location
  768.          The location to move to.
  769.      """
  770.  
  771.         # stop charging
  772.         world.charge_map[location] = 0
  773.  
  774.         # select a target neighbouring lement address to move to
  775.         new_location = self.new_location_generators[
  776.             str(self.new_location_generator)](
  777.             location,
  778.             world)
  779.  
  780.         world.bot_map[location[::-1]].update_maps(world,
  781.                                                   new_location,
  782.                                                   location)
  783.  
  784.         world.Acovered_map += np.copy(np.ma.make_mask(world.bot_map) * 1)
  785.  
  786.         #world.Acovered_map += np.ma.make_mask(world.bot_map) * 1
  787.  
  788.  
  789.     def update_maps(self, world, new_location, initial_location):
  790.  
  791.         maps_to_update = [world.move_map,
  792.                           world.Estored_map,
  793.                           world.bot_map]
  794.  
  795.         for _map in maps_to_update:
  796.             if isinstance(_map[initial_location[::-1]], Bot):
  797.                 new_value = _map[initial_location[::-1]]
  798.  
  799.             else:
  800.                 new_value = np.clip((_map[initial_location[::-1]]
  801.                                      - BOT_DEFAULTS["Ecost_perStep"]),
  802.                                      0, float("inf"))
  803.  
  804.             # DOES NOT MOVE
  805.             if world.bot_map[new_location[::-1]]:
  806.                 _map[initial_location[::-1]] = new_value
  807.  
  808.             # MOVES
  809.             elif world.bot_map[new_location[::-1]] == None:
  810.                 _map[new_location[::-1]] = new_value
  811.  
  812.                 # delete initial location
  813.                 if isinstance(_map[initial_location[::-1]], Bot):
  814.                     _map[initial_location[::-1]] = None
  815.                 else:
  816.                     _map[initial_location[::-1]] = 0
  817.  
  818.     def trophallaxis(self, world, neighbours):
  819.         #print("TROPHALAXIS")
  820.         # TODO: create a trophallaxis map of robots engagaed in trophallaxis so
  821.         # that only one exchnage happens per robot per timestep
  822.         global trophallaxis_value
  823.         if world.charge_map[self.location[::-1]] != 0:
  824.             # random.shuffle(neighbours)
  825.             # for neighbour in neighbours:
  826.             neighbour = random.choice(neighbours)
  827.             Eself = world.Estored_map[self.location[::-1]]
  828.             Eneighbour = world.Estored_map[neighbour[::-1]]
  829.             Eaverage = float((Eself + Eneighbour)/2)
  830.             trophallaxis_value += 1
  831.             print(trophallaxis_value, "sharinggggggggggggggggggggggggggggg")
  832.             world.Estored_map[self.location[::-1]] = Eaverage
  833.             world.Estored_map[neighbour[::-1]] = Eaverage
  834.             # E = float(Eself/ 2)
  835.             # world.Estored_map[self.location[::-1]] -= E
  836.             # world.Estored_map[neighbour[::-1]] += E
  837.         else:
  838.             pass
  839.  
  840.     def __repr__(self):
  841.         return "Bot({})".format(self.location)
  842.  
  843.     def __str__(self): # real signature unknown
  844.         """ Return str(self). """
  845.         return "x{}_y{}".format(self.location[0],self.location[1])
  846.  
  847. class World(object):
  848.     """
  849.  Maps the distribution of food over the grid space.
  850.  
  851.  Parameters
  852.  ----------
  853.  n_bots : int
  854.      The number of bots
  855.  _food : Food
  856.      The food distribution across the grid space.
  857.  
  858.  Attributes
  859.  ----------
  860.  n_bots : int
  861.      The number of bots
  862.  _food : object
  863.      The food distribution across the grid space.
  864.  n_cells :
  865.      The number of food cells
  866.  map_size : int
  867.      The length of each side of the food map.
  868.  food_map : np.ndarray
  869.      The distribution of food across the grid space.
  870.  bot_map : np.ndarray
  871.      The distribution of bots across the grid space.
  872.  bot_map_size : int
  873.      The length of each side of the bot map in grid units.
  874.  _bots_on_food : int
  875.      The number of bots located on a cell containing food
  876.  Estored_map : np.ndarray
  877.      The map of cumulative energy stored by each bot.
  878.  Acovered_map : np.ndarray
  879.      A map showing the number of times a grid cell has been entered by a bot.
  880.  trajectory_coords : Dictionary
  881.     Coordinates of start and end point that define robots motion vector
  882.  
  883.  """
  884.  
  885.     def __init__(self, food):
  886.         self.n_bots = n_bots
  887.         self._food = food
  888.         self.n_cells = n_cells
  889.         self.map_size = self._food.map_size
  890.         self.food_map, self.food_map_size = self._pad_map(
  891.             self._food.food_map, BOT_DEFAULTS['senseRange'])
  892.  
  893.         if show_plot == True:
  894.             plt.matshow(self.food_map)
  895.             plt.show()
  896.  
  897.         self.bot_map = None
  898.         self.bot_map_size = None
  899.         self._populate_bot_map()
  900.         self._bots_on_food = None
  901.  
  902.         self.Estored_map = np.ma.make_mask(self.bot_map) \
  903.                                      * BOT_DEFAULTS["Estored_init"]
  904.  
  905.         self.Acovered_map = np.copy(np.ma.make_mask(self.bot_map) * 1)
  906.  
  907.         self.move_map = np.zeros_like(self.food_map)
  908.  
  909.         self.charge_map = np.zeros_like(self.food_map)
  910.  
  911.         # self.charge_map = np.multiply(np.ma.make_mask(self.bot_map) * 1,
  912.         #                                    np.ma.make_mask(self.food_map) * 1)
  913.  
  914.         self.trajectory_coords = {"x_preMove" : [],
  915.                                   "y_preMove" : [],
  916.                                   "y_postMove": [],
  917.                                   "x_postMove": [],
  918.                                  }
  919.  
  920.     def _pad_map(self, map_to_pad, _border_width):
  921.         """
  922.      Creates a border of width = _border_width around the map as dictated by
  923.      the sense range of the bots. This is to prevent errors generated by
  924.      functions that use elements of a window around each bot, the size of
  925.      which is defined  by the robot sense range.
  926.  
  927.      Parameters
  928.      ----------
  929.      map_to_pad : array
  930.          The map to pad.
  931.  
  932.      _border_width :
  933.          The border width in grid units
  934.      """
  935.         _full_map_size = int(self.map_size + 2*_border_width)
  936.  
  937.         if map_to_pad.dtype == object:
  938.             _full_map = np.empty(
  939.                 (_full_map_size) ** 2, dtype=object).reshape(_full_map_size,
  940.                  _full_map_size)
  941.  
  942.         else:
  943.             _full_map = np.zeros(
  944.                 (_full_map_size) ** 2).reshape(_full_map_size,_full_map_size)
  945.  
  946.         _full_map[_border_width:(
  947.                 _border_width + self.map_size),
  948.                 _border_width:(_border_width + self.map_size)] = map_to_pad
  949.  
  950.         return _full_map, _full_map_size
  951.  
  952.     def _populate_bot_map(self):
  953.  
  954.  
  955.         """
  956.      Distributes n_bots start locations randomly over the grid space
  957.  
  958.      """
  959.         # TODO: if random seed gives you same starting map, this can be removed
  960.         if bot_map_style == "existing_map":
  961.             self.bot_map = np.load(path
  962.                                    + "/" + bot_map_dir
  963.                                    + "/" + bot_map_name + "bots.npy")
  964.             self.bot_map_size = np.shape(self.bot_map)[0]
  965.             bot_map_name = path \
  966.                            + "/" + dataName \
  967.                            + "/" + bot_map_name
  968.  
  969.         else:
  970.  
  971.             if bot_map_style == "new_map":
  972.                 self._new_map()
  973.  
  974.             if bot_map_style == "central_map":
  975.                 self._central_map()
  976.  
  977.             if bot_map_style == "random_map":
  978.                 self._random_map()
  979.                 if set_number_agents_on_food == True:
  980.                     while len(self._bots_on_food) != n_agents_on_food:
  981.                         self._random_map()
  982.  
  983.             # give each bot a location identity
  984.             y, x = np.where(self.bot_map)
  985.             for Y, X in zip(y, x):
  986.                 self.bot_map[Y, X].location = Location(X, Y)
  987.  
  988.             bot_map_name = (path
  989.                             + "/" + dataName
  990.                             + "/" + dataName)
  991.  
  992.         np.save(bot_map_name + "_bots", self.bot_map)
  993.  
  994.  
  995.  
  996.         if show_plot == True:
  997.             plt.matshow(np.ma.make_mask(self.bot_map)*1)
  998.             plt.show()
  999.  
  1000.     def _random_map(self):
  1001.  
  1002.         self.bot_map = np.empty(self.n_cells, dtype=object)
  1003.  
  1004.         for i in range(self.n_bots):
  1005.             self.bot_map[i] = Bot(self, **BOT_DEFAULTS)
  1006.  
  1007.         np.random.shuffle(self.bot_map)
  1008.         self.bot_map = np.reshape(self.bot_map, (self.map_size, self.map_size))
  1009.  
  1010.         self.bot_map, self.bot_map_size = self._pad_map(
  1011.             self.bot_map, BOT_DEFAULTS['senseRange'])
  1012.  
  1013.         self._bots_on_food = np.where(
  1014.             (np.ma.make_mask(self.bot_map) * 1 > 0) &
  1015.             (self.food_map > 0))
  1016.  
  1017.         #print(len(self._bots_on_food))
  1018.  
  1019.     def _new_map(self):
  1020.  
  1021.         self.bot_map = np.empty(self.n_cells, dtype=object)
  1022.  
  1023.         self.bot_map = np.reshape(self.bot_map, (self.map_size, self.map_size))
  1024.  
  1025.         for y, x in zip(bot_y_range, bot_x_range):
  1026.             self.bot_map[y,x] = Bot(self, **BOT_DEFAULTS)
  1027.  
  1028.         self.bot_map, self.bot_map_size = self._pad_map(
  1029.             self.bot_map, BOT_DEFAULTS['senseRange'])
  1030.  
  1031.     def _central_map(self):
  1032.         #print("central")
  1033.  
  1034.         self.bot_map = np.empty(self.n_cells, dtype=object)
  1035.  
  1036.         self.bot_map = np.reshape(self.bot_map, (self.map_size, self.map_size))
  1037.  
  1038.         _midpoint = int(self.map_size/2)
  1039.         _sideLength = int(np.sqrt(self.n_bots))
  1040.         _lower = int(_midpoint-(_sideLength/2))
  1041.         _upper = int(_lower + _sideLength)
  1042.         _range = np.arange(_lower, _upper,1)
  1043.  
  1044.         for y in _range:
  1045.             for x in _range:
  1046.                 self.bot_map[y,x] = Bot(self, **BOT_DEFAULTS)
  1047.  
  1048.         self.bot_map, self.bot_map_size = self._pad_map(
  1049.             self.bot_map, BOT_DEFAULTS['senseRange'])
  1050.  
  1051.     def save_data_per_timestep(self):
  1052.  
  1053.         # log data to data per cycle
  1054.         with open(dataTimestep, 'a') as c:
  1055.             writer = csv.writer(c)
  1056.             writer.writerow([
  1057.  
  1058.                 # count
  1059.                 count,
  1060.  
  1061.                 # total food
  1062.                 np.sum(self.food_map),
  1063.  
  1064.                 # number of food patches
  1065.                 len(np.where(self.food_map)[0]),
  1066.  
  1067.                 # _bots_with_Estored
  1068.                 len(np.where(self.Estored_map)[0]),
  1069.  
  1070.                 # total area covered
  1071.                 len(np.where(self.Acovered_map)[0]),
  1072.  
  1073.                 # total steps taken
  1074.                 np.sum(self.Acovered_map),
  1075.  
  1076.                 # maximum on board eergy
  1077.                 np.amax(self.Estored_map),
  1078.  
  1079.                 # trophallaxis
  1080.                 trophallaxis_value,
  1081.  
  1082.             ])
  1083.  
  1084.     def save_data_init(self, food_map):
  1085.  
  1086.         """
  1087.      Creates a dictionary of the attributes of the World object and the
  1088.      default properties of the bots. Saves these and other global data and
  1089.      parameters of the World object to a new csv file.
  1090.      Defines heaidings of parameters to be recorded at each timestep to a new
  1091.      csv file and calculates and saves initial values.
  1092.  
  1093.      Parameters
  1094.      ----------
  1095.      food_map : array
  1096.          An attribute to remove from the dictionary.
  1097.      """
  1098.  
  1099.         attributes = food_map.__dict__
  1100.         del attributes["food_map"]
  1101.         attributes.update(BOT_DEFAULTS)
  1102.  
  1103.         # write data to data summary
  1104.         with open(dataSummary, 'w') as s:
  1105.             writer = csv.writer(s)
  1106.             for key, value in attributes.items():
  1107.                 writer.writerow([key, value])
  1108.             writer.writerow(["n_food_cells_initial",
  1109.                              len(np.where(self.food_map)[0])])
  1110.             writer.writerow(["n_bots", self.n_bots])
  1111.             writer.writerow(["FiniteFood", FiniteFood])
  1112.             writer.writerow(["food_map_style", food_map_style])
  1113.             writer.writerow(["bot_map_style", bot_map_style])
  1114.             writer.writerow(["maxTimesteps", maxTimesteps])
  1115.             writer.writerow(["seed np:", seed_np])
  1116.             writer.writerow(["seed random:", seed_random])
  1117.  
  1118.         # setup data per timestep file
  1119.         with open(dataTimestep, 'w') as c:
  1120.             writer = csv.writer(c)
  1121.             writer.writerow(data_per_timestep)
  1122.  
  1123.         self.save_data_per_timestep()
  1124.  
  1125.     def save_data_food_finished(self):
  1126.  
  1127.         """
  1128.      Creates a dictionary of the attributes of the World object and the
  1129.      default properties of the bots. Saves these and other global data and
  1130.      parameters of the World object to a new csv file.
  1131.      Defines heaidings of parameters to be recorded at each timestep to a new
  1132.      csv file and calculates and saves initial values.
  1133.  
  1134.      Parameters
  1135.  
  1136.      ----------
  1137.      food_map : array
  1138.          An attribute to remove from the dictionary.
  1139.  
  1140.      """
  1141.  
  1142.         lst = ['time_food_finished', "bots_with_Estored_food_finished" ]
  1143.         with open(dataSummary, 'rt') as f:
  1144.             reader = csv.reader(f, delimiter=',')
  1145.             for row in reader:
  1146.                 print(row)
  1147.                 for l in lst:
  1148.                     if row[0] == l:
  1149.                         print(lst)
  1150.                         lst.remove(l)
  1151.         if lst != []:
  1152.             print(lst)
  1153.             with open(dataSummary, 'a') as s:
  1154.                 writer = csv.writer(s)
  1155.                 writer.writerow(["time_food_finished", count])
  1156.                 writer.writerow(["bots_with_Estored_food_finished",
  1157.                                  len(np.where(self.Estored_map)[0])])
  1158.  
  1159.     def save_data_final(self):
  1160.  
  1161.         """
  1162.      Creates a dictionary of the attributes of the World object and the
  1163.      default properties of the bots. Saves these and other global data and
  1164.      parameters of the World object to a new csv file.
  1165.      Defines heaidings of parameters to be recorded at each timestep to a new
  1166.      csv file and calculates and saves initial values.
  1167.  
  1168.      Parameters
  1169.  
  1170.      ----------
  1171.      food_map : array
  1172.          An attribute to remove from the dictionary.
  1173.  
  1174.      """
  1175.         with open(dataSummary, 'a') as s:
  1176.             writer = csv.writer(s)
  1177.             writer.writerow(["count", count])
  1178.             writer.writerow(["total_food_final", np.sum(self.food_map)])
  1179.             writer.writerow(["n_food_cells_final",
  1180.                              len(np.where(self.food_map)[0])])
  1181.             writer.writerow(["bots_with_Estored_final",
  1182.                              len(np.where(self.Estored_map)[0])])
  1183.             writer.writerow(["total_area_covered",
  1184.                              len(np.where(self.Acovered_map)[0])])
  1185.             writer.writerow(["total_steps_taken",
  1186.                              np.sum(self.Acovered_map)])
  1187.  
  1188.             lst = ['time_food_finished', "bots_with_Estored_food_finished"]
  1189.             with open(dataSummary, 'rt') as f:
  1190.                 reader = csv.reader(f, delimiter=',')
  1191.                 for row in reader:
  1192.                     print(row)
  1193.                     for l in lst:
  1194.                         if row[0] == l:
  1195.                             print(lst)
  1196.                             lst.remove(l)
  1197.             if lst != []:
  1198.                 print(lst)
  1199.                 with open(dataSummary, 'a') as s:
  1200.                     writer = csv.writer(s)
  1201.                         # writer.writerow(["time_food_finished"],0)
  1202.                         # writer.writerow(["bots_with_Estored_food_finished"],0)
  1203.                     writer.writerow(["time_food_finished"])
  1204.                     writer.writerow(["bots_with_Estored_food_finished"])
  1205.  
  1206.         AcoveredFinal = np.where(self.Acovered_map)
  1207.  
  1208.         np.save(path \
  1209.                       + "/" + dataName \
  1210.                       + "/" + dataName + '_AcoveredFinal',
  1211.                 np.where(self.Acovered_map))
  1212.  
  1213.         #print("done")
  1214.  
  1215.     def plot(self):
  1216.  
  1217.         global count
  1218.  
  1219.         plot_dir = path \
  1220.                    + "/" + dataName \
  1221.                    + "/" + "plot_data"\
  1222.                    + "/"
  1223.  
  1224.         plot_layer_names = ["_food", "_Estored", "_bots", "_bots_loc" ]
  1225.         plot_layers = [self.food_map,
  1226.                        self.Estored_map,
  1227.                        self.bot_map,
  1228.                        (np.ma.make_mask(self.bot_map)*1)]
  1229.  
  1230.         for name, layer in zip(plot_layer_names, plot_layers):
  1231.             y, x = np.where(layer)
  1232.             nonzero = zip(y, x)
  1233.  
  1234.             with open(plot_dir
  1235.                               + name
  1236.                               + str(count).zfill(4)
  1237.                               + '.txt', 'w+') as outf:
  1238.  
  1239.                 for r, k in nonzero:
  1240.                     if name == "_bots":
  1241.                         outf.write(
  1242.                             '{:d}{:d}{!s:s}\n'.format(
  1243.                                 r, k, layer[r, k]))
  1244.  
  1245.                     else:
  1246.                         outf.write(
  1247.                             '{:d} {:d} {:g}\n'.format(
  1248.                                 r, k, layer[r, k]))
  1249.  
  1250. #        for i in self.trajectory_coords:
  1251. #            with open(plot_dir
  1252. #                              + "_trajectory_coords"
  1253. #                              + str(count).zfill(4)
  1254. #                              + '.csv', 'w') as f:
  1255. #
  1256. #                writer = csv.writer(f)
  1257. #                for row in self.trajectory_coords.items():
  1258. #                    writer.writerow(row)
  1259.  
  1260.     def feed(self):
  1261.         """
  1262.      Decreases food map by 1 unit in every grid cell newly occupied by a bot
  1263.      Updates the bot charging map with new occupants
  1264.      Updates the stored energy map of all charging bots with the energy from
  1265.      feeding divided by the number of time steps taken to charge.
  1266.  
  1267.      """
  1268.  
  1269.         Ein = BOT_DEFAULTS["EinPerFeed"]
  1270.         eff = BOT_DEFAULTS["eff_E_conversion"]
  1271.         t_steps = BOT_DEFAULTS["t_steps_to_charge"]
  1272.  
  1273.         chargePerTimetep = float(Ein * eff / t_steps)
  1274.  
  1275.         new_bots_on_food = np.where((np.ma.make_mask(self.bot_map)*1>0)
  1276.                                    & (self.food_map > 0)
  1277.                                    & (self.charge_map == 0))
  1278.  
  1279.         if FiniteFood == True:
  1280.             self.food_map[new_bots_on_food] -= BOT_DEFAULTS["EinPerFeed"]
  1281.             np.clip(self.food_map, 0, float("inf"), self.food_map)
  1282.  
  1283.         if BOT_DEFAULTS["scavenge"] == True:
  1284.             self.charge(new_bots_on_food, chargePerTimetep)
  1285.  
  1286.     def charge(self, new_bots_on_food, chargePerTimetep):
  1287.         """
  1288.      Updates the stored energy map of all charging bots with the energy from
  1289.      feeding divided by the number of time steps taken to charge.
  1290.  
  1291.      """
  1292.         # self.charge_map[np.where(self.charge_map)] += chargePerTimetep
  1293.         #
  1294.         # self.charge_map[new_bots_on_food] += chargePerTimetep
  1295.  
  1296.         self.charge_map[np.where(self.charge_map)] += 1
  1297.  
  1298.         self.charge_map[new_bots_on_food] += 1
  1299.  
  1300.         self.move_map = np.multiply(
  1301.             self.move_map,
  1302.             np.invert(np.ma.make_mask(self.charge_map)) * 1)
  1303.  
  1304.         t_steps = BOT_DEFAULTS["t_steps_to_charge"]
  1305.  
  1306.         self.Estored_map = np.clip(np.where(self.charge_map,
  1307.                                             self.Estored_map + chargePerTimetep,
  1308.                                             self.Estored_map),
  1309.                                    0,
  1310.                                    BOT_DEFAULTS["Estored_max"],
  1311.                                    self.Estored_map)
  1312.         ### ****PRINT
  1313.         # print("charged")
  1314.         # print(self.charge_map)
  1315.         # print("charged")
  1316.         # print(self.charge_map[self.charge_map >= t_steps])
  1317.         # print("")
  1318.         # print("move")
  1319.         # print(self.move_map)
  1320.         # print("")
  1321.         # print("stored")
  1322.         # print(self.Estored_map)
  1323.         # print("")
  1324.  
  1325.         self.charge_map[self.charge_map >= t_steps] = 0
  1326.  
  1327.     def base_metabolism(self):
  1328.  
  1329.         """
  1330.  
  1331.      """
  1332.         np.clip(
  1333.             self.Estored_map - BOT_DEFAULTS["base_metabolism"],
  1334.             0, float("inf"), self.Estored_map)
  1335.  
  1336.     def functioning_bots(self):
  1337.  
  1338.         functioning_bots = []
  1339.  
  1340.         incapacitated_bots = self.incapacitated_bots()
  1341.         _bots = np.copy(self.bot_map)
  1342.         _bots[incapacitated_bots] = None
  1343.         _functioning_bots = np.argwhere(_bots)
  1344.         for _functioning_bot in _functioning_bots:
  1345.             bot = self.bot_map[_functioning_bot[0],
  1346.                                _functioning_bot[1]]
  1347.             functioning_bots.append(bot)
  1348.  
  1349.         return functioning_bots
  1350.  
  1351.  
  1352.     def incapacitated_bots(self):
  1353.         incapacitated_bots = np.where((self.bot_map != None)
  1354.                                       and self.Estored_map == 0)
  1355.         return incapacitated_bots
  1356.  
  1357.     def store_trajectory(self, preORpost, *initialPosition):
  1358.         if preORpost == "pre":
  1359.             y, x = np.nonzero(self.move_map)
  1360.             y=list(y)
  1361.             x=list(x)
  1362.  
  1363.             self.trajectory_coords["x_" + preORpost + "Move"].extend(x)
  1364.             self.trajectory_coords["y_" + preORpost + "Move"].extend(y)
  1365.  
  1366.         else:
  1367.             y, x = np.where(self.bot_map == initialPosition)
  1368.  
  1369.             self.trajectory_coords["x_" + preORpost + "Move"].append(x[0])
  1370.             self.trajectory_coords["y_" + preORpost + "Move"].append(y[0])
  1371.  
  1372.         return y,x
  1373.  
  1374.     def energy_transfer(self):
  1375.  
  1376.         # energy in
  1377.         self.feed()
  1378.  
  1379.         # energy out
  1380.         self.base_metabolism()
  1381.  
  1382.         functioning_bots = self.functioning_bots()
  1383.  
  1384.         if functioning_bots != []:
  1385.  
  1386.             random.shuffle(functioning_bots)
  1387.  
  1388.             for bot in functioning_bots:
  1389.  
  1390.                 neighbours = bot.sense(
  1391.                     np.ma.make_mask(self.bot_map) * 1,
  1392.  
  1393.                     "neighbouring_bot")
  1394.  
  1395.                 neighbours = bot.evaluate_neighbours(self)
  1396.  
  1397.                 if bool(neighbours) == False:
  1398.                     pass
  1399.  
  1400.                 else:
  1401.                     if BOT_DEFAULTS["trophallaxis"] == True:
  1402.                         bot.trophallaxis(self, neighbours)
  1403.  
  1404.  
  1405.     def movement(self):
  1406.         # self.move_map = np.where(
  1407.         #     self.Estored_map >= BOT_DEFAULTS["Eth_battFull"],
  1408.         #     self.Estored_map,
  1409.         #     self.move_map)
  1410.  
  1411.         # self.move_map = np.where(self.charge_map >= t_steps,
  1412.         #                          self.Estored_map,
  1413.         #                          self.move_map)
  1414.  
  1415.         # print("charge mode")
  1416.         # print(self.charge_map)
  1417.         # print("charge mode")
  1418.         # print(np.invert(self.charge_map))
  1419.  
  1420.  
  1421.         self.move_map = np.where(
  1422.             (self.Estored_map >= BOT_DEFAULTS["Eth_battFull"]) &
  1423.             (self.charge_map == 0),
  1424.             self.Estored_map,
  1425.             0)
  1426.  
  1427.         # print("move")
  1428.         # print(self.move_map)
  1429.         # print("")
  1430.  
  1431.         # print(self.move_map)
  1432.         # print("")
  1433.         # print(self.charge_map)
  1434.         # print("")
  1435.         # print(self.food_map)
  1436.         # print("")
  1437.  
  1438.         # print("MoveMap")
  1439.         # print(self.move_map[45:55 , 45:55] )
  1440.         # print("EstoredMap")
  1441.         # print(self.Estored_map[45:55 , 45:55] )
  1442.         # print("ChargeMap")
  1443.         # print(self.charge_map[45:55 , 45:55])
  1444.             #     self.Estored_map >= BOT_DEFAULTS["Eth_battFull"],
  1445.             #     self.Estored_map,
  1446.             #     self.move_map)
  1447.  
  1448.         #self.move_map = np.where(np.ma.make_map)
  1449.  
  1450.         if self.move_map.any():
  1451.  
  1452.             # print("move_map")
  1453.             # print(self.move_map)
  1454.  
  1455.             # log the initial position of each bot
  1456.             pre_move_y, pre_move_x = self.store_trajectory("pre")
  1457.             moving_bots = self.bot_map[pre_move_y, pre_move_x]
  1458.  
  1459.             # shuffle the bots
  1460.             # print(pre_move_y)
  1461.             # print(pre_move_x)
  1462.             # print("")
  1463.             bots_to_shuffle = list(zip(pre_move_y, pre_move_x))
  1464.             random.shuffle(bots_to_shuffle)
  1465.             pre_move_y, pre_move_x = zip(*bots_to_shuffle)
  1466.  
  1467.             # print(pre_move_y)
  1468.             # print(pre_move_x)
  1469.             # print("bots")
  1470.             # print(np.ma.make_mask(self.bot_map) * 1)
  1471.             # print("")
  1472.            
  1473.             # move all the bots
  1474.             for Y, X in zip(pre_move_y, pre_move_x):
  1475.                 # print(Y,X)
  1476.                 self.bot_map[Y, X].move(self, Location(X, Y))
  1477.                 # print(np.ma.make_mask(self.bot_map)*1)
  1478.  
  1479.             # log the final position of each bot
  1480.             for initPosition in moving_bots:
  1481.                 post_move_y, post_move_x = \
  1482.                     self.store_trajectory("post", initPosition)
  1483.  
  1484.                 # update each Bot instance location attribute to current position.
  1485.                 self.bot_map[post_move_y[0],
  1486.                               post_move_x[0]].location \
  1487.                     = Location(post_move_x[0], post_move_y[0])
  1488.  
  1489.  
  1490. def main():
  1491.  
  1492.     global count
  1493.     global trophallaxis_value
  1494.  
  1495.  
  1496.     # distributes food
  1497.     food_map = Food()
  1498.  
  1499.     # populate world with agents
  1500.     world = World(food_map)
  1501.     #print("food_map", world.food_map)
  1502.  
  1503.     world.save_data_init(food_map)
  1504.     if plot_output:
  1505.         world.plot()
  1506.  
  1507.     # loop until all bots incapacitated by hunger OR all food removed
  1508.     # while (np.any(world.Estored_map) and np.any(world.food_map)):
  1509.     while (np.any(world.Estored_map)
  1510.            #and np.any(world.food_map)
  1511.            and count <= maxTimesteps):
  1512.  
  1513.         # print(world.bot_map[45:55, 45:55])
  1514.         # print(np.ma.make_mask(world.bot_map[45:55, 45:55]) * 1)
  1515.  
  1516.  
  1517.         count += 1
  1518.         print("count", count, "=", trophallaxis_value)
  1519.         trophallaxis_value = 0
  1520.         world.energy_transfer()
  1521.         world.movement()
  1522.         world.save_data_per_timestep()
  1523.         if plot_output:
  1524.             world.plot()
  1525.         if np.any(world.food_map) == False:
  1526.             print("all food eaten")
  1527.             world.save_data_food_finished()
  1528.  
  1529.  
  1530.     if count >= maxTimesteps:
  1531.         print("exceeded maximum timesteps")
  1532.     else:
  1533.         print("all bots dead")
  1534.  
  1535.     world.save_data_final()
  1536.  
  1537. if __name__ == '__main__':
  1538.     try:
  1539.         main()
  1540.     finally:
  1541.         print("end")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement