Saturday, July 25, 2015

Python : breadth-first search (5), arrange network


Abstracts: arrange all nodes in a given network

The result:
The order of visiting nodes: ['A', 'B', 'C', 'E', 'F', 'D', 'I', 'G', 'H']
ok


The script:
# -*- coding: utf-8 -*-
"""
Created on Fri Jul 24 09:44:46 2015

@author: yuan
"""

import numpy as np
import pandas as pd
# search areas of islands in a map

#record a queue using circling list
class queue:
   
    def __init__(self,arr, q_len=1):
        self.size=len(arr)
        if q_len==1 or q_len<self.size:       
            self.q=[None]*self.size
            self.q_len=self.size
        else:
            self.q=[None]*q_len
            self.q_len=q_len
        self.q[0]=0
        self.q[1:self.size]=arr
        self.head=1       #skip the index 0
        self.tail=len(arr)+1 #the index of next element of arr
        #print 'Initiate queue:', self.q
       
    def q_size(self):
        #print 'Size of the queue:', self.size
        return self.size
       
    def isFull(self):
        return self.tail==(self.q_len+1)
       
    def export_arr(self):
        if self.tail>self.head:
            arr=self.q[self.head:self.tail]
        elif self.tail==self.head:
            arr=[]
        else:
            arr=self.q[self.head:(self.q_len+1)] + self.q[1:self.tail]
        return arr
   
    def enqueue(self, value):
        if self.size<self.q_len:
            #increase size
            self.size +=1
            #increase tail
            if self.tail==(self.q_len+1):
                self.tail=1
            #add value
            self.q[self.tail]=value
            self.tail += 1
        else:
            print "queue is full, fail to adding", value
        #print '##', self.q, self.head,self.tail
        #return self.export_arr()
       
    def dequeue(self):
        #increase head
        value='NA'
        #print self.head, self.tail
        if self.size>0:
            value=self.q[self.head]
            if self.head==self.q_len:
                self.head=1
            else:
                self.head +=1
                #decrease size
            self.size -= 1
            #print 'remove', value, self.export_arr()
        return value
##################
class breadth_first_search(queue):
   
    def __init__(self, connects):
        self.connects=connects
        #store network into dat frame using panda
        self.net=self.read_connects()

    def read_connects(self):
        self.connects=np.array(self.connects)
        self.edges_num=len(self.connects)
        self.nodes=np.unique(np.array(self.connects))
        self.nodes_num=len(self.nodes)
        net=np.zeros((self.nodes_num,self.nodes_num))
        net=pd.DataFrame(net, columns=self.nodes, index=self.nodes)
        #print net
        #get 2-D marix to store network
        for row in range(self.edges_num):
            nodeA=self.connects[row][0]
            nodeB=self.connects[row][1]
            net[nodeA][nodeB]=1
            net[nodeB][nodeA]=1
            net[nodeA][nodeA]=-1#remove self-connection
            net[nodeB][nodeB]=-1
        return net
       
    def arrange_network(self, start):
        q=queue([start], self.nodes_num**2)
        self.visited=[start]
        self.book=dict(zip(self.nodes, [0]*self.nodes_num) )
        self.book[start]=1
        while q.q_size()>0:
            start_node=q.dequeue()
            for node in self.nodes:
                if self.book[node]==0 and self.net[start_node][node]==1:
                    q.enqueue(node)
                    self.book[node]=1
                    self.visited.append(node)
        print 'The order of visiting nodes:', self.visited
       
                   
           
       
#main
if __name__ == "__main__":
    pool=[['A','C'], ['A','B'], ['A','E'], ['C','E'], ['B','D'],
          ['A','F'], ['C','B'], ['H','E'], ['G','E'], ['B','I']]


    #coordinate of the end point
    s=breadth_first_search(pool)
    start='A'
    s.arrange_network(start)
    print 'ok'

No comments:

Post a Comment