def delta(self, n, o, d): dK = 0 dW = {o:0, d:0} nE = set() dE = set() for v in self.neighbors(n): w = self[n][v]['weight'] e = self[n][v]['edge'] p = self.node[v]['partition'] if p == d: dK -= w dW[d] += w dE.add(e) elif p == o: dK += w dW[o] -= w nE.add(e) W = {p: self.W[p] for p in self.W} W[o] += dW[o] W[d] += dW[d] dB = max(W.values()) * self.k / float(sum(W.values())) - self.eval['to']['balance'] Wop = self.W[o] + dW[o] Wdp = self.W[d] + dW[d] Ko = self.K[o] * self.W[d] * Wop * Wdp Kd = self.K[d] * self.W[o] * Wop * Wdp Kop = (self.K[o] + dK) * self.W[o] * self.W[d] * Wdp Kdp = (self.K[d] + dK) * self.W[o] * self.W[d] * Wop Dn = self.W[o] * self.W[d] * Wop * Wdp dR = division(Kop + Kdp - Ko - Kd , Dn) return {'+e': nE, '-e': dE, 'dK': dK, 'dW': dW, 'cut': dK, 'balance': dB, 'ratio': dR}
def partition(self, k=2, depth=None, theta=None, preemption=['ratio'], replays=0, rand=False, log=Stub()): eval = preemption[0] # Get P, E and C from a greedy solution super(Local, self).partition(k, select='weight', rand=rand) self.eval = {'from': {}, 'to': {}} self.eval['from']['cut'] = self.cut() self.eval['to']['cut'] = self.eval['from']['cut'] self.eval['from']['balance'] = self.balance() self.eval['to']['balance'] = self.eval['from']['balance'] self.eval['from']['ratio'] = sum([division(self.K[p], self.W[p]) for p in range(k)]) self.eval['to']['ratio'] = self.eval['from']['ratio'] min = {e: self.eval['to'][e] for e in self.eval['to']} iter = 0 path = [] best = [] done = set() pool = [self.set_pool(eval, done)] move = Depth() step = 0 try: while iter >= 0: while len(pool[iter]) != 0: label = pool[iter].pop() delta = label.delta[eval] self.do(label) if not self.broke(label, move.value, eval=eval, depth=depth, theta=theta): step += 1 path.append(label) log.write('Iteration ' + str(step) + '\n') log.write('Eval(' + eval + ') ' + str(self.eval['to'][eval]) + '\n') if compare(self.eval['to'], min, preemption) < 0: min = {e: self.eval['to'][e] for e in self.eval['to']} best = [l for l in path] move.set(label=label) move.forward(label, eval=eval) pool.append(self.set_pool(eval, done, label=label)) iter += 1 else: self.undo(label) if iter != 0: label = path.pop() self.undo(label) move.backward(label, eval=eval) if self.broke(label, move.value, eval=eval, back=True, depth=depth, theta=theta): break pool.pop() iter -= 1 while len(path) != 0: label = path.pop() self.undo(label) for label in best: self.do(label) if compare(self.eval['to'], self.best['to'], preemption) < 0: P = [set() for p in range(self.k)] for n in self.nodes_iter(): P[self.node[n]['partition']].add(n) self.best['state'] = P self.best['step'] = step self.best['from'] = {e: self.eval['from'][e] for e in self.eval['from']} self.best['to'] = {e: self.eval['to'][e] for e in self.eval['to']} log.write('Operation success in ' + str(step) + ' iterations\n') log.write(str(self) + '\n\n') except KeyboardInterrupt: if compare(self.eval['to'], self.best['to'], preemption) < 0: self.best['state'] = P self.best['step'] = step self.best['from'] = {e: self.eval['from'][e] for e in self.eval['from']} self.best['to'] = {e: self.eval['to'][e] for e in self.eval['to']} eval = 'Operation interrupted during process\n' eval += 'Iteration ' + str(self.best['step']) + '\n' eval += 'Best solution found:\n' eval += str(self) + '\n' raise KeyboardInterrupt(eval) if replays > 0: self.partition(k=k, depth=depth, theta=theta, preemption=preemption, replays=replays - 1, rand=True, log=log) else: self.apply(self.best)