diff --git a/.gitignore b/.gitignore index d828103..37f9887 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ taurus taurus_b results .data +/python/otto_motor/.data_timing/ +/python/otto_motor/Scans/ diff --git a/python/otto_motor/bayes.py b/python/otto_motor/bayes.py new file mode 100644 index 0000000..974798a --- /dev/null +++ b/python/otto_motor/bayes.py @@ -0,0 +1,126 @@ +from bayes_opt import BayesianOptimization +import figsaver as fs +import plot_utils as pu +from hiro_models.one_qubit_model import StocProcTolerances +from hiro_models.otto_cycle import OttoEngine +import hiro_models.model_auxiliary as aux +import numpy as np +import qutip as qt +import utilities as ut +import stocproc +import matplotlib.pyplot as plt +import otto_utilities as ot + +import ray +ray.shutdown() + +#ray.init(address='auto') +ray.init() +from hops.util.logging_setup import logging_setup +import logging +logging_setup(logging.INFO) +plt.rcParams['figure.figsize'] = (12,4) + +def timings(τ_c, τ_i, percent_overlap=0): + τ_cI = τ_c * (1-percent_overlap) + + τ_thI = (1 - 2 * τ_cI) / 2 + τ_th = (1 - 2 * τ_c) / 2 + τ_i_on = (τ_thI - 2*τ_i) + timings_H = (0, τ_c, τ_c + τ_th, 2*τ_c + τ_th) + + timings_L_hot = (τ_cI, τ_cI + τ_i, τ_cI + τ_i + τ_i_on, τ_cI + 2 * τ_i + τ_i_on) + + timings_L_cold = tuple(time + timings_H[2] for time in timings_L_hot) + + return timings_H, (timings_L_cold, timings_L_hot) + +τ_mod, τ_I = 0.15, 0.15 +(p_H, p_L) = timings(τ_mod, τ_I, 0) +prototype = OttoEngine( + δ=[0.4, 0.4], + ω_c=[2, 2], + ψ_0=qt.basis([2], [1]), + description=f"Classic Cycle", + k_max=3, + bcf_terms=[4] * 2, + truncation_scheme="simplex", + driving_process_tolerances=[StocProcTolerances(1e-3, 1e-3)] * 2, + thermal_process_tolerances=[StocProcTolerances(1e-3, 1e-3)] * 2, + T=[0.5, 4], + therm_methods=["tanhsinh", "tanhsinh"], + Δ=1, + num_cycles=3, + Θ=1.5 / 0.05, + dt=0.01, + timings_H=p_H, + timings_L=p_L, + streaming_mode=True, + shift_to_resonance=(False, True), + L_shift=(0, 0), +) + + +def make_cycle(shift_c, shift_h): + crazy_model = prototype.copy() + (p_H, p_L) = timings(τ_mod, τ_I, 1) + p_L = [list(timings) for timings in p_L] + p_L[1][2] += τ_I + p_L[1][3] += τ_I + p_L[0][0] -= τ_I + p_L[0][1] -= τ_I + crazy_model.timings_H = p_H + crazy_model.timings_L = tuple(tuple(timing) for timing in p_L) + crazy_model.L_shift = (shift_c + τ_mod, shift_h) + crazy_model.description = "Full Overlap with Shift" + + return crazy_model + +def objective(shift_c, shift_h, N=500): + print(shift_c, shift_h) + model = make_cycle(shift_c, shift_h) + ot.integrate_online(model, N) + + return -1 * model.power(steady_idx=-2).value + +# Bounded region of parameter space +from bayes_opt.logger import JSONLogger +from bayes_opt.event import Events +from bayes_opt.util import load_logs +pbounds = {"shift_c": (-0.1, 0.5), "shift_h": (-0.1, 0.5)} + +optimizer = BayesianOptimization( + f=objective, + pbounds=pbounds, + random_state=1, +) +# load_logs(optimizer, logs=["./logs.json"]); + +# logger = JSONLogger(path="./logs.json") +# optimizer.subscribe(Events.OPTIMIZATION_STEP, logger) +optimizer.probe( + params={"shift_c": 0.15, "shift_h": 0.15}, + lazy=True, +) + +optimizer.maximize( + init_points=4, + n_iter=100, +) + +with aux.model_db(data_path=".data") as db: + model = db["05a638feb440fd913b41a5be74fbdd5a6cc358f2b556e61e4005b8539ca15115"]["model_config"] +c=make_cycle(0.401813980810373, 0.302982197157591) +# aux.import_results( +# other_data_path = "taurus/.data", +# results_path = "./results", +# other_results_path = "taurus/results", +# interactive = False, +# models_to_import = [model], +# force = False, +# ) +#ot.plot_cycle(c) +#model.L_shift +t, total = ot.val_relative_to_steady(model, model.total_energy_from_power(), steady_idx=-2) +pu.plot_with_σ(t, total) +model.power(steady_idx=-2) diff --git a/python/otto_motor/bayesian_optimization.org b/python/otto_motor/bayesian_optimization.org new file mode 100644 index 0000000..57b5c03 --- /dev/null +++ b/python/otto_motor/bayesian_optimization.org @@ -0,0 +1,391 @@ +#+PROPERTY: header-args :session otto_bayes :kernel python :pandoc no :async yes :tangle no + +Motivated by the striking result [[id:e8e99290-bd53-4d68-89f4-f903d6cf230c][from over here]] we would like to find +some approximation of the optimal cycle. + +Bayesian optimization allows us to optimize towards the result with as +few cycles as possible. + +* Boilerplate +#+name: boilerplate +#+begin_src jupyter-python :results none + from bayes_opt import BayesianOptimization + import figsaver as fs + import plot_utils as pu + from hiro_models.one_qubit_model import StocProcTolerances + from hiro_models.otto_cycle import OttoEngine + import hiro_models.model_auxiliary as aux + import numpy as np + import qutip as qt + import utilities as ut + import stocproc + import matplotlib.pyplot as plt + import otto_utilities as ot + + import ray + ray.shutdown() + + #ray.init(address='auto') + ray.init() + from hops.util.logging_setup import logging_setup + import logging + logging_setup(logging.INFO) + plt.rcParams['figure.figsize'] = (12,4) + + def timings(τ_c, τ_i, percent_overlap=0): + τ_cI = τ_c * (1-percent_overlap) + + τ_thI = (1 - 2 * τ_cI) / 2 + τ_th = (1 - 2 * τ_c) / 2 + τ_i_on = (τ_thI - 2*τ_i) + timings_H = (0, τ_c, τ_c + τ_th, 2*τ_c + τ_th) + + timings_L_hot = (τ_cI, τ_cI + τ_i, τ_cI + τ_i + τ_i_on, τ_cI + 2 * τ_i + τ_i_on) + + timings_L_cold = tuple(time + timings_H[2] for time in timings_L_hot) + + return timings_H, (timings_L_cold, timings_L_hot) +#+end_src + +* First Attempt: Only shifting the coupling to the bath +:PROPERTIES: +:header-args: :tangle bayes.py :session simple_bayes :noweb yes :async yes +:END: + +#+begin_src jupyter-python :results none + <> +#+end_src + +To keep the number of parameters down, we'll shift the bath coupling +without changing the coupling length. Later, an asymmetric approach +with more parameters may be attempted. + +#+begin_src jupyter-python + τ_mod, τ_I = 0.15, 0.15 + (p_H, p_L) = timings(τ_mod, τ_I, 0) + prototype = OttoEngine( + δ=[0.4, 0.4], + ω_c=[2, 2], + ψ_0=qt.basis([2], [1]), + description=f"Classic Cycle", + k_max=3, + bcf_terms=[4] * 2, + truncation_scheme="simplex", + driving_process_tolerances=[StocProcTolerances(1e-3, 1e-3)] * 2, + thermal_process_tolerances=[StocProcTolerances(1e-3, 1e-3)] * 2, + T=[0.5, 4], + therm_methods=["tanhsinh", "tanhsinh"], + Δ=1, + num_cycles=3, + Θ=1.5 / 0.05, + dt=0.01, + timings_H=p_H, + timings_L=p_L, + streaming_mode=True, + shift_to_resonance=(False, True), + L_shift=(0, 0), + ) + + + def make_cycle(shift_c, shift_h): + crazy_model = prototype.copy() + (p_H, p_L) = timings(τ_mod, τ_I, 1) + p_L = [list(timings) for timings in p_L] + p_L[1][2] += τ_I + p_L[1][3] += τ_I + p_L[0][0] -= τ_I + p_L[0][1] -= τ_I + crazy_model.timings_H = p_H + crazy_model.timings_L = tuple(tuple(timing) for timing in p_L) + crazy_model.L_shift = (shift_c + τ_mod, shift_h) + crazy_model.description = "Full Overlap with Shift" + + return crazy_model +#+end_src + +#+RESULTS: + + +This is the best known config so far. +#+begin_src jupyter-python :tangle no + #ot.plot_cycle(make_cycle(τ_mod, τ_mod)) + ot.plot_cycle(make_cycle(.4018, .303)) +#+end_src + +#+RESULTS: +:RESULTS: +|
| | +[[file:./.ob-jupyter/fb246ee7bdc3bb9cd2ff2e98dc02af2122dc7688.svg]] +:END: + + +Now we define our objective function +#+begin_src jupyter-python :results none + def objective(shift_c, shift_h, N=500): + print(shift_c, shift_h) + model = make_cycle(shift_c, shift_h) + ot.integrate_online(model, N) + + return -1 * model.power(steady_idx=-2).value +#+end_src + + +... and run the optimizer. +#+begin_src jupyter-python + # Bounded region of parameter space + from bayes_opt.logger import JSONLogger + from bayes_opt.event import Events + from bayes_opt.util import load_logs + pbounds = {"shift_c": (-0.1, 0.5), "shift_h": (-0.1, 0.5)} + + optimizer = BayesianOptimization( + f=objective, + pbounds=pbounds, + random_state=1, + ) + # load_logs(optimizer, logs=["./logs.json"]); + + # logger = JSONLogger(path="./logs.json") + # optimizer.subscribe(Events.OPTIMIZATION_STEP, logger) + optimizer.probe( + params={"shift_c": 0.15, "shift_h": 0.15}, + lazy=True, + ) + + optimizer.maximize( + init_points=4, + n_iter=100, + ) +#+end_src + +#+RESULTS: +:RESULTS: +#+begin_example + [INFO hops.core.integration 264609] Choosing the nonlinear integrator. + [INFO root 264609] Starting analysis process. + | iter | target | shift_c | shift_h | + ------------------------------------------------- + [INFO root 264609] Started analysis process with pid 268966. + [INFO hops.core.hierarchy_data 264609] Creating the streaming fifo at: /home/hiro/Documents/Projects/UNI/master/eflow_paper/python/otto_motor/results_49165931924fa512ce3e8357ea5e629d22c808f8070c3949c830b5948e16ecf2.fifo + [INFO hops.core.integration 264609] Using 16 integrators. + [INFO hops.core.integration 264609] Some 0 trajectories have to be integrated. + [INFO hops.core.integration 264609] Using 165 hierarchy states. + 0it [00:00, ?it/s] + [INFO hops.core.integration 264609] Choosing the nonlinear integrator. + [INFO root 264609] Starting analysis process. + | 1  | -0.0  | 0.1502  | 0.3322  | + [INFO root 264609] Started analysis process with pid 268971. + [INFO hops.core.hierarchy_data 264609] Creating the streaming fifo at: /home/hiro/Documents/Projects/UNI/master/eflow_paper/python/otto_motor/results_c369b7aefe5503442c698bdb4de83a3f7b1c88ae9cdf1456153e9087c7d9fc2f.fifo + [INFO hops.core.integration 264609] Using 16 integrators. + [INFO hops.core.integration 264609] Some 0 trajectories have to be integrated. + [INFO hops.core.integration 264609] Using 165 hierarchy states. + 0it [00:00, ?it/s] + [INFO hops.core.integration 264609] Choosing the nonlinear integrator. + [INFO root 264609] Starting analysis process. + | 2  | -0.01777  | -0.09993  | 0.0814  | + [INFO root 264609] Started analysis process with pid 268976. + [INFO hops.core.hierarchy_data 264609] Creating the streaming fifo at: /home/hiro/Documents/Projects/UNI/master/eflow_paper/python/otto_motor/results_f6fa2d1ea82b839e46df4013b731e3476b80119a206ef196c9a10f9d625066e4.fifo + [INFO hops.core.integration 264609] Using 16 integrators. + [INFO hops.core.integration 264609] Some 0 trajectories have to be integrated. + [INFO hops.core.integration 264609] Using 165 hierarchy states. + 0it [00:00, ?it/s] + [INFO hops.core.integration 264609] Choosing the nonlinear integrator. + [INFO root 264609] Starting analysis process. + | 3  | -0.001374 | -0.01195  | -0.0446  | + [INFO root 264609] Started analysis process with pid 268981. + [INFO hops.core.hierarchy_data 264609] Creating the streaming fifo at: /home/hiro/Documents/Projects/UNI/master/eflow_paper/python/otto_motor/results_1779c2e0c81b26e68f18a2298525a84c531fd36c909e6fddc0e41f3b78a02ee1.fifo + [INFO hops.core.integration 264609] Using 16 integrators. + [INFO hops.core.integration 264609] Some 0 trajectories have to be integrated. + [INFO hops.core.integration 264609] Using 165 hierarchy states. + 0it [00:00, ?it/s] + [INFO hops.core.integration 264609] Choosing the nonlinear integrator. + [INFO root 264609] Starting analysis process. + | 4  | -0.0  | 0.01176  | 0.1073  | + [INFO root 264609] Started analysis process with pid 269016. + [INFO hops.core.hierarchy_data 264609] Creating the streaming fifo at: /home/hiro/Documents/Projects/UNI/master/eflow_paper/python/otto_motor/results_4c924d501d086d896c1552881c628116ad03c2100d680cb6ef5cc81dd4b2a2a6.fifo + [INFO hops.core.integration 264609] Using 16 integrators. + [INFO hops.core.integration 264609] Some 0 trajectories have to be integrated. + [INFO hops.core.integration 264609] Using 165 hierarchy states. + 0it [00:00, ?it/s] + [INFO hops.core.integration 264609] Choosing the nonlinear integrator. + [INFO root 264609] Starting analysis process. + | 5  | -0.02987  | -0.03473  | 0.1213  | + [INFO root 264609] Started analysis process with pid 269051. + [INFO hops.core.hierarchy_data 264609] Creating the streaming fifo at: /home/hiro/Documents/Projects/UNI/master/eflow_paper/python/otto_motor/results_d8ae65a827650db8ac3da6b4bce3faef161be342650b8238d59244d1ec5f69bb.fifo + [INFO hops.core.integration 264609] Using 16 integrators. + [INFO hops.core.integration 264609] Some 0 trajectories have to be integrated. + [INFO hops.core.integration 264609] Using 165 hierarchy states. + 0it [00:00, ?it/s] + [INFO hops.core.integration 264609] Choosing the nonlinear integrator. + [INFO root 264609] Starting analysis process. + | 6  | 0.02888  | 0.398  | 0.2961  | + [INFO root 264609] Started analysis process with pid 269086. + [INFO hops.core.hierarchy_data 264609] Creating the streaming fifo at: /home/hiro/Documents/Projects/UNI/master/eflow_paper/python/otto_motor/results_97c6b5378d143228f25a568548ca12c00f145bef0320218d249394cdf75795d6.fifo + [INFO hops.core.integration 264609] Using 16 integrators. + [INFO hops.core.integration 264609] Some 0 trajectories have to be integrated. + [INFO hops.core.integration 264609] Using 165 hierarchy states. + 0it [00:00, ?it/s] + [INFO hops.core.integration 264609] Choosing the nonlinear integrator. + [INFO root 264609] Starting analysis process. + | 7  | -0.004074 | -0.01042  | 0.2773  | + [INFO root 264609] Started analysis process with pid 269121. + [INFO hops.core.hierarchy_data 264609] Creating the streaming fifo at: /home/hiro/Documents/Projects/UNI/master/eflow_paper/python/otto_motor/results_a5de368bb5ac8323883a97b14f8dc14ef84d021a9134152bd2e73a3bd4760052.fifo + [INFO hops.core.integration 264609] Using 16 integrators. + [INFO hops.core.integration 264609] Some 0 trajectories have to be integrated. + [INFO hops.core.integration 264609] Using 165 hierarchy states. + 0it [00:00, ?it/s] + [INFO hops.core.integration 264609] Choosing the nonlinear integrator. + [INFO root 264609] Starting analysis process. + | 8  | -0.04096  | -0.04836  | 0.3552  | + [INFO root 264609] Started analysis process with pid 269156. + [INFO hops.core.hierarchy_data 264609] Creating the streaming fifo at: /home/hiro/Documents/Projects/UNI/master/eflow_paper/python/otto_motor/results_c981612944d44cef75b47e1c972bc3e1b979a39b180aeceea5746a3cc49138b9.fifo + [INFO hops.core.integration 264609] Using 16 integrators. + [INFO hops.core.integration 264609] Some 0 trajectories have to be integrated. + [INFO hops.core.integration 264609] Using 165 hierarchy states. + 0it [00:00, ?it/s] + [INFO hops.core.integration 264609] Choosing the nonlinear integrator. + [INFO root 264609] Starting analysis process. + | 9  | 7.841e-06 | 0.1374  | -0.003125 | + [INFO root 264609] Started analysis process with pid 269191. + [INFO hops.core.hierarchy_data 264609] Creating the streaming fifo at: /home/hiro/Documents/Projects/UNI/master/eflow_paper/python/otto_motor/results_ad69b9cace9b50f1041832e082421a317348dcbb5bfda0a3e6b8efb7717c92e8.fifo + [INFO hops.core.integration 264609] Using 16 integrators. + [INFO hops.core.integration 264609] Some 610 trajectories have to be integrated. + [INFO hops.core.integration 264609] Using 165 hierarchy states. + 0% 0/610 [00:00 16 optimizer.maximize( +  17  init_points=4, +  18  n_iter=8, +  19 ) + + File /nix/store/vkzza81mzwyk5br1c6cm67g48xycvmvl-python3-3.9.15-env/lib/python3.9/site-packages/bayes_opt/bayesian_optimization.py:311, in BayesianOptimization.maximize(self, init_points, n_iter, acquisition_function, acq, kappa, kappa_decay, kappa_decay_delay, xi, **gp_params) +  309 x_probe = self.suggest(util) +  310 iteration += 1 + --> 311 self.probe(x_probe, lazy=False) +  313 if self._bounds_transformer and iteration > 0: +  314 # The bounds transformer should only modify the bounds after +  315 # the init_points points (only for the true iterations) +  316 self.set_bounds( +  317 self._bounds_transformer.transform(self._space)) + + File /nix/store/vkzza81mzwyk5br1c6cm67g48xycvmvl-python3-3.9.15-env/lib/python3.9/site-packages/bayes_opt/bayesian_optimization.py:208, in BayesianOptimization.probe(self, params, lazy) +  206 self._queue.add(params) +  207 else: + --> 208 self._space.probe(params) +  209 self.dispatch(Events.OPTIMIZATION_STEP) + + File /nix/store/vkzza81mzwyk5br1c6cm67g48xycvmvl-python3-3.9.15-env/lib/python3.9/site-packages/bayes_opt/target_space.py:236, in TargetSpace.probe(self, params) +  234 x = self._as_array(params) +  235 params = dict(zip(self._keys, x)) + --> 236 target = self.target_func(**params) +  238 if self._constraint is None: +  239 self.register(x, target) + + Cell In[4], line 3, in objective(shift_c, shift_h, N) +  1 def objective(shift_c, shift_h, N=1000): +  2 model = make_cycle(shift_c, shift_h) + ----> 3 ot.integrate_online(model, N) +  5 return -1 * model.power(steady_idx=-1).value + + File ~/Documents/Projects/UNI/master/eflow_paper/python/otto_motor/otto_utilities.py:155, in integrate_online(model, n, stream_folder, **kwargs) +  154 def integrate_online(model, n, stream_folder=None, **kwargs): + --> 155 aux.integrate( +  156  model, +  157  n, +  158  stream_file=("" if stream_folder is None else stream_folder) +  159  + f"results_{model.hexhash}.fifo", +  160  analyze=True, +  161  **kwargs, +  162  ) + + File ~/src/two_qubit_model/hiro_models/model_auxiliary.py:201, in integrate(model, n, data_path, clear_pd, single_process, stream_file, analyze, results_path, analyze_kwargs) +  199 supervisor.integrate_single_process(clear_pd) +  200 else: + --> 201 supervisor.integrate(clear_pd) +  203 cleanup(0) + + File ~/src/hops/hops/core/signal_delay.py:87, in sig_delay.__exit__(self, exc_type, exc_val, exc_tb) +  84 if len(self.sigh.sigs_caught) > 0 and self.handler is not None: +  85 self.handler(self.sigh.sigs_caught) + ---> 87 self._restore() + + File ~/src/hops/hops/core/signal_delay.py:68, in sig_delay._restore(self) +  66 for i, s in enumerate(self.sigs): +  67 signal.signal(s, self.old_handlers[i]) + ---> 68 self.sigh.emit() + + File ~/src/hops/hops/core/signal_delay.py:42, in SigHandler.emit(self) +  40 for s in self.sigs_caught: +  41 log.info("emit signal '{}'".format(SIG_MAP[s])) + ---> 42 os.kill(os.getpid(), s) + + KeyboardInterrupt: +#+end_example +:END: + +#+begin_src jupyter-python + with aux.model_db(data_path=".data") as db: + model = db["05a638feb440fd913b41a5be74fbdd5a6cc358f2b556e61e4005b8539ca15115"]["model_config"] + c=make_cycle(0.401813980810373, 0.302982197157591) + # aux.import_results( + # other_data_path = "taurus/.data", + # results_path = "./results", + # other_results_path = "taurus/results", + # interactive = False, + # models_to_import = [model], + # force = False, + # ) + #ot.plot_cycle(c) + #model.L_shift + t, total = ot.val_relative_to_steady(model, model.total_energy_from_power(), steady_idx=-2) + pu.plot_with_σ(t, total) + model.power(steady_idx=-2) +#+end_src + +#+RESULTS: +:RESULTS: +: EnsembleValue([(10000, 3.3527328716046976e-05, 5.0274219343398344e-05)]) +[[file:./.ob-jupyter/bb13221d6e76ccdb1e7068e301948add99c2104a.svg]] +:END: