Esempio n. 1
0
def test_parallel_map_fw_prop_step_loky(transmon_xgate_system):
    """Test optimization with parallel_map parameter, using loky."""
    objectives, pulse_options, tlist = transmon_xgate_system

    krotov.parallelization.USE_LOKY = True
    log = io.StringIO()
    opt_result_loky = krotov.optimize_pulses(
        objectives,
        pulse_options,
        tlist,
        propagator=krotov.propagators.expm,
        chi_constructor=krotov.functionals.chis_re,
        info_hook=partial(krotov.info_hooks.print_debug_information, out=log),
        iter_stop=1,
        skip_initial_forward_propagation=True,
        parallel_map=(
            krotov.parallelization.parallel_map,
            krotov.parallelization.parallel_map,
            krotov.parallelization.parallel_map_fw_prop_step,
        ),
    )
    tau1_loky = abs(opt_result_loky.tau_vals[0][0])
    tau2_loky = abs(opt_result_loky.tau_vals[0][1])
    assert abs(tau1_loky - 0.9693) < 1e-3
    assert abs(tau2_loky - 0.7743) < 1e-3

    krotov.parallelization.USE_LOKY = False
    # in order to be pickleable, all functions must be defined in a module
    # (transmon_xgate_system_mod)
    H = transmon_xgate_system_mod.transmon_hamiltonian()
    pulse_options = {
        H[1][1]: dict(lambda_a=1, update_shape=transmon_xgate_system_mod.S)
    }
    psi0, psi1 = transmon_xgate_system_mod.logical_basis(H)
    objectives = krotov.gate_objectives(
        basis_states=[psi0, psi1], gate=qutip.operators.sigmax(), H=H
    )
    try:
        opt_result = krotov.optimize_pulses(
            objectives,
            pulse_options,
            tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            iter_stop=1,
            skip_initial_forward_propagation=True,
            parallel_map=(
                krotov.parallelization.parallel_map,
                krotov.parallelization.parallel_map,
                krotov.parallelization.parallel_map_fw_prop_step,
            ),
        )
        tau1 = abs(opt_result.tau_vals[0][0])
        tau2 = abs(opt_result.tau_vals[0][1])
        assert abs(tau1_loky - tau1) < 1e-12
        assert abs(tau2_loky - tau2) < 1e-12
    except RuntimeError:
        # parallelization without LOKY doesn't work on all platforms
        pass
Esempio n. 2
0
def test_zero_iterations(iter_stop, simple_state_to_state_system):
    objectives, pulse_options, tlist = simple_state_to_state_system

    with io.StringIO() as log_fh:

        result = krotov.optimize_pulses(
            objectives,
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            store_all_pulses=True,
            info_hook=krotov.info_hooks.print_table(
                J_T=krotov.functionals.J_T_re, out=log_fh
            ),
            iter_stop=iter_stop,
            skip_initial_forward_propagation=True,
        )

        log = log_fh.getvalue()

    assert len(log.splitlines()) == 2
    assert result.message == 'Reached 0 iterations'
    assert len(result.guess_controls) == 1  # one control field
    assert len(result.guess_controls) == len(result.optimized_controls)
    assert len(result.guess_controls[0]) == len(result.tlist)
    assert len(result.optimized_controls[0]) == len(result.tlist)
    for (c1, c2) in zip(result.guess_controls, result.optimized_controls):
        assert np.all(c1 == c2)
    for pulses_for_iteration in result.all_pulses:
        for pulse in pulses_for_iteration:
            # the pulses are defined on the *intervals* of tlist
            assert len(pulse) == len(result.tlist) - 1
