Source code for pyslsqp.save_and_load

import warnings
import numpy as np
try:
    import h5py
except ImportError:
    warnings.warn("h5py not found, saving and loading data disabled")
    h5py = None

def import_h5py_file(filepath):
    if h5py is None:
        raise ImportError("h5py not found, saving and loading data disabled")
    try:
        return h5py.File(filepath, 'r')
    except:
        raise FileNotFoundError(f"File {filepath} not found or not a valid h5py file.")
    
def save_iteration(file, iter, vars, out_dict):
    '''
    Save the data from one iteration to an active file.

    Parameters
    ----------
    file : str
        Loaded file.
    iter : int
        Iteration number.
    vars : list
        List of variable names to save.
    out_dict : dict
        Dictionary with variable names as keys and variable values as values.
    '''
    file.create_group('iter_' + str(iter))
    for var in vars:
        file[f'iter_{iter}'][var] = out_dict[var]
    

    


[docs]def load_variables(filepath, vars, itr_start=0, itr_end=-1, major_only=False): ''' Load specified variable iterates between ``itr_start`` and ``itr_end`` from the saved file. Returns a dictionary with the variable names as keys and list of variable iterates as values. Note the variables at ``itr_start`` and ``itr_end`` are included in the output. Parameters ---------- filepath : str Path to the saved file. vars : str or list Variable names to load from the saved file. itr_start : int, default=0 Starting iteration to load the variables from. Negative indices are allowed with -1 representing the last iteration and -2 representing the second last iteration and so on. itr_end : int, default=-1 Ending iteration to load the variables from. Negative indices are allowed with -1 representing the last iteration and -2 representing the second last iteration and so on. major_only : bool, default=False If True, only major iterations are loaded. If False, all iterations are loaded irrespective of major or line search iterations. Returns ------- out_data : dict Dictionary with variable names as keys and list of variable iterates as values. Examples -------- >>> import numpy as np >>> from pyslsqp import optimize >>> obj = lambda x: np.sum(x**2) >>> grad = lambda x: 2*x >>> xl = 0.0 >>> xu = np.array([1, 1]) >>> x0 = np.array([0.5, 0.5]) >>> results = optimize(x0, obj=obj, grad=grad, xl=xl, xu=xu, save_itr='major', save_vars=['objective', 'optimality', 'x']) # doctest: +ELLIPSIS No constraints defined. Running an unconstrained optimization problem... Optimization terminated successfully (Exit mode 0) Final objective value : 0.000000e+00 Final optimality : 0.000000e+00 Final feasibility : 0.000000e+00 Number of major iterations : 2 Number of function evaluations : 2 Number of derivative evaluations : 2 Average Derivative evaluation time : ... s per evaluation Average Function evaluation time : ... s per evaluation Total Function evaluation time : ... s [ ...%] Total Derivative evaluation time : ... s [ ...%] Optimizer time : ... s [ ...%] Processing time : ... s [ ...%] Visualization time : ... s [ 0.00%] Total optimization time : ... s [100.00%] Summary saved to : slsqp_summary.out Iteration data saved to : slsqp_recorder.hdf5 >>> from pyslsqp.postprocessing import load_variables >>> load_variables('slsqp_recorder.hdf5', ['objective', 'optimality', 'x[0]'], itr_start=0, itr_end=-1, major_only=True) {'objective': [0.5, 0.0, 0.0], 'optimality': [99.0, 0.0, 0.0], 'x[0]': [0.5, 0.0, 0.0]} ''' if not isinstance(filepath, str): raise ValueError("filepath must be a string.") if not isinstance(vars, (str, list)): raise ValueError("vars must be a string or a list of strings") if isinstance(vars, str): vars = [vars] if not all(isinstance(var, str) for var in vars): raise ValueError("vars must be a string or a list of strings") if not isinstance(itr_start, int): raise ValueError("itr_start must be an integer.") if not isinstance(itr_end, int): raise ValueError("itr_end must be an integer.") file = import_h5py_file(filepath) niter = len(file.keys()) - 2 # Number of iterations saved in the file [excludes 0th iteration and results] num_saves = len(file.keys()) - 1 # Number of iterations saved [includes 0th iteration but excludes results] if major_only: niter = file['results']['num_majiter'][()] if (-(niter+1) <= itr_start <= niter) and (-(niter+1) <= itr_end <= niter): start = itr_start * 1 if itr_start < 0: start = niter + itr_start + 1 end = itr_end * 1 if itr_end < 0: end = niter + itr_end + 1 if start > end: raise ValueError(f"itr_start index ({start}) must be less than itr_end index ({end}).") else: raise ValueError(f"itr_start {itr_start} and itr_end {itr_end} must be within bounds (>={-(niter+1)} and <={niter}).") out_data = {} for var in vars: if var.split('[')[0] not in file['iter_0'].keys(): raise ValueError(f"Variable {var} not found in the file.") out_data[var] = [] if major_only: for i in range(num_saves): if file[f'iter_{i}']['ismajor'][()] and file[f'iter_{i}']['majiter'][()] >= start: for var in vars: if '[' in var: name = var.split('[')[0] if name == 'jacobian': idx1, idx2 = map(int, var.split('[')[1].split(']')[0].split(',')) out_data[var].append(file[f'iter_{i}'][name][idx1, idx2]) else: idx = int(var.split('[')[1].split(']')[0]) out_data[var].append(file[f'iter_{i}'][name][idx]) else: out_data[var].append(file[f'iter_{i}'][var][()]) if file[f'iter_{i}']['majiter'][()] == end: break else: for i in range(start, end+1): for var in vars: if '[' in var: name = var.split('[')[0] if name == 'jacobian': idx1, idx2 = map(int, var.split('[')[1].split(']')[0].split(',')) out_data[var].append(file[f'iter_{i}'][name][idx1, idx2]) else: idx = int(var.split('[')[1].split(']')[0]) out_data[var].append(file[f'iter_{i}'][name][idx]) else: out_data[var].append(file[f'iter_{i}'][var][()]) file.close() return out_data
[docs]def load_results(filepath): ''' Load the results of optimization from the saved file as a dictionary. Parameters ---------- filepath : str Path to the saved file. Returns ------- out_data : dict Dictionary with optimization results. Examples -------- >>> import numpy as np >>> from pyslsqp import optimize >>> obj = lambda x: np.sum(x**2) >>> grad = lambda x: 2*x >>> xl = 0.0 >>> xu = np.array([1, 1]) >>> x0 = np.array([0.5, 0.5]) >>> results = optimize(x0, obj=obj, grad=grad, xl=xl, xu=xu, save_itr='major', save_vars=['objective', 'optimality', 'x']) # doctest: +ELLIPSIS No constraints defined. Running an unconstrained optimization problem... Optimization terminated successfully (Exit mode 0) Final objective value : 0.000000e+00 Final optimality : 0.000000e+00 Final feasibility : 0.000000e+00 Number of major iterations : 2 Number of function evaluations : 2 Number of derivative evaluations : 2 Average Derivative evaluation time : ... s per evaluation Average Function evaluation time : ... s per evaluation Total Function evaluation time : ... s [ ...%] Total Derivative evaluation time : ... s [ ...%] Optimizer time : ... s [ ...%] Processing time : ... s [ ...%] Visualization time : ... s [ 0.00%] Total optimization time : ... s [100.00%] Summary saved to : slsqp_summary.out Iteration data saved to : slsqp_recorder.hdf5 >>> from pyslsqp.postprocessing import load_results >>> load_results('slsqp_recorder.hdf5') # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS {'constraints': array([], dtype=float64), 'feasibility': 0.0, 'fev_time': ..., 'gev_time': ..., 'gradient': array([0., 0.]), 'jacobian': array([], shape=(0, 2), dtype=float64), 'message': 'Optimization terminated successfully', 'multipliers': array([], dtype=float64), 'nfev': 2, 'ngev': 2, 'num_majiter': 2, 'objective': 0.0, 'optimality': 0.0, 'optimizer_time': ..., 'processing_time': ..., 'save_filename': 'slsqp_recorder.hdf5', 'status': 0, 'success': True, 'summary_filename': 'slsqp_summary.out', 'total_time': ..., 'visualization_time': 0.0, 'x': array([0., 0.])} ''' file = import_h5py_file(filepath) result_dict = {} for key in file['results'].keys(): result_dict[key] = file['results'][key][()] if key in ['message', 'save_filename', 'summary_filename']: result_dict[key] = result_dict[key].decode('utf-8') file.close() return result_dict
[docs]def load_attributes(filepath): ''' Load the attributes of optimization from the saved file as a dictionary. Parameters ---------- filepath : str Path to the saved file. Returns ------- out_data : dict Dictionary with optimization attributes. Examples -------- >>> import numpy as np >>> from pyslsqp import optimize >>> obj = lambda x: np.sum(x**2) >>> grad = lambda x: 2*x >>> xl = 0.0 >>> xu = np.array([1, 1]) >>> x0 = np.array([0.5, 0.5]) >>> results = optimize(x0, obj=obj, grad=grad, xl=xl, xu=xu, save_itr='major', save_vars=['objective', 'optimality', 'x']) # doctest: +ELLIPSIS No constraints defined. Running an unconstrained optimization problem... Optimization terminated successfully (Exit mode 0) Final objective value : 0.000000e+00 Final optimality : 0.000000e+00 Final feasibility : 0.000000e+00 Number of major iterations : 2 Number of function evaluations : 2 Number of derivative evaluations : 2 Average Derivative evaluation time : ... s per evaluation Average Function evaluation time : ... s per evaluation Total Function evaluation time : ... s [ ...%] Total Derivative evaluation time : ... s [ ...%] Optimizer time : ... s [ ...%] Processing time : ... s [ ...%] Visualization time : ... s [ 0.00%] Total optimization time : ... s [100.00%] Summary saved to : slsqp_summary.out Iteration data saved to : slsqp_recorder.hdf5 >>> from pyslsqp.postprocessing import load_attributes >>> load_attributes('slsqp_recorder.hdf5') # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS {'acc': 1e-06, 'con_scaler': 1.0, 'finite_diff_abs_step': 'None (undefined)', 'finite_diff_rel_step': 1.4901161193847656e-08, 'hot_start': False, 'iprint': 1, 'keep_plot_open': False, 'load_filename': 'None (undefined)', 'm': 0, 'maxiter': 100, 'meq': 0, 'n': 2, 'obj_scaler': 1.0, 'save_figname': 'slsqp_plot.pdf', 'save_filename': 'slsqp_recorder.hdf5', 'save_itr': 'major', 'save_vars': ['objective', 'optimality', 'x'], 'summary_filename': 'slsqp_summary.out', 'visualize': False, 'visualize_vars': ['objective', 'optimality', 'feasibility'], 'warm_start': False, 'x0': array([0.5, 0.5]), 'x_scaler': 1.0, 'xl': 0.0, 'xu': array([1, 1])} ''' file = import_h5py_file(filepath) attr_dict = {} for key in file.attrs.keys(): attr_dict[key] = file.attrs[key] if key in ['save_vars', 'visualize_vars']: attr_dict[key] = list(file.attrs[key]) file.close() return attr_dict
if __name__ == "__main__": import doctest doctest.testmod()