def test_decomp_sqrtswap_sandwich(): circ0 = qf.Circuit() circ0 += qf.CANONICAL(1 / 4, 1 / 4, 1 / 4, 0, 1) circ0 += qf.random_gate([0]) circ0 += qf.random_gate([1]) circ0 += qf.CANONICAL(1 / 4, 1 / 4, 1 / 4, 0, 1) gate0 = circ0.asgate() circ1 = qf.canonical_decomposition(gate0) gate1 = circ1.asgate() assert qf.gates_close(gate0, gate1)
def test_canonical_decomposition(): for tt1 in range(0, 10): for tt2 in range(tt1): for tt3 in range(tt2): t1, t2, t3 = tt1 / 20, tt2 / 20, tt3 / 20 if t3 == 0 and t1 > 0.5: continue coords = np.asarray((t1, t2, t3)) print('b') circ0 = qf.Circuit() circ0 += qf.ZYZ(0.2, 0.2, 0.2, q0=0) circ0 += qf.ZYZ(0.3, 0.3, 0.3, q0=1) circ0 += qf.CANONICAL(t1, t2, t3, 0, 1) circ0 += qf.ZYZ(0.15, 0.2, 0.3, q0=0) circ0 += qf.ZYZ(0.15, 0.22, 0.3, q0=1) gate0 = circ0.asgate() print('c') circ1 = qf.canonical_decomposition(gate0) assert qf.gates_close(gate0, circ1.asgate()) print('d') print(circ1) canon = circ1.elements[6] new_coords = np.asarray( [canon.params[n] for n in ['tx', 'ty', 'tz']]) assert np.allclose(coords, np.asarray(new_coords)) coords2 = qf.canonical_coords(gate0) assert np.allclose(coords, np.asarray(coords2)) print('>') print()
def sandwich_decompositions(coords0, coords1, samples=SAMPLES): """Create composite gates, decompose, and return a list of canonical coordinates""" decomps = [] for _ in range(samples): circ = qf.Circuit() circ += qf.CANONICAL(*coords0, 0, 1) circ += qf.random_gate([0]) circ += qf.random_gate([1]) circ += qf.CANONICAL(*coords1, 0, 1) gate = circ.asgate() coords = qf.canonical_coords(gate) decomps.append(coords) return decomps
def test_CANONICAL(): t1 = random.uniform(-2, +2) t2 = random.uniform(-2, +2) t3 = random.uniform(-2, +2) gate = qf.CANONICAL(t1, t2, t3) assert qf.almost_unitary(gate) inv = gate.H assert type(gate) == type(inv) assert qf.gates_close(qf.identity_gate(2), inv @ gate)
def test_EXCH(): t = random.uniform(-2, +2) gate = qf.EXCH(t) assert qf.almost_unitary(gate) inv = gate.H assert type(gate) == type(inv) assert qf.gates_close(qf.identity_gate(2), inv @ gate) gate1 = qf.CANONICAL(t, t, t) assert qf.gates_close(gate, gate1)
def test_gatepow(): gates = [ qf.I(), qf.X(), qf.Y(), qf.Z(), qf.H(), qf.S(), qf.T(), qf.PHASE(0.1), qf.RX(0.2), qf.RY(0.3), qf.RZ(0.4), qf.CZ(), qf.CNOT(), qf.SWAP(), qf.ISWAP(), qf.CPHASE00(0.5), qf.CPHASE01(0.6), qf.CPHASE10(0.6), qf.CPHASE(0.7), qf.PSWAP(0.15), qf.CCNOT(), qf.CSWAP(), qf.TX(2.7), qf.TY(1.2), qf.TZ(0.3), qf.ZYZ(3.5, 0.9, 2.1), qf.CANONICAL(0.1, 0.2, 7.4), qf.XX(1.8), qf.YY(0.9), qf.ZZ(0.45), qf.PISWAP(0.2), qf.EXCH(0.1), qf.TH(0.3) ] for gate in gates: assert qf.gates_close(gate.H, gate**-1) for gate in gates: sqrt_gate = gate**(1 / 2) two_gate = sqrt_gate @ sqrt_gate assert qf.gates_close(gate, two_gate) for gate in gates: gate0 = gate**0.3 gate1 = gate**0.7 gate2 = gate0 @ gate1 assert qf.gates_close(gate, gate2) for K in range(1, 5): gate = qf.random_gate(K) # FIXME: Throw error on K=0 sqrt_gate = gate**0.5 two_gate = sqrt_gate @ sqrt_gate assert qf.gates_close(gate, two_gate) for gate in gates: rgate = qf.Gate((gate**0.5).tensor) tgate = rgate @ rgate assert qf.gates_close(gate, tgate)