Esempio n. 3
0
def test_infohook_chaining(transmon_ham_and_states):
    """Test that transmon_ham_and_states and info_hooks get chained together
    correctly. This tests a whole bunch of implementation details:

    - return values from multiple info_hooks combine in tuple
    - return value None (from modify_params_after_iter) gets ignored
    - shared_data gets passed along through multiple hooks
    - shared_data is cleared in each iteration
    """
    H, psi0, psi1 = transmon_ham_and_states
    obj = krotov.Objective(initial_state=psi0, target=psi1, H=H)
    tlist = np.array([0, 0.01, 0.02])
    pulse_options = {H[1][1]: dict(lambda_a=1, update_shape=1)}
    stdout = io.StringIO()

    def adjust_lambda_a(**args):
        λₐ = args['lambda_vals'][0]
        args['lambda_vals'][0] *= 0.5
        if 'messages' not in args['shared_data']:
            args['shared_data']['messages'] = []
        args['shared_data']['messages'].append(
            'λₐ: %s → %s' % (λₐ, args['lambda_vals'][0])
        )

    def print_fidelity(**args):
        F_re = np.average(np.array(args['tau_vals']).real)
        print("Iteration %d: \tF = %f" % (args['iteration'], F_re))
        return F_re

    def print_messages(**args):
        if 'messages' in args['shared_data']:
            message = "; ".join(
                [msg for msg in args['shared_data']['messages']]
            )
            print("\tmsg: " + message)
            return message

    with contextlib.redirect_stdout(stdout):
        oct_result = krotov.optimize_pulses(
            [obj],
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            info_hook=krotov.info_hooks.chain(print_fidelity, print_messages),
            modify_params_after_iter=adjust_lambda_a,
            iter_stop=2,
        )

    assert len(oct_result.info_vals) == 3
    assert isinstance(oct_result.info_vals[1], tuple)
    assert len(oct_result.info_vals[1]) == 2
    assert abs(oct_result.info_vals[1][0] - 0.001978333994757067) < 1e-8
    assert oct_result.info_vals[1][1] == 'λₐ: 0.5 → 0.25'
    assert 'Iteration 0: \tF = 0.000000' in stdout.getvalue()
    assert 'msg: λₐ: 1.0 → 0.5' in stdout.getvalue()
    assert 'Iteration 1: \tF = 0.001978' in stdout.getvalue()
    assert 'msg: λₐ: 0.5 → 0.25' in stdout.getvalue()
Esempio n. 4
0
def test_complex_control_rejection():
    """Test that complex controls are rejected"""
    H0 = qutip.Qobj(0.5 * np.diag([-1, 1]))
    H1 = qutip.Qobj(np.mat([[1, 2], [3, 4]]))

    psi0 = qutip.Qobj(np.array([1, 0]))
    psi1 = qutip.Qobj(np.array([0, 1]))

    def eps0(t, args):
        return 0.2 * np.exp(1j * t)

    def S(t):
        """Shape function for the field update"""
        return krotov.shapes.flattop(
            t, t_start=0, t_stop=5, t_rise=0.3, t_fall=0.3, func='sinsq'
        )

    H = [H0, [H1, eps0]]

    objectives = [krotov.Objective(initial_state=psi0, target=psi1, H=H)]

    pulse_options = {H[1][1]: dict(lambda_a=5, update_shape=S)}

    tlist = np.linspace(0, 5, 500)

    with pytest.raises(ValueError) as exc_info:
        krotov.optimize_pulses(
            objectives,
            pulse_options,
            tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            iter_stop=0,
        )
    assert 'all controls must be real-valued' in str(exc_info.value)

    def S2(t):
        """Shape function for the field update"""
        return 2.0 * krotov.shapes.flattop(
            t, t_start=0, t_stop=5, t_rise=0.3, t_fall=0.3, func='sinsq'
        )
