def find_equilibrium(self, solver_name='ustm', composite=True, solver_kwargs={}): if solver_name == 'ustm': solver_func = ustm.universal_similar_triangles_method starting_msg = 'Universal similar triangles method...' if not 'L_init' in solver_kwargs: solver_kwargs[ 'L_init'] = 0.1 * self.graph.max_path_length * self.total_od_flow / self.gamma elif solver_name == 'ugd': solver_func = ugd.universal_gradient_descent_method starting_msg = 'Universal gradient descent method...' if not 'L_init' in solver_kwargs: solver_kwargs[ 'L_init'] = 0.1 * self.graph.max_path_length * self.total_od_flow / self.gamma else: raise NotImplementedError('Unknown solver!') phi_big_oracle = oracles.PhiBigOracle(self.graph, self.graph_correspondences, gamma=self.gamma) h_oracle = oracles.HOracle(self.graph.free_flow_times, self.graph.capacities, rho=self.rho, mu=self.mu) primal_dual_calculator = dfc.PrimalDualCalculator( phi_big_oracle, h_oracle, self.graph.free_flow_times, self.graph.capacities, rho=self.rho, mu=self.mu) if composite == True: print('Composite optimization...') oracle = phi_big_oracle prox = h_oracle.prox else: print('Non-composite optimization...') oracle = phi_big_oracle + h_oracle def prox_func(grad, point, A): """ Computes argmin_{t: t \in Q} <g, t> + A / 2 * ||t - p||^2 where Q - the feasible set {t: t >= free_flow_times}, A - constant, g - (sub)gradient vector, p - point at which prox is calculated """ return np.maximum(point - grad / A, self.graph.free_flow_times) prox = prox_func print('Oracles created...') print(starting_msg) result = solver_func(oracle, prox, primal_dual_calculator, t_start=self.graph.free_flow_times, **solver_kwargs) #TODO: add equilibrium travel times between zones return result
def find_equilibrium(self, solver_name='ustf', solver_kwargs={}, verbose=False): if solver_name == 'fwa': solver_func = fwa.frank_wolfe_algorithm starting_msg = 'Frank-Wolfe algorithm...' elif solver_name == 'ustf': solver_func = ustf.universal_similar_triangles_function starting_msg = 'Universal similar triangles function...' if not 'L_init' in solver_kwargs: solver_kwargs[ 'L_init'] = self.graph.max_path_length**0.5 * self.total_od_flow elif solver_name == 'ugd': solver_func = ugd.universal_gradient_descent_function starting_msg = 'Universal gradient descent...' if not 'L_init' in solver_kwargs: solver_kwargs['L_init'] = 1.0 elif solver_name == 'sd': solver_func = ugd.universal_gradient_descent_function starting_msg = 'Subgradient descent...' elif solver_name == 'uagmsdr': solver_func = uagmsdr.UAGMsDR starting_msg = 'Universal Accelerated Gradient Method with Small-Dimensional Relaxation...' else: raise NotImplementedError('Unknown solver!') if solver_name in ['ugd', 'ustf', 'sd', 'uagmsdr']: prox_h = ProxH(self.graph.freeflow_times, self.graph.capacities, mu=self.mu, rho=self.rho) phi_big_oracle = oracles.PhiBigOracle(self.graph, self.graph_correspondences) primal_dual_calculator = dfc.PrimalDualCalculator( phi_big_oracle, self.graph.freeflow_times, self.graph.capacities, mu=self.mu, rho=self.rho) if verbose: print('Oracles created...') print(starting_msg) if solver_name == 'fwa': result = solver_func(phi_big_oracle, primal_dual_calculator, t_start=self.graph.freeflow_times, verbose=verbose, **solver_kwargs) else: result = solver_func(phi_big_oracle, prox_h, primal_dual_calculator, t_start=self.graph.freeflow_times, verbose=verbose, **solver_kwargs) return result
def model_solve(graph, graph_correspondences, total_od_flow, solver_name='ustf', gamma=1.0, mu=0.25, rho=1.0, epsilon=1e-3, max_iter=1000, verbose=False): if solver_name == 'ustf': solver_func = ustf.universal_similar_triangles_function phi_small_solver_func = pss.PhiSmallSolver starting_msg = 'Universal similar triangles function...' elif solver_name == 'ugd': solver_func = ugd.universal_gradient_descent_function phi_small_solver_func = ug_pss.UnivGradPhiSmallSolver starting_msg = 'Universal gradient descent...' else: print('Define function!') #L_init = 1.0 L_init = 0.1 * graph.max_path_length * total_od_flow / gamma phi_small_solver = phi_small_solver_func(graph.free_flow_times, graph.capacities, rho=rho, mu=mu) phi_big_oracle = oracles.PhiBigOracle(graph, graph_correspondences, gamma=gamma) primal_dual_calculator = dfc.PrimalDualCalculator(phi_big_oracle, graph.free_flow_times, graph.capacities, rho=rho, mu=mu) if verbose: print('Oracles created...') print(starting_msg) result = solver_func(phi_big_oracle, phi_small_solver, primal_dual_calculator, graph.free_flow_times, L_init, max_iter=max_iter, epsilon=epsilon, verbose=verbose) #t_average_w = phi_big_oracle.time_av_w_matrix(t_result) return result
def __init__(self, data_reader, mu=0.25, rho=0.15): self.graph = tg.TransportGraph(data_reader) self.graph_correspondences = data_reader.graph_correspondences self.mu = mu self.rho = rho self.t = torch.tensor(self.graph.freeflow_times, requires_grad=True) self.grad_sum = torch.zeros(self.t.size()) self.phi_big_oracle = oracles.PhiBigOracle(self.graph, self.graph_correspondences) self.primal_dual_calculator = dfc.PrimalDualCalculator( self.phi_big_oracle, self.graph.freeflow_times, self.graph.capacities, mu=self.mu, rho=self.rho)
def find_equilibrium(self, solver_name='ustm', composite=True, solver_kwargs={}, base_flows=None): if solver_name == 'fwm': solver_func = fwm.frank_wolfe_method starting_msg = 'Frank-Wolfe method...' elif solver_name == 'ustm': solver_func = ustm.universal_similar_triangles_method starting_msg = 'Universal similar triangles method...' if not 'L_init' in solver_kwargs: solver_kwargs[ 'L_init'] = self.graph.max_path_length**0.5 * self.total_od_flow elif solver_name == 'ugd': solver_func = ugd.universal_gradient_descent_method starting_msg = 'Universal gradient descent method...' if not 'L_init' in solver_kwargs: solver_kwargs[ 'L_init'] = self.graph.max_path_length**0.5 * self.total_od_flow elif solver_name == 'wda': solver_func = wda.weighted_dual_averages_method starting_msg = 'Weighted dual averages method...' elif solver_name == 'sd': solver_func = sd.subgradient_descent_method starting_msg = 'Subgradient descent method...' else: raise NotImplementedError('Unknown solver!') phi_big_oracle = oracles.PhiBigOracle(self.graph, self.graph_correspondences) h_oracle = oracles.HOracle(self.graph.freeflow_times, self.graph.capacities, rho=self.rho, mu=self.mu) primal_dual_calculator = dfc.PrimalDualCalculator( phi_big_oracle, h_oracle, self.graph.freeflow_times, self.graph.capacities, rho=self.rho, mu=self.mu, base_flows=base_flows) if composite == True or solver_name == 'fwm': if not solver_name == 'fwm': print('Composite optimization...') oracle = phi_big_oracle prox = h_oracle.prox else: print('Non-composite optimization...') oracle = phi_big_oracle + h_oracle def prox_func(grad, point, A): """ Computes argmin_{t: t \in Q} <g, t> + A / 2 * ||t - p||^2 where Q - the feasible set {t: t >= free_flow_times}, A - constant, g - (sub)gradient vector, p - point at which prox is calculated """ return np.maximum(point - grad / A, self.graph.freeflow_times) prox = prox_func print('Oracles created...') print(starting_msg) if solver_name == 'fwm': result = solver_func(oracle, primal_dual_calculator, t_start=self.graph.freeflow_times, **solver_kwargs) else: result = solver_func(oracle, prox, primal_dual_calculator, t_start=self.graph.freeflow_times, **solver_kwargs) #getting travel times of every non-zero trips between zones: result['zone travel times'] = {} for source in self.graph_correspondences: targets = self.graph_correspondences[source]['targets'] travel_times, _ = self.graph.shortest_distances( source, targets, result['times']) #mapping nodes' indices to initial nodes' names: source_nodes = [self.inds_to_nodes[source]] * len(targets) target_nodes = list(map(self.inds_to_nodes.get, targets)) result['zone travel times'].update( zip(zip(source_nodes, target_nodes), travel_times)) return result