def do_simulate(self, variables, initial_state: int = None, *args, **kwargs) -> QubitWaveFunction:
        qubits = dict()
        count = 0
        for q in self.abstract_circuit.qubits:
            qubits[q] = count
            count +=1

        n_qubits = len(self.abstract_circuit.qubits)

        if initial_state is None:
            initial_state = QubitWaveFunction.from_int(i=0, n_qubits=n_qubits)
        elif isinstance(initial_state, int):
            initial_state = QubitWaveFunction.from_int(initial_state, n_qubits=n_qubits)

        result = initial_state
        for g in self.abstract_circuit.gates:
            result = self.apply_gate(state=result, gate=g, qubits=qubits, variables=variables)

        wfn = QubitWaveFunction()
        if self.convert_to_numpy:
            for k,v in result.items():
                wfn[k] = numpy.complex(v)
        else:
            wfn = result

        return wfn
    def apply_on_standard_basis(cls, gate: QGate, basisfunction: BitString, qubits:dict, variables) -> QubitWaveFunction:

        basis_array = basisfunction.array
        if gate.is_controlled():
            do_apply = True
            check = [basis_array[qubits[c]] == 1 for c in gate.control]
            for c in check:
                if not c:
                    do_apply = False
            if not do_apply:
                return QubitWaveFunction.from_int(basisfunction)

        if len(gate.target) > 1:
            raise Exception("Multi-targets not supported for symbolic simulators")

        result = QubitWaveFunction()
        for tt in gate.target:
            t = qubits[tt]
            qt = basis_array[t]
            a_array = copy.deepcopy(basis_array)
            a_array[t] = (a_array[t] + 1) % 2
            current_state = QubitWaveFunction.from_int(basisfunction)
            altered_state = QubitWaveFunction.from_int(BitString.from_array(a_array))

            fac1 = None
            fac2 = None
            if gate.name == "H":
                fac1 = (sympy.Integer(-1) ** qt * sympy.sqrt(sympy.Rational(1 / 2)))
                fac2 = (sympy.sqrt(sympy.Rational(1 / 2)))
            elif gate.name.upper() == "CNOT" or gate.name.upper() == "X":
                fac2 = sympy.Integer(1)
            elif gate.name.upper() == "Y":
                fac2 = sympy.I * sympy.Integer(-1) ** (qt)
            elif gate.name.upper() == "Z":
                fac1 = sympy.Integer(-1) ** (qt)
            elif gate.name.upper() == "RX":
                angle = sympy.Rational(1 / 2) * gate.parameter(variables)
                fac1 = sympy.cos(angle)
                fac2 = -sympy.sin(angle) * sympy.I
            elif gate.name.upper() == "RY":
                angle = -sympy.Rational(1 / 2) * gate.parameter(variables)
                fac1 = sympy.cos(angle)
                fac2 = +sympy.sin(angle) * sympy.Integer(-1) ** (qt + 1)
            elif gate.name.upper() == "RZ":
                angle = sympy.Rational(1 / 2) * gate.parameter(variables)
                fac1 = sympy.exp(-angle * sympy.I * sympy.Integer(-1) ** (qt))
            else:
                raise Exception("Gate is not known to simulators, " + str(gate))

            if fac1 is None or fac1 == 0:
                result += fac2 * altered_state
            elif fac2 is None or fac2 == 0:
                result += fac1 * current_state
            elif fac1 is None and fac2 is None:
                raise Exception("???")
            else:
                result += fac1 * current_state + fac2 * altered_state

        return result
Beispiel #3
0
def test_hadamard(qubit, init):
    gate = gates.H(target=qubit)
    iwfn = QubitWaveFunction.from_int(i=init, n_qubits=qubit + 1)
    wfn = simulate(gate, initial_state=init)
    test = 1.0 / numpy.sqrt(2) * (iwfn.apply_qubitoperator(paulis.Z(qubit)) +
                                  iwfn.apply_qubitoperator(paulis.X(qubit)))
    assert (wfn.isclose(test))
Beispiel #4
0
def test_rotations(rot, qubit, angle, init):
    pauli = rot[1](qubit)
    gate = rot[0](target=qubit, angle=angle)
    iwfn = QubitWaveFunction.from_int(i=init, n_qubits=qubit + 1)
    wfn = simulate(gate, initial_state=init)
    test = numpy.cos(-angle / 2.0) * iwfn + 1.0j * numpy.sin(
        -angle / 2.0) * iwfn.apply_qubitoperator(pauli)
    assert (wfn.isclose(test))
