Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import random
- import matplotlib.pyplot as plt
- import numpy
- class Node:
- def __init__(self, name, fitness, isSpecial, neighbors):
- self._name = name
- self._fitness = fitness
- self._isSpecial = isSpecial
- self._neighbors = neighbors
- def setName(self, name):
- self._name = name
- def getName(self):
- return self._name
- def setFitness(self, fitness):
- self._fitness = fitness
- def getFitness(self):
- return self._fitness
- def markSpecial(self, isSpecial):
- self._isSpecial = isSpecial
- def isSpecial(self):
- return self._isSpecial
- def setNeighbors(self, neighbors):
- self._neighbors = neighbors
- def getNeighbors(self):
- return self._neighbors
- def addNeighbor(self, neighbor):
- self._neighbors.add(neighbor)
- def getDegree(self):
- return len(self._neighbors)
- def __str__(self):
- return "Node {}, fitness={}, isSpecial={}, neighbor={}".format(self._name,
- self._fitness,
- self._isSpecial,
- self._neighbors)
- class Network:
- def __init__(self, initialNodes, fitness, finalNodes, links, specialNodes):
- if finalNodes <= initialNodes:
- raise ValueError("finalNodes should be greater than initialNodes")
- if specialNodes >= initialNodes:
- raise ValueError("specialNodes should be less than initialNodes")
- if specialNodes <= 0:
- raise ValueError("Please give the graph the number of special nodes")
- self._initialNodes = initialNodes
- self._fitness = fitness
- self._finalNodes = finalNodes
- self._links = links
- self._specialNodes = specialNodes
- self._graph = self.__generateRandomNetwork(initialNodes, 0.999)
- self._data = {}
- # My implementation for random graph (Erdös-Rènyi model)
- def __generateRandomNetwork(self, n, p):
- # a dictionany represents a random network with key(node) and value(node object)
- network = {}
- for i in range(n):
- if not i in network.keys():
- network[i] = Node(name=i,
- fitness=self._fitness,
- isSpecial=True if i < self._specialNodes else False,
- neighbors=set())
- for j in range(n):
- if i != j:
- r = random.random()
- if r < p:
- # add j as a neighbor of i
- network[i].addNeighbor(j)
- # add i as a neighbor of j too
- if j in network.keys():
- network[j].addNeighbor(i)
- else:
- network[j] = Node(name=j,
- fitness=self._fitness,
- isSpecial=True if j < self._specialNodes else False,
- neighbors=set([i]))
- else:
- continue
- network = dict(sorted(network.items(), key=lambda t: t[0]))
- return network
- # return a list of neighbors which represents adjacent list of the new node
- def __getNeighborsOfNewNode(self, nodePopolation, nodePrefAtt, neighborSize):
- neighborsOfNewNode = numpy.random.choice(nodePopolation,
- neighborSize,
- replace=True,
- p=nodePrefAtt)
- return neighborsOfNewNode
- def __getPreferentialAttachments(self):
- prefAttachs = {}
- totalDegrees = sum((nodeObject.getDegree()*nodeObject.getFitness()) for nodeObject in self._graph.values())
- for nodeKey, nodeObject in self._graph.items():
- degree = nodeObject.getDegree()*nodeObject.getFitness()
- prefAttachs[nodeKey] = degree/totalDegrees
- return prefAttachs
- def __updateFitness(self, node, timeStep):
- if node.isSpecial() & (timeStep < self._finalNodes/2):
- fitnessValue = node.getFitness() + node.getFitness()/1000
- node.setFitness(fitnessValue)
- else:
- # do nothing
- pass
- def growNetwork(self):
- for timeStep in range(self._initialNodes, self._finalNodes):
- # create new node at time step with initial fitness, not special and with empty neighbors
- newNode = Node(name=timeStep,
- fitness=self._fitness,
- isSpecial=False,
- neighbors=set())
- # retrieve neigbors of new node
- prefAttDict = self.__getPreferentialAttachments()
- neighborsOfNewNode = self.__getNeighborsOfNewNode(list(prefAttDict.keys()),
- list(prefAttDict.values()),
- self._links)
- for neighborNode in list(neighborsOfNewNode):
- newNode.addNeighbor(neighborNode)
- self._graph[neighborNode].addNeighbor(timeStep)
- # add new node to the graph
- self._graph[timeStep] = newNode
- # update fitness and save degree of each special node at time step
- self._data[timeStep] = {}
- for eachSpecial in range(self._specialNodes):
- self.__updateFitness(self._graph[eachSpecial], timeStep)
- self._data[timeStep][eachSpecial] = self._graph[eachSpecial].getDegree()
- # save degree of the normal node at time step
- self._data[timeStep][self._specialNodes] = self._graph[self._specialNodes].getDegree()
- def saveData(self):
- try:
- file1 = open('Degree.txt', mode='w', encoding='utf-8')
- for key, value in self._data.items():
- file1.write("{} : {}\n".format(key, value))
- finally:
- file1.close()
- def plotNetwork(self):
- timeSteps = []
- degreeDataByStep = []
- for specialNode in range(self._specialNodes+1):
- degreeDataByStep.append([])
- for timeStep, degreeDictionary in self._data.items():
- timeSteps.append(timeStep)
- for specialNode in range(self._specialNodes+1):
- degreeDataByStep[specialNode].append(degreeDictionary[specialNode])
- # linear scale
- legendNames = []
- for index in range(len(degreeDataByStep)):
- legendNames.append("special{}".format(index) if (index != len(degreeDataByStep)-1) else "normal{}".format(index))
- plt.plot(timeSteps, degreeDataByStep[index])
- plt.xscale('linear')
- plt.yscale('linear')
- plt.title('linear')
- plt.legend(legendNames, loc='upper left')
- plt.show()
- # log-log scale
- for eachData in degreeDataByStep:
- plt.plot(timeSteps, eachData)
- plt.xscale('log')
- plt.yscale('log')
- plt.title('log')
- plt.legend(legendNames, loc='upper left')
- plt.show()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement