Esempio n. 1
0
def column_generation_loop(instance, instance_manager):
    # a signle loop of column generation : adds all available types of cuts to the instance
    # also verifies if a feasible integer solution is found

    #0) check if solution is integer and has valid paths
    if managing.solution_is_integer(instance):
        instance0 = instance.clone()
        managing.integerize_solution(instance0)
        if paths_are_feasible(instance0):
            log.subtitle(
                "!!!!! feasible integer solution found with objective value of "
                + str(round(instance0.objective_value, 2)), instance0.id)
            assertion = " " if instance_manager.upper_bound > instance0.objective_value else " not "
            log.write(
                "new solution is" + assertion +
                "better than one previously found, this branch is dropped and its solution is"
                + assertion + "recorded")
            instance_manager.record_feasible_integer_solution(instance0)
            return True, False

    if column_input == "python":
        raise Exception(
            "hand implemented heuristics have been commented out in cap_constraint.py for more clarity in code reading, these methods are outdated in comparaison to the c++ library. If you whish to test them, uncomment them and comment this exception out"
        )
        #1) adding capacity cuts
        #success, count = cap.add_c_cap(instance)
        #log.write_awaiting_answer("capacity cuts: " +str(count))

        #2),3),4) ...
        # other types of cuts to be added

    elif column_input == "c++":
        success = cpp.generate_and_add_columns(instance)

    else:
        raise NameError("Enter a valide column input type")

    remove_inactive_constraints(instance)

    return False, success
Esempio n. 2
0
def branch(instance,instance_manager):
    #branches instance problem into complementary sub problem instances following various rules
    #adds new instances that have been correctly initialised to instance_manager 
    #returns success of branching 
    log.subtitle("entering branching",instance.id)
    initial_time = time()

    branching_candidates = []
    if index_branching:
        partial_time = time()
        log.write_awaiting_answer("index branching--> ")
        candidate = index_branching_candidates(instance)
        if candidate["instances"] != None:
            branching_candidates.append(candidate)
            log.write_answer(", score: "+str(branching_candidates[-1]["score"])+", time: "+str(round(time()-partial_time,2)))
            log.write_answer(", score: "+str(branching_candidates[-1]["score"])+", time: "+str(round(time()-partial_time,2)))
    if integer_branching:
        partial_time = time()
        log.write_awaiting_answer("integer branching--> ")
        candidate = integer_branching_candidates(instance)
        if candidate["instances"] != None:
            branching_candidates.append(candidate)
            log.write(", score: "+str(branching_candidates[-1]["score"])+", time: "+str(round(time()-partial_time,2)))
    
    if cpp_constraint_branching:
        partial_time = time()
        log.write_awaiting_answer("c++ constraint branching--> ")
        candidate = cpp_constraint_branching_candidate(instance)
        if candidate["instances"] != None:
            branching_candidates.append(candidate)
            log.write(", score: "+str(branching_candidates[-1]["score"])+", time: "+str(round(time()-partial_time,2)))
        
    if branching_candidates==[]:
        return False

    #coefficients = {"integer branching":1.1,"constraint branching":0.8,"index branching":1} #the bigger the coefficient, the lyklier it will be selected
    #best_candidate = sorted( branching_candidates, key = lambda candidate : candidate["score"]*coefficients[candidate["method"]], reverse=True )[0]
    best_candidate = select_best_candidate(branching_candidates,instance)
    log.write("BEST STRATEGY: "+str(best_candidate["method"]))
    
    #adding new instances to solving queue
    for instance in best_candidate["instances"]:
        set_lower_bound(instance)
        log.write("value of objective function is " +str(round(instance.objective_value,2)) + " for new instance " +list_to_string(instance.id)+" with lower bound "+str(instance.lower_bound)[:-1])
        instance_manager.add(instance)
    
    log.end_subtitle("end of branching, method: "+best_candidate["method"]+", smallest boost: "+str(best_candidate["score"]) +", time: "+str(round(time()-initial_time,2))+" seconds")
    return True