Beispiel #5
0
    def do_sample(self,
                  samples,
                  circuit,
                  noise_model=None,
                  initial_state=None,
                  *args,
                  **kwargs) -> QubitWaveFunction:
        """
        Helper function for performing sampling.

        Parameters
        ----------
        samples: int:
            the number of samples to be taken.
        circuit:
            the circuit to sample from.
        noise_model: optional:
            noise model to be applied to the circuit.
        initial_state:
            sampling supports initial states for qulacs. Indicates the initial state to which circuit is applied.
        args
        kwargs

        Returns
        -------
        QubitWaveFunction:
            the results of sampling, as a Qubit Wave Function.
        """
        n_qubits = max(self.highest_qubit + 1, self.n_qubits,
                       self.abstract_circuit.max_qubit() + 1)
        if initial_state is not None:
            if isinstance(initial_state, int):
                wave = QubitWaveFunction.from_int(i=initial_state,
                                                  n_qubits=n_qubits)
            elif isinstance(initial_state, str):
                wave = QubitWaveFunction.from_string(
                    string=initial_state).to_array()
            elif isinstance(initial_state, QubitWaveFunction):
                wave = initial_state
            elif isinstance(initial_state, np.ndarray):
                wave = QubitWaveFunction.from_array(
                    arr=initial_state,
                    n_qubits=n_qubits)  # silly but necessary
            else:
                raise TequilaQiboException(
                    'received an unusable initial state of type {}'.format(
                        type(initial_state)))
            state = wave.to_array()
            result = circuit(state, nshots=samples)
        else:
            result = circuit(nshots=samples)

        back = self.convert_measurements(backend_result=result)
        return back
Beispiel #6
0
    def map_state(self, state: list, *args, **kwargs) -> list:
        """
        Expects a state in spin-orbital ordering
        Returns the corresponding qubit state in the class encoding
        :param state:
            basis-state as occupation number vector in spin orbitals
            sorted as: [0_up, 0_down, 1_up, 1_down, ... N_up, N_down]
            with N being the number of spatial orbitals
        :return:
            basis-state as qubit state in the corresponding mapping
        """
        """Does a really lazy workaround ... but it works
        :return: Hartree-Fock Reference as binary-number

        Parameters
        ----------
        reference_orbitals: list:
            give list of doubly occupied orbitals
            default is None which leads to automatic list of the
            first n_electron/2 orbitals

        Returns
        -------

        """
        # default is a lazy workaround, but it workds
        n_qubits = 2 * self.n_orbitals

        spin_orbitals = sorted([i for i, x in enumerate(state) if int(x) == 1])

        string = "1.0 ["
        for i in spin_orbitals:
            string += str(i) + "^ "
        string += "]"

        fop = openfermion.FermionOperator(string, 1.0)
        op = self(fop)
        from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction
        wfn = QubitWaveFunction.from_int(0, n_qubits=n_qubits)
        wfn = wfn.apply_qubitoperator(operator=op)
        assert (len(wfn.keys()) == 1)
        key = list(wfn.keys())[0].array
        return key
Beispiel #7
0
    def do_simulate(self, variables, initial_state=None, *args, **kwargs):
        """
        Helper function to perform simulation.

        Parameters
        ----------
        variables: dict:
            variables to supply to the circuit.
        initial_state:
            information indicating the initial state on which the circuit should act.
        args
        kwargs

        Returns
        -------
        QubitWaveFunction:
            QubitWaveFunction representing result of the simulation.
        """
        n_qubits = max(self.highest_qubit + 1, self.n_qubits,
                       self.abstract_circuit.max_qubit() + 1)
        if initial_state is not None:
            if isinstance(initial_state, int) or isinstance(
                    initial_state, np.int):
                wave = QubitWaveFunction.from_int(i=initial_state,
                                                  n_qubits=n_qubits)
            elif isinstance(initial_state, str):
                wave = QubitWaveFunction.from_string(
                    string=initial_state).to_array()
            elif isinstance(initial_state, QubitWaveFunction):
                wave = initial_state
            elif isinstance(initial_state, np.ndarray):
                wave = QubitWaveFunction.from_array(initial_state)
            else:
                raise TequilaQiboException(
                    'could not understand initial state of type {}'.format(
                        type(initial_state)))
            state = wave.to_array()
            result = self.circuit(state)
        else:
            result = self.circuit()
        back = QubitWaveFunction.from_array(arr=result.numpy())
        return back
Beispiel #8
0
def test_pauli_gates(paulis, qubit, init):
    iwfn = QubitWaveFunction.from_int(i=init, n_qubits=qubit + 1)
    wfn = simulate(paulis[0](qubit), initial_state=init)
    iwfn = iwfn.apply_qubitoperator(paulis[1](qubit))
    assert (iwfn.isclose(wfn))