def increment_depth_and_id(instances,type): # updates the ids and depths of instances = [instance1,instance2...] # update method depends on the type of branching that was performed id0 = instances[0].id depth = instances[0].depth if type == "constraint branching": n = 1 for inst in instances: inst.depth = depth+1 c = inst.c_branch[list(inst.c_branch.keys())[-1]] if pyo.value(c.lower) == None: new_id = 'c'+str(n)+'_'+str(int(pyo.value(c.upper))) elif pyo.value(c.upper) == None: new_id = 'c'+str(n)+'_'+str(int(pyo.value(c.lower))) else: #necessarily an equality constraint new_id = 'c'+str(n)+'_'+str(int(pyo.value(c.upper))) inst.id = id0+[new_id] n += 1 elif type == "index branching": for inst in instances: inst.depth = depth+1 inst.id = id0+["i"+str(inst.x[inst.branching_indexes[-1]].value)] elif type == "integer branching": for inst in instances: inst.depth = depth+1 inst.id = id0+["0"] else: raise NameError("Enter a valid branching type for increment depth and id function")
def test_instance(instance): clist = [] for c, val in list(instance.dual.items()): lower = m.pyo.value(c.body) if m.pyo.value( c.lower) == None else m.pyo.value(c.lower) upper = m.pyo.value(c.body) if m.pyo.value( c.upper) == None else m.pyo.value(c.upper) if upper + precision >= pyo.value(c.body) >= lower - precision: continue clist.append(c) return clist
def initialize_instance(instance): # takes an instsanciated pyomo concrete model and adds all the custom attributes that will be used later in the process # among others things it will : define the variables, add the constraint containers, delete the variables that are not usefull (we only keep the strictly inferior trianble of the X matrix), # delete the locations matrix for it is not necessary, we keep it as a seperate variable that will be used only by the graphing functions if instance.entry_type.value == "COORD": ''' we need to retrieve the locations and delete them from all instances for smaller size''' locations = to_list_locations( instance) #global parameter used for graphing of solutions del (instance.locations) # WORKS! else: #entry type is necessarily "WEIGHT" ''' we need to generate random coordinates for the plotting ''' locations = [(random() * 20, random() * 20) for i in range(instance.n.value)] max_cost = 0 for k in instance.costs.values(): if k > max_cost: max_cost = k instance.max_cost = max_cost #managing.normalize_costs(instance) ''' define variable x ''' instance.x = pyo.Var(instance.nodes, instance.nodes, bounds=set_bounds) #deleting uneused variables (i<=j) for i in instance.nodes: for j in instance.nodes: if i <= j: del (instance.x[i, j]) # instance.x[i,j].deactivate() ''' define flow variable ''' instance.flow = pyo.Var(instance.nodes, instance.nodes, bounds=set_bounds_flow) ''' define the objective function ''' instance.objective = pyo.Objective(expr=sum( instance.costs[i, j] * instance.x[i, j] for i in instance.nodes for j in instance.nodes if i > j)) ''' define degree constraints ''' instance.c_deg = pyo.Constraint(instance.nodes, rule=rule_deg) ''' define flow constraints ''' if flow_constraints: instance.c_flow = pyo.Constraint(instance.nodes, rule=rule_flow) instance.c_flow_deg = pyo.Constraint(instance.nodes, instance.nodes, rule=rule_flow_deg) instance.c_flow_deg_indirect = pyo.Constraint( instance.nodes, instance.nodes, rule=rule_flow_deg_indirect) ''' define capacity constraints as an empty list for now ''' instance.c_cap = pyo.ConstraintList( ) # on utilise cette structure pour pouvoir ajouter et supprimer des contraintes par la suite instance.c_mstar = pyo.ConstraintList() instance.c_glm = pyo.ConstraintList() instance.c_fci = pyo.ConstraintList() instance.c_sci = pyo.ConstraintList() instance.c_hti = pyo.ConstraintList() #liste vide pour commencer ''' defining dual values ''' instance.dual = pyo.Suffix(direction=pyo.Suffix.IMPORT) ''' definig list of values that will be fixed by branching (used for problem reduction) ''' ''' and the list of constraints used for branching if constraint branching is used ''' instance.branching_indexes = [] if cpp_constraint_branching: instance.c_branch = pyo.ConstraintList() instance.branching_sets = [] if not (index_branching) and not (integer_branching) and not ( cpp_constraint_branching): log.subtitle( "instance generation failed because no valid branching type is given" ) raise NameError("enter a valid branching type in globals settings") ''' defining wether or not the instance can be subject to constraint deactivation ''' if disable_constraint_deactivation or integer_branching or integer_simplifications: log.write( "disabling constraint deactivation because integer variables are activated (integer branching or simplifications)" ) instance.disable_constraint_deactivation = True instance.constraints_inactivity = {} else: instance.disable_constraint_deactivation = False instance.constraints_inactivity = {} ''' defining others parameters based on those in global.py ''' instance.reduction = 1 instance.id = [0] instance.depth = 0 if reduce_problem: managing.reduce_problem(instance, initial_problem_reduction) #managing.reduce_problem_neighboors(instance,5) if force_integer_to_depot: managing.integerize_edges_to_depot(instance) log.write("integerized " + str(instance.n.value) + " edges to depot " + str(len(list(instance.x.keys()))) + " variables") if force_all_edges_integer: managing.integerize_all_edges(instance) if force_closest_neighboors_integer: integerized = managing.integerize_edges( instance, max_dist=relative_distance_closest_neighboor) log.write("integerized " + str(len(integerized)) + " shortest edges out of " + str(len(list(instance.x.keys()))) + " variables with a relative distance of " + str(relative_distance_closest_neighboor * 100) + '%' + " of max_distance") '''solving the initial instance in order to initialize instance.x values ''' opt.solve(instance) instance.objective_value = pyo.value( instance.objective ) #recording this as attribute to save computation time log.write_timed("finished constructing instance model") return instance, locations
elif feasible_integer_found : log.write("feasible integer solution already found",instance.id) elif not(solver_success): log.write("instance could not be solved after column generation") elif instance.objective_value >= instance_manager.upper_bound: log.write("instance lower bound exceeds upper bound of problem") full_graph(instance,locations,"partial solution that was cut "+str(round(global_time(),2)),True) instance = instance_manager.pop() #will return none if there are no instances left in queue ''' solving is finished ''' log.title("finished solving") log.write_timed("") if search_tree == "end": SearchTree(instance_manager,old_nodes).show() ''' printing results ''' if instance_manager.best_feasible_integer_solution==None: #no actual solution was found log.subtitle("no optimal integer solution found") if len(instance_manager.partial_solution_recorded)>0: log.write("best lower bound found :" +str(pyo.value(instance_manager.partial_solution_recorded[0].objective))+" and is "+str(managing.integer_percent(instance_manager.partial_solution_recorded[0]))+"% integer") log.write(managing.print_solution_routes(instance_manager.partial_solution_recorded[0])) full_graph(instance_manager.partial_solution_recorded[0],locations,"partial") else: log.write("not a single partial solution was recorded...") else: log.subtitle("best feasible integer solution found has objective value of "+str(pyo.value(instance_manager.best_feasible_integer_solution.objective))) log.write(managing.print_solution_routes(instance_manager.best_feasible_integer_solution)) full_graph(instance_manager.best_feasible_integer_solution,locations,"final")
def show_bad_constraint(instance, cst): parent, index = cst.parent_component().name, cst.index() print("ctype: " + str(parent)) print( str(pyo.value(cst.lower)) + " <= " + str(pyo.value(cst.body)) + " <= " + str(pyo.value(cst.upper)))