Esempio n. 5
0
def test_print_table_custom_header(request, simple_state_to_state_system):
    """Test print_table with custom col_formats."""
    objectives, pulse_options, tlist = simple_state_to_state_system
    testdir = Path(os.path.splitext(request.module.__file__)[0])

    with io.StringIO() as log_fh:

        krotov.optimize_pulses(
            objectives,
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            store_all_pulses=True,
            info_hook=krotov.info_hooks.print_table(
                J_T=krotov.functionals.J_T_re,
                col_headers=(
                    'iteration',
                    ' final time functional',
                    ' running cost (pulse {l})',
                    ' total running cost',
                    ' total functional',
                    ' change in final time functional',
                    ' change in total functional',
                    ' seconds for iteration',
                ),
                show_g_a_int_per_pulse=True,
                out=log_fh,
            ),
            iter_stop=1,
            skip_initial_forward_propagation=True,
        )

        log = log_fh.getvalue()

    expected_log = (testdir /
                    'custom_header_out.txt').read_text(encoding='utf8')
    for (ln, ln_e) in zip(log.splitlines(), expected_log.splitlines()):
        # we have to remove the secs in the last column (not stable)
        assert ln[:-2] == ln_e[:-2]
def test_numpy_controls(numpy_control_system):
    """Test optimization with numpy array controls.

    Test the resolution of https://github.com/qucontrol/krotov/issues/79
    """
    tlist, objectives, pulse_options = numpy_control_system
    opt_result = krotov.optimize_pulses(
        objectives,
        pulse_options=pulse_options,
        tlist=tlist,
        propagator=krotov.propagators.expm,
        chi_constructor=krotov.functionals.chis_ss,
        check_convergence=krotov.convergence.Or(
            krotov.convergence.value_below('1e-3', name='J_T'),
            krotov.convergence.check_monotonic_error,
        ),
        iter_stop=0,
        skip_initial_forward_propagation=True,
    )
    assert opt_result.message == 'Reached 0 iterations'
Esempio n. 7
0
    ax.set_ylabel('Population')
    plt.show()

proj_G = psi_0 * psi_0.dag()
proj_GHZ = target_state * target_state.dag()
if SHOW_PLOTS and not CONTINUE_FROM:
    guess_dynamics = objectives[0].mesolve(norm_t_list, e_ops=[proj_G, proj_GHZ])
    plot_population(guess_dynamics)

opt_result = krotov.optimize_pulses(
    objectives,
    pulse_options=pulse_options,
    tlist=norm_t_list,
    propagator=krotov.propagators.expm,
    chi_constructor=krotov.functionals.chis_re,
    # info_hook=krotov.info_hooks.print_table(J_T=krotov.functionals.J_T_re),
    # info_hook=krotov.info_hooks.chain(krotov.info_hooks.print_debug_information, print_fidelity),
    info_hook=print_fidelity,
    # check_convergence=krotov.convergence.check_monotonic_error,
    iter_stop=40,
    continue_from=Result.load(OPT_RESULT_DUMP, objectives=objectives) if CONTINUE_FROM else None
)

dump_file_name = OPT_RESULT_DUMP if not CONTINUE_FROM else OPT_RESULT_DUMP + "_1"
opt_result.dump(dump_file_name)

print(opt_result)

if SHOW_PLOTS:
    plot_pulse(opt_result.optimized_controls[0], norm_t_list, "Optimised $\Omega$")
    plot_pulse(opt_result.optimized_controls[1], norm_t_list, "Optimised $\Delta$")
                                                qutip.ket("0"), qutip.ket("0"),
                                                qutip.ket("0")),
                     target=qutip.tensor(qutip.ket("0"), qutip.ket("1"),
                                         qutip.ket("1"), qutip.ket("1"),
                                         qutip.ket("1"), qutip.ket("1"),
                                         qutip.ket("1")),
                     H=H)
]

opt_result = krotov.optimize_pulses(
    objectives,
    pulse_options=pulse_options,
    tlist=tlist,
    propagator=krotov.propagators.expm,
    chi_constructor=krotov.functionals.chis_ss,
    info_hook=krotov.info_hooks.print_table(J_T=krotov.functionals.J_T_ss),
    check_convergence=krotov.convergence.Or(
        krotov.convergence.value_below('5e-3', name='J_T'),
        krotov.convergence.check_monotonic_error,
    ),
    store_all_pulses=True,
)
plot_iterations(opt_result)

from numpy import linalg as npla


def eigenvalues(A):
    eigenValues, eigenVectors = npla.eig(A)
    idx = np.argsort(eigenValues)
    eigenValues = eigenValues[idx]