Esempio n. 3
0
def full_graph(instance, locations, status, bypass=False, show_only=False):
    if graphing or bypass:
        log.write("saving " + status + " solution to " + log.name + "_" +
                  status + "_solution_graph.png in current folder")
        g = Graph(instance, locations)
        g.update_with_x(instance.x)
        fig = plt.figure(figsize=(15, 15))
        plt.axis('off')
        plt.title("graph of " + status +
                  " solution found for CVRP solving with \n" +
                  str(instance.n.value) + " nodes, " +
                  str(instance.number_of_vehicles.value) +
                  " vehicles with capacity of " + str(instance.capacity.value))
        g.show()
        # fig.show()
        if show_only:
            fig.show()
            return
        fig.savefig(log.name + "/" + status + "_solution_graph.png",
                    bbox_inches='tight',
                    dpi=fig.dpi * 2)
        log.write_timed("finished saving graph")
        plt.close(fig)
        del (fig)
Esempio n. 4
0
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
Esempio n. 5
0
def rule_flow_deg(instance, i, j):
    return pyo.Constraint.Skip if j >= i else (
        instance.x[i, j] >= instance.flow[i, j])


def rule_flow_deg_indirect(instance, i, j):
    return pyo.Constraint.Skip if j >= i else (
        instance.x[i, j] >= instance.flow[j, i])


def to_list_locations(instance):
    d = []
    for i in instance.nodes:
        d.append((instance.locations[i, 0], instance.locations[i, 1]))
    return d


if __name__ == "main":
    ''' instanciate model with inbound data '''
    model = initialize_model()
    if len(sys.argv) == 1:
        file = "test3.dat"
        instance = model.create_instance(file)
    elif len(sys.argv) == 2:
        file = sys.argv[1]
        instance = construct_instance(model, file)
    else:
        raise "erroneous entry arguments"
    log.write("using input file " + file)
    instance, locations = initialize_instance(instance)
Esempio n. 6
0
elif "carp" in sys.argv[1]:
	raise "Carp problems (without specified number of vehicles) are not yet supported"
else:
	instance,locations = init.full_init(sys.argv[1])

log.title("starting CVRP solving for "+str(instance.n.value)+" nodes, "+str(instance.number_of_vehicles.value)+" vehicles with capacity of "+str(instance.capacity.value))

''''initialise instance manager '''
instance_manager = managing.instance_manager(instance)
full_graph(instance_manager.best_feasible_integer_solution,locations,"Google Opt solution")

'''computing lower_bound and adding to queue for column generation and branching '''
managing.set_lower_bound(instance)
instance_manager.add(instance)

log.write("initial upper bound of cvrp problem is "+str(instance_manager.upper_bound))

''' printing initial value of objective function '''
log.write("initial value of objective function "+str(round(instance.objective_value,2))+" and is "+str(managing.integer_percent(instance))+"% integer")

'''saving initial graph  '''
full_graph(instance,locations,"initial")

''' list of old instances used for the graping of the search Tree '''
old_nodes = []

''' actual branch and cut '''
instance = instance_manager.pop()
while instance!=None and max_time_not_reached() and instance.depth<=max_depth:		
	log.subtitle("starting processing of new instance with lower_bound of "+str(instance.lower_bound)+" ( upper_bound is "+str(instance_manager.upper_bound)+") ,depth: "+ str(instance.depth) +", global time: "+str(global_time()),instance.id)
	
