How to parallelize this situation with robots

I am working on a robotic problem. The situation is something like this:

  • A total of N generations (N> 100) contains N numbers.
  • Each robot attracts all other robots having a radius r.
  • I have a system of equations with which I can calculate the acceleration, speed and, therefore, the position of the robot after delta time t. Simply put, I can find the position of each robot after the delta t.
  • All I have to do is set delta t. I need to display the position of each robot for each delta t.

The problem is actually very simple. Algo will be something like:

del_t = ;its given
initialPositions = ;its given
num_robots = ;its given

The following code is executed for each del_t

robots = range(1,no_robots)
for R in robots:
    for r in robots:
        if  distanceBetween(r,R) <= radius and r is not R:
            acceleration_along_X[R] += xAcceleration( position(r), position(R) )
            acceleration_along_Y[R] += yAcceleration( position(r), position(R) )
    currVelocity_along_X[R] = prevVelocity_along_X[R] + acceleration_along_X[R] * del_t
    currVelocity_along_Y[R] = prevVelocity_along_Y[R] + acceleration_along_Y[R] * del_t
    curr_X_coordinate[R] = prev_X_coordinate[R] + currVelocity_along_X[R] * del_t
    curr_Y_coordinate[R] = prev_Y_coordinate[R] + currVelocity_along_Y[R] * del_t
    print 'Position of robot ' + str(R) + ' is (' + curr_X_coordinate[R] + ', ' + curr_Y_coordinate[R] +' ) \n'
    prev_X_coordinate[R] = curr_X_coordinate[R]
    prev_Y_coordinate[R] = curr_Y_coordinate[R]
    prevVelocity_along_X[R] = currVelocity_along_X[R]
    prevVelocity_along_Y[R] = currVelocity_along_Y[R]

MPI.

  • . . ?
  • MPI. " MPI"? ? .

EDIT:

. , , . Unode answer. , .

