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 make_q(n, m, weight=None): k = n - 2 * m assert k >= 0 assert m > 0 Hx = [rand2(1, n, weight=weight)[0]] Hz = [] while 1: _Hx = array2(Hx) while 1: v = rand2(1, n, weight=weight) if dot2(Hx, v.transpose()).sum() == 0: break Hz.append(v[0]) if len(Hz) == m: break while 1: v = rand2(1, n, weight=weight) if dot2(Hz, v.transpose()).sum() == 0: break Hx.append(v[0]) Hx = array2(Hx) Hz = array2(Hz) assert dot2(Hx, Hz.transpose()).sum() == 0 return Hx, Hz
def is_transversal(A, code): Lz = [Clifford.make_op(l, Clifford.z) for l in code.Lz] Lx = [Clifford.make_op(l, Clifford.x) for l in code.Lx] Hz = [Clifford.make_op(l, Clifford.z) for l in code.Hz] Hx = [Clifford.make_op(l, Clifford.x) for l in code.Hx] hz = [op.get_translation() for op in Hz] hx = [op.get_translation() for op in Hx] h = array2(hz + hx) ht = h.transpose() Ai = A.inverse() tgt = [] for u in Hz + Hx: v = A * u * Ai assert v.is_translation() v = v.get_translation() tgt.append(v) #print(u.get_translation()) #print("-->") #print(v) #print() tgt = array2(tgt) src = array2([u.get_translation() for u in Hz + Hx]) tgt, src = tgt.transpose(), src.transpose() if solve(tgt, src) is None: return False if solve(src, tgt) is None: return False return True
def build(r, m, puncture=False): "Build Reed-Muller code" assert 0 <= r <= m, "r=%s, m=%d" % (r, m) n = 2**m # length one = array2([1] * n) basis = [one] vs = [[] for i in range(m)] for i in range(2**m): for j in range(m): vs[j].append(i % 2) i >>= 1 assert i == 0 vs = [array2(v) for v in vs] for k in range(r): for items in choose(vs, k + 1): v = one #print(items) for u in items: v = v * u basis.append(v) G = numpy.array(basis) code = Code(G, d=2**(m - r), desc="reed_muller(%d, %d)" % (r, m)) if puncture: code = code.puncture(0) return code
def show_stabx(self, sx): gxs = [] for gx in self.Gx: if eq2(gx * sx, gx): gxs.append(gx) Gx = array2(gxs) #print "Gx:", Gx.shape #print shortstr(Gx) print("sx.sum() =", sx.sum(), end=' ') Gxt = Gx.transpose() K = find_kernel(Gxt) #print "kernel:", K K = array2(K) #print "kernel:", len(K) #print shortstr(K) #print best = None ubest = None u = solve(Gxt, sx) for w in enum2(len(K)): u2 = (u + dot2(w, K)) % 2 if best is None or u2.sum() < best: best = u2.sum() ubest = u2 print("u.sum() =", u2.sum(), end=' ') print()
def unit_test(): A = array2([[1,1,1]]) B = array2([[1,1,0],[0,0,1]]) C = array2([[0,1,0]]) assert rowspan_le(A, B) assert not rowspan_le(B, A) assert not rowspan_le(A, C) assert not rowspan_le(B, C)
def build_ham(self, excite=None, weights=None, Jx=1., Jz=1.): Gx, Gz = self.Gx, self.Gz Rx, Rz = self.Rx, self.Rz Hx, Hz = self.Hx, self.Hz Tx, Tz = self.Tx, self.Tz gz = len(Gz) r = len(Rx) n = self.n if type(excite) is int: _excite = [0] * len(Tx) _excite[excite] = 1 excite = tuple(_excite) if excite is not None: assert len(excite) == len(Tx) t = zeros2(n) for i, ex in enumerate(excite): if ex: t = (t + Tx[i]) % 2 #print "t:", shortstr(t) Gzt = dot2(Gz, t) else: Gzt = 0 if weights is None: weights = [1.] * len(Gx) assert len(weights) == len(Gx), len(weights) H = numpy.zeros((2**r, 2**r)) for i, v in enumerate(genidx((2, ) * r)): v = array2(v) syndrome = (dot2(Gz, Rx.transpose(), v) + Gzt) % 2 value = gz - 2 * syndrome.sum() #print shortstr(dot2(Rx.transpose(), v)), value H[i, i] = Jz * value #U.append(value) Pxt = self.Px.transpose() Qx = Rz.transpose() #print dot2(Rx, Qx) PxtQx = dot2(Pxt, Qx) for i, v in enumerate(genidx((2, ) * r)): v = array2(v) #print shortstr(v), #for g in Gx: for j, g in enumerate(Gx): u = (v + dot2(g, PxtQx)) % 2 k = eval('0b' + shortstr(u, zero='0')) H[i, k] += Jx * weights[j] #A[i, k] = A.get((i, k), 0) + 1 return H
def test_colimit(): 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]) B = Chain([zeros2(0, 0)]) C = Chain([array2([[1]])]) CAm = zeros2(m, 1) CAm[0, 0] = 1 CAm[m - 1, 0] = 1 CAn = zeros2(n, 1) CAn[0, 0] = 1 CAn[n - 1, 0] = 1 CA = Morphism(C, A, [CAm, CAn]) CBm = zeros2(0, 1) CBn = zeros2(0, 1) CB = Morphism(C, B, [CBm, CBn]) AD, BD, D, _ = chain.pushout(CA, CB) assert eq2(D[0], array2([[1, 1, 1], [0, 1, 1]])) # glue two checks at a bit # -------------------------- A = Chain([H.transpose()]) B = Chain([zeros2(0, 0)]) C = Chain([zeros2(1, 0)]) CAn = zeros2(n, 1) CAn[0, 0] = 1 CAn[n - 1, 0] = 1 CAm = zeros2(m, 0) CA = Morphism(C, A, [CAn, CAm]) CBn = zeros2(0, 1) CBm = zeros2(0, 0) CB = Morphism(C, B, [CBn, CBm]) AD, BD, D, _ = chain.pushout(CA, CB) D = D[0] #print(D) assert eq2(D, array2([[1, 0, 1], [1, 1, 0], [0, 1, 1]])) # glue two bits
def build_reduced(): Gx, Gz, Hx, Hz = build() Px = get_reductor(Hx) # projector onto complement of rowspan of Hx Pz = get_reductor(Hz) Rz = [dot2(Pz, g) for g in Gz] Rz = array2(Rz) Rz = row_reduce(Rz, truncate=True) Rx = [dot2(Px, g) for g in Gx] Rx = array2(Rx) Rx = row_reduce(Rx, truncate=True) return Rx, Rz
def solve(self, H, minimize=True, verbose=True): m, n = H.shape # rows, cols u1 = self.u1 assert u1.shape == (m, ) rows = [i for i in range(m) if u1[i]] #print rows H = H[rows, :] u0 = self.u0[rows] v = self.v cols = [i for i in range(n) if v[i]] #print cols H = H[:, cols] assert cols, self.u0 #print shortstr(H) #print "u0:", shortstr(u0) if verbose: print("Cluster.solve:", H.shape) v = solve.solve(H, u0) if v is None: return if minimize: kern = solve.find_kernel(H) if kern: kern = array2(kern) write("[w=%d, kern=%d, " % (v.sum(), len(list(kern)))) graph = dynamic.Tanner(kern) #v = graph.minimize(v, target=30, verbose=True) v = graph.localmin(v, verbose=True) write("w=%d]" % v.sum()) #u = dot(H, v) #assert numpy.abs(u-u0).sum() == 0 v0 = numpy.zeros((n, ), dtype=numpy.int32) v0[cols] = v #print "v0:", shortstr(v0) #write("[%d]"%v0.sum()) return v0
def load(cls, name, build=True, check=False, rebuild=False): write("loading..") f = open(name) data = f.read() data = data.replace('.', '0') lines = data.split('\n') name = None items = {} for line in lines: line = line.strip() if not line: continue if '=' in line: name = line.split('=')[0].strip() #print name rows = [] items[name] = rows else: #line = list(int(x) for x in line) line = numpy.fromstring(line, dtype=numpy.uint8) - 48 rows.append(line) #print items.keys() #print [len(x) for x in items.values()] kw = {} for key in list(items.keys()): #print items[key] value = array2(items[key]) kw[key] = value write("done\n") if rebuild: for op in 'Lx Lz Tx Tz'.split(): kw[op] = None code = cls(build=build, check=check, **kw) return code
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 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 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 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 build(items): items = items.strip().split() #print(items) rows = [] n = None for item in items: assert n is None or len(items)==n n = len(items) row = [] for i in item: if i=="X": row += [1, 0] elif i=="Z": row += [0, 1] elif i=="Y": row += [1, 1] elif i=="I": row += [0, 0] else: assert 0 rows.append(row) H = solve.array2(rows) #print(H) J = sy_form(n) HJ = solve.dot2(H, J) #print(HJ) T = solve.pseudo_inverse(HJ.transpose()) #print(T) TJ = solve.dot2(T, J) #print(TJ) #print(solve.dot2(TJ, H.transpose())) # identity ops = [] for row in T: op = [] for i in range(n): opi = list(row[2*i : 2*(i+1)]) if opi == [0, 0]: op.append(I) #write("I") elif opi == [1, 0]: op.append(X) #write("X") elif opi == [0, 1]: op.append(Z) #write("Z") elif opi == [1, 1]: op.append(Y) #write("Y") else: assert 0, opi op = reduce(matmul, op) ops.append(op) #write("\n") return ops
def test_color(): HxA = array2([[1, 1, 0, 0], [1, 0, 1, 0], [1, 1, 1, 1]]) HzA = array2([[1, 1, 1, 1]]) A = Chain([HxA, HzA.transpose()]) HxB = HxA HzB = HzA B = Chain([HxB, HzB.transpose()]) HzC = zeros2(0, 2) HxC = array2([[1, 0], [0, 1]]) 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 = dot2(HxA, CAn) #print(CAx) 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() print(code) print("A --> D") print(fstr(AD[0])) print("-----------") print(fstr(AD[1])) print("B --> D") print(fstr(BD[0])) print("-----------") print(fstr(BD[1])) print("Hx:") print(fstr(code.Hx))
def shorten(G, i): print(shortstrx(G)) H = array2(list(find_kernel(G))) m, n = H.shape H1 = zeros2(m + 1, n) H1[:m, :] = H H1[m, i] = 1 print() print(shortstrx(H1)) print() G1 = array2(list(find_kernel(H1))) m, n = G1.shape G2 = zeros2(m, n - 1) G2[:, :i] = G1[:, :i] G2[:, i:] = G1[:, i + 1:] print() print(shortstrx(G2)) print(strong_morthogonal(G2, 2)) H2 = array2(list(find_kernel(G2))) print(classical_distance(H2))
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 sparsecss_FAIL(n, mx, mz, weight=3, **kw): print("sparsecss", n, mx, mz) k = n-mx-mz assert k>=0 Hz = rand2(mz, n, weight=weight) #print shortstrx(Hx) kern = numpy.array(solve.find_kernel(Hz)) mkern = kern.shape[0] print("kern:") print(shortstr(kern)) print() kern1 = zeros2(mkern, n) for i in range(mkern): v = rand2(1, mkern) kern1[i] = dot2(v, kern) print("kern1:") print(shortstr(kern1)) print() kern = kern1 Hx = [] for i in range(mx): j = randint(0, mkern-1) v = kern[j].copy() count = 0 while 1: v += kern[randint(0, mkern-1)] v %= 2 w = v.sum() if w==weight and count > 100: break count += 1 Hx.append(v) Hx = array2(Hx) print(shortstrx(Hx)) C = CSSCode(Hx=Hx, Hz=Hz, **kw) return C
def z_weld(acode, bcode, pairs): for c in [acode, bcode]: print("Lx:") print(c.Lx) print("Lz:") print(c.Lz) print("Hx:") print(c.Hx) print("Hz:") print(c.Hz) print("-------------------") mx = acode.mx + bcode.mx #for (i, j) in pairs: assert len(set(pairs)) == len(pairs) # uniq n = acode.n + bcode.n - len(pairs) # Hx = zeros2(mx, n) # Hx[:acode.mx, :acode.n] = acode.Hx # Hx[acode.mx:, acode.n-len(pairs):] = bcode.Hx # # az = acode.mz + bcode.mz + acode.k + bcode.k # Az = zeros2(az, n) # r0, r1 = 0, acode.mz # Az[r0:r1, :acode.n] = acode.Hx; r0, r1 = r1, r1+len(acode.Hx) # Az[r0:r1, acode.n-len(pairs):] = bcode.Hx; r0, r1 = r1, r1+len(bcode.Hx) ## Az[r0:r1, :acode.n] = acode.Lz; r0, r1 = r1, r1+len(acode.Lz) ## #assert r1 == len(Az), (r1, len(Az)) ## Az[r0:r1, acode.n-len(pairs):] = bcode.Lz; r0, r1 = r1, r1+len(bcode.Lz) # # print("Az:") # print(Az) #print(Az) Hz = [] for z in span(Az): #print(z) #print( dot2(Hx, z.transpose())) if dot2(Hx, z.transpose()).sum() == 0: Hz.append(z) Hz = array2(Hz) Hz = row_reduce(Hz) print("Hx:") print(Hx) print("Hz:") print(Hz)
def __init__(self, code): Decoder.__init__(self, code) syndromes = [] errors = [] for i in range(code.n + 1): error = zeros2(code.n) if i < code.n: error[i] = 1 syndrome = dot2(code.Hz, error) syndromes.append(syndrome) errors.append(error) #for i in range(code.n): # for j in range(i+1, code.n): # error = zeros2(code.n) # error[i] = 1 # error[j] = 1 # syndrome = dot2(code.Hz, error) # syndromes.append(syndrome) # errors.append(error) self.xs = array2(syndromes) self.ys = array2(errors)
def __init__(self, G, H=None, d=None, desc="", check=True): assert len(G.shape) == 2 self.G = G.copy() self.k, self.n = G.shape self.d = d self.desc = desc if H is None: H = list(find_kernel(G)) H = array2(H) if H.shape == (0, ): H.shape = (0, self.n) self.H = H.copy() if check: self.check()
def transvect(cls, x): assert len(x.shape) == 1 assert x.shape[0] % 2 == 0 n = x.shape[0] // 2 assert x.shape == (2 * n, ) F = cls.symplectic_form(n) Fx = dot2(F.A, x) A = zeros2(2 * n, 2 * n) for i in range(2 * n): u = array2([0] * (2 * n)) u[i] = 1 v = dot2(u, Fx) u += v * x A[:, i] = u A %= 2 A = Matrix(A) return A
def strop(self, u, fancy=False): m = SMap() u = array2(u) n = u.shape[0] for i in range(n): c = str(min(1, u[i])) i, j, k = self.keys[i] row = 2 * i + (1 - k) col = 4 * j + 2 * k #if i%2==0 and j%2==0 and k==0: if fancy: if k == 0: m[row - 1, col] = '+' if c == 'I': c = '|-'[k] m[row, col] = c return str(m).replace('0', '.')
def build_cycle(m, n, row): H = [] for i in range(n): h = [0]*n for j, c in enumerate(row): h[(i+j)%n] = int(c) H.append(h) delta = n-m for i in range(delta): H.pop(i*n//delta-i) Hz = array2(H) return Hz
def build_xy3(li, lj=None, lk=None): if lj is None: lj = li if lk is None: lk = li n = li * lj * lk keys = [(i, j, k) for i in range(li) for j in range(lj) for k in range(lk)] coords = {} for i, j, k in keys: for di in range(-li, li + 1): for dj in range(-lj, lj + 1): for dk in range(-lk, lk + 1): coords[i + di, j + dj, k + dk] = keys.index( ((i + di) % li, (j + dj) % lj, (k + dk) % lk)) Gx = [] if argv.open: idxs = list(range(li - 1)) jdxs = list(range(lj - 1)) kdxs = list(range(lk - 1)) else: idxs = list(range(li)) jdxs = list(range(lj)) kdxs = list(range(lk)) for i in idxs: for j in jdxs: for k in kdxs: g = zeros2(n) g[coords[i, j, k]] = 1 g[coords[i, j + 1, k]] = 1 g[coords[i + 1, j, k]] = 1 g[coords[i + 1, j + 1, k]] = 1 g[coords[i, j, k + 1]] = 1 g[coords[i, j + 1, k + 1]] = 1 g[coords[i + 1, j, k + 1]] = 1 g[coords[i + 1, j + 1, k + 1]] = 1 Gx.append(g) Gx = array2(Gx) Gz = Gx.copy() return Gx, Gz, None, None
def show_delta(Gx, Gz, Hx, Hz, Rx, Rz, Pxt, Qx, Pz, Tx, **kw): r, n = Rx.shape N = 2**r gz = len(Gz) GzTx = dot2(Gz, Tx.transpose()) RR = dot2(Gz, Rx.transpose()) PxtQx = dot2(Pxt, Qx) if argv.excite: excites = [argv.excite] else: excites = genidx((2,)*len(Tx)) for excite in excites: print("excite:", excite) assert len(excite)==len(Tx) t = zeros2(n) for i, ex in enumerate(excite): if ex: t = (t + Tx[i])%2 print("t:", shortstr(t)) Gzt = dot2(Gz, t) #print "Gzt:", shortstr(Gzt) #for i in range(N): pos = neg = 0 for i, v in enumerate(genidx((2,)*r)): v = array2(v) syndrome0 = dot2(Gz, Rx.transpose(), v) syndrome = (dot2(Gz, Rx.transpose(), v) + Gzt)%2 delta = syndrome.sum() - syndrome0.sum() if delta > 0: pos += 1 elif delta < 0: neg += 1 if delta: print("%3d %3d" % (gz-2*syndrome0.sum(), gz-2*syndrome.sum())) print(pos, neg, "total:", i+1)
def glue1(H, i1, i2): m, n = H.shape A = Chain([H]) C = Chain([array2([[1]])]) fn = zeros2(n, 1) fn[i1, 0] = 1 fm = dot2(H, fn) f = Morphism(C, A, [fm, fn]) gn = zeros2(n, 1) gn[i2, 0] = 1 gm = dot2(H, gn) g = Morphism(C, A, [gm, gn]) _, _, D = chain.equalizer(f, g) H = D[0] #print(H.shape) #print(H) return H
def min_span(K): "find minimum weight span" Kt = K.transpose() dist = {} for u in numpy.ndindex((2, ) * K.shape[0]): v = dot2(Kt, u) if v.sum() == 0: continue weight = v.sum() #dist[weight] = dist.get(weight, 0) + 1 dist.setdefault(weight, []).append(v) keys = list(dist.keys()) keys.sort(reverse=True) rows = [] for k in keys: #print("%s:%s" % (k, len(dist[k])), end=" ") rows.extend(dist[k]) #print() A = array2(rows) #print(A.shape) A = remove_dependent(A) #print(shortstr(A)) return A