Esempio n. 7
0
def column_generation(instance, instance_manager):
    # general method that will apply all available cut finding algorithms in a loop whose parameters are defined in globals.py
    log.subtitle("entering column generation", instance.id)
    initial_time, feasible_integer_found, loop_count, unmoving_count, solver_success, failure_count, obj_val_old, obj_val_old_global = round(
        time(), 2
    ), False, 1, 0, True, 0, instance.objective_value, instance.objective_value
    while instance.objective_value < instance_manager.upper_bound and loop_count <= (
            max_column_generation_count if len(instance.id) > 1 else
            max_column_generation_count_first_instance) and unmoving_count <= (
                max_unmoving_count if len(instance.id) > 1 else
                max_unmoving_count_first_instance) and not (
                    feasible_integer_found) and solver_success:
        log.write_awaiting_answer("loop " + str(loop_count) + "--> ",
                                  instance.id)
        # adding cuts
        feasible_integer_found, cuts_found = column_generation_loop(
            instance, instance_manager)
        #solving updated instance
        if cuts_found:
            solver_success = managing.solve(instance)

        #different cases are verified

        # we verify if the adding cuts method is a failure
        if not (cuts_found) and not (feasible_integer_found):
            log.write_awaiting_answer("all heurisitcs have failed")

        if not (feasible_integer_found):
            log.write_answer("improvement: " + str(
                round(
                    100 * (instance.objective_value - obj_val_old) /
                    obj_val_old, 5)) + '%' + ", objective: " +
                             str(round(instance.objective_value, 5)) + ", " +
                             str(managing.integer_percent(instance)) + '%' +
                             " integer, unmoving count:" +
                             str(unmoving_count) + ", reduction: " +
                             str(instance.reduction))

        # we verify if the objective value is increasing, if not : the cuts found have no effect
        if (instance.objective_value -
                obj_val_old) / obj_val_old < unmoving_constraint_threshold:
            unmoving_count += 1
            if unmoving_count >= (max_unmoving_count if instance.depth > 0 else
                                  max_unmoving_count_first_instance):
                log.write(
                    "no evolution in column_generation, moving on to branching",
                    instance.id)
                break
        else:
            unmoving_count = 0

        # we verifiy if the objective value is decreasing : if it is, we have probably dropped constraints that were usefull
        if (instance.objective_value - obj_val_old) / obj_val_old < -0.0001:
            log.write(
                "we are losing objective function value! useful constraints were dropped",
                instance.id)

        # we count the number of consecutive total failure
        if not (cuts_found):
            failure_count += 1
            if failure_count > max_failure_count_cuts:
                log.write(
                    "no evolution in column_generation, moving on to branching",
                    instance.id)
                break
        else:
            failure_count = 0

        obj_val_old = instance.objective_value
        loop_count += 1

    log.end_subtitle(
        "end of column generation, gain " +
        str(instance.objective_value - obj_val_old_global) + ", objective: " +
        str(instance.objective_value) + ", time: " +
        str(round(time() - initial_time, 2)), instance.id)
    return feasible_integer_found, solver_success
Esempio n. 8
0
def select_best_candidate(branching_candidates,initial_instance):
    # heuristics to select "best" candidate
    # we want to avoid having too many integer branchings to avoid too great calculation time. 

    # first ranking factor : minimum boost
    for candidate in branching_candidates:
        log.write_awaiting_answer(candidate["method"]+":" )
        for instance in candidate["instances"]:
            log.write_awaiting_answer(str(instance.id[-1])+", boost : "+str(instance.objective_value-initial_instance.objective_value))
        log.write_answer("")
    if len(branching_candidates)==1:
        return branching_candidates[0]
    for candidate in branching_candidates:
        for inst in candidate["instances"]:
            if inst.objective_value-initial_instance.objective_value<precision:
                branching_candidates.remove(candidate)
                break
    if len(branching_candidates)==1:
        return branching_candidates[0]
    clear_winner_thresh = 2
    min_boosts = {branching_candidate["method"]:(min( branching_candidate["instances"], key = lambda instance : instance.objective_value - initial_instance.objective_value ).objective_value-initial_instance.objective_value) for branching_candidate in branching_candidates}
    branching_candidates = sorted( branching_candidates, key = lambda candidate :   min_boosts[candidate["method"]], reverse = True ) #sorts them in decreasing order of smallest boost
    # we have at least 2
    try:
        if min_boosts[branching_candidates[0]["method"]] / min_boosts[branching_candidates[1]["method"]] >= clear_winner_thresh:
            log.write("biggest smallest boost is clear winner")
            return branching_candidates[0]
        # if we get here, the two "best" candidates are not distinguishable by their smallest boost ("best" as in biggest smallest boost)
        if len(branching_candidates) == 3 and min_boosts[branching_candidates[2]["method"]] / min_boosts[branching_candidates[0]["method"]] >= clear_winner_thresh: # checking if the last candidate holds a chance
            branching_candidates.pop(2)
    except ZeroDivisionError:
        raise Exception(str([inst.objective_value for inst in branching_candidates[0]["instances"]]) + " " + str([inst.objective_value for inst in branching_candidates[1]["instances"]]) + " " + str([inst.objective_value for inst in branching_candidates[2]["instances"]]) + " " + str(initial_instance.objective_value) )
    # at this point, all remaining candidates have a similar smallest boost, other factors must be taken into account 
    # second class ranking factors : number of instances created and their respective boost
    # we like having only one instance, but that considerably slows down solving process (integer fixing): we must find a trade-off
    branching_candidates = sorted( branching_candidates, key = lambda candidate : len(candidate["instances"]) )
    for candidate in branching_candidates:
        if len(candidate["instances"])==1 and candidate["method"]!= "integer branching":
            log.write("not intger branching with cut branches wins")
            return candidate # smallest amount of instances without slowing down solving time: perfect! (happens for instance when index branching has one of its branches unfeasible)
    m = sum( 1 for b in initial_instance.id if b==-1 ) # number of fixed integers
    if m<=6 and random()>0.6: #we can still fix integers without too much trouble
        for candidate in branching_candidates: 
            if len(candidate["instances"])==1:
                log.write("not too many integer branching")
                return candidate # this will always only return integer_branching if it is still in the remaining candidates
    # now we will simply assess if the remaining candidates have highly unbalanced instances, which is good. If so, we choose them, else we will simply take that with least amount of instances
    highly_unbalanced_candidates = []
    for candidate in branching_candidates:
        if len(candidate["instances"])>1 and max( (abs(candidate["instances"][j].objective_value-initial_instance.objective_value))/max((candidate["instances"][i].objective_value-initial_instance.objective_value),0.00001) for i in range(len(candidate["instances"])) for j in range(len(candidate["instances"])) if i!=j ) > 10 :
            highly_unbalanced_candidates.append(candidate)
    if len(highly_unbalanced_candidates)==1:
        log.write("unique highly unbalanced is winner")
        return highly_unbalanced_candidates[0]
    if len(highly_unbalanced_candidates)>=2: #can only be equal to 1 or 2
        log.write("smallest highly unbalanced is winner")
        return min( highly_unbalanced_candidates, key = lambda candidate : len(candidate["instances"]) )
    log.write("smallest balanced is winner")
    return branching_candidates[0]
