コード例 #1
0
ファイル: test_mappings.py プロジェクト: philipp-q/tequila-1
def test_endianness_simulators():
    tests = ["000111",
             "111000",
             "101010",
             "010101",
             "10010010001",
             "111100101000010"]

    for string in tests:
        binary = BitString.from_binary(binary=string)
        c = QCircuit()
        for i, v in enumerate(binary):
            if v == 1:
                c += gates.X(target=i)
            if v == 0:
                c += gates.Z(target=i)

        wfn_cirq = simulate(c, initial_state=0, backend="cirq")
        counts_cirq = simulate(c, samples=1, backend="cirq")
        counts_qiskit = simulate(c, samples=1, backend="qiskit")
        print("counts_cirq  =", type(counts_cirq))
        print("counts_qiskit=", type(counts_qiskit))
        print("counts_cirq  =", counts_cirq)
        print("counts_qiskit=", counts_qiskit)
        assert (counts_cirq.isclose(counts_qiskit))
        assert (wfn_cirq.state == counts_cirq.state)
コード例 #2
0
    def __call__(self, wfn: QubitWaveFunction) -> QCircuit:
        """
        :param coeffs: The QubitWaveFunction you want to initialize
        :return:
        """
        try:
            assert (len(wfn) == len(self._target_space))
            for key in wfn.keys():
                try:
                    assert (key in self._target_space)
                except AssertionError:
                    print("key=", key.binary, " not found in target space")
        except AssertionError:
            raise TequilaException(
                "UnaryStatePrep was not initialized for the basis states in your wavefunction\n"
                "You gave:\n" + str(wfn) + "\n"
                "But the target_space is " +
                str([k.binary for k in self._target_space]) + "\n")

        angles = self._evaluate_angles(wfn=wfn)

        # construct new circuit with evaluated angles
        result = QCircuit()
        for g in self._abstract_circuit.gates:
            g2 = copy.deepcopy(g)
            if hasattr(g, "parameter"):
                symbol = g.parameter
                # the module needs repairing ....
                g2._parameter = assign_variable(
                    -angles[-symbol()]
                )  # the minus follows mahas convention since the circuits are daggered in the end
            result += g2

        return result
コード例 #3
0
def test_endianness_simulators():
    tests = [
        "000111", "111000", "101010", "010101", "10010010001",
        "111100101000010"
    ]

    for string in tests:
        number = int(string, 2)
        binary = BitString.from_binary(binary=string)
        c = QCircuit()
        for i, v in enumerate(binary):
            if v == 1:
                c += gates.X(target=i)

        c += gates.Measurement(target=[x for x in range(len(string))])

        wfn_cirq = simulate(c, initial_state=0, backend="cirq")
        counts_cirq = simulate(c, samples=1, backend="cirq")
        counts_qiskit = simulate(c, samples=1, backend="qiskit")
        print("counts_cirq  =", type(counts_cirq))
        print("counts_qiskit=", type(counts_qiskit))
        print("counts_cirq  =", counts_cirq)
        print("counts_qiskit=", counts_qiskit)
        assert (counts_cirq == counts_qiskit)
        assert (wfn_cirq.state == counts_cirq.state)
コード例 #4
0
    def get_circuit(self, s):
        '''
        s = []
        for counter in range(4):
            string = input("Enter your state: ")
            s.append(string)
        if not silenced: print(s)
        '''
        if not self.silenced: print("s on start=", s)
        moves_list = []
        moves_list = self.get_next_move(s, moves_list)
        if not self.silenced: print("last s=", s)

        circuit = QCircuit()
        for move in moves_list:
            circuit += self.create_sub_circ(move[0], move[1], move[2])

        return circuit.dagger()
コード例 #5
0
ファイル: qasm.py プロジェクト: philipp-q/tequila-1
def apply_custom_gate(custom_circuit: QCircuit,
                      qregisters_values: list) -> QCircuit:
    applied_custom_circuit = QCircuit()
    for gate in custom_circuit.gates:
        g = gate.copy()
        g._target = tuple([qregisters_values[i] for i in gate._target])
        g._control = tuple([qregisters_values[i] for i in gate._control
                            ]) if gate.is_controlled() else gate._control
        applied_custom_circuit += g
    return applied_custom_circuit