Esempio n. 9
0
    plt.legend()
    fig.savefig('EField6cells.png')


# NBVAL_IGNORE_OUTPUT
# the DensityMatrixODEPropagator is not sufficiently exact to guarantee that
# you won't get slightly different results in the optimization when
# running this on different systems
opt_result = krotov.optimize_pulses(
    objectives,
    pulse_options,
    tlist,
    iter_stop=20000,
    propagator=krotov.propagators.DensityMatrixODEPropagator(atol=1e-10,
                                                             rtol=1e-8),
    chi_constructor=chis_qubit,
    info_hook=krotov.info_hooks.chain(
        krotov.info_hooks.print_debug_information, print_qubit_error),
    check_convergence=krotov.convergence.Or(
        krotov.convergence.value_below('5e-3', name='J_T'),
        krotov.convergence.check_monotonic_error,
    ),
    store_all_pulses=True,
)

plot_iterations(opt_result)

opt_result

from numpy import linalg as npla

Esempio n. 10
0
    def optimize(self):
        # We can now call any Python lib to
        # perform pulse optimization (marshalling the options/parameters if required)
        # For example, one can use Qutip pulse optimization:
        # Notes about data types:
        # - targerU: flatten (row-by-row) U matrix into a 1-D array of complex numbers
        # - H0: string-type representation of the static Hamiltonian:
        # e.g.: 0.123 Z0Z1
        # - Hops: array of strings represent terms on the Hamiltonian which can be controlled.
        # Depending on the specific library we use for pulse optimization,
        # we may need to marshal these data types accordingly.
        # Run the optimization

        H = self.construct_hamiltonian()
        tlist = np.arange(0.0, self.tMax, self.dt)

        # TODO: this should be an IR transformation option
        def S(t):
            """Shape function for the field update"""
            return krotov.shapes.flattop(
                t,
                t_start=0,
                t_stop=self.tMax,
                t_rise=self.tMax / self.rise_fall_coeff,
                t_fall=self.tMax / self.rise_fall_coeff,
                func=self.func_name)

        pulse_options = {H[1][1]: dict(lambda_a=self.lambda_a, update_shape=S)}
        print('Krotov: Target Unitary Object:')
        print(self.targetObj())

        objectives = krotov.gate_objectives(
            # Target is the unitary: i.e. transform all states -> expected result.
            basis_states=self.logical_basis(),
            gate=self.targetObj(),
            H=H)

        opt_result = krotov.optimize_pulses(
            objectives,
            pulse_options,
            tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_ss,
            info_hook=krotov.info_hooks.print_table(
                J_T=krotov.functionals.J_T_ss),
            check_convergence=krotov.convergence.Or(
                krotov.convergence.value_below('1e-3', name='J_T'),
                krotov.convergence.check_monotonic_error,
            ),
            store_all_pulses=True,
        )

        plotFile = self.plot_control_field_iterations(opt_result)
        print(opt_result)
        print('*************************************************')
        print('**Plot of control field iterations is saved to:**')
        print(plotFile)
        print('*************************************************')

        pulse = opt_result.optimized_controls[0]
        return (0.0, pulse)
