Exemplo n.º 1
0
def bb(adjacency, p=1):
    n = len(adjacency)
    comm = PSim(p)
    Q = []
    path = [0]
    Q.append(Vertex(path))
    bound = float("inf')
    optimal = None
    local_vertices = comm.one2all_scatter(0, range(n))
    while True:
        if comm.rank == 0:
            vertex = Q.pop() if Q else None
        else:
            vertex = None
        vertex = comm.one2all_broadcast(0, vertex)
        if vertex is None:
            break
        P = []
        for k in local_vertices:
            if not k in vertex.path:
                new_path = vertex.path+[k]
                new_path_length = weight(new_path, adjacency)
                if new_path_length<bound:
                    if len(new_path) == n:
                        new_path.append(new_path[0])
                        new_path_length = weight(new_path, adjacency)
                        if new_path_length<bound:
                            bound = new_path_length  # bcast
                            optimal = new_path       # bcast
                    else:
                        new_vertex = Vertex(new_path)
                        P.append(new_vertex)  # fix this
                print(new_path, new_path_length)
        x = (bound, optimal)
        x = comm.all2all_reduce(x, lambda a, b: min(a, b))
        (bound, optimal) = x

        P = comm.all2one_collect(0, P)
        if comm.rank == 0:
            for item in P:
                Q+=item
    return optimal, bound
Exemplo n.º 2
0
def dijkstra_p(g, source, p):
    """
    PYsim parallel implementation of dijkstra's algorithm
    Result: One source shourtest paths to all nodes
    Implementation parallelizes finding minimums and 
    updating the results (inner loop is parallelized)
    Uses the method of collecting of intermediate minimums and 
    broadcasting of newly found path to all processes
    """
    # Initialize communicator
    comm = PSim(p)
    myRank = comm.rank
    chunkSize = len(g) / p

    # Scatter the graph by partitioning it one dimensionally,
    # along with known distances to source, and remaining node information
    myGraphChunk = comm.one2all_scatter(0, g)
    localResultView = comm.one2all_scatter(0, g[source])
    localRemainView = comm.one2all_scatter(0, g[source])

    # Each process will iterate q times, where q is number of nodes in graph
    for q in range(len(g)):
        # Get shortest path to locally un-visited nodes
        lowestLocalDist = min(localRemainView)
        lowestLocalDistIdx = localRemainView.index(lowestLocalDist)

        # Collect the lowest distances and node indexes from all processes
        gatheredCandidatesDist = comm.all2one_collect(0, lowestLocalDist)
        gatheredCandidatesIdxs = comm.all2one_collect(0, lowestLocalDistIdx + myRank * chunkSize)

        processWithLowestDist = -1
        addedNodeIdx = -1
        lowestOverallDistance = -1

        # One 'main' process finds the global minimum
        if myRank == 0:
            lowestOverallDistance = min(gatheredCandidatesDist)
            processWithLowestDist = gatheredCandidatesDist.index(lowestOverallDistance)
            addedNodeIdx = gatheredCandidatesIdxs[processWithLowestDist]

        # 'Main' process broadcasts the finding to all processes
        receivedBroadcast = comm.one2all_broadcast(0, (processWithLowestDist, addedNodeIdx, lowestOverallDistance))

        # If this process is responsible for the newly found shortest path,
        # then mark this node as visited.
        if myRank == receivedBroadcast[0]:
            indexToUpdate = receivedBroadcast[1] - myRank * chunkSize
            localRemainView[indexToUpdate] = ""

        # Each process loop over all connections to this last visited node
        # that they have the visibility to.
        for iter in range(len(localResultView)):
            potentialNewDistance = myGraphChunk[iter][receivedBroadcast[1]] + receivedBroadcast[2]
            # If the distances through this node are less than what we know
            if potentialNewDistance < localResultView[iter]:
                # Update the local portion of the result list and
                # remaining nodes list
                localResultView[iter] = potentialNewDistance
                localRemainView[iter] = potentialNewDistance

    # Reduce the final result to a single list and return it
    reassembled = comm.all2one_reduce(0, localResultView)
    if myRank == 0:
        return reassembled
    else:
        return []
Exemplo n.º 3
0
def dijkstra_p(g, source, p):
    """
    PYsim parallel implementation of dijkstra's algorithm
    Result: One source shourtest paths to all nodes
    Implementation parallelizes finding minimums and 
    updating the results (inner loop is parallelized)
    Uses the method of collecting of intermediate minimums and 
    broadcasting of newly found path to all processes
    """
    # Initialize communicator
    comm = PSim(p)
    myRank = comm.rank
    chunkSize = len(g) / p

    # Scatter the graph by partitioning it one dimensionally,
    # along with known distances to source, and remaining node information
    myGraphChunk = comm.one2all_scatter(0, g)
    localResultView = comm.one2all_scatter(0, g[source])
    localRemainView = comm.one2all_scatter(0, g[source])

    # Each process will iterate q times, where q is number of nodes in graph
    for q in range(len(g)):
        # Get shortest path to locally un-visited nodes
        lowestLocalDist = min(localRemainView)
        lowestLocalDistIdx = localRemainView.index(lowestLocalDist)

        # Collect the lowest distances and node indexes from all processes
        gatheredCandidatesDist = comm.all2one_collect(0, lowestLocalDist)
        gatheredCandidatesIdxs = comm.all2one_collect(
            0, lowestLocalDistIdx + myRank * chunkSize)

        processWithLowestDist = -1
        addedNodeIdx = -1
        lowestOverallDistance = -1

        # One 'main' process finds the global minimum
        if myRank == 0:
            lowestOverallDistance = min(gatheredCandidatesDist)
            processWithLowestDist = gatheredCandidatesDist.index(
                lowestOverallDistance)
            addedNodeIdx = gatheredCandidatesIdxs[processWithLowestDist]

        # 'Main' process broadcasts the finding to all processes
        receivedBroadcast = \
            comm.one2all_broadcast(0,\
            (processWithLowestDist,addedNodeIdx,lowestOverallDistance,))

        # If this process is responsible for the newly found shortest path,
        # then mark this node as visited.
        if myRank == receivedBroadcast[0]:
            indexToUpdate = receivedBroadcast[1] - myRank * chunkSize
            localRemainView[indexToUpdate] = ''

        # Each process loop over all connections to this last visited node
        # that they have the visibility to.
        for iter in range(len(localResultView)):
            potentialNewDistance = \
                    myGraphChunk[iter][receivedBroadcast[1]]+receivedBroadcast[2]
            # If the distances through this node are less than what we know
            if potentialNewDistance < localResultView[iter]:
                # Update the local portion of the result list and
                # remaining nodes list
                localResultView[iter] = potentialNewDistance
                localRemainView[iter] = potentialNewDistance

    # Reduce the final result to a single list and return it
    reassembled = comm.all2one_reduce(0, localResultView)
    if myRank == 0:
        return reassembled
    else:
        return []
		MST = [] #minimum spanning tree to return
		total_worker_trees = 0
		edges_processed = 0;
		cont_parallel = True
		cont_serial = False
		while cont_parallel:
			#for i in sorted_edges:
			if len(sorted_edges)==0:
				cont_parallel = False
			else:
				curr_edge = sorted_edges.pop(0)
				#command for workers to be sent with message
				cmnd = 1 
				v1, v2, w = curr_edge 
				#send the vertices to the workers so they can search their local forest 
				comm.one2all_broadcast(0,(cmnd,v1,v2))
				add = False
				send_union_tree = False
				#if vertices are in different worker's forests, must get the rank of the 
				#worker with vertex_1 and both trees to union and send to that worker
				worker = -1
				half_tree_1 = []
				half_tree_2 = []
				#loop through all of the worker responses
				for r in range(1,p):
					total_worker_trees = 0
					resp = comm.recv(r)
					if resp[0] == 0:
						b=1
						#print 'worker: ', r, ' does not have these vertices in their forest'
					elif resp[0] == 1:
 MST = []  #minimum spanning tree to return
 total_worker_trees = 0
 edges_processed = 0
 cont_parallel = True
 cont_serial = False
 while cont_parallel:
     #for i in sorted_edges:
     if len(sorted_edges) == 0:
         cont_parallel = False
     else:
         curr_edge = sorted_edges.pop(0)
         #command for workers to be sent with message
         cmnd = 1
         v1, v2, w = curr_edge
         #send the vertices to the workers so they can search their local forest
         comm.one2all_broadcast(0, (cmnd, v1, v2))
         add = False
         send_union_tree = False
         #if vertices are in different worker's forests, must get the rank of the
         #worker with vertex_1 and both trees to union and send to that worker
         worker = -1
         half_tree_1 = []
         half_tree_2 = []
         #loop through all of the worker responses
         for r in range(1, p):
             total_worker_trees = 0
             resp = comm.recv(r)
             if resp[0] == 0:
                 b = 1
                 #print 'worker: ', r, ' does not have these vertices in their forest'
             elif resp[0] == 1: