Ejemplo n.º 1
0
    def compile(self, circuit):
        # need to compile Hadamard gates
        # take over to tq compiler at some point
        compiled = []
        for gate in circuit.gates:
            if gate.name.lower() == "h":
                angle = gate.parameter if hasattr(gate, "parameter") else 1.0
                decomposed = tq.QCircuit()
                decomposed += tq.gates.Ry(angle=-numpy.pi / 4, target=gate.target)
                decomposed += tq.gates.Rz(angle=angle * numpy.pi, target=gate.target, control=gate.control)
                decomposed += tq.gates.Ry(angle=numpy.pi / 4, target=gate.target)
                compiled += decomposed.gates
            else:
                compiled.append(gate)

        return tq.QCircuit(gates=compiled)
Ejemplo n.º 2
0
def run_ising_circuits(n_qubits, g=1.0, *args, **kwargs):
    H = simplified_ising(n_qubits=n_qubits, g=g)
    if n_qubits < 10:
        exact_gs = numpy.linalg.eigvalsh(H.to_matrix())[0]
    else:
        exact_gs = None
    
    # orquestra workaround
    if "generators" in kwargs:
        kwargs["generators"] = json.loads(kwargs["generators"])
    if "fix_angles" in kwargs:
        kwargs["fix_angles"] = yaml.load(kwargs["fix_angles"], Loader=yaml.SafeLoader)
    if "connectivity" in kwargs:
        kwargs["connectivity"] = yaml.load(kwargs["connectivity"], Loader=yaml.SafeLoader)
    
    # initial mean-field like state
    n_qubits = H.n_qubits
    UMF = sum([tq.gates.Ry(angle=("a", q), target=q) for q in range(n_qubits)],tq.QCircuit())
    # encoder to save circuits as string
    encoder = CircuitGenEncoder()
    # solve "mean field"
    EMF = tq.ExpectationValue(H=H, U=UMF)
    result = tq.minimize(EMF)

    result_dict = {"schema":"schema"}
    result_dict["data"] = test_circuits(H=H, UMF=UMF, mf_variables=result.variables, *args, **kwargs)
    result_dict["kwargs"]=kwargs
    result_dict["g"]=g
    result_dict["exact_ground_state"]=exact_gs
    result_dict["mean_field_energy"]=float(result.energy)
    with open("isingdata.json", "w") as f:
        f.write(json.dumps(result_dict, indent=2))
Ejemplo n.º 3
0
 def ans4(num_qubits, layers, arg, enc):
     U = tq.QCircuit()
     for l in range(layers):
         # Layer single-qubit gates
         for q in range(num_qubits):
             # No encoding:
             if enc == False:
                 theta = tq.Variable(name="th_{}{}".format(l, q))
                 phi = tq.Variable(name="ph_{}{}".format(l, q))
                 U += tq.gates.Rx(target=q, angle=theta) + tq.gates.Rz(target=q, angle=phi)
             # Encoding:
             if enc == True:
                 theta = tq.Variable(name="thenc_{}{}".format(l, q))
                 phi = tq.Variable(name="phenc_{}{}".format(l, q))
                 wth = tq.Variable(name="thw_{}{}".format(l, q))
                 wph = tq.Variable(name="phw_{}{}".format(l, q))
                 U += tq.gates.Rx(target=q, angle=wth*arg + theta) +  tq.gates.Rz(target=q, angle=wph*arg + phi)
             # Layer XX gates      
         # no encoding in entangling gates
         # SAME entangling gates
         U += XX(0,1,"a") + XX(2,3,"b") + XX(1,2,"c") + XX(0,3,"d") + XX(0,2,"e") + XX(1,3,"f")
         #if enc == False:
             #U += XX(0,1, "a{}".format(l)) + XX(2,3,"b{}".format(l)) + XX(1,2,"c{}".format(l)) + XX(0,3,"d{}".format(l)) + XX(0,2,"e{}".format(l)) + XX(1,3,"f{}".format(l))
         #if enc == True:
         #   U += XX(0,1, "aw{}".format(l)) + XX(2,3,"bw{}".format(l)) + XX(1,2,"cw{}".format(l)) + XX(0,3,"dw{}".format(l)) + XX(0,2,"ew{}".format(l)) + XX(1,3,"fw{}".format(l))      
     return (U)
Ejemplo n.º 4
0
    def get_qubit_wise(self, binary=False):
        '''
        Return the qubit-wise form of the current binary hamiltonian.
        And the unitary transformation U, 
        where U = prod_i (1/2) ** (1/2) * (lagrangian_basis[i] + new_basis[i])
        
        Parameters
        ----------
        binary : determines whether the returned qwc hamiltonian is binary or qubit hamiltonian


        Returns
        -------
        hamiltonian : BinaryHamiltonian or QubitHamiltonian
            The original hamiltonian in qubit-wise commuting form
        U : QCircuit
            The unitary circuit that transforms the original hamiltonian into qwc form
        '''
        if not self.is_commuting():
            raise TequilaException(
                'Not all terms in the Hamiltonians are commuting.')
        if self.is_qubit_wise_commuting():
            qubit_wise_hamiltonian = self
            qwc_u = tq.QCircuit()
        else:
            qubit_wise_hamiltonian, lagrangian_basis, new_basis = self.single_qubit_form(
            )

            # Constructing the unitary that rotates into qubit-wise parts
            qwc_u = tq.QCircuit()
            for i in range(len(lagrangian_basis)):
                sigma = lagrangian_basis[i].to_pauli_strings()
                tau = new_basis[i].to_pauli_strings()
                qwc_u += tq.gates.ExpPauli(angle=-tq.numpy.pi / 2,
                                           paulistring=sigma)
                qwc_u += tq.gates.ExpPauli(angle=-tq.numpy.pi / 2,
                                           paulistring=tau)
                qwc_u += tq.gates.ExpPauli(angle=-tq.numpy.pi / 2,
                                           paulistring=sigma)

        single_qub_u = qubit_wise_hamiltonian.z_form()
        # Return the basis in terms of Binary Hamiltonian
        if binary:
            return qubit_wise_hamiltonian, qwc_u + single_qub_u
        else:
            return qubit_wise_hamiltonian.to_qubit_hamiltonian(
            ), qwc_u + single_qub_u
Ejemplo n.º 5
0
 def prune_circuit(self, circuit, variables, threshold=1.e-4):
     gates = []
     for gate in circuit.gates:
         if hasattr(gate, "parameter"):
             angle = self.fix_periodicity(gate.parameter(variables))
             if not numpy.isclose(angle, 0.0, atol=threshold):
                 gates.append(gate)
         else:
             gates.append(gate)
     if len(gates) != len(circuit.gates):
         print("pruned from {} to {}".format(len(circuit.gates), len(gates)))
     return tq.QCircuit(gates=gates)
Ejemplo n.º 6
0
 def decode(self, string: str, variables: dict = None):
     string_gates = string.split(self.gate_separator)
     circuit = tq.QCircuit()
     for gate in string_gates:
         gate = gate.strip()
         if gate == "":
             continue
         angle, gate = gate.split(self.angle_separator)
         try:
             angle = float(angle)
         except:
             angle = angle.strip()
             if angle == "":
                 angle = 1.0
             elif variables is not None and angle in variables:
                 angle = variables[angle]
         ps = self.decode_paulistring(input=gate)
         circuit += tq.gates.ExpPauli(paulistring=ps, angle=angle)
     return circuit
Ejemplo n.º 7
0
    def make_random_constant_depth_circuit(self, depth, past_moment=None):
        connectivity = self.connectivity
        circuit = tq.QCircuit()

        primitives = self.generators
        if past_moment is None:
            past_moment = []
        else:
            if hasattr(past_moment, "gates"):
                past_moment = [g.make_generator().paulistrings[0] for g in past_moment.gates]
        for moment in range(depth):
            qubits = list(connectivity.keys())
            current_moment = []
            while (len(qubits) > 0):
                try:
                    p = numpy.random.choice(primitives, 1)[0]
                    q0 = int(numpy.random.choice(qubits, 1, replace=False)[0])
                    available_connections = [x for x in connectivity[q0] if x in qubits]
                    q = [q0]
                    if len(p) > 1:
                        q += list(numpy.random.choice(available_connections, len(p) - 1, replace=False))
                    ps = tq.PauliString(data={q[i]: p[i] for i in range(len(p))})
                    current_moment.append(ps)
                    if ps in past_moment:
                        # will result in not adding the gate
                        qubits = [x for x in qubits if x not in q]
                        continue

                    angle = "a_{}_{}".format(p, len(circuit.gates))
                    if p in self.fix_angles:
                        angle = self.fix_angles[p]
                    circuit += tq.gates.ExpPauli(paulistring=str(ps), angle=angle)
                    qubits = [x for x in qubits if x not in q]
                except ValueError as E:
                    print("failed", "\n", str(E))
                    print(qubits)
                    continue

            past_moment = current_moment

        return circuit