コード例 #6
0
ファイル: qasm.py プロジェクト: philipp-q/tequila-1
def parse_from_open_qasm_2(qasm_code: str, rigorous: bool = True) -> QCircuit:

    lines = qasm_code.splitlines()
    clean_code = []
    # ignore comments
    for line in lines:
        if line.find("//") != -1:
            clean_line = line[0:line.find("//")].strip()
        else:
            clean_line = line.strip()
        if clean_line:
            clean_code.append(clean_line)

    if clean_code[0].startswith("OPENQASM"):
        clean_code.pop(0)
    elif rigorous:
        raise TequilaException("File must start with the 'OPENQASM' directive")

    if clean_code[0].startswith('include "qelib1.inc";'):
        clean_code.pop(0)
    elif rigorous:
        raise TequilaException(
            "File must import standard library (qelib1.inc)")

    code_circuit = "\n".join(clean_code)
    # separate the custom command definitions from the normal commands
    custom_gates_map: Dict[str, QCircuit] = {}
    while True:
        i = code_circuit.find("gate ")
        if i == -1:
            break
        j = code_circuit.find("}", i)
        custom_name, custom_circuit = parse_custom_gate(
            code_circuit[i:j + 1], custom_gates_map=custom_gates_map)
        custom_gates_map[custom_name] = custom_circuit
        code_circuit = code_circuit[:i] + code_circuit[j + 1:]

    # parse regular commands
    commands = [s.strip() for s in code_circuit.split(";") if s.strip()]
    qregisters: Dict[str, int] = {}

    circuit = QCircuit()
    for c in commands:
        partial_circuit = parse_command(command=c,
                                        custom_gates_map=custom_gates_map,
                                        qregisters=qregisters)
        if partial_circuit is not None:
            circuit += partial_circuit

    return circuit
コード例 #7
0
    def get_circuit(self):
        """
        :return: Return the abstract circuit with tequila parameters
        """
        result = QCircuit()
        for g in self._abstract_circuit.gates:
            g2 = copy.deepcopy(g)
            if hasattr(g, "parameter"):
                symbol = g.parameter
                name = str(-symbol)  # kill the minus from the dagger
                g2._parameter = assign_variable(name)
            result += g2

        return result
コード例 #8
0
ファイル: qasm.py プロジェクト: philipp-q/tequila-1
def parse_custom_gate(
        gate_custom: str, custom_gates_map: Dict[str,
                                                 QCircuit]) -> (str, QCircuit):
    """
    Parse custom gates code

    Args:
        gate_custom: code with custom gates
    """
    gate_custom = gate_custom[5:]
    spec, body = gate_custom.split("{", 1)

    if "(" in spec:
        i = spec.find("(")
        j = spec.find(")")
        if spec[i + 1:j].strip():
            raise TequilaException(
                "Parameters for custom gates not supported: {}".format(spec))
        spec = spec[:i] + spec[j + 1:]

    spec = spec.strip()

    if " " in spec:
        name, qargs = spec.split(" ", 1)
        name = name.strip()
        qargs = qargs.strip()
    else:
        raise TequilaException(
            "Custom gate specification doesn't have any arguments: {}".format(
                spec))

    custom_qregisters: Dict[str, int] = {}
    for qarg in qargs.split(','):
        custom_qregisters[qarg] = len(custom_qregisters)

    body = body[:-1].strip()
    commands = [s.strip() for s in body.split(";") if s.strip()]

    custom_circuit = QCircuit()
    for c in commands:
        partial_circuit = parse_command(command=c,
                                        custom_gates_map=custom_gates_map,
                                        qregisters=custom_qregisters)
        if partial_circuit is not None:
            custom_circuit += partial_circuit

    return name, custom_circuit
