import random
from AbstractNetwork import AbstractNetwork
import Tools
from Node import Node

class ScaleFreeNetwork(AbstractNetwork):
    """Scale-free network implementation of AbstractNetwork"""
    degreeSum = 0
          
    def __createNetwork__(self, amount_nodes, amount_links):
        """
        Create a network with an amount of n nodes, add m links per iteration step
        for n nodes:
            for m links:
                link node to other nodes
        """
        random.seed()
        numOfNodes = 0
        linksPerIteration = (amount_links-3)/(amount_nodes-3) if amount_nodes > 3 else 1
        #generate n nodes
        while numOfNodes < amount_nodes:
            node = Node(numOfNodes)
            self.appendNode(node)
            numOfNodes += 1
            #make first three nodes fully connected
            if numOfNodes == 2:
                self.__connectNode__(numOfNodes, 1)
            if numOfNodes == 3:
                self.__connectNode__(numOfNodes, 2)
            #link following nodes
            if numOfNodes > 3:
                self.__connectNode__(numOfNodes, linksPerIteration)

    def __connectNode__(self, numOfNodes, linksPerIteration):
        """
        Connect an existing node to m other nodes
        :param numOfNodes: current amount of nodes
        :param linksPerIterations: number of links that should be added in this iteration
        """
        numOfLinks = 0
        node1 = self.getNode(numOfNodes - 1)
        # add n links per iteration
        while numOfLinks < linksPerIteration:
            #choose second node randomly
            nodeid2 = 0
            r = random.random()
            while nodeid2 < numOfNodes-1:
                node2 = self.getNode(nodeid2)
                #determine probability to choose node
                if self.degreeSum != 0 and node2.degree() != 0:
                    pi = float(node2.degree()) / (self.degreeSum - node1.degree())
                else:
                    pi = float(1)
                if not node1.hasLinkTo(node2):
                    #choose node with probability pi
                    if r < pi:
                        numOfLinks += 1
                        self.degreeSum += 2
                        node1.addLinkTo(node2)
                        node2.addLinkTo(node1)
                        break
                r -= pi
                nodeid2 += 1

6d31f4a8dfde0e05bb505ec893fc83dd73d47eb3
<mask token>


class ScaleFreeNetwork(AbstractNetwork):
    <mask token>
    <mask token>

    def __createNetwork__(self, amount_nodes, amount_links):
        """
        Create a network with an amount of n nodes, add m links per iteration step
        for n nodes:
            for m links:
                link node to other nodes
        """
        random.seed()
        numOfNodes = 0
        linksPerIteration = (amount_links - 3) / (amount_nodes - 3
            ) if amount_nodes > 3 else 1
        while numOfNodes < amount_nodes:
            node = Node(numOfNodes)
            self.appendNode(node)
            numOfNodes += 1
            if numOfNodes == 2:
                self.__connectNode__(numOfNodes, 1)
            if numOfNodes == 3:
                self.__connectNode__(numOfNodes, 2)
            if numOfNodes > 3:
                self.__connectNode__(numOfNodes, linksPerIteration)

    def __connectNode__(self, numOfNodes, linksPerIteration):
        """
        Connect an existing node to m other nodes
        :param numOfNodes: current amount of nodes
        :param linksPerIterations: number of links that should be added in this iteration
        """
        numOfLinks = 0
        node1 = self.getNode(numOfNodes - 1)
        while numOfLinks < linksPerIteration:
            nodeid2 = 0
            r = random.random()
            while nodeid2 < numOfNodes - 1:
                node2 = self.getNode(nodeid2)
                if self.degreeSum != 0 and node2.degree() != 0:
                    pi = float(node2.degree()) / (self.degreeSum - node1.
                        degree())
                else:
                    pi = float(1)
                if not node1.hasLinkTo(node2):
                    if r < pi:
                        numOfLinks += 1
                        self.degreeSum += 2
                        node1.addLinkTo(node2)
                        node2.addLinkTo(node1)
                        break
                r -= pi
                nodeid2 += 1