Ejemplo n.º 8
0
    def z_form(self):
        '''
        Parameters
        ----------
        self : BinaryHamiltonian 
            a qubit-wise commuting hamiltonian

        Modifies
        ----------
        self : BinaryHamiltoina
            The original hamiltonian but in qubit-wise commuting form with all z

        Returns
        ----------
        U : QCircuit
            the single qubit transformation that rotates each term to z
        '''
        U = tq.QCircuit()
        non_z = {}
        for p in self.binary_terms:
            for qub in range(self.n_qubit):
                z_data = {qub: 'z'}
                if p.has_x(qub):
                    p.set_z(qub)
                    non_z[qub] = 'x'
                elif p.has_y(qub):
                    p.set_z(qub)
                    non_z[qub] = 'y'

        for qub, term in non_z.items():
            xy_data = {qub: term}
            z_data = {qub: 'z'}
            U += tq.gates.ExpPauli(angle=-tq.numpy.pi / 2,
                                   paulistring=tq.PauliString(z_data))
            U += tq.gates.ExpPauli(angle=-tq.numpy.pi / 2,
                                   paulistring=tq.PauliString(xy_data))
            U += tq.gates.ExpPauli(angle=-tq.numpy.pi / 2,
                                   paulistring=tq.PauliString(z_data))

        return U
Ejemplo n.º 9
0
def manual_ansatz(n_qubits, n_layers=1, connectivity=None, static=False):
    # no pbc
    U = tq.QCircuit()
    for l in range(n_layers):
        for q in range(n_qubits):
            angle = (l,q,0) if not static else (l,0)
            angle = tq.assign_variable(angle)
            U += tq.gates.Ry(angle=angle*numpy.pi, target=q)
        for q in range(n_qubits//2):
            angle = (l, 2*q,2*q+1, 1) if not static else 1.0
            angle = tq.assign_variable(angle)
            U += tq.gates.ExpPauli(paulistring="X({})Y({})".format(2*q,2*q+1), angle=angle*numpy.pi)
            #U += tq.gates.ExpPauli(paulistring="Y({})X({})".format(2*q,2*q+1), angle=angle*numpy.pi)

        # for q in range(n_qubits):
        #     angle = (l, q,1) if not static else (l,1)
        #     U += tq.gates.Ry(angle=angle, target=q)
        for q in range(n_qubits//2-1):
            angle = (l, 2*q+1, 2*q+2, 1) if not static else 1.0
            angle = tq.assign_variable(angle)
            U += tq.gates.ExpPauli(paulistring="X({})Y({})".format(2*q+1,(2*q+2)%n_qubits), angle=angle*numpy.pi)
            #U += tq.gates.ExpPauli(paulistring="Y({})X({})".format(2*q+1,(2*q+2)%n_qubits), angle=angle*numpy.pi)

    return U
Ejemplo n.º 10
0
    initial_state = "|1>_a|1>_b"  # Notation has to be consistent with your S
    trotter_steps = 20  # number of trotter steps for the BeamSplitter
    samples = 1000  # number of samples to simulate
    simulator = None  # Pick the Simulator (None -> let tequila do it)
    t = 0.25  # beam-splitter parameter

    setup = PhotonicSetup(pathnames=['a', 'b'], S=S, qpm=qpm)

    # the beam splitter is parametrized as phi=i*pi*t
    setup.add_beamsplitter(path_a='a', path_b='b', t=t, steps=trotter_steps)

    # need explicit circuit for initial state
    state = setup.initialize_state(state=initial_state)
    # can only do product states right now, alltough more general ones are possible
    # with code adaption
    Ui = tq.QCircuit()
    assert (len(state.state) == 1)
    key = [k for k in state.state.keys()][0]
    for i, q in enumerate(key.array):
        if q == 1:
            Ui += tq.gates.X(target=i)

    # full circuit (initial state plus mapped HOM setup)
    U = Ui + setup.setup + tq.gates.Measurement(target=[0, 1, 2, 3])

    print(U)

    # those are the qubit counts given back by tequila
    qcounts = tq.simulate(U, samples=samples)
    # those are the qubit counts re-interpreted as photonic counts
    pcounts = PhotonicStateVector(paths=setup.paths, state=qcounts)