Esempio n. 11
0
def test_reject_invalid_shapes():
    """Test that invalid control shapes are rejected"""
    H0 = qutip.Qobj(0.5 * np.diag([-1, 1]))
    H1 = qutip.Qobj(np.mat([[1, 2], [3, 4]]))

    psi0 = qutip.Qobj(np.array([1, 0]))
    psi1 = qutip.Qobj(np.array([0, 1]))

    def eps0(t, args):
        return 0.2

    H = [H0, [H1, eps0]]

    objectives = [krotov.Objective(initial_state=psi0, target=psi1, H=H)]

    tlist = np.linspace(0, 5, 500)

    def S_complex(t):
        """Shape function for the field update"""
        return 1j * krotov.shapes.flattop(
            t, t_start=0, t_stop=5, t_rise=0.3, t_fall=0.3, func='sinsq'
        )

    def S_negative(t):
        """Shape function for the field update"""
        return -1 * krotov.shapes.flattop(
            t, t_start=0, t_stop=5, t_rise=0.3, t_fall=0.3, func='sinsq'
        )

    def S_large(t):
        """Shape function for the field update"""
        return 2 * krotov.shapes.flattop(
            t, t_start=0, t_stop=5, t_rise=0.3, t_fall=0.3, func='sinsq'
        )

    with pytest.raises(ValueError) as exc_info:
        pulse_options = {H[1][1]: dict(lambda_a=5, update_shape=S_complex)}
        krotov.optimize_pulses(
            objectives,
            pulse_options,
            tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            iter_stop=0,
        )
    assert 'must be real-valued' in str(exc_info.value)

    with pytest.raises(ValueError) as exc_info:
        pulse_options = {H[1][1]: dict(lambda_a=5, update_shape=S_negative)}
        krotov.optimize_pulses(
            objectives,
            pulse_options,
            tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            iter_stop=0,
        )
    assert 'must have values in the range [0, 1]' in str(exc_info.value)

    with pytest.raises(ValueError) as exc_info:
        pulse_options = {H[1][1]: dict(lambda_a=5, update_shape=S_large)}
        krotov.optimize_pulses(
            objectives,
            pulse_options,
            tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            iter_stop=0,
        )
    assert 'must have values in the range [0, 1]' in str(exc_info.value)