<mask token>


class ScaleFreeNetwork(AbstractNetwork):
    <mask token>
    degreeSum = 0

    def __createNetwork__(self, amount_nodes, amount_links):
        """
        Create a network with an amount of n nodes, add m links per iteration step
        for n nodes:
            for m links:
                link node to other nodes
        """
        random.seed()
        numOfNodes = 0
        linksPerIteration = (amount_links - 3) / (amount_nodes - 3
            ) if amount_nodes > 3 else 1
        while numOfNodes < amount_nodes:
            node = Node(numOfNodes)
            self.appendNode(node)
            numOfNodes += 1
            if numOfNodes == 2:
                self.__connectNode__(numOfNodes, 1)
            if numOfNodes == 3:
                self.__connectNode__(numOfNodes, 2)
            if numOfNodes > 3:
                self.__connectNode__(numOfNodes, linksPerIteration)

    def __connectNode__(self, numOfNodes, linksPerIteration):
        """
        Connect an existing node to m other nodes
        :param numOfNodes: current amount of nodes
        :param linksPerIterations: number of links that should be added in this iteration
        """
        numOfLinks = 0
        node1 = self.getNode(numOfNodes - 1)
        while numOfLinks < linksPerIteration:
            nodeid2 = 0
            r = random.random()
            while nodeid2 < numOfNodes - 1:
                node2 = self.getNode(nodeid2)
                if self.degreeSum != 0 and node2.degree() != 0:
                    pi = float(node2.degree()) / (self.degreeSum - node1.
                        degree())
                else:
                    pi = float(1)
                if not node1.hasLinkTo(node2):
                    if r < pi:
                        numOfLinks += 1
                        self.degreeSum += 2
                        node1.addLinkTo(node2)
                        node2.addLinkTo(node1)
                        break
                r -= pi
                nodeid2 += 1

<mask token>


class ScaleFreeNetwork(AbstractNetwork):
    """Scale-free network implementation of AbstractNetwork"""
    degreeSum = 0

    def __createNetwork__(self, amount_nodes, amount_links):
        """
        Create a network with an amount of n nodes, add m links per iteration step
        for n nodes:
            for m links:
                link node to other nodes
        """
        random.seed()
        numOfNodes = 0
        linksPerIteration = (amount_links - 3) / (amount_nodes - 3
            ) if amount_nodes > 3 else 1
        while numOfNodes < amount_nodes:
            node = Node(numOfNodes)
            self.appendNode(node)
            numOfNodes += 1
            if numOfNodes == 2:
                self.__connectNode__(numOfNodes, 1)
            if numOfNodes == 3:
                self.__connectNode__(numOfNodes, 2)
            if numOfNodes > 3:
                self.__connectNode__(numOfNodes, linksPerIteration)

    def __connectNode__(self, numOfNodes, linksPerIteration):
        """
        Connect an existing node to m other nodes
        :param numOfNodes: current amount of nodes
        :param linksPerIterations: number of links that should be added in this iteration
        """
        numOfLinks = 0
        node1 = self.getNode(numOfNodes - 1)
        while numOfLinks < linksPerIteration:
            nodeid2 = 0
            r = random.random()
            while nodeid2 < numOfNodes - 1:
                node2 = self.getNode(nodeid2)
                if self.degreeSum != 0 and node2.degree() != 0:
                    pi = float(node2.degree()) / (self.degreeSum - node1.
                        degree())
                else:
                    pi = float(1)
                if not node1.hasLinkTo(node2):
                    if r < pi:
                        numOfLinks += 1
                        self.degreeSum += 2
                        node1.addLinkTo(node2)
                        node2.addLinkTo(node1)
                        break
                r -= pi
                nodeid2 += 1

import random
from AbstractNetwork import AbstractNetwork
import Tools
from Node import Node


