def glouton(k, graph, verbose, log): if log: print "Starting basic Glouton.." startTime = time.time() # initialisation initGraph = graph.copy() niList = [] markingList = [] potentialNodesList = [] partitionList = [] # initialisation du sommet de départ s0 = nodeWithLessNeighbor(graph, markingList) markingList.append(s0) potentialNodesList = setPotentialNodesList(graph,s0, markingList, potentialNodesList) if verbose : print "Sommet de depart :", s0 print "Potential Nodes : ", potentialNodesList # initialisation de i : numéro de partition courante i = 1 while i < k: # Calcul de ni : nombre de sommets pour la prochaine partition niList = calculateSizeListSubGraph(k, i, niList, initGraph) ni = niList[i-1] # j : nombre de sommets actuellement dans la partition courante j=1 # on compte le sommet de départ while potentialNodesList != [] and j < ni: m = potentialNodesList[-1][0] markingList.append(m) potentialNodesList = setPotentialNodesList(graph,m, markingList, potentialNodesList) j = j+1 # Affectation de la partition créée à la liste de partitions partitionList.append(markingList) # Réinitialisation des structures # Restructuration du graphe : suppression des sommets marqués graph.remove_nodes_from(markingList) markingList = [] potentialNodesList = [] i = i+1 # Initialisation de la prochaine partition if i != k : s0 = nodeWithLessNeighbor(graph, markingList) markingList.append(s0) potentialNodesList = setPotentialNodesList(graph,s0, markingList, potentialNodesList) # partitionList ← sommets restants partitionList.append(graph.nodes()) graph = initGraph # probleme : si on ne return pas le graphe, ici il est bien égal # à tout le graphe mais sans le return il vaut une partition... stopTime = time.time() if verbose: print "Partition finale 1:", partitionList[0] print "Partition finale 2:", partitionList[1] if log: print "Optimum trouve:", objf.calculateCut(partitionList[0],partitionList[1],graph) print "Execution Time :", stopTime-startTime return partitionList, graph
def calculateFictifGain(s1,s2,P1,P2,graph): # échange des sommets s1 et s2 newP1 = list(P1) newP1.remove(s1) newP1.append(s2) newP2 = list(P2) newP2.remove(s2) newP2.append(s1) # newG : gain si on permute s1 et s2 newG = objf.calculateCut(newP1, newP2, graph) #newG = objf.calculateGainNodesAB(s1, s2, newP1, newP2, graph) return newG
def calculateFictifGainUnique(s,P1,P2,graph): # déplacement du sommet s de P1 vers P2 newP1 = list(P1) newP2 = list(P2) if s in newP1: newP1.remove(s) newP2.append(s) else : newP2.remove(s) newP1.append(s) # newG : gain si on déplace s de P1 vers P2 newG = objf.calculateCut(newP1, newP2, graph) return newG
def kl(graph,verbose): print "Starting KL version 2.." startTime = time.time() ## Initialisation ## # Liste de partitions partitionsList = [] # Initialisation des listes de sommets à étudier # (une par partition) remainingNodesS1 = [] remainingNodesS2 = [] ## Déroulement de l'algo ## # bipartition partitionsList, graph = g.gloutonWithCut(2,graph,False,False) if verbose: print "Partition Init 1: ", partitionsList[0] print "Partition Init 2: ", partitionsList[1] deltaTime = -time.time() ratio = 20 # Mise a jour des listes des sommets à étudier remainingNodesS1 = list(partitionsList[0])[len(partitionsList[0])*(100-ratio)/100:] remainingNodesS2 = list(partitionsList[1])[len(partitionsList[1])*(100-ratio)/100:] # calcul du gain global initial globalMin = objf.calculateCut(remainingNodesS1,remainingNodesS2,graph) # Initialisation du gain fictif GainGlobalFictif = globalMin if verbose: print "Global Min Initial:", globalMin print "" print "Recherche de sommets uniques à changer..." nodesList = nx.nodes(graph) iterations = 100 while iterations > 0 : improvement = False localMin = sys.maxint for node in nodesList: gain = calculateFictifGainUnique(node, partitionsList[0], partitionsList[1], graph) # recherche du meilleur gain local if gain < localMin and gain > 0 : improvement = True localMin = gain s = node GainGlobalFictif = globalMin - gain if verbose: print "Nouveau gain local:", localMin, "Node: ", node print "Gain Global Fictif =", GainGlobalFictif if improvement : nodesList.remove(s) if (GainGlobalFictif < globalMin): globalMin = GainGlobalFictif if verbose: print "Nouveau gain global:", globalMin, "Node:", s print "Le noeud",s,"a été échangé de partition" partitionsList = switchNodesUnique(partitionsList,s) iterations = iterations - 1 stopTime = time.time() deltaTime += time.time() print "Temps d'exécution total:", stopTime-startTime print "Temps d'exécution KL:", deltaTime if verbose: print "Partition Finale 1:", partitionsList[0] print "Partition Finale 2:", partitionsList[1] print "Global cut:", objf.calculateCut(partitionsList[0], partitionsList[1], graph)
def kl(graph,verbose): print "Starting KL version 3.." startTime = time.time() ## Initialisation ## # Sert à mémoriser les sommets échangés exchangedNodes = [] # Liste de partitions partitionsList = [] # Initialisation des listes de sommets à étudier # (une par partition) remainingNodesS1 = [] remainingNodesS2 = [] # Initialisation des listes de gain fictif GFictif = 0 ## Déroulement de l'algo ## # bipartition partitionsList, graph = g.glouton(2,graph,False,False) # Mise a jour des listes des sommets à étudier remainingNodesS1 = list(partitionsList[0]) remainingNodesS2 = list(partitionsList[1]) if verbose: print "Partition Init 1: ", remainingNodesS1 print "Partition Init 2: ", remainingNodesS2 optimumEqu = False # boucle principale deltaTime = -time.time() # calcul du gain global initial globalMin = objf.calculateCut(remainingNodesS1,remainingNodesS2,graph) if verbose: print "Global Min Initial:", globalMin while remainingNodesS1 != [] and remainingNodesS2 != [] and not optimumEqu: improvement = False P1 = list(partitionsList[0]) P2 = list(partitionsList[1]) localMin = sys.maxint # On inverse l'ordre de P1 et de P2 car les derniers sommets ajoutés # sont les plus susceptibles à ressortir en premier for nodeA in reversed(remainingNodesS1): # s1 : sommet candidat de S1 pour un échange s1 = nodeA for nodeB in reversed(remainingNodesS2): # on cherche le meilleur candidat pour un échange avec s1 # Calcul du gain lié à l'échange de a et b : G(a,b) #gainAB = calculateFictifGain(s1, nodeB, P1, P2, graph) gainAB = objf.calculateGainNodesAB(s1, nodeB, P1, P2, graph) if gainAB + globalMin < localMin: localMin = gainAB + globalMin # s2 : sommet candidat de S2 pour un échange avec s1 s2 = nodeB if verbose: print "Nouveau gain local:", localMin, "Nodes: ", s1, s2 #GFictif = gainAB GFictif = localMin # Mise a jour du gain global if (GFictif < globalMin): improvement = True globalMin = GFictif if verbose: print "Nouveau gain global:", globalMin, "Nodes:", s1, s2 exchangedNodes.append(s1) exchangedNodes.append(s2) # P ← échanger les sommets s1 et s2 partitionsList = switchNodes(partitionsList,s1,s2) if verbose: print "Les noeuds",s1,"et",s2, "ont été échangés" print "Partition 1:", partitionsList[0] print "Partition 2:", partitionsList[1] # Mise a jour des listes des sommets à étudier remainingNodesS1 = setRemainingNodes(partitionsList[0],exchangedNodes) remainingNodesS2 = setRemainingNodes(partitionsList[1],exchangedNodes) if (improvement == False): if verbose: print "Optimum équilibré trouvé:", objf.calculateCut(partitionsList[0], partitionsList[1], graph) optimumEqu = True if verbose: print "" print "Recherche de sommets uniques à changer..." while exchangedNodes != [] : localMin = sys.maxint for node in exchangedNodes: gain = calculateFictifGainUnique(node, partitionsList[0], partitionsList[1], graph) # recherche du meilleur gain local if gain < localMin: localMin = gain if verbose: print "Nouveau gain local:", localMin, "Node: ", node s = node GFictif = gain exchangedNodes.remove(s) if (GFictif < globalMin): globalMin = GFictif if verbose: print "Nouveau gain global:", globalMin, "Node:", s print "Le noeud",s,"a été échangé de partition" partitionsList = switchNodesUnique(partitionsList,s) stopTime = time.time() deltaTime += time.time() print "Temps d'exécution total:", stopTime-startTime print "Temps d'exécution KL:", deltaTime if verbose: print "Partition Finale 1:", partitionsList[0] print "Partition Finale 2:", partitionsList[1] print "Global cut:", objf.calculateCut(partitionsList[0], partitionsList[1], graph)
def recuitSimule(graph, iterations, tempI, remonteeMax,verbose): print "Starting Recuit Simule with", iterations, "iterations,", tempI, "as initial temperature and", remonteeMax, "as max upgoing movements" deltaTime0 = -time.time() ## Initialisation ## # Liste de partitions partitionsList = [] # Appel du Glouton partitionsList, graph = g.gloutonWithCut(2,graph,False,False) P1Final = list(partitionsList[0]) P2Final = list(partitionsList[1]) if verbose : print "Partition P1 init :", P1Final print "Partition P2 init :", P2Final print "Number of nodes in graph:", nx.number_of_nodes(graph) # calcul du gain global initial globalMin = objf.calculateCut(partitionsList[0],partitionsList[1],graph) # Initialisation du gain fictif GainGlobalFictif = globalMin print "Global Min Initial:", globalMin # Temps de départ deltaTime = -time.time() # Nombre d'iteration de l'algorithme iterationsC = 0 # Nombre courant de remontée de temperature consecutives remontee = 0 # Temperature courante tempC = tempI list_pourcentage = [0,10,20,30,40,50,60,70,80,90] nodesOnLimit,neighborsList = neighbors(partitionsList[0],graph) # Boucle principale while iterationsC < iterations : pourcentage = (iterationsC*100)/iterations if pourcentage in list_pourcentage: del(list_pourcentage[0]) print '------------------',pourcentage, "% effectués", '------------------' change = False # Candidat aleatoire de la partition P1 nodeA = selectNode(nodesOnLimit) # Candidat aleatoire de la partition P2 nodeB = selectNode(neighborsList) # Calcul du gain lié à l'échange de nodeA et nodeB : G(nodeA,nodeB) gainAB = calculateFictifGain(nodeA, nodeB, partitionsList[0], partitionsList[1], graph) if verbose: print "Gain entre",nodeA,"et",nodeB,"=",gainAB # Amelioration solution locale if gainAB >= 0 : change = True remontee = 0 if verbose : print "Descente en temperature avec les noeuds", nodeA, "et", nodeB else: # Acceptation de la solution dégradante if random() < exp(gainAB/tempC) and remontee < remonteeMax : change = True remontee +=1 if verbose : print "Remontee en temperature avec les noeuds", nodeA, "et", nodeB # Changement a effectuer if change : # On echange les sommets nodeA et nodeB partitionsList = switchNodes(partitionsList,nodeA,nodeB) updateNeighbors(nodeA,nodeB,nodesOnLimit,neighborsList,partitionsList[0],partitionsList[1],graph) GainGlobalFictif = GainGlobalFictif - gainAB if verbose: print "Les noeuds",nodeA,"et",nodeB, "ont été échangés" print "Gain fictif =", GainGlobalFictif if GainGlobalFictif < globalMin and GainGlobalFictif > 0: globalMin = GainGlobalFictif print "Update globalMin =",globalMin P1Final = list(partitionsList[0]) P2Final = list(partitionsList[1]) # cas où la remontee de temperature n'a que fait dégrader la solution if remontee == remonteeMax and not change : if verbose: print "Degradation trop élevée --> récupération des anciennes partitions" # récupération de la meilleure partition partitionsList[0] = list(P1Final) partitionsList[1] = list(P2Final) nodesOnLimit,neighborsList = neighbors(partitionsList[0],graph) addRandomNode(nodesOnLimit, partitionsList[0]) addRandomNode(neighborsList, partitionsList[1]) iterationsC +=1 tempC = 0.99*tempC deltaTime += time.time() deltaTime0 += time.time() if verbose: print "Partition Finale 1:", P1Final print "Partition Finale 2:", P2Final print "Temps d'exécution recuit-simule:", deltaTime print "Temps d'exécution global:", deltaTime0 print "Global cut:", globalMin