def parallel_tempering(graph, function, X, T, iterr, prev_E, history, swap_function, nswaps, nbefore, process_number, process_count, queues_A, pipes_swap, send_ret_val): best_path = [] best_path_value = float('inf') for step in range(iterr): # Run nbefore steps of simulated annealing X, prev_E, delta_E, history, _ = anneal_once(graph, function, X, T, prev_E, history, swap_function, nswaps) if prev_E < best_path_value: best_path = X best_path_value = prev_E # Decide which chains, if any, to exchange if step % nbefore == 0: #Each process can swap with prior processes if process_number < process_count - 1: queues_A[process_number].put(delta_E) queues_A[process_number].put(T) # Acceptance probability if process_number > 0: next_delta_E = queues_A[process_number - 1].get() next_T = queues_A[process_number - 1].get() #0 = ln(1) A = np.exp(min(0, ((delta_E - next_delta_E)/T) + ((next_delta_E - delta_E)/next_T))) #Finish any started swap before going to next one if process_number < process_count - 1: #Check if need to swap with subsequent process swap_bool = pipes_swap[0].recv() if swap_bool: #If so, publish info then retrieve info pipes_swap[0].send([prev_E, X]) prev_E, X = pipes_swap[0].recv() #Only initiate swap from higher-indexed process, i.e. not first process if process_number > 0: if np.random.uniform() < A: #Swap is happening pipes_swap[-1].send(True) #Send info to next process, then retrieve info pipes_swap[-1].send([prev_E, X]) prev_E, X = pipes_swap[-1].recv() else: #No swap necessary pipes_swap[-1].send(False) send_ret_val.send([best_path, history]) return
def serial_parallel_tempering(graph, function, initial_Xs, initial_temps, iterr, swap_function, nswaps, nbefore): # Make sure inputs are as expected assert(len(initial_temps) == len(initial_Xs)), "Mismatched input dimensions" assert(initial_temps[0] == 1), "First temperature should be one" # Initialize stuff nsystems = len(initial_temps) Xs = list(initial_Xs) Ts = initial_temps prev_Es = [function(graph, Xs[i]) for i in range(nsystems)] delta_Es = [0] * nsystems history = [[] for i in xrange(nsystems)] best_path = [] best_path_value = float('inf') current_time = time.time() for i in xrange(nsystems): history[i].append([prev_Es[i], initial_Xs[i], Ts[i], current_time]) for step in range(iterr): for i in range(nsystems): # Run nbefore steps of simulated annealing Xs[i], prev_Es[i], delta_Es[i], history[i], _ =\ anneal_once(graph, function, Xs[i], Ts[i], prev_Es[i], history[i], swap_function, nswaps) # Store best path if prev_Es[i] < best_path_value: best_path = Xs[i] best_path_value = prev_Es[i] # Decide which chains, if any, to exchange if step % nbefore == 0: for i in range(nsystems - 1, 0, -1): # Acceptance probability # 0 = ln(1) A = np.exp(min(0, ((delta_Es[i] - delta_Es[i-1])/Ts[i]) + ((delta_Es[i-1] - delta_Es[i])/Ts[i-1]))) if np.random.uniform() < A: # Exchange most recent updates and paths prev_Es[i], prev_Es[i-1] = prev_Es[i-1], prev_Es[i] Xs[i], Xs[i-1] = Xs[i-1], Xs[i] return best_path, history