Esempio n. 9
0
def create_dat(in_name, out_name):
    with open(in_name, "r") as f:
        """reading .vrp data file"""
        ''' supported formats : all formats from http://vrp.atd-lab.inf.puc-rio.br/index.php/en/ 
		letters must all be put to capital, all seperation characters (except . for commas) will be treated equally
		excepted arguments are : dimension, number of vehicles, capacity, locations or weights, demands '''
        lines = f.readlines()

        for i in range(len(lines)):
            line = sanitize(lines[i], " ")
            line = line.split(" ")
            while "" in line:
                line.remove("")
            lines[i] = line

        #expected_headers = ["NAME","COMMENT","TYPE","CVRP","DIMENSION","CAPACITY","DISTANCE","VEHICLES","EDGE WEIGHT TYPE","EDGE WEIGHT FORMAT","DISPLAY DATA TYPE","NODE COORD TYPE","NODE COORD SECTION","EDGE WEIGHT SECTION","DEMAND SECTION","DEPOT SECTION"]

        #dimension
        found = False
        for line in lines:
            if line[0] == "DIMENSION":
                found = True
                try:
                    dimension = int(float(line[-1]))
                except:
                    raise NameError(line)
                break
        if not (found):
            raise "Could not locate DIMENSION parameter"

        #capacity
        found = False
        for line in lines:
            if line[0] == "CAPACITY":
                found = True
                try:
                    capacity = int(float(line[-1]))
                except:
                    raise NameError(line)
                break
        if not (found):
            raise "Could not locate DIMENSION parameter"

        #demands
        found = False
        start_index_demand = 0
        for i in range(len(lines)):
            line = lines[i]
            if line[0] == "DEMAND" and line[1] == "SECTION":
                start_index_demand = i + 1
                found = True
                break
        if not (found):
            raise "Could not locate DEMAND SECTION parameter"

        #we want depot to be index 0 (needed for the coord/weights section)
        depot_set_apart = int(float(lines[start_index_demand][1])) > 0
        indexing_offset = int(float(
            lines[start_index_demand][0])) - (1 if depot_set_apart else 0)

        demands = [0]
        for i in range(0 if depot_set_apart else 1, dimension):
            line = lines[start_index_demand + i]
            try:
                demands.append(int(float(sanitize(line[1]))))
            except ValueError:
                print("error while adding demands with : ")
                print(start_index_demand + i)
                print(line)
                print(line[1])
                print(float(sanitize(line[1])))
            except IndexError:
                print("error while adding demands with : ")
                print(start_index_demand + i)
                print(line)
                print(line[1])
                print(float(sanitize(line[1])))

        #locations/weights
        found = False
        start_index = 0
        for i in range(len(lines)):
            line = lines[i]
            if line[0] == "NODE" and line[1] == "COORD" and line[
                    2] == "SECTION":
                found = True
                start_index = i + 1
                break
        if found:
            input_type = "COORD"
            locations = {}
            line = lines[start_index]
            for i in range(dimension):
                line = lines[start_index + i]
                try:
                    n, i, j = int(float(
                        sanitize(line[0]))) - indexing_offset, float(
                            sanitize(line[1])), float(sanitize(line[2]))
                except IndexError:
                    print("mauvaise indentation dans locations avec : ")
                    print(line)
                    print(n)
                    print(i)
                    print(j)
                    print(len(line))
                locations[(n, 0)] = i
                locations[(n, 1)] = j
            if depot_set_apart:
                depot_found = False
                depot_index = 0
                for i in range(len(lines)):
                    line = lines[i]
                    if line[0] == "DEPOT" and line[1] == "SECTION":
                        depot_index = i + 1
                        break
                if not (depot_found):
                    raise "could not locate DEPOT SECTION paremeter"
                line = lines[depot_index]
                locations[(0, 0)] = float(line[0])
                locations[(0, 1)] = float(line[1])
        else:
            raise Exception(
                "WEIGHT INPUT not yet implemented, must take into account the different types of wieghts input (lower,higher,complete etc.)"
            )
            for i in range(len(lines)):
                line = lines[i]
                if line[0] == "EDGE" and line[1] == "WEIGHT" and line[
                        2] == "SECTION":
                    start_index = i + 1
                    found = True
                    break
            if not (found):
                raise "Could locate neither EDGE WEIGTH SECTION nor NODE COORD SECTION parameters"
            input_type = "WEIGHT"
            weights = {}
            for i in range(dimension):
                line = lines[start_index + i]
                for j in range(len(line)):
                    try:
                        weights[(i, j)] = float(line[j])
                    except:
                        raise Exception(
                            "Error in writing of weights with paremeters " +
                            str(i) + " " + str(j) + " " + str(start_index))

        #number of vehicles
        found = False
        for i in range(len(lines)):
            line = lines[i]
            if line[0] == "VEHICLES":
                found = True
                number_of_vehicles = int(float(line[-1]))
                break
        if not (found):
            for i in range(len(lines)):
                line = lines[i]
                if line[0] == "NAME" and line[-1][0] == "k":
                    found = True
                    number_of_vehicles = int(float(line[-1][1:]))
                    break
        if not (found):
            number_of_vehicles = int(
                sum(demand for demand in demands) / capacity) + 4
            log.write(
                "could not locate VEHICLES. We calculated that we could use " +
                str(number_of_vehicles) + "vehicles")
    ''' constructing distances matrix if needed '''
    weights = {}
    if input_type == "COORD":
        for i in range(dimension):
            for j in range(dimension):
                weights[i,
                        j] = sqrt((locations[(i, 0)] - locations[(j, 0)])**2 +
                                  (locations[(i, 1)] - locations[(j, 1)])**2)
    '''writing those variables in the right format'''

    with open(out_name, "w") as f:

        #number of vehicles
        f.write("param number_of_vehicles := " + str(number_of_vehicles) +
                ";\n")
        f.write("\n")

        #dimension
        f.write("param n := " + str(dimension) + ";\n")
        f.write("\n")

        #capacity
        f.write("param capacity := " + str(capacity) + ";\n")
        f.write("\n")

        #type of entry
        f.write("param entry_type := " + input_type + ";\n")
        f.write("\n")

        if input_type == "COORD":
            f.write("param locations := \n")
            for k in locations.keys():
                f.write(
                    str(k[0]) + " " + str(k[1]) + " " + str(locations[k]) +
                    "\n")
            f.write(";\n")
            f.write("\n")

            f.write("param costs := \n")
            for k in weights.keys():
                f.write(
                    str(k[0]) + " " + str(k[1]) + " " + str(weights[k]) + "\n")
            f.write(";\n")
            f.write("\n")

        elif input_type == "WEIGHT":
            f.write("param locations := \n")
            for i in range(dimension):
                f.write(str(i) + " 0 -1" + "\n")
                f.write(str(i) + " 1 -1" + "\n")
            f.write(";\n")
            f.write("\n")

            f.write("param costs := \n")
            for k in weights.keys():
                f.write(
                    str(k[0]) + " " + str(k[1]) + " " + str(weights[k]) + "\n")
            f.write(";\n")
            f.write("\n")

        else:
            raise "We screwed up : input_type not recognized at time of writing"

        #demands
        f.write("param demands := \n")
        for i in range(dimension):
            f.write(str(i) + " " + str(demands[i]) + "\n")
        f.write(";\n")