def __init__(self, N=0, E=None, type=None, w=None, M=None): """Costruisce un grafo vuoto con N vertici, e insieme di archi E (se specificato). Se type e' specificato, costruisce invece un grafo di quel tipo. I valori ammissibili per type sono cycle,path,tree,forest,clique. Se w e' specificato, il grafo viene considerato pesato, con pesi generati dalla funzione w(). E' anche ammessa l'instanziazione graph(G) con G un grafo gia' esistente.""" if isinstance(N, graph) and E is None and M is None and type is None: E = sortedset(N.E) N = N.V if not isinstance(N, int): raise StandardError("Incompatible parameters specified.") if isinstance(E, int): M = E E = None if E is None: E = sortedset([]) else: if (M is not None) or (type is not None): raise StandardError("Incompatible parameters specified.") if len(E) > 0 and isinstance(E.__iter__().next(), list): E = [self.cod(e) for e in E] E = sortedset(E) if len(E) == 0 and N > 1: if type == 'cycle': for i in xrange(N): E.add(self.cod([i, (i + 1) % N])) if type == 'path': for i in xrange(N - 1): E.add(self.cod([i, (i + 1) % N])) if type == 'tree': for i in xrange(1, N): E.add(self.cod([randint(i), i])) if type == 'forest': if not (0 <= M < N): raise StandardError("Parameter M out of bounds.") for i in lsample(N - 1, M): E.add(self.cod([randint(i + 1), i + 1])) if type == 'clique': for i in xrange(N - 1): for j in xrange(i + 1, N): E.add(self.cod([i, j])) if type == 'star': for i in xrange(1, N): E.add(self.cod([0, i])) if type == 'wheel': for i in xrange(1, N): E.add(self.cod([0, i])) E.add(self.cod([i, (i + 1) % N])) # eventualmente aggiungere: gear, caterpillar/lobster self.V = N self.w = w self.E = E
def addedges(self, K, candidates = None): """Aggiunge K archi a caso al grafo, tra i candidati (oggetto di tipo edgerange o set/list di archi).""" if candidates is None: candidates = self.mMax() if isinstance(candidates, int): candidates = xrange(candidates) if isinstance(candidates, xrange): i = bisect_left(self.E, candidates[0]) j = bisect_left(self.E, candidates[-1]+1) dup = self.E[i:j] else: dup = sortedset([]) for e in self: if e in candidates: dup.add(self.cod(e)) self.E |= sortedset(lsample(candidates, K, dup))
def addedges(self, K, candidates=None): """Aggiunge K archi a caso al grafo, tra i candidati (oggetto di tipo edgerange o set/list di archi).""" if candidates is None: candidates = self.mMax() if isinstance(candidates, int): candidates = xrange(candidates) if isinstance(candidates, xrange): i = bisect_left(self.E, candidates[0]) j = bisect_left(self.E, candidates[-1] + 1) dup = self.E[i:j] else: dup = sortedset([]) for e in self: if e in candidates: dup.add(self.cod(e)) self.E |= sortedset(lsample(candidates, K, dup))
def __iadd__(self,other): """Unione disgiunta di grafi.""" if isinstance(other,graph): self.E |= sortedset([self.cod([e[0]+self.V,e[1]+self.V]) for e in other]) self.V += other.V self.lbl += [i+self.V for i in other.lbl] else: self.add(other) return self
def __iadd__(self, other): """Unione disgiunta di grafi.""" if isinstance(other, graph): self.E |= sortedset( [self.cod([e[0] + self.V, e[1] + self.V]) for e in other]) self.V += other.V else: self.add(other) return self
def __init__(self,mdp,disc,**kwargs): self.mdp = mdp self.disc = disc self.val_reg = kwargs.get('val_reg',0.0) self.flow_reg = kwargs.get('flow_reg',1e-15) self.num_states = mdp.num_states self.num_actions = mdp.num_actions # List of nodes to be spliced from the model # Format: NODE_ID -> TERMINAL COST self.included_nodes = sortedset(xrange(self.num_states)) self.omitted_nodes = {}
def __invert__(self): """Grafo complementare.""" G = self.__class__(self.V,sortedset(xrange(self.mMax())) - self.E) return G
def __init__(self, N=0, E=None, type=None, w=None, M=None, lbl=None): """Costruisce un grafo vuoto con N vertici, e insieme di archi E (se specificato). Se type e' specificato, costruisce invece un grafo di quel tipo. I valori ammissibili per type sono cycle,path,tree,forest,clique. Se w e' specificato, il grafo viene considerato pesato, con pesi generati dalla funzione w(). E' anche ammessa l'instanziazione graph(G) con G un grafo gia' esistente.""" if isinstance(N,graph) and E is None and M is None and type is None: E = sortedset(N.E) if w is None: w = N.w if lbl is None: lbl = list(N.lbl) N = N.V if not isinstance(N,int): raise StandardError("Incompatible parameters specified.") if isinstance(E,int): M=E E=None if E is None: E = sortedset([]) else: if (M is not None) or (type is not None): raise StandardError("Incompatible parameters specified.") if len(E) > 0 and isinstance(E.__iter__().next(),list): E = [self.cod(e) for e in E] E = sortedset(E) if len(E)==0 and N > 1: if type == 'cycle': for i in xrange(N): E.add(self.cod([i,(i+1)%N])) if type == 'path': for i in xrange(N-1): E.add(self.cod([i,i+1])) if type == 'tree': for i in xrange(1,N): E.add(self.cod([randint(i),i])) if type == 'forest': if not (0 <= M < N): raise StandardError("Parameter M out of bounds.") for i in lsample(N-1,M): E.add(self.cod([randint(i+1),i+1])) if type == 'clique': for i in xrange(N-1): for j in xrange(i+1,N): E.add(self.cod([i,j])) if type == 'star': for i in xrange(1,N): E.add(self.cod([0,i])) if type == 'wheel': for i in xrange(1,N): E.add(self.cod([0,i])) E.add(self.cod([i,(i+1)%N])) # eventualmente aggiungere: gear, caterpillar/lobster self.V=N self.lbl = lbl if lbl is not None else range(self.V) if w is not None: try: w([0,1]) self.w=w except TypeError: self.w = lambda e: w() else: self.w=w self.E=E
def shuffle(self, perm=None): """Permuta casualmente i nodi del grafo tra di loro.""" if perm is None: perm = range(self.V) shuffle(perm) self.E = sortedset([self.cod([perm[e[0]], perm[e[1]]]) for e in self])
def __invert__(self): """Grafo complementare.""" G = self.__class__(self.V, sortedset(xrange(self.mMax())) - self.E) return G
def run(X, T): V = 1 if T == 1 else MAXV K = X if (randint(0, 2) == 0) else randint(2, X) N = MAXN - K + 2 if (randint(0, 2) == 0) else randint( 2 * K + 2 if T == 2 else 6, MAXN - K + 2) M = 2 * N - K if T == 2 else MAXM - K + 1 M = M if (randint(0, 2) == 0) else randint(N + K + 2, M) N1 = randint((K + 1) / 2, N - (K + 1) / 2) if T == 2 else randint(3, N - 3) N2 = N - N1 M1 = randint(max(0, M - K - 2 - 2 * N2), min(2 * N1 - 2 - K, M - K - 2)) if T == 2 else randint( N1, M - N - K - 2 + N1) M2 = M - M1 - K - 2 V1 = randint(1, V) if T == 2: assert (0 <= M1 <= 2 * N1 - K - 2) assert (0 <= M2 <= 2 * N2) deg = [0 for _ in xrange(N)] E = [] # links tra parte 1 e 2 E.append([randint(1, N1 - 1), randint(N1, N - 1), 0]) deg[E[-1][0]] += 1 E.append((randint(N1, N - 1), randint(0, N1 - 1), randint(0, V))) deg[E[-1][0]] += 1 deg[0] += 1 # per via del ciclo esterno # K-ciclo lasti = newi = 0 for i in xrange(K - 1): while newi == lasti or (newi == 0 and i == K - 2) or (deg[newi] == T == 2): newi = randint(0, N1 - 1) E.append((lasti, newi, randint(0, randint(0, V1)))) deg[E[-1][0]] += 1 lasti = newi E.append((lasti, 0, randint(0, V1))) deg[E[-1][0]] += 1 # archi in zona 1 e 2 for xxx in [(M1, 0, N1, 0, V1), (M2, N1, N, V1, V)]: nodes = sortedset([i for i in xrange(xxx[1], xxx[2]) if deg[i] < 2 ]) if T == 2 else xrange(xxx[1], xxx[2]) for i in xrange(xxx[0]): lasti = newi = choice(nodes) while newi == lasti: newi = randint(0, xxx[2] - 1) E.append( (lasti, newi, randint(0 if randint(0, 1) else xxx[3], xxx[4]))) deg[E[-1][0]] += 1 if deg[E[-1][0]] == T == 2: nodes.discard(E[-1][0]) # aggiusto peso E[0] e asserto maxv = V1 for ed in E[1:]: if ed[0] == E[0][0]: maxv = min(maxv, ed[2]) E[0][2] = randint(0, maxv) if T == 2: assert (all([deg[i] <= 2 for i in xrange(N)])) # inserisco ciclo fallace esterno E.append((0, N, V)) for i in xrange(N, N + K - 3): E.append((i, i + 1, V)) E.append((N + K - 3, 0, V)) N += K - 2 M += K - 1 # shuffling shuf = range(1, N) shuffle(E) shuffle(shuf) shuf = [0] + shuf print K, N, M for ed in E: print shuf[ed[0]], shuf[ed[1]], ed[2]