Esempio n. 12
0
def test_continue_optimization(
    simple_state_to_state_system, request, tmpdir, caplog
):
    """Big integration test for a simple optimization, with various
    uses of `continue_from`. This covers a lot of edge cases not covered by the
    example notebooks.
    """
    objectives, pulse_options, tlist = simple_state_to_state_system

    dumpfile = str(tmpdir.join("oct_result_{iter:03d}.dump"))
    logfile = str(tmpdir.join("oct.log"))
    testdir = os.path.splitext(request.module.__file__)[0]
    logfile_expected = os.path.join(testdir, 'oct.log')

    with open(logfile, 'w', encoding='utf8') as log_fh:

        # initial optimization
        with caplog.at_level(logging.WARNING):
            oct_result1 = krotov.optimize_pulses(
                objectives,
                pulse_options=pulse_options,
                tlist=tlist,
                propagator=krotov.propagators.expm,
                chi_constructor=krotov.functionals.chis_re,
                store_all_pulses=True,
                info_hook=krotov.info_hooks.print_table(
                    J_T=krotov.functionals.J_T_re, out=log_fh
                ),
                check_convergence=krotov.convergence.Or(
                    krotov.convergence.check_monotonic_error,
                    krotov.convergence.dump_result(dumpfile, every=2),
                ),
                iter_stop=3,
                skip_initial_forward_propagation=True,
                # not officially supported, but should work in this case
            )
        assert (
            "You should not use `skip_initial_forward_propagation`"
            in caplog.text
        )

        assert len(oct_result1.iters) == 4  # 0 ... 3
        assert len(oct_result1.iter_seconds) == 4
        assert len(oct_result1.info_vals) == 4
        assert len(oct_result1.all_pulses) == 4
        assert len(oct_result1.states) == 1
        assert "3 iterations" in oct_result1.message

        # another 2 iterations
        oct_result2 = krotov.optimize_pulses(
            objectives,
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            store_all_pulses=True,
            info_hook=krotov.info_hooks.print_table(
                J_T=krotov.functionals.J_T_re, out=log_fh
            ),
            check_convergence=krotov.convergence.Or(
                krotov.convergence.check_monotonic_error,
                krotov.convergence.dump_result(dumpfile, every=2),
            ),
            continue_from=oct_result1,
            iter_stop=5,
        )

        assert len(oct_result2.iters) == 6  # 0 ... 5
        assert len(oct_result2.iter_seconds) == 6
        assert len(oct_result2.info_vals) == 6
        assert len(oct_result2.all_pulses) == 6
        assert len(oct_result2.states) == 1
        assert "5 iterations" in oct_result2.message

        # and 2 more (skipping initial propagation)
        oct_result3 = krotov.optimize_pulses(
            objectives,
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            store_all_pulses=True,
            info_hook=krotov.info_hooks.print_table(
                J_T=krotov.functionals.J_T_re, out=log_fh
            ),
            check_convergence=krotov.convergence.Or(
                krotov.convergence.check_monotonic_error,
                krotov.convergence.dump_result(dumpfile, every=2),
            ),
            continue_from=oct_result2,
            iter_stop=7,
            skip_initial_forward_propagation=True,
        )

        assert len(oct_result3.iters) == 8  # 0 ... 7
        assert len(oct_result3.iter_seconds) == 8
        assert len(oct_result3.info_vals) == 8
        assert len(oct_result3.all_pulses) == 8
        assert len(oct_result3.states) == 1
        assert "7 iterations" in oct_result3.message

        # no-op: already anough iterations
        oct_result4 = krotov.optimize_pulses(
            objectives,
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            store_all_pulses=True,
            info_hook=krotov.info_hooks.print_table(
                J_T=krotov.functionals.J_T_re, out=log_fh
            ),
            check_convergence=krotov.convergence.Or(
                krotov.convergence.check_monotonic_error,
                krotov.convergence.dump_result(dumpfile, every=2),
            ),
            continue_from=oct_result3,
            iter_stop=5,  # < 7  in oct_result3
            skip_initial_forward_propagation=True,
        )

        assert len(oct_result4.iters) == 8  # 0 ... 7
        assert len(oct_result4.iter_seconds) == 8
        assert len(oct_result4.info_vals) == 8
        assert len(oct_result4.all_pulses) == 8
        assert len(oct_result4.states) == 1
        assert "7 iterations" in oct_result4.message

        assert (
            oct_result4.start_local_time_str
            == oct_result3.start_local_time_str
        )
        assert oct_result4.iters == oct_result3.iters
        assert oct_result4.message == oct_result3.message

    # fmt: off
    # check the combined log file
    if not os.path.isfile(logfile_expected):
        copyfile(logfile, logfile_expected)
    with open(logfile, encoding='utf8') as fh1, open(logfile_expected, encoding='utf8') as fh2:
        for line1 in fh1:
            line2 = next(fh2)
            assert line1[:65] == line2[:65]
    # fmt: on

    # continue from an incomplete dump file

    with caplog.at_level(logging.WARNING):
        result = krotov.result.Result.load(
            str(tmpdir.join("oct_result_004.dump"))
        )
    assert 'Result.objectives contains control placeholders' in caplog.text
    with pytest.raises(ValueError) as exc_info:
        oct_result5 = krotov.optimize_pulses(
            objectives,
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            store_all_pulses=True,
            check_convergence=krotov.convergence.Or(
                krotov.convergence.check_monotonic_error,
                krotov.convergence.dump_result(dumpfile, every=2),
            ),
            continue_from=result,
            iter_stop=7,
            skip_initial_forward_propagation=True,
        )
    assert "objectives must remain unchanged" in str(exc_info.value)
    result = krotov.result.Result.load(
        str(tmpdir.join("oct_result_004.dump")), objectives=objectives
    )
    assert result.iters[-1] == 4
    oct_result5 = krotov.optimize_pulses(
        objectives,
        pulse_options=pulse_options,
        tlist=tlist,
        propagator=krotov.propagators.expm,
        chi_constructor=krotov.functionals.chis_re,
        store_all_pulses=True,
        info_hook=krotov.functionals.J_T_re,
        check_convergence=krotov.convergence.Or(
            krotov.convergence.check_monotonic_error,
            krotov.convergence.dump_result(dumpfile, every=2),
        ),
        continue_from=result,
        iter_stop=7,
        skip_initial_forward_propagation=True,
    )
    assert oct_result5.iters == oct_result3.iters
    assert len(oct_result5.iter_seconds) == 8
    assert len(oct_result5.info_vals) == 8
    assert len(oct_result5.all_pulses) == 8
    assert "7 iterations" in oct_result5.message
    Δ = np.max(
        np.abs(
            oct_result5.optimized_controls[-1]
            - oct_result3.optimized_controls[-1]
        )
    )
    assert Δ < 1e-10

    # broken continuation: different number of objectives
    result_with_extra_objective = deepcopy(result)
    result_with_extra_objective.objectives.append(
        deepcopy(result.objectives[0])
    )
    with pytest.raises(ValueError) as exc_info:
        krotov.optimize_pulses(
            objectives,
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            continue_from=result_with_extra_objective,
        )
    assert "number of objectives must be the same" in str(exc_info.value)

    # broken continuation: different value for store_all_pulses
    with pytest.raises(ValueError) as exc_info:
        krotov.optimize_pulses(
            objectives,
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            continue_from=result,
            store_all_pulses=False,
        )
    assert "store_all_pulses parameter cannot be changed" in str(
        exc_info.value
    )

    # broken continuation: different time units
    result_with_scaled_tlist = deepcopy(result)
    result_with_scaled_tlist.objectives = result.objectives
    result_with_scaled_tlist.tlist *= 2
    with pytest.raises(ValueError) as exc_info:
        krotov.optimize_pulses(
            objectives,
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            continue_from=result_with_scaled_tlist,
            store_all_pulses=True,
        )
    assert "same time grid" in str(exc_info.value)

    # broken continuation: changed nt
    result_with_changed_nt = deepcopy(result)
    result_with_changed_nt.objectives = result.objectives
    result_with_changed_nt.tlist = np.linspace(0, 5, 1000)
    with pytest.raises(ValueError) as exc_info:
        krotov.optimize_pulses(
            objectives,
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            continue_from=result_with_changed_nt,
            store_all_pulses=True,
        )
    assert "same time grid" in str(exc_info.value)

    # incongruent controls
    result_with_incongruent_pulse = deepcopy(result)
    result_with_incongruent_pulse.objectives = result.objectives
    result_with_incongruent_pulse.optimized_controls[0] = np.stack(
        [result.optimized_controls[0], result.optimized_controls[0]]
    ).flatten()
    with pytest.raises(ValueError) as exc_info:
        krotov.optimize_pulses(
            objectives,
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            continue_from=result_with_incongruent_pulse,
            store_all_pulses=True,
        )
    assert "optimized_controls and tlist are incongruent" in str(
        exc_info.value
    )

    # passing complete garbage to `continue_from`
    with pytest.raises(ValueError) as exc_info:
        krotov.optimize_pulses(
            objectives,
            pulse_options=pulse_options,
            tlist=tlist,
            propagator=krotov.propagators.expm,
            chi_constructor=krotov.functionals.chis_re,
            continue_from=result.objectives[0],
            store_all_pulses=True,
        )
    assert "only possible from a Result object" in str(exc_info.value)
Esempio n. 13
0
plot_population(guess_dynamics[1])

pulse_options = {H[1][1]: dict(lambda_a=1, update_shape=S)}

opt_result = krotov.optimize_pulses(
    objectives,
    pulse_options,
    tlist,
    propagator=krotov.propagators.expm,
    chi_constructor=krotov.functionals.chis_re,
    info_hook=krotov.info_hooks.print_table(
        J_T=krotov.functionals.J_T_re,
        show_g_a_int_per_pulse=True,
        unicode=False,
    ),
    check_convergence=krotov.convergence.Or(
        krotov.convergence.value_below(1e-3, name='J_T'),
        krotov.convergence.delta_below(1e-5),
        krotov.convergence.check_monotonic_error,
    ),
    iter_stop=5,
    parallel_map=(
        krotov.parallelization.parallel_map,
        krotov.parallelization.parallel_map,
        krotov.parallelization.parallel_map_fw_prop_step,
    ),
)

plot_pulse(opt_result.optimized_controls[0], tlist)
plot_spectrum(opt_result.optimized_controls[0], tlist, xlim=(0, 40))