コード例 #1
0
def time_evolution(
    hamiltonian: QubitOperator,
    time: Union[float, sympy.Expr],
    method: str = "Trotter",
    trotter_order: int = 1,
) -> circuits.Circuit:
    """Create a circuit simulating evolution under given Hamiltonian.

    Args:
        hamiltonian: The Hamiltonian to be evolved under.
        time: Time duration of the evolution.
        method: Time evolution method. Currently the only option is 'Trotter'.
        trotter_order: order of Trotter evolution (1 by default).

    Returns:
        Circuit approximating evolution under `hamiltonian`.
        Circuit's unitary i approximately equal to exp(-i * time * hamiltonian).
    """
    if method != "Trotter":
        raise ValueError(f"Currently the method {method} is not supported.")

    terms: Iterable = list(hamiltonian.get_operators())

    return reduce(
        operator.add,
        (time_evolution_for_term(term, time / trotter_order)
         for _index_order in range(trotter_order) for term in terms),
    )
コード例 #2
0
def time_evolution_derivatives(
    hamiltonian: QubitOperator,
    time: float,
    method: str = "Trotter",
    trotter_order: int = 1,
) -> Tuple[List[circuits.Circuit], List[float]]:
    """Generates derivative circuits for the time evolution operator defined in
    function time_evolution

    Args:
        hamiltonian: The Hamiltonian to be evolved under. It should contain numeric
            coefficients, symbolic expressions aren't supported.
        time: time duration of the evolution.
        method: time evolution method. Currently the only option is 'Trotter'.
        trotter_order: order of Trotter evolution

    Returns:
        A Circuit simulating time evolution.
    """
    if method != "Trotter":
        raise ValueError(f"The method {method} is currently not supported.")

    single_trotter_derivatives = []
    factors = [1.0, -1.0]
    output_factors = []
    terms: Iterable = list(hamiltonian.get_operators())

    for i, term_1 in enumerate(terms):
        for factor in factors:
            output = circuits.Circuit()

            try:
                if isinstance(term_1, QubitOperator):
                    r = list(term_1.terms.values())[0] / trotter_order
                else:
                    r = complex(term_1.coefficient).real / trotter_order
            except TypeError:
                raise ValueError("Term coefficients need to be numerical. "
                                 f"Offending term: {term_1}")
            output_factors.append(r * factor)
            shift = factor * (np.pi / (4.0 * r))

            for j, term_2 in enumerate(terms):
                output += time_evolution_for_term(
                    term_2,
                    (time + shift) / trotter_order if i == j else time /
                    trotter_order,
                )

            single_trotter_derivatives.append(output)

    if trotter_order > 1:
        output_circuits = []
        final_factors = []

        repeated_circuit = time_evolution(hamiltonian,
                                          time,
                                          method="Trotter",
                                          trotter_order=1)

        for position in range(trotter_order):
            for factor, different_circuit in zip(output_factors,
                                                 single_trotter_derivatives):
                output_circuits.append(
                    _generate_circuit_sequence(repeated_circuit,
                                               different_circuit,
                                               trotter_order, position))
                final_factors.append(factor)
        return output_circuits, final_factors
    else:
        return single_trotter_derivatives, output_factors