コード例 #9
0
ファイル: qc_base.py プロジェクト: akpc/margarita
def prepare_product_state(state: BitString) -> QCircuit:
    """Small convenience function

    Parameters
    ----------
    state :
        product state encoded into a bitstring
    state: BitString :
        

    Returns
    -------
    type
        unitary circuit which prepares the product state

    """
    result = QCircuit()
    for i, v in enumerate(state.array):
        if v == 1:
            result += gates.X(target=i)
    return result
コード例 #10
0
ファイル: qc_base.py プロジェクト: akpc/margarita
    def make_uccsd_ansatz(
            self,
            trotter_steps: int,
            initial_amplitudes: typing.Union[str, Amplitudes,
                                             ClosedShellAmplitudes] = "mp2",
            include_reference_ansatz=True,
            parametrized=True,
            threshold=1.e-8,
            trotter_parameters: gates.TrotterParameters = None) -> QCircuit:
        """

        Parameters
        ----------
        initial_amplitudes :
            initial amplitudes given as ManyBodyAmplitudes structure or as string
            where 'mp2', 'cc2' or 'ccsd' are possible initializations
        include_reference_ansatz :
            Also do the reference ansatz (prepare closed-shell Hartree-Fock) (Default value = True)
        parametrized :
            Initialize with variables, otherwise with static numbers (Default value = True)
        trotter_steps: int :

        initial_amplitudes: typing.Union[str :

        Amplitudes :

        ClosedShellAmplitudes] :
             (Default value = "mp2")
        trotter_parameters: gates.TrotterParameters :
             (Default value = None)

        Returns
        -------
        type
            Parametrized QCircuit

        """

        if self.n_electrons % 2 != 0:
            raise TequilaException(
                "make_uccsd_ansatz currently only for closed shell systems")

        nocc = self.n_electrons // 2
        nvirt = self.n_orbitals // 2 - nocc

        Uref = QCircuit()
        if include_reference_ansatz:
            Uref = self.prepare_reference()

        amplitudes = initial_amplitudes
        if hasattr(initial_amplitudes, "lower"):
            if initial_amplitudes.lower() == "mp2":
                amplitudes = self.compute_mp2_amplitudes()
            elif initial_amplitudes.lower() == "ccsd":
                amplitudes = self.compute_ccsd_amplitudes()
            else:
                try:
                    amplitudes = self.compute_amplitudes(
                        method=initial_amplitudes.lower())
                except Exception as exc:
                    raise TequilaException(
                        "{}\nDon't know how to initialize \'{}\' amplitudes".
                        format(exc, initial_amplitudes))

        if amplitudes is None:
            amplitudes = ClosedShellAmplitudes(
                tIjAb=numpy.zeros(shape=[nocc, nocc, nvirt, nvirt]),
                tIA=numpy.zeros(shape=[nocc, nvirt]))

        closed_shell = isinstance(amplitudes, ClosedShellAmplitudes)
        generators = []
        variables = []

        if not isinstance(amplitudes, dict):
            amplitudes = amplitudes.make_parameter_dictionary(
                threshold=threshold)
            amplitudes = dict(sorted(amplitudes.items(), key=lambda x: x[1]))

        for key, t in amplitudes.items():
            assert (len(key) % 2 == 0)
            if not numpy.isclose(t, 0.0, atol=threshold):

                if closed_shell:
                    spin_indices = []
                    if len(key) == 2:
                        spin_indices = [[2 * key[0], 2 * key[1]],
                                        [2 * key[0] + 1, 2 * key[1] + 1]]
                        partner = None
                    else:
                        spin_indices.append([
                            2 * key[0] + 1, 2 * key[1] + 1, 2 * key[2],
                            2 * key[3]
                        ])
                        spin_indices.append([
                            2 * key[0], 2 * key[1], 2 * key[2] + 1,
                            2 * key[3] + 1
                        ])
                        if key[0] != key[1] and key[2] != key[3]:
                            spin_indices.append([
                                2 * key[0], 2 * key[1], 2 * key[2], 2 * key[3]
                            ])
                            spin_indices.append([
                                2 * key[0] + 1, 2 * key[1] + 1, 2 * key[2] + 1,
                                2 * key[3] + 1
                            ])
                        partner = tuple([key[2], key[1], key[0],
                                         key[3]])  # taibj -> tbiaj

                    for idx in spin_indices:
                        idx = [(idx[2 * i], idx[2 * i + 1])
                               for i in range(len(idx) // 2)]
                        generators.append(
                            self.make_excitation_generator(indices=idx))

                    if parametrized:
                        variables.append(Variable(name=key))  # abab
                        variables.append(Variable(name=key))  # baba
                        if partner is not None and key[0] != key[1] and key[
                                2] != key[3]:
                            variables.append(
                                Variable(name=key) - Variable(partner))  # aaaa
                            variables.append(
                                Variable(name=key) - Variable(partner))  # bbbb
                    else:
                        variables.append(t)
                        variables.append(t)
                        if partner is not None and key[0] != key[1] and key[
                                2] != key[3]:
                            variables.append(t - amplitudes[partner])
                            variables.append(t - amplitudes[partner])
                else:
                    generators.append(
                        self.make_excitation_operator(indices=spin_indices))
                    if parametrized:
                        variables.append(Variable(name=key))
                    else:
                        variables.append(t)

        return Uref + gates.Trotterized(generators=generators,
                                        angles=variables,
                                        steps=trotter_steps,
                                        parameters=trotter_parameters)
コード例 #11
0
ファイル: qasm.py プロジェクト: philipp-q/tequila-1
def convert_to_open_qasm_2(circuit: QCircuit,
                           variables=None,
                           zx_calculus: bool = False) -> str:
    """
    Allow export to OpenQASM version 2.0

    Args:
        circuit: to be exported to OpenQASM
        variables: optional dictionary with values for variables
        zx_calculus: indicate if y-gates must be transformed to xz equivalents

    Returns:
        str: OpenQASM string
    """

    if variables is None and not (len(circuit.extract_variables()) == 0):
        raise TequilaException(
            "You called export_open_qasm for a parametrized type but forgot to pass down the variables: {}"
            .format(circuit.extract_variables()))

    compiler = Compiler(multitarget=True,
                        multicontrol=False,
                        trotterized=True,
                        generalized_rotation=True,
                        exponential_pauli=True,
                        controlled_exponential_pauli=True,
                        hadamard_power=True,
                        controlled_power=True,
                        power=True,
                        toffoli=True,
                        controlled_phase=True,
                        phase=True,
                        phase_to_z=True,
                        controlled_rotation=True,
                        swap=True,
                        cc_max=True,
                        gradient_mode=False,
                        ry_gate=zx_calculus,
                        y_gate=zx_calculus,
                        ch_gate=zx_calculus)

    compiled = compiler(circuit, variables=None)

    result = "OPENQASM 2.0;\ninclude \"qelib1.inc\";\n"

    qubits_names: Dict[int, str] = {}
    for q in compiled.qubits:
        name = "q[" + str(q) + "]"
        qubits_names[q] = name

    result += "qreg q[" + str(compiled.n_qubits) + "];\n"
    result += "creg c[" + str(compiled.n_qubits) + "];\n"

    for g in compiled.gates:

        control_str = ''
        if g.is_controlled():

            if len(g.control) > 2:
                raise TequilaException(
                    "Multi-controls beyond 2 not yet supported for OpenQASM 2.0. Gate was:\n{}"
                    .format(g))

            controls = list(map(lambda c: qubits_names[c], g.control))
            control_str = ','.join(controls) + ','

        gate_name = name_and_params(g, variables)
        for t in g.target:
            result += gate_name
            result += control_str
            result += qubits_names[t]
            result += ";\n"

    return result
コード例 #12
0
ファイル: qasm.py プロジェクト: philipp-q/tequila-1
def parse_command(command: str, custom_gates_map: Dict[str, QCircuit],
                  qregisters: Dict[str, int]) -> QCircuit:
    """
    Parse qasm code command

    Args:
        command: open qasm code to be parsed
        custom_gates_map: map with custom gates
    """

    name, rest = command.split(" ", 1)

    if name in ("barrier", "creg", "measure", "id"):
        return None
    if name in ("opaque", "if"):
        raise TequilaException("Unsupported operation {}".format(command))

    args = [s.strip() for s in rest.split(",") if s.strip()]

    if name == "qreg":
        regname, sizep = args[0].split("[", 1)
        size = int(sizep[:-1])
        for i in range(size):
            qregisters[regname + "[" + str(i) + "]"] = len(qregisters)
        return None

    for arg in args:
        if not (arg in qregisters
                or arg in [key.split("[", 1)[0] for key in qregisters.keys()]):
            raise TequilaException("Invalid register {}".format(arg))

    if name in custom_gates_map:
        custom_circuit = custom_gates_map[name]
        qregisters_values = []
        for a in args:
            qregisters_values.append(get_qregister(a, qregisters))
        return apply_custom_gate(custom_circuit=custom_circuit,
                                 qregisters_values=qregisters_values)

    if name in ("x", "y", "z", "h", "cx", "cy", "cz", "ch"):
        return QCircuit.wrap_gate(
            gates.impl.QGateImpl(
                name=(name[1] if name[0] == 'c' else name).upper(),
                control=get_qregister(args[0], qregisters)
                if name[0] == 'c' else None,
                target=get_qregister(args[1 if name[0] == 'c' else 0],
                                     qregisters)))
    if name in ("ccx", "ccy", "ccz"):
        return QCircuit.wrap_gate(
            gates.impl.QGateImpl(name=name.upper()[2],
                                 control=[
                                     get_qregister(args[0], qregisters),
                                     get_qregister(args[1], qregisters)
                                 ],
                                 target=get_qregister(args[2], qregisters)))
    if name.startswith("rx(") or name.startswith("ry(") or name.startswith("rz(") or \
        name.startswith("crx(") or name.startswith("cry(") or name.startswith("crz("):
        return QCircuit.wrap_gate(
            gates.impl.RotationGateImpl(
                axis=name[2 if name[0] == 'c' else 1],
                angle=get_angle(name)[0],
                control=get_qregister(args[0], qregisters)
                if name[0] == 'c' else None,
                target=get_qregister(args[1 if name[0] == 'c' else 0],
                                     qregisters)))
    if name.startswith("U("):
        angles = get_angle(name)
        return gates.U(theta=angles[0],
                       phi=angles[1],
                       lambd=angles[2],
                       control=None,
                       target=get_qregister(args[0], qregisters))
    if name.startswith("u1("):
        angles = get_angle(name)
        return gates.u1(lambd=angles[0],
                        control=None,
                        target=get_qregister(args[0], qregisters))
    if name.startswith("u2("):
        angles = get_angle(name)
        return gates.u2(phi=angles[0],
                        lambd=angles[1],
                        control=None,
                        target=get_qregister(args[0], qregisters))
    if name.startswith("u3("):
        angles = get_angle(name)
        return gates.u3(theta=angles[0],
                        phi=angles[1],
                        lambd=angles[2],
                        control=None,
                        target=get_qregister(args[0], qregisters))
    if name.startswith("cu1("):
        angles = get_angle(name)
        return gates.u1(lambd=angles[0],
                        control=get_qregister(args[0], qregisters),
                        target=get_qregister(args[1], qregisters))
    if name.startswith("cu2("):
        angles = get_angle(name)
        return gates.u2(phi=angles[0],
                        lambd=angles[1],
                        control=get_qregister(args[0], qregisters),
                        target=get_qregister(args[1], qregisters))
    if name.startswith("cu3("):
        angles = get_angle(name)
        return gates.u3(theta=angles[0],
                        phi=angles[1],
                        lambd=angles[2],
                        control=get_qregister(args[0], qregisters),
                        target=get_qregister(args[1], qregisters))
    if name in ("s", "t", "sdg", "tdg"):
        g = gates.Phase(pi / (2 if name.startswith("s") else 4),
                        control=None,
                        target=get_qregister(args[0], qregisters))
        if name.find("dg") != -1:
            g = g.dagger()
        return g