def compute_max_cut(n: int, nodes: List[int]) -> int: """Compute (inefficiently) the max cut, exhaustively.""" max_cut = -1000 for bits in helper.bitprod(n): # Collect in/out sets. iset = [] oset = [] for idx, val in enumerate(bits): iset.append(idx) if val == 0 else oset.append(idx) # Compute costs for this cut, record maximum. cut = 0 for node in nodes: if node[0] in iset and node[1] in oset: cut += node[2] if node[1] in iset and node[0] in oset: cut += node[2] if cut > max_cut: max_cut_in, max_cut_out = iset.copy(), oset.copy() max_cut = cut max_bits = bits state = bin(helper.bits2val(max_bits))[2:].zfill(n) print('Max Cut. N: {}, Max: {:.1f}, {}-{}, |{}>' .format(n, np.real(max_cut), max_cut_in, max_cut_out, state)) return helper.bits2val(max_bits)
def simple_walk(): """Simple quantum walk, allowing initial experiments.""" nbits = 8 qc = circuit.qc('simple_walk') x = qc.reg(nbits, 0b10000000) aux = qc.reg(nbits, 0) coin = qc.reg(1, 0) for _ in range(32): # Using a Hadamard coin, others are possible, of course. qc.h(coin[0]) incr(qc, 0, nbits, aux, [coin[0]]) decr(qc, 0, nbits, aux, [[coin[0]]]) # Find and print the non-zero amplitudes for all states for bits in helper.bitprod(nbits): idx_bits = bits for i in range(nbits): idx_bits = idx_bits + (0,) idx_bits0 = idx_bits + (0,) idx_bits1 = idx_bits + (1,) # Printing bits0 only, this can be changed, of course. if qc.psi.ampl(*idx_bits0) != 0.0: print('{:5.1f} {:5.4f}'.format(float(helper.bits2val(bits)), qc.psi.ampl(*idx_bits0).real))
def check_result(psi, a, b, nbits, factor=1.0): """Find most likely result, dump it, compare against expected.""" maxbits, _ = psi.maxprob() result = helper.bits2val(maxbits[0:nbits][::-1]) if result != a + factor * b: print(f'{a} + ({factor} * {b}) = {result}') raise AssertionError('incorrect addition')
def main(argv): if len(argv) > 1: raise app.UsageError('Too many command-line arguments.') print('Order finding.') number = flags.FLAGS.N a = flags.FLAGS.a # The classical part are handled in 'shor_classic.py' nbits = number.bit_length() print('Shor: N = {}, a = {}, n = {} -> qubits: {}'.format( number, a, nbits, nbits * 4 + 2)) qc = circuit.qc('order_finding') # Aux register for additional and multiplication. aux = qc.reg(nbits + 2, name='q0') # Register for QFT. This reg will hold the resulting x-value. up = qc.reg(nbits * 2, name='q1') # Register for multiplications. down = qc.reg(nbits, name='q2') qc.h(up) qc.x(down[0]) for i in range(nbits * 2): cmultmodn(qc, up[i], down, aux, int(a**(2**i)), number, nbits) inverse_qft(qc, up, 2 * nbits, with_swaps=1) qc.dump_to_file() print('Measurement...') total_prob = 0.0 for bits in helper.bitprod(nbits * 4 + 2): prob = qc.psi.prob(*bits) if prob > 0.01: intval = helper.bits2val(bits[nbits + 2:nbits + 2 + nbits * 2][::-1]) phase = helper.bits2frac(bits[nbits + 2:nbits + 2 + nbits * 2][::-1]) r = fractions.Fraction(phase).limit_denominator(8).denominator guesses = [ math.gcd(a**(r // 2) - 1, number), math.gcd(a**(r // 2) + 1, number) ] print( 'Final x: {:3d} phase: {:3f} prob: {:.3f} factors: {}'.format( intval, phase, prob.real, guesses)) total_prob += qc.psi.prob(*bits) if total_prob > 0.999: break print(qc.stats())
def bitstring(*bits) -> State: """Produce a state from a given bit sequence, eg., |0101>.""" d = len(bits) if d == 0: raise ValueError('Rank must be at least 1.') for _, val in enumerate(bits): if val != 0 and val != 1: raise ValueError(f'Bits must be 0 or 1, got: {val}') t = np.zeros(1 << d, dtype=tensor.tensor_type()) t[helper.bits2val(bits)] = 1 return State(t)
def check_result(psi: state.State, a, b, nbits: int, factor: float = 1.0) -> None: """Find most likely result, dump it, compare against expected.""" maxbits, _ = psi.maxprob() result = helper.bits2val(maxbits[0:nbits][::-1]) if result != a + factor * b: print(f'{a} + ({factor} * {b}) != {result}') raise AssertionError('Incorrect addition.')
def experiment_decr(): """Run a few decr experiments.""" qc = circuit.qc('decr') x = qc.reg(4, 15) aux = qc.reg(4) for val in range(15, 0, -1): decr(qc, 0, 4, aux) maxbits, _ = qc.psi.maxprob() res = helper.bits2val(maxbits[0:4]) if val-1 != res: raise AssertionError('Invalid Result')
def experiment_mod_9(): """Run a few incr-mod-9 experiments.""" qc = circuit.qc('incr') x = qc.reg(4, 0) aux = qc.reg(5) # extra aux for val in range(18): incr_mod_9(qc, aux) maxbits, _ = qc.psi.maxprob() res = helper.bits2val(maxbits[0:4]) if ((val+1) % 9) != res: raise AssertionError('Invalid Result')
def Permutation(nbits, f): """Compute a permutation from function f.""" dim = 2**nbits perm = [] for row in range(dim): bits = helper.val2bits(row, nbits) fx = f(bits[0:-1]) xor = bits[-1] ^ fx new_bits = bits[0:-1] new_bits.append(xor) # Construct new column (int) from the new bit sequence. new_col = helper.bits2val(new_bits) perm.append(new_col) return perm
def arith_quantum_constant(n, init_a, c): """Run a quantum add-constant experiment.""" qc = circuit.qc('qadd') a = qc.reg(n + 1, helper.val2bits(init_a, n)[::-1], name='a') for i in range(0, n + 1): qft(qc, a, n - i) angles = precompute_angles(c, n) for i in range(0, n): qc.u1(a[i], angles[i]) for i in range(0, n + 1): inverse_qft(qc, a, i) maxbits, _ = qc.psi.maxprob() result = helper.bits2val(maxbits[0:n][::-1]) if result != init_a + c: print(f'{init_a} + {c} = {result}') raise AssertionError('incorrect addition')
def OracleUf(nbits, f): """Make an n-qubit Oracle for function f (eg. Deutsch, Grover).""" # This Oracle is constructed similar to the implementation in # ./deutsch.py, just with an n-bit |x> and a 1-bit |y> # dim = 2**nbits u = np.zeros(dim**2).reshape(dim, dim) for row in range(dim): bits = helper.val2bits(row, nbits) fx = f(bits[0:-1]) # f(x) without the y. xor = bits[-1] ^ fx new_bits = bits[0:-1] new_bits.append(xor) # Construct new column (int) from the new bit sequence. new_col = helper.bits2val(new_bits) u[row][new_col] = 1.0 op = Operator(u) if not op.is_unitary(): raise AssertionError('constructed non-unitary operators.') return op
def func(*bits): return answers[helper.bits2val(*bits)]
def ampl(self, *bits) -> np.complexfloating: """Return amplitude for state indexed by 'bits'.""" idx = helper.bits2val(bits) return self[idx]
def test_bits_converstions(self): bits = helper.val2bits(6, 3) self.assertEqual(bits, [1, 1, 0]) val = helper.bits2val(bits) self.assertEqual(val, 6)
def f(*bit_string): """Return f(bits) for one of the 2 possible function types.""" # pylint: disable=no-value-for-parameter idx = helper.bits2val(*bit_string) return bits[idx]