print(__doc__)
import numpy as np
import os
import sys

"""
Explanation: Store and load skopt optimization results
Mikhail Pak, October 2016.
Reformatted by Holger Nahrstaedt 2020
.. currentmodule:: skopt
Problem statement
We often want to store optimization results in a file. This can be useful,
for example,

if you want to share your results with colleagues;
if you want to archive and/or document your work;
or if you want to postprocess your results in a different Python instance or on an another computer.

The process of converting an object into a byte stream that can be stored in
a file is called serialization.
Conversely, deserialization means loading an object from a byte stream.
Warning: Deserialization is not secure against malicious or erroneous
code. Never load serialized data from untrusted or unauthenticated sources!
End of explanation
"""


from skopt import gp_minimize
noise_level = 0.1


def obj_fun(x, noise_level=noise_level):
    return np.sin(5 * x[0]) * (1 - np.tanh(x[0] ** 2)) + np.random.randn() \
        * noise_level

res = gp_minimize(obj_fun,            # the function to minimize
                  [(-2.0, 2.0)],      # the bounds on each dimension of x
                  x0=[0.],            # the starting point
                  acq_func="LCB",     # the acquisition function (optional)
                  n_calls=15,         # the number of evaluations of f including at x0
                  n_random_starts=3,  # the number of random initial points
                  random_state=777)

"""
Explanation: Simple example
We will use the same optimization problem as in the
sphx_glr_auto_examples_bayesian-optimization.py notebook:
End of explanation
"""


from skopt import dump, load

dump(res, 'result.pkl')

"""
Explanation: As long as your Python session is active, you can access all the
optimization results via the res object.
So how can you store this data in a file? skopt conveniently provides
functions :class:skopt.dump and :class:skopt.load that handle this for you.
These functions are essentially thin wrappers around the
joblib &lt;https://joblib.readthedocs.io/en/latest/&gt;_ module's :obj:joblib.dump and :obj:joblib.load.
We will now show how to use :class:skopt.dump and :class:skopt.load for storing
and loading results.
Using skopt.dump() and skopt.load()
For storing optimization results into a file, call the :class:skopt.dump
function:
End of explanation
"""


res_loaded = load('result.pkl')

res_loaded.fun

"""
Explanation: And load from file using :class:skopt.load:
End of explanation
"""


dump(res, 'result.gz', compress=9)

from os.path import getsize
print('Without compression: {} bytes'.format(getsize('result.pkl')))
print('Compressed with gz:  {} bytes'.format(getsize('result.gz')))

"""
Explanation: You can fine-tune the serialization and deserialization process by calling
:class:skopt.dump and :class:skopt.load with additional keyword arguments. See the
joblib &lt;https://joblib.readthedocs.io/en/latest/&gt;_ documentation
:obj:joblib.dump and
:obj:joblib.load for the additional parameters.
For instance, you can specify the compression algorithm and compression
level (highest in this case):
End of explanation
"""


dump(res, 'result_without_objective.pkl', store_objective=False)

"""
Explanation: Unserializable objective functions
Notice that if your objective function is non-trivial (e.g. it calls MATLAB
engine from Python), it might be not serializable and :class:skopt.dump will
raise an exception when you try to store the optimization results.
In this case you should disable storing the objective function by calling
:class:skopt.dump with the keyword argument store_objective=False:
End of explanation
"""


res_loaded_without_objective = load('result_without_objective.pkl')

print('Loaded object: ', res_loaded_without_objective.specs['args'].keys())
print('Local variable:', res.specs['args'].keys())

"""
Explanation: Notice that the entry 'func' is absent in the loaded object but is still
present in the local variable:
End of explanation
"""


del res.specs['args']['func']

dump(res, 'result_without_objective_2.pkl')

"""
Explanation: Possible problems

Python versions incompatibility: In general, objects serialized in
  Python 2 cannot be deserialized in Python 3 and vice versa.
Security issues: Once again, do not load any files from untrusted
  sources.
Extremely large results objects: If your optimization results object

is extremely large, calling :class:skopt.dump with store_objective=False might
cause performance issues. This is due to creation of a deep copy without the
objective function. If the objective function it is not critical to you, you
can simply delete it before calling :class:skopt.dump. In this case, no deep
copy is created:
End of explanation
"""


