def GRAPE(param, model: MODEL, init=False): n_step = param['n_step'] n_fid_eval = 0 if init: # Random initialization model.update_protocol( np.random.uniform(-1.0, 1.0, size=param['n_step'])) old_fid = model.compute_fidelity(protocol=model.protocol(), discrete=False) best_protocol = np.copy(model.protocol()) else: # So user can feed in data say from a specific protocol raise NotImplementedError("yet to be implemented.") #old_fid = model.compute_fidelity(discrete=False) #best_protocol = np.copy(model.protocol()) eta = 0.6 # initial learning rate n_fid_eval = 0 fid_diff = 1.0 while np.abs(fid_diff) > 1E-9 and n_fid_eval < param[ 'n_quench']: # guaranteed to break but after very long time # compute protocol gradient protocol_gradient = model.compute_protocol_gradient() # normalise gradient protocol_gradient /= np.max(np.abs(protocol_gradient)) # GD update rule new_protocol = model.protocol() + eta * protocol_gradient # impose boundedness condition ind_max = np.where(new_protocol > param['hx_max']) new_protocol[ind_max] = param['hx_max'] ind_min = np.where(new_protocol < param['hx_min']) new_protocol[ind_min] = param['hx_min'] ### fid = model.compute_fidelity(protocol=new_protocol, discrete=False) # if we overshoot, decrease step size, otherwise update protocol fid_diff = fid - old_fid if fid_diff < 0: eta *= 0.5 print('overshot minimum:', n_fid_eval, eta, np.abs(fid_diff)) else: # update protocol model.update_protocol(new_protocol) old_fid = fid.copy() n_fid_eval += 1 print(fid) print(n_fid_eval, eta, fid_diff) return old_fid, model.protocol(), n_fid_eval
def run_ES(parameters, model:MODEL, utils): n_step = parameters['n_step'] n_protocol = 2**n_step exact_data = np.zeros((n_protocol,2), dtype=np.float64) # 15 digits precision b2_array = lambda n10 : np.array(list(np.binary_repr(n10, width=n_step)), dtype=np.int) st=time.time() # ---> measuring estimated time <--- model.update_protocol(b2_array(0)) psi = model.compute_evolved_state() model.compute_fidelity(psi_evolve=psi) model.compute_energy(psi_evolve=psi) print("Est. run time : \t %.3f s"%(0.5*n_protocol*(time.time()-st))) # ---> Starting real calculation <--- st=time.time() for p in range(n_protocol): model.update_protocol(b2_array(p)) psi = model.compute_evolved_state() exact_data[p] = (model.compute_fidelity(psi_evolve=psi), model.compute_energy(psi_evolve=psi)) outfile = utils.make_file_name(parameters,root=parameters['root']) with open(outfile,'wb') as f: pickle.dump(exact_data, f, protocol=4) print("Total run time : \t %.3f s"%(time.time()-st)) print("\n Thank you and goodbye !") f.close()
def Gibbs_Sampling(param, model:MODEL): # should also measure acceptance rate Ti = param['Ti'] beta = 1./Ti n_step = param['n_step'] n_equilibrate = 10000 n_auto_correlate = n_step*10 # should look at auto-correlation time ! # initial random protocol model.update_protocol( np.random.randint(0, model.n_h_field, size=n_step) ) old_fid = model.compute_fidelity() best_fid = old_fid for i in range(n_equilibrate): random_time = np.random.randint(0,n_step) current_hx = model.protocol_hx(random_time) model.update_hx(random_time, model.random_flip(random_time)) new_fid = model.compute_fidelity() d_fid = new_fid - old_fid if d_fid > 0. : # accept move old_fid = new_fid elif np.exp(beta*d_fid) > np.random.uniform() : # accept move old_fid = new_fid else: # reject move model.update_hx(random_time, current_hx) samples = [] fid_samples = [] energy_samples = [] for i in range(n_sample): for j in range(n_auto_correlate): random_time = np.random.randint(0,n_step) current_hx = model.protocol_hx(random_time) model.update_hx(random_time, model.random_flip(random_time)) new_fid = model.compute_fidelity() d_fid = new_fid - old_fid if d_fid > 0. : # accept move old_fid = new_fid elif np.exp(beta*d_fid) > np.random.uniform() : # accept move old_fid = new_fid else: # reject move model.update_hx(random_time, current_hx) samples.append(np.copy(model.protocol())) fid_samples.append(model.compute_fidelity()) energy_samples.append(model.compute_energy()) return samples, fid_samples, energy_samples
def SD_2SF_M0(param, model: MODEL, init_random=False): """Two spin flip stochastic descent in the M=0 sector """ if model.n_h_field > 2: assert False, 'This works only for bang-bang protocols' n_step = param['n_step'] n_fid_eval = 0 n_visit = 1 if init_random: # Random initialization tmp = np.ones(n_step, dtype=int) # m = 0 state ... tmp[0:n_step // 2] = 0 np.random.shuffle(tmp) model.update_protocol(tmp) old_fid = model.compute_fidelity() best_protocol = np.copy(model.protocol()) else: # So user can feed in data say from a specific protocol old_fid = model.compute_fidelity() best_protocol = np.copy(model.protocol()) x1_ar, x2_ar = np.triu_indices(n_step, 1) order = np.arange(0, x1_ar.shape[0], dtype=np.int) while True: # careful with this. For binary actions, this is guaranteed to break np.random.shuffle(order) local_minima = True for pos in order: t1, t2 = (x1_ar[pos], x2_ar[pos]) if model.protocol_hx(t1) != model.protocol_hx(t2): model.swap(t1, t2) new_fid = model.compute_fidelity() n_fid_eval += 1 if new_fid > old_fid: # accept descent #print("%.15f"%new_fid,'\t',n_fid_eval) old_fid = new_fid n_visit += 1 #best_protocol = np.copy(model.protocol()) local_minima = False # will exit for loop before it ends ... local update accepted break else: model.swap(t1, t2) if local_minima: break return old_fid, np.copy(model.protocol()), n_fid_eval, n_visit
def SD(param, model: MODEL, init_random=False): """ Single spin flip stochastic descent """ n_step = param['n_step'] n_fid_eval = 1 n_visit = 1 if init_random: # Random initialization model.update_protocol( np.random.randint(0, model.n_h_field, size=n_step)) old_fid = model.compute_fidelity() best_protocol = np.copy(model.protocol()) else: # So user can feed in data say from a specific protocol old_fid = model.compute_fidelity() best_protocol = np.copy(model.protocol()) random_position = np.arange(n_step, dtype=int) fid_series = [old_fid] while True: np.random.shuffle(random_position) local_minima_reached = True # trick for t in random_position: model.update_hx(t, model.protocol_hx(t) ^ 1) # assumes binary fields new_fid = model.compute_fidelity() n_fid_eval += 1 fid_series.append(old_fid) if new_fid > old_fid: # accept descent old_fid = new_fid n_visit += 1 local_minima_reached = False break else: model.update_hx(t, model.protocol_hx(t) ^ 1) # assumes binary fields if local_minima_reached: break return old_fid, np.copy(model.protocol()), n_fid_eval, n_visit, fid_series
def SA(param, model: MODEL): Ti = param['Ti'] n_quench = param['n_quench'] if n_quench == 0: return n_step = param['n_step'] # initial random protocol model.update_protocol(np.random.randint(0, model.n_h_field, size=n_step)) old_fid = model.compute_fidelity() best_fid = old_fid best_protocol = np.copy(model.protocol()) T = Ti step = 0 r = 0 while T > 1e-12: beta = 1. / T # --- ---> single spin flip update <--- --- random_time = np.random.randint(0, n_step) current_hx = model.protocol_hx(random_time) model.update_hx(random_time, model.random_flip(random_time)) # --- --- --- --- --- --- --- --- --- --- new_fid = model.compute_fidelity() if new_fid > best_fid: best_fid = new_fid best_protocol = np.copy( model.protocol()) # makes an independent copy ! d_fid = new_fid - old_fid if d_fid > 0.: # accept move old_fid = new_fid elif np.exp(beta * d_fid) > np.random.uniform(): # accept move old_fid = new_fid else: # reject move r += 1 model.update_hx(random_time, current_hx) step += 1 T = Ti * (1.0 - step / n_quench) print(1 - r / n_quench) return best_fid, best_protocol, n_quench
def compute_initial_Ti(param, model:MODEL, n_sample = 100, rate = 0.8): # OK how is this acceptable ? >>>>>>> not tested at all <<<<<<<< # Estimates the high-temperature limit (where the acceptance rate is 99 the average worst case excitations %) n_step = param['n_step'] dF_mean = [] for _ in range(n_sample): model.update_protocol( np.random.randint(0, model.n_h_field, size=n_step) ) old_fid = model.compute_fidelity() rand_pos = np.random.randint(n_step) model.update_hx(rand_pos, model.random_flip(rand_pos)) dF = model.compute_fidelity()-old_fid if dF < 0: dF_mean.append(dF) return np.mean(dF_mean)/ np.log(rate)
def sample_m0(n_sample, n_step, model: MODEL): X = np.empty((n_sample, n_step), dtype=int) y = np.zeros(n_sample) tmp = np.ones(n_step, dtype=int) # m = 0 state ... tmp[0:n_step // 2] = 0 np.random.shuffle(tmp) for i in range(n_sample): X[i] = tmp model.update_protocol(tmp) y[i] = model.compute_fidelity() np.random.shuffle(tmp) return X, y
def SD(param, model: MODEL, init=False): n_step = param['n_step'] n_fid_eval = 0 if init: # Random initialization model.update_protocol( np.random.randint(0, model.n_h_field, size=n_step)) old_fid = model.compute_fidelity() best_protocol = np.copy(model.protocol()) else: # So user can feed in data say from a specific protocol old_fid = model.compute_fidelity() best_protocol = np.copy(model.protocol()) while True: # careful with this. For binary actions, this is guaranteed to break random_position = np.arange(n_step, dtype=int) np.random.shuffle(random_position) local_minima = True for t in random_position: model.update_hx(t, model.random_flip(t)) new_fid = model.compute_fidelity() n_fid_eval += 1 if new_fid > old_fid: # accept descent old_fid = new_fid best_protocol = np.copy(model.protocol()) local_minima = False # will exit for loop before it ends ... local update accepted break else: model.update_hx(t, model.random_flip(t)) if local_minima: break return old_fid, best_protocol, n_fid_eval
def main(): # Reading parameters from para.dat file parameters = utils.read_parameter_file() # Printing parameters for user utils.print_parameters(parameters) # Defining Hamiltonian H = HAMILTONIAN(**parameters) # Defines the model, and precomputes evolution matrices given set of states model = MODEL(H, parameters) L = 6 T = 0.1 n_step = 28 param = {'L' : L, 'T': T, 'n_step': n_step} file_name = make_file_name(param, root= "/projectnb/fheating/SGD/ES/dynamicQL/SA/ES/data/") with open(file_name, 'rb') as f: fidelities=pickle.load(f) nfid=fidelities.shape[0] fid_and_energy=np.empty((nfid,2),dtype=np.float) for i,f in zip(range(nfid),fidelity): if i%10000 == 0: print(i) model.update_protocol(b2_array(i, w = 28)) psi = model.compute_evolved_state() fid_and_energy[i][0]=model.compute_fidelity(psi_evolve = psi) fid_and_energy[i][1]=model.compute_energy(psi_evolve = psi) print(fid_and_energy[0],'\t',f) break with open("ES_L-06_T-0.500_n_step-28-test.pkl", ‘wb’) as f: fidelities=pickle.dump(fid_and_energy,f, protocol=4)
def SD_2SF(param, model:MODEL, init_random=False): # 2 spin flip algorithm --> note that scaling is O(N^3) so can only deal with n_step < 500 or so ! if model.n_h_field > 2: assert False, 'This works only for bang-bang protocols' n_step = param['n_step'] n_fid_eval = 0 n_visit = 1 if init_random: # Random initialization model.update_protocol( np.random.randint(0, model.n_h_field, size=n_step) ) old_fid = model.compute_fidelity() best_protocol = np.copy(model.protocol()) else: # So user can feed in data say from a specific protocol old_fid = model.compute_fidelity() best_protocol = np.copy(model.protocol()) x1_ar, x2_ar = np.triu_indices(n_step,1) n_2F_step = x1_ar.shape[0] # number of possible 2-flip updates order2F = np.arange(0,n_2F_step, dtype=np.int) # ordering sequenc // to be randomly shuffled n_1F_step = n_step order1F = np.arange(0,n_1F_step, dtype=np.int) # ordering sequenc // to be randomly shuffled order1F_vs_2F = 2*np.ones(n_2F_step + n_1F_step, dtype=np.int) order1F_vs_2F[:n_1F_step]=1 ############################ ######################### while True: # careful with this. For binary actions, this is guaranteed to break np.random.shuffle(order1F) np.random.shuffle(order2F) np.random.shuffle(order1F_vs_2F) idx_1F=0 idx_2F=0 local_minima_reached = True for update_type in order1F_vs_2F: if update_type == 1: # perform 1 SF update t = order1F[idx_1F] model.update_hx(t, model.protocol_hx(t)^1) # assumes binary fields new_fid = model.compute_fidelity() n_fid_eval +=1 idx_1F+=1 if new_fid > old_fid : # accept descent #print("%.15f"%new_fid,'\t',n_fid_eval) n_visit+=1 old_fid = new_fid local_minima_reached = False # will exit for loop before it ends ... local update accepted break else: model.update_hx(t, model.protocol_hx(t)^1) else: # perform 2 SF update o2F=order2F[idx_2F] t1,t2 = x1_ar[o2F],x2_ar[o2F] model.update_hx(t1, model.protocol_hx(t1)^1) # assumes binary fields model.update_hx(t2, model.protocol_hx(t2)^1) new_fid = model.compute_fidelity() n_fid_eval +=1 idx_2F+=1 if new_fid > old_fid : # accept descent #print("%.15f"%new_fid,'\t',n_fid_eval) n_visit+=1 old_fid = new_fid local_minima_reached = False # will exit for loop before it ends ... local update accepted break else: model.update_hx(t1, model.protocol_hx(t1)^1) # assumes binary fields model.update_hx(t2, model.protocol_hx(t2)^1) if local_minima_reached: break return old_fid, np.copy(model.protocol()), n_fid_eval, n_visit