def glue_self_classical(Hz, pairs): mz, n = Hz.shape k = len(pairs) A = Chain([Hz]) C = Chain([identity2(k)]) fn = zeros2(n, k) for idx, pair in enumerate(pairs): i1, i2 = pair fn[i1, idx] = 1 fm = dot2(Hz, fn) f = Morphism(C, A, [fm, fn]) gn = zeros2(n, k) for idx, pair in enumerate(pairs): i1, i2 = pair gn[i2, idx] = 1 gm = dot2(Hz, gn) g = Morphism(C, A, [gm, gn]) _, _, D = chain.equalizer(f, g) Hz = D[0] return Hz
def test_selfdual(): HxA = array2([[1, 1, 1, 1]]) HzA = array2([[1, 1, 1, 1]]) A = Chain([HxA, HzA.transpose()]) HxB = array2([[1, 1, 1, 1]]) HzB = array2([[1, 1, 1, 1]]) B = Chain([HxB, HzB.transpose()]) HzC = zeros2(0, 2) HxC = array2([[1, 1]]) C = Chain([HxC, HzC.transpose()]) #HzC = zeros2(0, 2) #HxC = zeros2(0, 2) #C = Chain([HxC, HzC.transpose()]) # Chain map from C -> A CAz = zeros2(1, 0) CAn = zeros2(4, 2) CAn[0, 0] = 1 CAn[1, 1] = 1 CAx = array2([[1]]) CA = Morphism(C, A, [CAx, CAn, CAz]) # Chain map from C -> B CBz = CAz CBn = CAn CBx = CAx CB = Morphism(C, B, [CBx, CBn, CBz]) AD, BD, D, _ = chain.pushout(CA, CB) code = D.get_code()
def test_glue(): m = argv.get("m", 9) n = argv.get("n", 10) d = argv.get("d", 0) p = argv.get("p", 0.5) weight = argv.weight H1 = rand2(m, n, p, weight) G1 = find_kernel(H1) G1t = G1.transpose() H1t = H1.transpose() A1 = Chain([G1, H1t]) k1 = len(G1) print("H1") print(fstr(H1)) print() print(fstr(G1)) w = wenum(H1) print("wenum:", [len(wi) for wi in w]) H2 = rand2(m, n, p, weight) H2t = H2.transpose() G2 = find_kernel(H2) G2t = G2.transpose() A2 = Chain([G2, H2t]) k2 = len(G2) print("H2") print(fstr(H2)) print() print(fstr(G2)) w = wenum(H2) print("wenum:", [len(wi) for wi in w]) if k1 != k2: return k = k1 I = identity2(k) B = Chain([I, zeros2(k, 0)]) a = zeros2(n, k) for i in range(k): a[i, i] = 1 f1 = Morphism(B, A1, [dot2(G1, a), a, zeros2(m, 0)]) f2 = Morphism(B, A2, [dot2(G2, a), a, zeros2(m, 0)]) a, b, C, _ = chain.pushout(f1, f2) H = C[1].transpose() print("H:") print(fstr(H)) w = wenum(H) print("wenum:", [len(wi) for wi in w])
def glue2(H1, H2, i1, i2): m1, n1 = H1.shape m2, n2 = H2.shape A1 = Chain([H1]) A2 = Chain([H2]) C = Chain([array2([[1]])]) C1n = zeros2(n1, 1) C1n[i1, 0] = 1 C1m = dot2(H1, C1n) C1 = Morphism(C, A1, [C1m, C1n]) C2n = zeros2(n2, 1) C2n[i2, 0] = 1 C2m = dot2(H2, C2n) C2 = Morphism(C, A2, [C2m, C2n]) AD, BD, D, _ = chain.pushout(C1, C2) H = D[0] #print(H.shape) #print(H) return H
def glue_pairs(H1, H2, pairs): m1, n1 = H1.shape m2, n2 = H2.shape k = len(pairs) A1 = Chain([H1]) A2 = Chain([H2]) C = Chain([identity2(k)]) C1n = zeros2(n1, k) for idx, pair in enumerate(pairs): i, j = pair C1n[i, idx] = 1 C1m = dot2(H1, C1n) C1 = Morphism(C, A1, [C1m, C1n]) C2n = zeros2(n2, k) for idx, pair in enumerate(pairs): i, j = pair C2n[j, idx] = 1 C2m = dot2(H2, C2n) C2 = Morphism(C, A2, [C2m, C2n]) AD, BD, D, _ = chain.pushout(C1, C2) H = D[0] #print(H.shape) #print(H) return H
def glue(self, i1, i2): assert i1!=i2 Hx = self.Hx Hz = self.Hz mx, n = Hx.shape mz, _ = Hz.shape k = 1 A = Chain([Hz, Hx.transpose()]) C = Chain([identity2(k), zeros2(k, 0)]) fn = zeros2(n, 1) fn[i1, 0] = 1 fm = dot2(Hz, fn) f = Morphism(C, A, [fm, fn, zeros2(mx, 0)]) gn = zeros2(n, 1) gn[i2, 0] = 1 gm = dot2(Hz, gn) g = Morphism(C, A, [gm, gn, zeros2(mx, 0)]) _, _, D = equalizer(f, g) Hz, Hxt = D[0], D[1] Hx = Hxt.transpose() code = CSSCode(Hx=Hx, Hz=Hz) return code
def glue_quantum(Hx1, Hz1, Hx2, Hz2, pairs): mx1, n1 = Hx1.shape mx2, n2 = Hx2.shape mz1, _ = Hz1.shape mz2, _ = Hz2.shape k = len(pairs) A1 = Chain([Hz1, Hx1.transpose()]) A2 = Chain([Hz2, Hx2.transpose()]) C = Chain([identity2(k), zeros2(k, 0)]) C1n = zeros2(n1, k) for idx, pair in enumerate(pairs): i, j = pair C1n[i, idx] = 1 C1m = dot2(Hz1, C1n) C1 = Morphism(C, A1, [C1m, C1n, zeros2(mx1, 0)]) C2n = zeros2(n2, k) for idx, pair in enumerate(pairs): i, j = pair C2n[j, idx] = 1 C2m = dot2(Hz2, C2n) C2 = Morphism(C, A2, [C2m, C2n, zeros2(mx2, 0)]) AD, BD, D, _ = chain.pushout(C1, C2) Hz, Hxt = D[0], D[1] #print(H.shape) #print(H) return Hz, Hxt.transpose()
def build_tree(n): assert n%2 Hz = [] Hx = [] k0 = -1 k1 = 1 while k1+1<n: h = zeros2(n) h[max(0, k0)] = 1 h[k1] = 1 h[k1+1] = 1 Hz.append(h) if k0+2>=n//4: h = zeros2(n) h[k1] = 1 h[k1+1] = 1 Hx.append(h) k1 += 2 k0 += 1 Hz = array2(Hz) Hx = array2(Hx) print(shortstr(Hz)) print() print(shortstr(Hx)) code = CSSCode(Hz=Hz, Hx=Hx) return code
def get_cell(row, col, p=2): """ return all matrices in bruhat cell at (row, col) These have shape (col, col+row). """ if col == 0: yield zeros2(0, row) return if row == 0: yield identity2(col) return # recursive steps: m, n = col, col + row for left in get_cell(row, col - 1, p): A = zeros2(m, n) A[:m - 1, :n - 1] = left A[m - 1, n - 1] = 1 yield A els = list(range(p)) vecs = list(cross((els, ) * m)) for right in get_cell(row - 1, col, p): for v in vecs: A = zeros2(m, n) A[:, :n - 1] = right A[:, n - 1] = v yield A
def glue_self(Hx, Hz, pairs): mx, n = Hx.shape mz, _ = Hz.shape k = len(pairs) A = Chain([Hz, Hx.transpose()]) C = Chain([identity2(k), zeros2(k, 0)]) fn = zeros2(n, k) for idx, pair in enumerate(pairs): i1, i2 = pair fn[i1, idx] = 1 fm = dot2(Hz, fn) f = Morphism(C, A, [fm, fn, zeros2(mx, 0)]) gn = zeros2(n, k) for idx, pair in enumerate(pairs): i1, i2 = pair gn[i2, idx] = 1 gm = dot2(Hz, gn) g = Morphism(C, A, [gm, gn, zeros2(mx, 0)]) _, _, D = chain.equalizer(f, g) Hz, Hxt = D[0], D[1] return Hxt.transpose(), Hz
def sparsecss(n, mx, mz, weight=8, **kw): print("sparsecss", n, mx, mz) k = n-mx-mz assert k>=0 vec = lambda n=n, weight=weight : rand2(1, n, weight=weight) Hz = zeros2(0, n) Hx = zeros2(0, n) Hx = append2(Hx, vec()) while len(Hz)<mz or len(Hx)<mx: # append2 Hz rows = shortstr(Hz).split() #print rows while Hz.shape[0]<mz: v = vec() u = dot2(Hx, v.transpose()) if u.sum() == 0 and shortstr(v) not in rows: Hz = append2(Hz, v) break # append2 Hx rows = shortstr(Hx).split() #print rows while Hx.shape[0]<mx: v = vec() u = dot2(Hz, v.transpose()) if u.sum() == 0 and shortstr(v) not in rows: Hx = append2(Hx, v) break print(shortstrx(Hz, Hx)) print() bits = [] for i in range(n): if Hx[:, i].sum() == 0: bits.append(i) elif Hz[:, i].sum() == 0: bits.append(i) for i in reversed(bits): Hx = numpy.concatenate( (Hx[:, :i], Hx[:, i+1:]), axis=1) Hz = numpy.concatenate( (Hz[:, :i], Hz[:, i+1:]), axis=1) #print shortstrx(Hx, Hz) C = CSSCode(Hx=Hx, Hz=Hz, **kw) return C
def x_split(C0, build=True, **kw): "split the x-stabilizers of C0" #print "x_split" mz, n, mx = C0.mz, C0.n+C0.mx, 2*C0.mx #print C0.longstr() Hz = zeros2(mz, n) Hz[:, :C0.n] = C0.Hz Hx = zeros2(mx, n) #print "Hz:" #print shortstrx(Hz) for i in range(C0.mx): op = C0.Hx[i] #Hx[:C0.mx-1, :C0.n] = pop2(C0.Hx, i) #print "Hx:" #print shortstrx(Hx) idxs = [j for j in range(C0.n) if op[j]] idxs0 = idxs[:len(idxs)//2] idxs1 = idxs[len(idxs)//2:] #print idxs, idxs0, idxs1 i0, i1 = 2*i, 2*i+1 for j in idxs0: Hx[i0, j] = 1 for j in idxs1: Hx[i1, j] = 1 Hx[i0, C0.n+i] = 1 Hx[i1, C0.n+i] = 1 #print "Hx:" #print shortstrx(Hx) for j in range(mz): if dot2(Hz[j], Hx[i0]): assert dot2(Hz[j], Hx[i1]) # brilliant! Hz[j, C0.n+i] = 1 C1 = CSSCode(Hx=Hx, Hz=Hz, build=build, **kw) #print C1.weightsummary() return C1
def build_pauli(n): m = 2**n Gx = zeros2(m, n) Gz = zeros2(m, n) for i, idx in enumerate(genidx((2, ) * n)): for j in idx: Gx[i, j] = 1 Gz[i, j] = 1 Hx = zeros2(0, n) Hz = zeros2(0, n) return Gx, Gz, Hx, Hz
def to_zero(self): Hs = self.Hs Ds = [] chain = [] # _zero n = len(Hs) for i in range(n): H = Hs[i] chain.append(zeros2(0, 0)) Ds.append(zeros2(0, H.shape[0])) Ds.append(zeros2(0, H.shape[1])) chain = Chain(chain) assert len(self) == len(chain) f = Morphism(self, chain, Ds) return f
def get_trivial(cls, n, idx): Lx = zeros2(1, n) Lz = zeros2(1, n) Lx[0, idx] = 1 Lz[0, idx] = 1 Hx = zeros2(0, n) Hz = zeros2(n-1, n) for i in range(n-1): if i<idx: Hz[i, i] = 1 elif i>=idx: Hz[i, i+1] = 1 code = cls(Lx=Lx, Lz=Lz, Hx=Hx, Hz=Hz, check=True) #print(code.longstr()) return code
def build_compass(li, lj=None): if lj is None: lj = li n = li * lj keys = [(i, j) for i in range(li) for j in range(lj)] coords = {} for i, j in keys: for di in range(-li, li + 1): for dj in range(-lj, lj + 1): coords[i + di, j + dj] = keys.index( ((i + di) % li, (j + dj) % lj)) m = n Gx = zeros2(m, n) Gz = zeros2(m, n) idx = 0 for i in range(li): for j in range(lj): Gx[idx, coords[i, j]] = 1 Gx[idx, coords[i, j + 1]] = 1 Gz[idx, coords[i, j]] = 1 Gz[idx, coords[i + 1, j]] = 1 idx += 1 assert idx == m mx = lj - 1 Hx = zeros2(mx, n) for idx in range(mx): for i in range(li): Hx[idx, coords[i, idx]] = 1 Hx[idx, coords[i, idx + 1]] = 1 mz = li - 1 Hz = zeros2(mz, n) for idx in range(mz): for j in range(lj): Hz[idx, coords[idx, j]] = 1 Hz[idx, coords[idx + 1, j]] = 1 assert dot2(Hx, Hz.transpose()).sum() == 0 return Gx, Gz, Hx, Hz
def find(self, target=None, stopat=None, idx=None, verbose=False): Hx = self.Hx Lx = self.Lx M0 = argv.get("M0", 1) target = target or argv.target if idx is None: best_i = 0 best_w = Lx[0].sum() for i in range(1, Lx.shape[0]): w = Lx[i].sum() if w < best_w: best_i = i best_w = w i = best_i else: i = idx best_w = Lx[i].sum() best_T = Lx[i] write("%s:" % best_w) H = zeros2(Lx.shape[0] - 1 + Hx.shape[0], self.n) H[:i] = Lx[:i] H[i:Lx.shape[0] - 1] = Lx[i + 1:] H[Lx.shape[0] - 1:] = Hx graph = Tanner(H) T1 = Lx[i].copy() for j in range(M0): #print "l_op:" #print strop(l_op) T1 = best_T.copy() #for op in Hx: # if random()<0.5: # T1 += op # T1 %= 2 #for op in Lx: # if random()<0.5: # T1 += op # T1 %= 2 if target: T1 = graph.minimize(T1, target, maxsize=argv.maxsize, verbose=verbose) break else: T1 = graph.localmin(T1, stopat=stopat, verbose=verbose) w = T1.sum() if w and w < best_w: best_T = T1 best_w = w write("%s:" % w) if stopat is not None and w <= stopat: return best_T return best_T
def lookup_distance(code): n = code.n Hz, Tx = code.Hz, code.Tx d = n u = zeros2(n) for i0 in range(n): u[i0] = 1 if dot2(Hz, u).sum() == 0: #print("*", shortstr(u)) d = min(d, 1) for i1 in range(i0+1, n): u[i1] = 1 if dot2(Hz, u).sum() == 0: #print("*", shortstr(u)) if d>2: print("d=", d) d = min(d, 2) for i2 in range(i1+1, n): u[i2] = 1 if dot2(Hz, u).sum() == 0: #print("*", shortstr(u)) if d>3: print("d=", d) d = min(d, 3) for i3 in range(i2+1, n): u[i3] = 1 if dot2(Hz, u).sum() == 0: #print("*", shortstr(u)) d = min(d, 4) u[i3] = 0 u[i2] = 0 u[i1] = 0 u[i0] = 0 return d
def get_op(self, weight=1): n = len(self.qubits) op = zeros2(n) for i in range(weight): j = randint(0, n - 1) op[j] = 1 return op
def __init__(self, Lx=None, Lz=None, Hx=None, Tz=None, Hz=None, Tx=None, # XXX swap these two args? Gx=None, Gz=None, build=True, check=True, verbose=False, logops_only=False): if Hx is None and Hz is not None: # This is a classical code Hx = zeros2(0, Hz.shape[1]) self.Lx = Lx self.Lz = Lz self.Hx = Hx self.Tz = Tz self.Hz = Hz self.Tx = Tx self.Gx = Gx self.Gz = Gz if Hx is not None and len(Hx.shape)<2: Hx.shape = (0, Hz.shape[1]) if Hz is not None and Hx is not None and Lz is not None and Gz is None: assert Hx.shape[0]+Hz.shape[0]+Lz.shape[0] == Hx.shape[1] assert Hx.shape[1] == Hz.shape[1] == Lz.shape[1], Lz.shape n = None if Gz is not None and Gx is not None: _, n = Gz.shape if build: self.build_from_gauge(check=check) #elif None in (Lx, Lz, Tx, Tz) and build: elif build and (Lx is None or Lz is None or Tx is None or Tz is None): self.build(check=check, logops_only=logops_only, verbose=verbose) elif Hz is not None and Hx is not None: _, n = Hz.shape self.k = n - Hz.shape[0] - Hx.shape[0] for op in [Lx, Lz, Hx, Tz, Hz, Tx]: if op is None: continue #print op.shape if n is not None and op.shape==(0,): op.shape = (0, n) n = op.shape[1] self.n = n if self.Hx is not None: self.mx = self.Hx.shape[0] if self.Hz is not None: self.mz = self.Hz.shape[0] if self.Lx is not None: self.k = self.Lx.shape[0] if self.Gx is not None: self.gx = self.Gx.shape[0] if self.Gz is not None: self.gz = self.Gz.shape[0] self.check = check self.do_check()
def find_skip(Hx, Lx, R): m, n = Hx.shape bitss = [] for i in range(m): for _ in range(2): # we double like this, right??? bits = [j for j in range(n) if Hx[i, j]] shuffle(bits) bitss.append(bits) bits = [j for j in range(n) if Lx[0, j]] shuffle(bits) bitss.append(bits) shuffle(bitss) print(bitss) print(len(bitss)) skip = zeros2(n) # for i in bits: # skip[i] = 1 #print skip r = skip_rank(Hx, R, skip) stack = search_skip(Hx, R, r, bitss, skip, []) print("FOUND") print(stack)
def symplectic_form(cls, n): A = zeros2(2 * n, 2 * n) I = identity2(n) A[:n, n:] = I A[n:, :n] = I A = Matrix(A) return A
def build_projective(n, dim=2): import geometry g = geometry.projective(n, dim) P = g.types[0] L = g.types[1] if dim == 3: L = g.types[2] points = g.tplookup[P] lines = g.tplookup[L] #lines = lines[:-4] # throw one out #points = points[:-1] # throw one out n = len(points) m = len(lines) Gx = zeros2(m, n) for i, line in enumerate(lines): for j, point in enumerate(points): if (line, point) in g.incidence: Gx[i, j] = 1 #print shortstr(Gx) Gz = Gx.copy() Hx = None Hz = None return Gx, Gz, Hx, Hz
def __init__(self, code): Decoder.__init__(self, code) Hx, Lx = self.Hx, self.Lx H = zeros2(Lx.shape[0] + Hx.shape[0], self.n) H[:Lx.shape[0]] = Lx H[Lx.shape[0]:] = Hx self.graph = Tanner(H)
def build_xy2(li, lj=None): if lj is None: lj = li n = li * lj keys = [(i, j) for i in range(li) for j in range(lj)] coords = {} for i, j in keys: for di in range(-li, li + 1): for dj in range(-lj, lj + 1): coords[i + di, j + dj] = keys.index( ((i + di) % li, (j + dj) % lj)) Gx = [] if argv.open: idxs = list(range(li - 1)) jdxs = list(range(lj - 1)) else: idxs = list(range(li)) jdxs = list(range(lj)) for i in idxs: for j in jdxs: g = zeros2(n) g[coords[i, j]] = 1 g[coords[i, j + 1]] = 1 g[coords[i + 1, j]] = 1 g[coords[i + 1, j + 1]] = 1 Gx.append(g) Gx = array2(Gx) Gz = Gx.copy() return Gx, Gz, None, None
def test_equalizer(): n = 4 m = n - 1 H = zeros2(m, n) for i in range(m): H[i, i] = 1 H[i, i + 1] = 1 A = Chain([H]) C = Chain([array2([[1]])]) fm = zeros2(m, 1) fm[m - 1, 0] = 1 fn = zeros2(n, 1) fn[n - 1, 0] = 1 f = Morphism(C, A, [fm, fn]) gm = zeros2(m, 1) gm[0, 0] = 1 gn = zeros2(n, 1) gn[0, 0] = 1 g = Morphism(C, A, [gm, gn]) AD, BD, D = chain.equalizer(f, g) assert eq2(D[0], array2([[1, 1, 1], [0, 1, 1]])) # glue two checks at a bit # -------------------------- A = Chain([H.transpose()]) C = Chain([zeros2(1, 0)]) fn = zeros2(n, 1) fn[0, 0] = 1 fm = zeros2(m, 0) f = Morphism(C, A, [fn, fm]) gn = zeros2(n, 1) gn[n - 1, 0] = 1 gm = zeros2(m, 0) g = Morphism(C, A, [gn, gm]) AD, BD, D = chain.equalizer(f, g) D = D[0] #print(D) assert eq2(D, array2([[1, 0, 1], [1, 1, 0], [0, 1, 1]])) # glue two bits
def concat(Cout, Cin): n = Cout.n * Cin.n #print Cout.longstr() Hx = [] for i in range(Cout.mx): Hout = Cout.Hx[i] for j in range(Cin.k): Lin = Cin.Lx[j] #print Hout, Lin h = numpy.tensordot(Hout, Lin, 0) #h = shortstr(h.flatten()) h = h.flatten() #print h Hx.append(h) Hz = [] for i in range(Cout.mz): Hout = Cout.Hz[i] for j in range(Cin.k): Lin = Cin.Lz[j] #print Hout, Lin h = numpy.tensordot(Hout, Lin, 0) h = h.flatten() #print h assert len(h) == n Hz.append(h) for i in range(Cout.n): for j in range(Cin.mx): h = zeros2(n) h[i*Cin.n : (i+1)*Cin.n] = Cin.Hx[j] Hx.append(h) for j in range(Cin.mz): h = zeros2(n) h[i*Cin.n : (i+1)*Cin.n] = Cin.Hz[j] Hz.append(h) #print Hx Hx = array2(Hx) Hz = array2(Hz) #print shortstr(Hx) C = CSSCode(Hx=Hx, Hz=Hz) return C
def get_logops(idxs_C, idxs_Ct, idxs_D, idxs_Dt): # Lx -------------------------------------------------------------- Ic1 = identity2(c1)[idxs_C, :] Lx_h = kron(Ic1, CokerD), zeros2(len(idxs_C) * CokerD.shape[0], c0 * d1) Lx_h = numpy.concatenate(Lx_h, axis=1) assert dot2(Lx_h, Hz.transpose()).sum() == 0 Id1 = identity2(d1)[idxs_D, :] Lx_v = zeros2(CokerC.shape[0] * len(idxs_D), c1 * d0), kron(CokerC, Id1) Lx_v = numpy.concatenate(Lx_v, axis=1) Lxi = numpy.concatenate((Lx_h, Lx_v), axis=0) # Lz -------------------------------------------------------------- KerCt = KerC.transpose() Id0 = identity2(d0)[:, idxs_Dt] Lzt_h = kron(KerCt, Id0), zeros2(c0 * d1, KerCt.shape[1] * len(idxs_Dt)) Lzt_h = numpy.concatenate(Lzt_h, axis=0) assert dot2(Hx, Lzt_h).sum() == 0 KerDt = KerD.transpose() assert KerDt.shape[0] == d1 Ic0 = identity2(c0)[:, idxs_Ct] Lzt_v = zeros2(c1 * d0, len(idxs_Ct) * KerDt.shape[1]), kron(Ic0, KerDt) Lzt_v = numpy.concatenate(Lzt_v, axis=0) assert dot2(Hx, Lzt_v).sum() == 0 Lzti = numpy.concatenate((Lzt_h, Lzt_v), axis=1) Lzi = Lzti.transpose() # checking --------------------------------------------------------- assert dot2(Hx, Lzti).sum() == 0 assert rank(Lxi) == len(Lxi) # full rank assert rank(Lzi) == len(Lzi) # full rank assert eq_span(numpy.concatenate((Lxi, Hx)), LxiHx) assert eq_span(numpy.concatenate((Lzi, Hz)), LziHz) return Lxi, Lzi
def kron(A, B): if 0 in A.shape or 0 in B.shape: C = zeros2(A.shape[0] * B.shape[0], A.shape[1] * B.shape[1]) else: #print("kron", A.shape, B.shape) C = numpy.kron(A, B) #print("\t", C.shape) return C
def get_bipuncture(H, G=None, verbose=True): n = H.shape[1] if G is None: G = find_kernel(H) k = len(G) if verbose: print(shortstrx(G, H)) while 1: # copied from classical.py idxs = set() while len(idxs) < k: idx = randint(0, n - 1) idxs.add(idx) idxs = list(idxs) idxs.sort() G1 = in_support(G, idxs) if len(G1): continue jdxs = set() while len(jdxs) < k: jdx = randint(0, n - 1) if jdx not in idxs: jdxs.add(jdx) jdxs = list(jdxs) jdxs.sort() G2 = in_support(G, jdxs) if len(G2) == 0: break if 0: v = zeros2(1, n) v[:, idxs] = 1 print(shortstr(v)) v = zeros2(1, n) v[:, jdxs] = 1 print(shortstr(v)) if verbose: print("in_support(H):", in_support(H, idxs), in_support(H, jdxs)) return idxs, jdxs