. printPositionOfRobot - . , ( id robot_id) t = 1,2,3,4,5,6,7,8,9,10. ( del_t 1. num_iterations = 10. : Robot8 : Position at t = 9 is (21.1051065245, -53.8757356694 )

. t = 0 position() xAcceleration yAcceleration. .

from multiprocessing import Pool
import math


def printPositionOfRobot(robot_id):
    radius = 3
    del_t = 1
    num_iterations = 10
    no_robots = 10

    prevVelocity_along_X = 0
    prevVelocity_along_Y = 0
    acceleration_along_X = 0
    acceleration_along_Y = 0
    (prev_X_coordinate,prev_Y_coordinate) = position(robot_id)#!!it should call initialPosition()
    for i in range(1,num_iterations+1):
        for r in range(no_robots):
            if  distanceBetween(r,robot_id) <= radius and r is not robot_id:
                acceleration_along_X += xAcceleration( position(r), position(robot_id) ) #!! Problem !!
                acceleration_along_Y += yAcceleration( position(r), position(robot_id) )#!! Problem !!
        currVelocity_along_X = prevVelocity_along_X + acceleration_along_X * del_t
        currVelocity_along_Y = prevVelocity_along_Y + acceleration_along_Y * del_t
        curr_X_coordinate = prev_X_coordinate + currVelocity_along_X * del_t
        curr_Y_coordinate = prev_Y_coordinate + currVelocity_along_Y * del_t
        print 'Robot' + str(robot_id) + ' : Position at t = '+ str(i*del_t) +' is (' + str(curr_X_coordinate) + ', ' + str(curr_Y_coordinate) +' ) \n'
        prev_X_coordinate = curr_X_coordinate
        prev_Y_coordinate = curr_Y_coordinate
        prevVelocity_along_X = currVelocity_along_X
        prevVelocity_along_Y = currVelocity_along_Y

def xAcceleration((x1,y1),(x2,y2)):
    s = distance((x1,y1),(x2,y2))
    return 12*(x2-x1)*( pow(s,-15) - pow(s,-7) + 0.00548*s )

def yAcceleration((x1,y1),(x2,y2)):
    s = distance((x1,y1),(x2,y2))
    return 12*(y2-y1)*( pow(s,-15) - pow(s,-7) + 0.00548*s )

def distanceBetween(r,robot_id):
    return distance(position(r), position(robot_id))

def distance((x1,y1),(x2,y2)):
    return math.sqrt( (x2-x1)**2 + (y2-y1)**2 )

def Position(r): #!!name of this function should be initialPosition
    k = [(-8.750000,6.495191) , (-7.500000,8.660254) , (-10.000000,0.000000) , (-8.750000,2.165064) , (-7.500000,4.330127) , (-6.250000,6.495191) , (-5.000000,8.660254) , (-10.000000,-4.330127) , (-8.750000,-2.165064) , (-7.500000,0.000000) ]
    return k[r]

if __name__ == "__main__":
    no_robots = 10  # Number of robots you need
    p = Pool(no_robots)  # Spawn a pool of processes (one per robot in this case)
    p.map(printPositionOfRobot, range(no_robots))

position acceleration_along_X acceleration_along_Y . . , . , .

, . (, , ). , .

, ? , MPI.

+3
3

, , - . !

, , , . , ! , ( N-) , , , .

python mpi ( mpi4py matplotlib/pylab ). ; , , , . , .

mpirun -np 2 ./robots.py; , MPI, mpi4py , .

, ; - .

#!/usr/bin/env python
import numpy
import pylab
from mpi4py import MPI

class Robot(object):
    def __init__(self, id, x, y, vx, vy, mass):
        self.id = id
        self.x = x
        self.y = y
        self.vx = vx
        self.vy = vy
        self.ax = 0.
        self.ay = 0.
        self.mass = mass
    def rPrint(self):
        print "Robot ",self.id," at (",self.x,",",self.y,")"
    def interact(self, robot2):
        dx = (self.x-robot2.x)
        dy = (self.y-robot2.y)
        eps = 0.25
        idist3 = numpy.power(numpy.sqrt(dx*dx +dy*dy + eps*eps),-3)
        numerator = -self.mass*robot2.mass
        self.ax += numerator*dx*idist3
        self.ay += numerator*dy*idist3
        robot2.ax -= numerator*dx*idist3
        robot2.ay -= numerator*dy*idist3
    def updatePos(self, dt):
        self.x += 0.5*self.vx*dt
        self.y += 0.5*self.vy*dt
        self.vx += self.ax*dt
        self.vy += self.ay*dt
        self.x += 0.5*self.vx*dt
        self.y += 0.5*self.vy*dt
        self.ax = 0.
        self.ay = 0.



def init(nRobots):
    myRobotList = []
    vx = 0.
    vy = 0.
    mass = 1.
    for i in range(nRobots):
        randpos = numpy.random.uniform(-3,+3,2)
        rx = randpos[0]
        ry = randpos[1]
        myRobotList.append(Robot(i, rx, ry, vx, vy, mass))
    return myRobotList

def selfForces(robotList):
    nRobots = len(robotList)
    for i in range(nRobots-1): 
       for j in range (i+1, nRobots):
            robotList[i].interact(robotList[j])

def otherRobotForces(myRobotList, otherRobotList):
    for i in myRobotList:
        for j in otherRobotList:
            i.interact(j)

def plotRobots(robotList):
    xl = []
    yl = []
    vxl = []
    vyl = [] 
    for i in robotList:
       xl.append(i.x)
       yl.append(i.y)
       vxl.append(i.vx)
       vyl.append(i.vy)
    pylab.subplot(1,1,1)
    pylab.plot(xl,yl,'o')
    pylab.quiver(xl,yl,vxl,vyl)
    pylab.show()

if __name__ == "__main__":
    comm = MPI.COMM_WORLD
    nprocs = comm.Get_size()
    rank   = comm.Get_rank()

    if (nprocs != 2):
        print "Only doing this for 2 for now.."
        sys.exit(-1)
    neigh = (rank + 1) %  nprocs

    robotList = init(50)

    for i in range (10):
        print "[",rank,"] Doing step ", i
        selfForces(robotList)

        request = comm.isend(robotList, dest=neigh, tag=11)
        otherRobotList = comm.recv(source=neigh, tag=11)

        otherRobotForces(robotList,otherRobotList)

        request.Wait()

        for r in robotList:
            r.updatePos(0.05)



    if (rank == 0):
        print "plotting Robots"
        plotRobots(robotList + otherRobotList)
+1

. Python threads . , multiprocessing (python2.6 +).

MPI , .

. , ( ) , , concurrency.

1 - Linux script ( - Windows BATCH):

#!/bin/sh
for i in {0..99}; do
    echo "Running $i"
    python launch.py $i &
done

: & . , , .

2 - python, :

from multiprocessing import Pool

def your_algorithm(robot_id):
    print(robot_id)

if __name__ == "__main__":
    robots = 100  # Number of robots you need
    p = Pool(robots)  # Spawn a pool of processes (one per robot in this case)
    p.map(your_algorithm, range(robots))

.

MPI, mpi4py.

, Cartesian grid, this

+2

My solution is also similar to Unode, but I prefer to use the method apply_asyncin multiprocessingsince it is asynchronous.

from multiprocessing import Pool

    def main():
        po = Pool(100) #subprocesses
        po.apply_async(function_to_execute, (function_params,), callback=after_processing)
        po.close() #close all processes
        po.join() #join the output of all processes
        return    
0
source

Source: https://habr.com/ru/post/1768286/


All Articles