class ScaleFreeNetwork(AbstractNetwork):
    """Scale-free network implementation of AbstractNetwork"""
    degreeSum = 0

    def __createNetwork__(self, amount_nodes, amount_links):
        """
        Create a network with an amount of n nodes, add m links per iteration step
        for n nodes:
            for m links:
                link node to other nodes
        """
        random.seed()
        numOfNodes = 0
        linksPerIteration = (amount_links - 3) / (amount_nodes - 3
            ) if amount_nodes > 3 else 1
        while numOfNodes < amount_nodes:
            node = Node(numOfNodes)
            self.appendNode(node)
            numOfNodes += 1
            if numOfNodes == 2:
                self.__connectNode__(numOfNodes, 1)
            if numOfNodes == 3:
                self.__connectNode__(numOfNodes, 2)
            if numOfNodes > 3:
                self.__connectNode__(numOfNodes, linksPerIteration)

    def __connectNode__(self, numOfNodes, linksPerIteration):
        """
        Connect an existing node to m other nodes
        :param numOfNodes: current amount of nodes
        :param linksPerIterations: number of links that should be added in this iteration
        """
        numOfLinks = 0
        node1 = self.getNode(numOfNodes - 1)
        while numOfLinks < linksPerIteration:
            nodeid2 = 0
            r = random.random()
            while nodeid2 < numOfNodes - 1:
                node2 = self.getNode(nodeid2)
                if self.degreeSum != 0 and node2.degree() != 0:
                    pi = float(node2.degree()) / (self.degreeSum - node1.
                        degree())
                else:
                    pi = float(1)
                if not node1.hasLinkTo(node2):
                    if r < pi:
                        numOfLinks += 1
                        self.degreeSum += 2
                        node1.addLinkTo(node2)
                        node2.addLinkTo(node1)
                        break
                r -= pi
                nodeid2 += 1

import random
from AbstractNetwork import AbstractNetwork
import Tools
from Node import Node

class ScaleFreeNetwork(AbstractNetwork):
    """Scale-free network implementation of AbstractNetwork"""
    degreeSum = 0
          
    def __createNetwork__(self, amount_nodes, amount_links):
        """
        Create a network with an amount of n nodes, add m links per iteration step
        for n nodes:
            for m links:
                link node to other nodes
        """
        random.seed()
        numOfNodes = 0
        linksPerIteration = (amount_links-3)/(amount_nodes-3) if amount_nodes > 3 else 1
        #generate n nodes
        while numOfNodes < amount_nodes:
            node = Node(numOfNodes)
            self.appendNode(node)
            numOfNodes += 1
            #make first three nodes fully connected
            if numOfNodes == 2:
                self.__connectNode__(numOfNodes, 1)
            if numOfNodes == 3:
                self.__connectNode__(numOfNodes, 2)
            #link following nodes
            if numOfNodes > 3:
                self.__connectNode__(numOfNodes, linksPerIteration)

    def __connectNode__(self, numOfNodes, linksPerIteration):
        """
        Connect an existing node to m other nodes
        :param numOfNodes: current amount of nodes
        :param linksPerIterations: number of links that should be added in this iteration
        """
        numOfLinks = 0
        node1 = self.getNode(numOfNodes - 1)
        # add n links per iteration
        while numOfLinks < linksPerIteration:
            #choose second node randomly
            nodeid2 = 0
            r = random.random()
            while nodeid2 < numOfNodes-1:
                node2 = self.getNode(nodeid2)
                #determine probability to choose node
                if self.degreeSum != 0 and node2.degree() != 0:
                    pi = float(node2.degree()) / (self.degreeSum - node1.degree())
                else:
                    pi = float(1)
                if not node1.hasLinkTo(node2):
                    #choose node with probability pi
                    if r < pi:
                        numOfLinks += 1
                        self.degreeSum += 2
                        node1.addLinkTo(node2)
                        node2.addLinkTo(node1)
                        break
                r -= pi
                nodeid2 += 1
