def score_function_ellipsoid_maker(param = 0.05, sigma=1.5): """ param: decay rate of the exponentials """ eta = np.linalg.norm(target_state-saddle_state)/np.linalg.norm(target_state-initial_state) covariance_matrix_start, quad_form_initial, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function(force_matrix, initial_state, sigma, noise_matrix=noise_matrix) covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function(force_matrix, target_state, sigma, noise_matrix=noise_matrix) def score_function(v): return eta - eta*np.exp(-param*quad_form_initial(v))+(1-eta)*np.exp(-param*quad_form_target(v)) return score_function
def remap_score_function_ell(score_function, force_matrix, equilibrium_point, noise): """ This function warps the score function so that the target set is the 0.95-confidence ellipsoid. return the score function and the associated threshold """ C, quad_form, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, equilibrium_point, noise, confidence=0.95, warning_threshold=1e-3) ellipsoid_array = ellipsoid_fun.get_ellipsoid_array( equilibrium_point, quad_form, level, bound) score_level = np.min( np.apply_along_axis(score_function, 1, ellipsoid_array)) def remapped_score_function(v): score = score_function(v) if score >= score_level: if ellipsoid_fun.ellipsoid_test(v, quad_form, level): return 1 else: return score_level else: return score return remapped_score_function, (1 - score_level) / 2
def score_function_composite_maker(filename='trajectory.hdf5', decay=4, param=0.01, sigma=1.5): custom_score_function = score_function_custom_maker(filename, decay) eta = np.linalg.norm(target_state - saddle_state) / np.linalg.norm(target_state - initial_state) covariance_matrix_start, quad_form_initial, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, initial_state, sigma, noise_matrix=noise_matrix) covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, target_state, sigma, noise_matrix=noise_matrix) def score_function(v): return (custom_score_function(v) + eta - eta * np.exp(-param * quad_form_initial(v))) / 1.5 return score_function
def score_function_fred_ell_maker(sigma=1.5): covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, target_state, sigma, noise_matrix=noise_matrix) def score_function(v): da = np.linalg.norm(v - initial_state) db = np.sqrt(quad_form_target(v)) if da <= db: return da / 2 / db else: return 1 - db / 2 / da return score_function
def score_function_ellipsoid_maker(param=0.01, sigma=1.5, direction=None, forward=0.3, backward=0.1): """ param: decay rate of the exponentials """ eta = np.linalg.norm(target_state - saddle_state) / np.linalg.norm(target_state - initial_state) covariance_matrix_start, quad_form_initial, spectral_radius, level_initial, bound_initial = ellipsoid_fun.ingredients_score_function( force_matrix, initial_state, sigma, noise_matrix=noise_matrix) covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, target_state, sigma, noise_matrix=noise_matrix) if direction is None: def score_function(v): return eta - eta * np.exp(-param * quad_form_initial(v)) + ( 1 - eta) * np.exp(-param * quad_form_target(v)) return score_function else: direction = direction / np.linalg.norm(direction) s = np.linspace(-3 * bound, 3 * bound, 1000) s = np.linspace(0, 3 * bound_initial, 1000) s = np.expand_dims(s, 1) line = s * direction + initial_state direction_on_border = line[np.argmin( np.apply_along_axis(quad_form_initial, 1, line) < level_initial )] - initial_state print(direction_on_border) def score_function(v): return eta - eta * np.exp( -param * forward * (backward + 1 + np.tanh( 0.2 * np.dot(v - initial_state, direction_on_border.T))) * quad_form_initial(v)) + (1 - eta) * np.exp( -param * quad_form_target(v)) return score_function
def plot_trajectory(time_array, force, initial_state, target_state, sigma1, noise_matrix, force_matrix, xmin=-15, xmax=15, ymin=-15, ymax=15, zmin=0, zmax=15, save_path=None, vs=None): """ plots the trajectories of two particles starting in the initial states, for two values of noise strength sigma """ fig = plt.figure(1) ax = fig.add_subplot(111, projection='3d') ax.patch.set_facecolor('white') ax.tick_params(axis='both', which='major', pad=-2) if vs is None: solver_scheme = functools.partial(schemes.Euler_Maruyama_no_stop, force=force, time_array_length=len(time_array), dt=0.01, dims=3, noise_matrix=noise_matrix) vs = solver_scheme(0, initial_state, sigma1) ax.plot(vs[:, 1], vs[:, 0], zs=vs[:, 2], zdir='z', linewidth=0.2, color='C1') #plt.title(r'$\sigma$'+' = {}'.format(sigma1)) ax.set_ylabel('x', labelpad=-7) ax.set_xlabel('y', labelpad=-7) ax.set_zlabel('z', labelpad=-7) ax.set_xlim(xmin, xmax) ax.set_zlim(zmin, zmax) ax.set_ylim(ymin, ymax) plt.scatter(initial_state[1], initial_state[0], zs=initial_state[2], marker='o', label='$X_A$', s=40, color='black', zorder=1000) plt.scatter(target_state[1], target_state[0], zs=target_state[2], marker='x', label='$X_B$', s=40, color='black', zorder=1000) if force_matrix is not None: covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, target_state, sigma1, noise_matrix) plot_ellipsoid(np.linalg.inv(covariance_matrix_target), level, target_state, ax, color='C0', label=None) covariance_matrix_initial, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, initial_state, sigma1, noise_matrix) plot_ellipsoid(np.linalg.inv(covariance_matrix_initial), level, initial_state, ax, label=None, color='C0') plt.scatter(initial_state[1], initial_state[0], zs=initial_state[2], marker='o', label='$X_A$', s=40, color='black', zorder=1000) plt.scatter(target_state[1], target_state[0], zs=target_state[2], marker='x', label='$X_B$', s=40, color='black', zorder=1000) #plt.legend() plt.xticks([-5, 0, 5]) plt.yticks([-5, 0, 5]) ax.set_zticks([0, 5, 10, 15]) ax.text2D(0.1, 0.9, '(a)', horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, fontsize=9) if save_path is not None: plt.savefig(save_path) plt.show()
def trajectory(time_array, force, initial_state, target_state, sigma1, noise_matrix, force_matrix, index_time=[0, 1], index_traj=[0, 1], label_time=['x', 'y'], label_traj=['x', 'y'], score_function=None, xmin=None, xmax=None, ymin=None, ymax=None, save_path=None): """ plots the trajectories of two particles starting in the initial states, for two values of noise strength sigma """ plt.figure() solver_scheme = functools.partial(schemes.Euler_Maruyama_no_stop, force=force, time_array_length=len(time_array), dt=0.01, dims=4, noise_matrix=noise_matrix) #solve first trajectory vs = solver_scheme(0, initial_state, sigma1) plt.plot(vs[:, index_traj[0]], vs[:, index_traj[1]], linewidth=0.1, color='C1') plt.title(r'$\sigma$' + ' = {}'.format(sigma1)) plt.ylabel(label_traj[1]) plt.ylim((ymin, ymax)) plt.xlim(xmin, xmax) plt.scatter(initial_state[index_traj[0]], initial_state[index_traj[1]], marker='o', label='initial', s=40, color='black') plt.scatter(target_state[index_traj[0]], target_state[index_traj[1]], marker='x', label='target', s=40) if force_matrix is not None: dim = len(initial_state) indices = [0, 2] index1, index2 = indices rest1, rest2 = [idx for idx in range(dim) if idx not in indices] covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, target_state, sigma1, noise_matrix) proj = target_state lims = bound binslist = [None] * dim binslist[rest1] = np.array([proj[rest1]]) binslist[rest2] = np.array([proj[rest2]]) binslist[index1] = np.linspace(proj[index1] - lims, proj[index1] + lims, 300) binslist[index2] = np.linspace(proj[index2] - lims, proj[index2] + lims, 300) a0, a1, a2, a3 = binslist grids = list(np.meshgrid(a0, a1, a2, a3)) ell = np.apply_along_axis(quad_form_target, 0, np.array(grids)) ell = np.squeeze(ell) plt.contour(np.squeeze(grids[index1]), np.squeeze(grids[index2]), ell, levels=[level], colors=['black'], label='confidence ellipsoid') covariance_matrix_initial, quad_form_initial, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, initial_state, sigma1, noise_matrix) proj = initial_state lims = bound binslist = [None] * dim binslist[rest1] = np.array([proj[rest1]]) binslist[rest2] = np.array([proj[rest2]]) binslist[index1] = np.linspace(proj[index1] - lims, proj[index1] + lims, 300) binslist[index2] = np.linspace(proj[index2] - lims, proj[index2] + lims, 300) a0, a1, a2, a3 = binslist grids = list(np.meshgrid(a0, a1, a2, a3)) ell = np.apply_along_axis(quad_form_initial, 0, np.array(grids)) ell = np.squeeze(ell) plt.contour(np.squeeze(grids[index1]), np.squeeze(grids[index2]), ell, levels=[level], colors=['black'], label='confidence ellipsoid') plt.legend() if save_path is not None: plt.savefig(save_path) plt.show() plt.figure() #solve trajectory ax = plt.subplot(222) ax.plot(time_array, initial_state[2] + np.zeros((len(time_array))), linestyle='--') ax.plot(time_array, target_state[2] + np.zeros((len(time_array))), linestyle='--') ax.plot(time_array, vs[:, 2], linewidth=0.3) ax.set_ylabel('$A_3$') plt.setp(ax.get_xticklabels(), visible=False) ax = plt.subplot(221, sharex=ax) ax.plot(time_array, initial_state[0] + np.zeros((len(time_array))), linestyle='--', label='initial state') ax.plot(time_array, target_state[0] + np.zeros((len(time_array))), linestyle='--', label='target state') ax.plot(time_array, vs[:, 0], linewidth=0.3) ax.set_ylabel('$A_1$') ax.legend(fontsize='xx-small') plt.setp(ax.get_xticklabels(), visible=False) ax = plt.subplot(224) ax.plot(time_array, initial_state[3] + np.zeros((len(time_array))), linestyle='-') ax.plot(time_array, target_state[3] + np.zeros((len(time_array))), linestyle='--', dashes=(3.5, 3.5)) ax.plot(time_array, vs[:, 3], linewidth=0.3) ax.set_ylabel('$A_4$') ax.set_xlabel('time') ax = plt.subplot(223, sharex=ax) ax.plot(time_array, initial_state[1] + np.zeros((len(time_array))), linestyle='-') ax.plot(time_array, target_state[1] + np.zeros((len(time_array))), linestyle='--', dashes=(3.5, 3.5)) ax.plot(time_array, vs[:, 1], linewidth=0.3) ax.set_ylabel('$A_2$') ax.set_xlabel('time') if save_path is not None: plt.savefig(save_path) plt.show() print([f'{elem:.15e}' for elem in vs[-1]])
def draw_projection( initial_state, target_state, indices, proj, noise_matrix, lims=[2, 2], function=None, sigma=None, force_matrix=None, ): dim = len(initial_state) plt.figure() index1, index2 = indices [rest1] = [idx for idx in range(dim) if idx not in indices] binslist = [None] * dim binslist[rest1] = np.array([proj[rest1]]) binslist[index1] = np.linspace(proj[index1] - lims[0], proj[index1] + lims[0], 300) binslist[index2] = np.linspace(proj[index2] - lims[1], proj[index2] + lims[1], 300) a0, a1, a2 = binslist grids = list(np.meshgrid(a0, a1, a2)) if function is not None: values = np.apply_along_axis(function, 0, np.array(grids)) values = np.squeeze(values) im = plt.contourf(np.squeeze(grids[index1]), np.squeeze(grids[index2]), values, 50) plt.colorbar(im) if initial_state is not None: plt.scatter(initial_state[index1], initial_state[index2], marker='o', label='initial', s=40, color='black') if target_state is not None: plt.scatter(target_state[index1], target_state[index2], marker='x', label='target', s=40) if sigma is not None and force_matrix is not None: covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, target_state, sigma, noise_matrix) ell = np.apply_along_axis(quad_form_target, 0, np.array(grids)) ell = np.squeeze(ell) plt.contour(np.squeeze(grids[index1]), np.squeeze(grids[index2]), ell, levels=[level], colors=['black'], label='confidence ellipsoid') plt.legend() plt.show()
def check(time_array, force, initial_state, target_state, sigma1, noise_matrix, force_matrix, xmin=-15, xmax=15, ymin=-15, ymax=15, zmin=0, zmax=15, save_path=None): fig = plt.figure() ax = fig.add_subplot(111, projection='3d') solver_scheme = functools.partial(schemes.Euler_Maruyama_no_stop, force=force, time_array_length=len(time_array), dt=0.01, dims=3, noise_matrix=noise_matrix) plt.title(r'$\sigma$' + ' = {}'.format(sigma1)) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_zlabel('z') plt.scatter(initial_state[0], initial_state[1], zs=initial_state[2], marker='o', label='initial', s=40, color='black') plt.scatter(target_state[0], target_state[1], zs=target_state[2], marker='x', label='target', s=40) if force_matrix is not None: covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, target_state, sigma1, noise_matrix, confidence=0.99) plot_ellipsoid(np.linalg.inv(covariance_matrix_target), level, target_state, ax, color='C0') covariance_matrix_initial, quad_form_initial, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, initial_state, sigma1, noise_matrix, confidence=0.99) plot_ellipsoid(np.linalg.inv(covariance_matrix_initial), level, initial_state, ax, label=None) print(level) ell = ellipsoid_fun.get_ellipsoid_interior(target_state, quad_form_target, level, bound, nb_points=1e6, sample=100) for elem in ell: vs = solver_scheme(0, elem, 0) plt.plot(vs[:, 0], vs[:, 1], vs[:, 2], linewidth=0.1, color='C1') plt.scatter(vs[-1, 0], vs[-1, 1], zs=vs[-1:2], s=10, color='red') plt.scatter(vs[0, 0], vs[0, 1], zs=vs[0, 2], s=10, color='green') print(quad_form_target(elem), level) plt.legend() if save_path is not None: plt.savefig(save_path) ax.set_xlim(xmin, xmax) ax.set_zlim(zmin, zmax) ax.set_ylim(ymin, ymax) plt.show()
def monte_carlo_run(self, sigma_grid, N_particles, freq=1000, output_path=None): #transition_probability matrix transition_probability_grid_MC = np.zeros((len(sigma_grid))) #hitting time matrix, computing time matrix computing_time = np.zeros((len(sigma_grid))) number_timesteps = np.zeros((len(sigma_grid))) job_start_time = tm.time() print("############################") print("Starting Monte Carlo job ...") print("############################\n\n") for s, sigma in enumerate(sigma_grid): print( 'Parameters: \n noise strength sigma: {:.2f}. \n particles number: {:.1e} \n trajectory length: {} seconds. \n dt = {} seconds' .format(sigma, N_particles, self.t_trajectory, self.dt)) sigma_start_time = tm.time() #covariance matrix and associated quadratic form covariance_matrix, quad_form, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( self.force_matrix, equilibrium_point=self.target_state, noise=sigma) for n in range(N_particles): ndt, vs, count = schemes.Euler_Maruyama_ellipsoid_stop( 0, self.initial_state, sigma=sigma, ellipsoid_test=functools.partial( ellipsoid_fun.ellipsoid_test, quad_form=quad_form, level=level), dims=self.dims, force=self.force, time_array_length=self.time_array_length, dt=self.dt) transition_probability_grid_MC[s] += count number_timesteps[s] += ndt if n % freq == 0: print( f'Estimated probability: {transition_probability_grid_MC[s]}/{n+1} = {transition_probability_grid_MC[s]/(n+1):.2e}' ) transition_probability_grid_MC[ s] = transition_probability_grid_MC[s] / N_particles sigma_end_time = tm.time() computing_time[s] += sigma_end_time - sigma_start_time print( f"Computed transition probability: {transition_probability_grid_MC[s]:.3e}" ) job_end_time = tm.time() job_elapsed_time = job_end_time - job_start_time print('Total computing time: ' + self.display_time(job_elapsed_time)) if output_path != None: #write data to hdf5 file with h5py.File(output_path, 'a') as file: transition_proability_dataset_MC = file.create_dataset( f'transition_probability_grid_MC', data=transition_probability_grid_MC) transition_proability_dataset_MC.attrs[ 'sigma_grid'] = sigma_grid transition_proability_dataset_MC.attrs[ 'trajectory_length'] = self.t_trajectory transition_proability_dataset_MC.attrs['dt'] = self.dt transition_proability_dataset_MC.attrs[ 'N_particles'] = N_particles transition_proability_dataset_MC.attrs[ 'number_timesteps'] = number_timesteps transition_proability_dataset_MC.attrs[ 'computing_time'] = computing_time file.close() print(f'Wrote data to file {output_path}.') return transition_probability_grid_MC, computing_time, number_timesteps
initial guess force matrix noise """ #arguments score_function_maker = tw.score_function_ellipsoid_maker force_matrix = tw.force_matrix noise = noise initial_guess = 3 initial_state = tw.initial_state target_state = tw.target_state threshold_param = tw.threshold_simexp_param #result covariance_matrix_start, quad_form_initial, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, initial_state, noise) covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, target_state, noise) ell = ellipsoid_fun.get_ellipsoid_array(target_state, quad_form_target, level, bound) score_function, score_threshold = ellipsoid_fun.optimize_param( score_function_maker, initial_guess, ell, noise, functools.partial(threshold_param, level=level)) #%% if test_histogram_to_trajectory: """ input: histogram start and end states binslist
def TAMS_run(self, sigma_grid, N_particles, N_samples, Nitermax, listbins, output_path, histbis=False, quadrant=False, branching_points=False, verbose=True, quadrant_factor=1000, geom_stopping=False, score_stopping=False, warp=False): #transition_probability matrix transition_probability_grid_TAMS = np.zeros( (len(sigma_grid), N_samples)) #computing time matrix computing_time = np.zeros((len(sigma_grid), N_samples)) number_timesteps = np.zeros((len(sigma_grid), N_samples)) #same_score_error matrix (0 if no error, 1 if same score error is encountered) same_score_error = np.zeros((len(sigma_grid), N_samples)) #density probability or histogram, mean trajectory probability_density = np.zeros([len(sigma_grid)] + [len(elem) - 1 for elem in listbins]) mean_trajectory = np.zeros( (len(sigma_grid), len(self.time_array), self.dims)) #samples for the preferred initial direction WARNING: this only works if running N_samples=1 sample quadrant_samples = None direction = None #branching points at each iteration WARNING: this only works if running N_samples=1 sample branching_points_list = [] pre_branching_points_list = [] branching_scores_list = [] pre_branching_scores_list = [] job_start_time = tm.time() print('\n######################') print("Starting TAMS job ...") print('###################### \n\n') for s, sigma in enumerate(sigma_grid): print( 'Parameters: \n noise strength sigma: {:.2f}. \n particles number: {:.1e} \n trajectory length: {} seconds. \n dt = {} seconds \n' .format(sigma, N_particles, self.t_trajectory, self.dt)) """ if self.adapt_param: #covariance matrix and associated quadratic form covariance_matrix, quad_form_start, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function(self.force_matrix, equilibrium_point=self.initial_state, noise = sigma) covariance_matrix, quad_form, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function(self.force_matrix, equilibrium_point=self.target_state, noise = sigma) ell = ellipsoid_fun.get_ellipsoid_array(self.target_state, quad_form, level, bound) self.score_function, self.score_threshold = ellipsoid_fun.optimize_param_normal(self.score_function_param, initial_guess= 1/quad_form_start(self.saddle_state)*2, ell=ell, threshold_param = functools.partial(self.threshold_param, level = level)) """ #adapt the score function run_score_function = self.score_function #warp the score function so that the target set is the confidence ellipsoid if warp: print('Warping the score function...') run_score_function, run_threshold = warp_score_function_ell.remap_score_function_ell( run_score_function, self.force_matrix, self.target_state, noise=sigma) print( f'Used the ellipsoid to warp the score function threshold. Automatic threshold: {run_threshold:.2e} \n' ) # if you want to sample the exit direction of the ellipsoid, calculate the ellipsoid and the function that tests if a point is in the ellipsoid if quadrant: covariance_matrix_initial, quad_form_initial, spectral_radius_initial, level_initial, bound_initial = ellipsoid_fun.ingredients_score_function( self.force_matrix, self.initial_state, sigma, self.noise_matrix, confidence=0.99) initial_test = functools.partial(ellipsoid_fun.ellipsoid_test, quad_form=quad_form_initial, level=level_initial) # defines the criterion for knowing if a trajectory has converged or not: either score (automatic or manual) or geometric if score_stopping: if warp: score_stopping_level = 1 - run_threshold else: score_stopping_level = float(score_stopping) print( f'Using score stopping with level : {score_stopping_level: .2e}' ) target_test = lambda v: run_score_function( v ) > score_stopping_level #stopping if score > score_stopping_level else: if not geom_stopping: covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( self.force_matrix, self.target_state, sigma, self.noise_matrix) target_test = functools.partial( ellipsoid_fun.ellipsoid_test, quad_form=quad_form_target, level=level) else: geom_stopping_threshold = float(geom_stopping) print( f'Using geometrical stopping with threshold : {geom_stopping_threshold: .2e}' ) target_test = lambda v: np.linalg.norm( v - self.target_state ) < geom_stopping_threshold #stopping if the trajectory is close to the target state by geom_stopping_threshold #generate Euler-Maruyama solver solver_scheme = functools.partial( self.solver_scheme_no_stop, dims=self.dims, force=self.force, time_array_length=self.time_array_length, dt=self.dt, noise_matrix=self.noise_matrix) for n in range(N_samples): print('Computing sample number {} out of {} ... \n'.format( n + 1, N_samples)) #initialize variables k = 1 #iteration number weights = [1] #initial weight number_discarded_trajectories = [ ] #number discarded trajectories at each iteration TAMS_start_time = tm.time() #timer #1. generate N independent trajectories, starting in initial condition traj = np.empty( (N_particles, self.time_array_length, self.dims)) for i in range(N_particles): xs = solver_scheme(0, self.initial_state, sigma) traj[i, :, :] = xs local_number_timesteps = N_particles * self.time_array_length #stores number of computed steps #2. calculate scores scores_array = np.apply_along_axis(run_score_function, 2, traj) scores = np.max(scores_array, axis=1) min_score = np.min(scores) #3. target reached based on defined criterion target_reached_array = np.any(np.apply_along_axis( target_test, 2, traj), axis=1) while k < Nitermax and np.count_nonzero( target_reached_array ) < N_particles and not same_score_error[s, n]: #3.get worst trajectories indexes_to_discard = np.array( scores == min_score).nonzero()[0] if len(indexes_to_discard) == N_particles: same_score_error[s, n] = 1 break #4. update weights and number of discarded trajectories if verbose: print(f'\n Iteration # {k}') print( f'Number of branched trajectories: {len(indexes_to_discard)}. Minimum score: {min_score}' ) number_discarded_trajectories.append( len(indexes_to_discard)) weights.append(weights[-1] * (1 - len(indexes_to_discard) / N_particles)) indexes_choice_pool = [ elem for elem in range(N_particles) if not elem in indexes_to_discard ] #5. branch the discarded trajectories for discarded_index in indexes_to_discard: #select random trajectory in the rest branch_traj_index = np.random.choice( indexes_choice_pool) #get branching time and position branch_time_index = np.argmax( scores_array[branch_traj_index, :] >= min_score) branch_x = traj[branch_traj_index, branch_time_index] #store branching points if asked if branching_points: reached_max = np.argmax( scores_array[discarded_index]) assert scores_array[discarded_index, reached_max] == min_score pre_branch_x = traj[discarded_index][ reached_max, :] pre_branching_points_list.append(pre_branch_x) branching_points_list.append(branch_x) pre_branching_scores_list.append( run_score_function(pre_branch_x)) branching_scores_list.append( run_score_function(branch_x)) #compute the branched trajectory and update total computed timesteps x_new = solver_scheme(branch_time_index, branch_x, sigma) scores_new = np.apply_along_axis( run_score_function, 1, x_new) local_number_timesteps += self.time_array_length - branch_time_index #update the trajectory storage matrix traj[discarded_index, :branch_time_index] = traj[ branch_traj_index, : branch_time_index] #necessary only for the histogram? traj[discarded_index, branch_time_index:] = x_new #update the scores list and target reached scores_array[discarded_index, : branch_time_index] = scores_array[ branch_traj_index, : branch_time_index] #unnecessary? scores_array[discarded_index, branch_time_index:] = scores_new scores[discarded_index] = np.max(scores_new) #update target reached target_reached_array[discarded_index] = np.any( np.apply_along_axis(target_test, 1, x_new)) #verbose if verbose: print( f'Branching index {discarded_index} to {branch_traj_index}. New score: {scores[discarded_index]}' ) if scores[discarded_index] == min_score: print('No score improvement') else: print('Score improved') print( f'{np.count_nonzero(target_reached_array)}/{N_particles} reached the target.' ) #update iteration number k += 1 min_score = np.min(scores) if same_score_error[s, n]: print('All trajectories have the same score! :(') else: #convert lists to numpy arrays weights = np.array(weights) number_discarded_trajectories = np.array( number_discarded_trajectories) #calculate transition probability target_reached_indexes = np.nonzero( target_reached_array)[0] target_reached_number = np.count_nonzero( target_reached_array) #print(target_reached,k) weight_normalisation_constant = N_particles * weights[ -1] + np.sum( number_discarded_trajectories * weights[:-1]) transition_probability = target_reached_number / weight_normalisation_constant * weights[ -1] transition_probability_grid_TAMS[ s, n] = transition_probability #update mean_trajectory with warnings.catch_warnings(): warnings.simplefilter("ignore", category=RuntimeWarning) mean_trajectory[s] += np.mean( traj[target_reached_indexes], axis=0) / N_samples #update histogram if histbis: traj = np.asarray(traj) traj_reshaped = traj.reshape((-1, self.dims)) time_weights = np.broadcast_to( np.exp(self.time_array**2), (N_particles, self.time_array_length)) weights = time_weights.reshape((-1)) hist, bins = np.histogramdd(traj_reshaped, bins=listbins, weights=weights) probability_density[s] += hist else: traj = np.asarray( traj ) #convert matrix to array otherwise dimensionnality error in histogram traj_reshaped = traj.reshape((-1, self.dims)) hist, bins = np.histogramdd(traj_reshaped, bins=listbins) probability_density[s] += hist #calculates the preferred directions if quadrant: traj = np.asarray(traj) #matrix to arrat tested = np.apply_along_axis( initial_test, 2, traj ) #tests if the positions are in the initial confidence ellipsoid indices_start = self.time_array_length - np.apply_along_axis( np.argmax, 1, tested[:, ::-1] ) #gets the last position at which all the positions after are outside the ellipsoid indices_end = indices_start + int( self.time_array_length // quadrant_factor ) #defines the sample window (int(self.time_array_length//quadrant_factor) ) r = np.arange(self.time_array_length) mask = (indices_start[:, None] <= r) & (r <= indices_end[:, None]) quadrant_samples = traj[ mask, :] #get the defined samples #get the first two eigenvectors of the covariance matrix (can be easily generalized to more) spectrum, eigvec = np.linalg.eig( np.linalg.inv(covariance_matrix_initial)) eigvec1 = eigvec[:, 0] eigvec2 = eigvec[:, 1] #define projections onto the eigenvectors def proj_1(v): return np.sum((eigvec1) * (v - self.initial_state)) def proj_2(v): return np.sum((eigvec2) * (v - self.initial_state)) #compute the average projections avg_1 = np.mean( np.apply_along_axis(proj_1, 1, quadrant_samples)) avg_2 = np.mean( np.apply_along_axis(proj_2, 1, quadrant_samples)) #compute the direction direction = avg_1 * eigvec1 + avg_2 * eigvec2 vector_direction = avg_1 * eigvec1 + avg_2 * eigvec2 + self.initial_state #computing time update TAMS_end_time = tm.time() computing_time[s, n] = TAMS_end_time - TAMS_start_time number_timesteps[s, n] = local_number_timesteps #verbose print( f'\nTAMS algorithm stopped after {k}/{Nitermax} iterations' ) print( f'Computed transition probability: {transition_probability:.2e}' ) print( f'Number of computed timesteps: {local_number_timesteps:.2e}\n' ) print( f'Average number of trajectories discarded/iteration : {np.mean(number_discarded_trajectories):.2f}' ) print( f'Computed a total of {np.sum(number_discarded_trajectories)} trajectories.' ) print( f'Computed {target_reached_number} reactive trajectories.' ) if quadrant: print( f"Collected {quadrant_samples.shape[0]} points for direction calculation." ) print( f'Computed starting direction: {direction} and direction vector: {vector_direction}' ) print( f'TAMS computing time: {self.display_time(TAMS_end_time - TAMS_start_time)} \n' ) job_end_time = tm.time() job_elapsed_time = job_end_time - job_start_time print("\n" + "TAMS job finished. ") print( f'Total timesteps computed: {np.sum(number_timesteps, axis = (0,1)):.2e}' ) print('Total computing time: ' + self.display_time(job_elapsed_time)) if 1 in same_score_error: print('WARNING: Same score error occured at some point.') if output_path is not None: #write data to hdf5 file with h5py.File(output_path, 'a') as file: transition_proability_dataset_TAMS = file.create_dataset( 'transition_probability_grid_TAMS', data=transition_probability_grid_TAMS) if quadrant: file.create_dataset('quadrant_samples', data=quadrant_samples) file.create_dataset('direction', data=direction) if branching_points: file.create_dataset('branching_points', data=np.array(branching_points_list)) file.create_dataset( 'pre_branching_points', data=np.array(pre_branching_points_list)) file.create_dataset('branching_scores', data=np.array(branching_scores_list)) file.create_dataset( 'pre_branching_scores', data=np.array(pre_branching_scores_list)) transition_proability_dataset_TAMS.attrs[ 'sigma_grid'] = sigma_grid transition_proability_dataset_TAMS.attrs[ 'trajectory_length'] = self.t_trajectory transition_proability_dataset_TAMS.attrs['dt'] = self.dt #transition_proability_dataset_TAMS.attrs['score_threshold'] = run_threshold transition_proability_dataset_TAMS.attrs[ 'Initial state'] = self.initial_state transition_proability_dataset_TAMS.attrs[ 'N_samples'] = N_samples transition_proability_dataset_TAMS.attrs[ 'N_particles'] = N_particles transition_proability_dataset_TAMS.attrs[ 'Maximum_number_iterations'] = Nitermax file.create_dataset('number_timesteps', data=number_timesteps) file.create_dataset('computing_time', data=computing_time) file.create_dataset('probability_density', data=probability_density) file.create_dataset('listbins', data=listbins) mean_trajectory = mean_trajectory / N_samples file.create_dataset('mean_trajectory', data=mean_trajectory) file.close() print(f'Wrote data to file {output_path}.') return transition_probability_grid_TAMS, probability_density, quadrant_samples
def monte_carlo_run(self, sigma_grid, N_particles, freq=1000, geom_stopping=False, output_path=None, listbins=None): #transition_probability matrix transition_probability_grid_MC = np.zeros((len(sigma_grid))) #hitting time matrix, computing time matrix computing_time = np.zeros((len(sigma_grid))) number_timesteps = np.zeros((len(sigma_grid))) if listbins is not None: probability_density = np.zeros( [len(sigma_grid)] + [len(elem) - 1 for elem in listbins]) job_start_time = tm.time() print("############################") print("Starting Monte Carlo job ...") print("############################\n\n") for s, sigma in enumerate(sigma_grid): print( 'Parameters: \n noise strength sigma: {:.2f}. \n particles number: {:.1e} \n trajectory length: {} seconds. \n dt = {} seconds' .format(sigma, N_particles, self.t_trajectory, self.dt)) sigma_start_time = tm.time() #covariance matrix and associated quadratic form if not geom_stopping: covariance_matrix, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( self.force_matrix, equilibrium_point=self.target_state, noise=sigma) target_test = functools.partial(ellipsoid_fun.ellipsoid_test, quad_form=quad_form_target, level=level) else: geom_stopping_threshold = float(geom_stopping) print( f'Using geometrical stopping with threhsold : {geom_stopping_threshold: .2e}' ) target_test = lambda v: np.linalg.norm( v - self.target_state) < geom_stopping_threshold solver_scheme = functools.partial( self.solver_scheme_no_stop, dims=self.dims, force=self.force, time_array_length=self.time_array_length, dt=self.dt, noise_matrix=self.noise_matrix) for n in range(N_particles): vs = solver_scheme(0, self.initial_state, sigma=sigma) reached = np.any(np.apply_along_axis(target_test, 1, vs)) transition_probability_grid_MC[s] += reached if reached and listbins is not None: hist, bins = np.histogramdd(vs, bins=listbins) probability_density[s] += hist number_timesteps[s] += self.time_array_length if n % freq == 0 and n != 0: print( f'Estimated probability: {transition_probability_grid_MC[s]}/{n+1} = {transition_probability_grid_MC[s]/(n+1):.2e}' ) transition_probability_grid_MC[ s] = transition_probability_grid_MC[s] / N_particles sigma_end_time = tm.time() computing_time[s] += sigma_end_time - sigma_start_time print("Computing time: " + self.display_time(computing_time[s])) print( f"Computed transition probability: {transition_probability_grid_MC[s]:.3e} \n" ) job_end_time = tm.time() job_elapsed_time = job_end_time - job_start_time print('Total computing time: ' + self.display_time(job_elapsed_time)) if output_path != None: #write data to hdf5 file with h5py.File(output_path, 'a') as file: transition_proability_dataset_MC = file.create_dataset( f'transition_probability_grid_MC', data=transition_probability_grid_MC) transition_proability_dataset_MC.attrs[ 'sigma_grid'] = sigma_grid transition_proability_dataset_MC.attrs[ 'trajectory_length'] = self.t_trajectory transition_proability_dataset_MC.attrs['dt'] = self.dt transition_proability_dataset_MC.attrs[ 'N_particles'] = N_particles transition_proability_dataset_MC.attrs[ 'number_timesteps'] = number_timesteps transition_proability_dataset_MC.attrs[ 'computing_time'] = computing_time if listbins is not None: file.create_dataset('probability_density', data=probability_density) file.close() print(f'Wrote data to file {output_path}.') return transition_probability_grid_MC, computing_time, number_timesteps
import functools import ellipsoid_fun import numpy as np sigma = 3 covariance_matrix_initial, quad_form_initial, spectral_radius_initial, level_initial, bound_initial = ellipsoid_fun.ingredients_score_function( run.force_matrix, run.initial_state, sigma, run.noise_matrix) initial_test = functools.partial(ellipsoid_fun.ellipsoid_test, quad_form=quad_form_initial, level=level_initial) tested = np.apply_along_axis(initial_test, 2, traj) indices_start = run.time_array_length - np.apply_along_axis( np.argmax, 1, tested[:, ::-1]) indices_end = indices_start + 1 #TOOOO CHANGE §§§ r = np.arange(run.time_array_length) mask = (indices_start[:, None] <= r) & (r <= indices_end[:, None]) print(mask.shape) samples = traj[mask, :] print(traj[mask, :].shape) import matplotlib.pyplot as plt plt.scatter(samples[:, 0], samples[:, 1], label='last exit points') plt.scatter(run.initial_state[0], run.initial_state[1], marker='o', s=20) CS = ellipsoid_fun.draw_ellipsoid_2D(run.force_matrix, run.initial_state, noise=sigma,
def check(time_array, force, initial_state, target_state, sigma1, noise_matrix, force_matrix, index_time=[0, 2], index_traj=[0, 2], label_time=['x', 'y'], label_traj=['x', 'y'], score_function=None, xmin=None, xmax=None, ymin=None, ymax=None, save_path=None): plt.figure() dim = len(initial_state) indices = [0, 2] index1, index2 = indices rest1, rest2 = [idx for idx in range(dim) if idx not in indices] covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, target_state, sigma1, noise_matrix) solver_scheme = functools.partial(schemes.Euler_Maruyama_no_stop, force=force, time_array_length=len(time_array), dt=0.01, dims=4, noise_matrix=noise_matrix) proj = target_state lims = bound binslist = [None] * dim binslist[rest1] = np.array([proj[rest1]]) binslist[rest2] = np.array([proj[rest2]]) binslist[index1] = np.linspace(proj[index1] - lims, proj[index1] + lims, 300) binslist[index2] = np.linspace(proj[index2] - lims, proj[index2] + lims, 300) a0, a1, a2, a3 = binslist grids = list(np.meshgrid(a0, a1, a2, a3)) ell = np.apply_along_axis(quad_form_target, 0, np.array(grids)) ell = np.squeeze(ell) #plt.contour(np.squeeze(grids[index1]), np.squeeze(grids[index2]), ell, levels = [level], colors = ['black'], label = 'confidence ellipsoid') ell = ellipsoid_fun.get_ellipsoid_interior(target_state, quad_form_target, level, bound, nb_points=1e6, sample=200) for elem in ell: vs = solver_scheme(0, elem, 0) plt.plot(vs[:, index_traj[0]], vs[:, index_traj[1]], linewidth=0.1, color='C1') plt.scatter(vs[-1, index_traj[0]], vs[-1, index_traj[1]], linewidth=0.1, s=30, color='red', zorder=10) plt.scatter(vs[0, index_traj[0]], vs[0, index_traj[1]], linewidth=0.1, s=7, color='green', zorder=10) #plt.title(r'$\sigma$'+' = {}'.format(sigma1)) plt.xlabel(label_traj[0]) plt.ylabel(label_traj[1]) plt.ylim((ymin, ymax)) plt.xlim(xmin, xmax) plt.scatter(initial_state[index_traj[0]], initial_state[index_traj[1]], marker='o', label='$X_A$', s=20, color='black', zorder=50) plt.scatter(target_state[index_traj[0]], target_state[index_traj[1]], marker='x', label='$X_B$', color='black', s=20, zorder=50) plt.legend() if save_path is not None: plt.savefig(save_path)
def trajectory_plot_report1(time_array, dt, force, initial_state, target_state, sigma1, save_path, force_matrix=None, score_threshold=None, score_function=None, xmin=-10, xmax=10, ymin=-10, ymax=15): """ plots the trajectories of two particles starting in the initial states, for two values of noise strength sigma """ fig, ax = plt.subplots(1, 1) x, y = np.linspace(xmin, xmax, 100), np.linspace(ymin, ymax, 100) xx, yy = np.meshgrid(x, y) #solve first trajectory vs = schemes.Euler_Maruyama_no_stop(0, initial_state, sigma1, dt=dt, dims=2, force=force, time_array_length=len(time_array)) ax.plot(vs[:, 0], vs[:, 1], linewidth=0.03, color='C0') print( np.sum(vs[:, 0] * vs[:, 1]) / np.sqrt(np.sum(vs[:, 0] * vs[:, 0]) * np.sum(vs[:, 1] * vs[:, 1]))) vs2 = schemes.Euler_Maruyama_no_stop(0, target_state, sigma1, dt=dt, dims=2, force=force, time_array_length=len(time_array)) ax.plot(vs2[:, 0], vs2[:, 1], linewidth=0.03, color='C1') #ax.set_title(r'$\sigma$'+' = {}'.format(sigma1)) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_ylim((ymin, ymax)) ax.set_xlim((xmin, xmax)) plt.scatter(initial_state[0], initial_state[1], marker='o', color='black', s=40, zorder=10) plt.scatter(target_state[0], target_state[1], marker='x', color='black', s=40, zorder=10) #threshold and stopping criterion if score_function is not None: #score function threshold for the TAMS algorithm stopping criterion score_levels = np.apply_along_axis(score_function, 0, np.array([xx, yy])) ax.contour(xx, yy, score_levels, levels=[1 - score_threshold], zorder=10) if force_matrix is not None: ellipsoid_fun.draw_ellipsoid_2D(force_matrix, target_state, noise=sigma1, zorder=20) CS = ellipsoid_fun.draw_ellipsoid_2D(force_matrix, initial_state, noise=sigma1, zorder=20) CS.collections[0].set_label('confidence ellipsoid') covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, initial_state, sigma1) target_test = functools.partial(ellipsoid_fun.ellipsoid_test, quad_form=quad_form_target, level=level) a = np.apply_along_axis(target_test, 1, vs) print(len(a[a == True]) / len(a)) covariance_matrix_target, quad_form_target, spectral_radius, level, bound = ellipsoid_fun.ingredients_score_function( force_matrix, target_state, sigma1) target_test = functools.partial(ellipsoid_fun.ellipsoid_test, quad_form=quad_form_target, level=level) b = np.apply_along_axis(target_test, 1, vs2) print(len(b[b == True]) / len(b)) plt.legend() plt.text(-0.2, 1, '(a)', horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, fontsize=9) if save_path is not None: plt.savefig(save_path, bbox_inches='tight') plt.show()