feat: assignment 2
This commit is contained in:
parent
bae2763db1
commit
b5ea6f9865
34
Assignment2/A/tsp.P
Normal file
34
Assignment2/A/tsp.P
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*Jacob Besse
|
||||
Prolog*/
|
||||
|
||||
/*This is the data set.*/
|
||||
|
||||
edge(a,b,2). edge(a,c,3). edge(a,d,1).
|
||||
edge(b,d,2). edge(b,e,2). edge(b,f,4).
|
||||
edge(c,a,3). edge(c,d,2). edge(c,e,2).
|
||||
edge(d,a,1). edge(d,b,2).
|
||||
edge(e,c,2). edge(e,d,2). edge(e,f,1).
|
||||
edge(f,b,4). edge(f,c,3). edge(f,e,1).
|
||||
|
||||
len([], 0).
|
||||
len([_|T], N):- len(T, X), N is X+1 .
|
||||
|
||||
best_path(Visited, Total):- path(a, a, Visited, Total).
|
||||
|
||||
path(Start, Fin, Visited, Total) :- path(Start, Fin, [Start], Visited, 0, Total).
|
||||
|
||||
path(Start, Fin, CurrentLoc, Visited, Costn, Total) :-
|
||||
edge(Start, StopLoc, Distance), NewCostn is Costn + Distance, \+ member(StopLoc, CurrentLoc),
|
||||
path(StopLoc, Fin, [StopLoc|CurrentLoc], Visited, NewCostn, Total).
|
||||
|
||||
path(Start, Fin, CurrentLoc, Visited, Costn, Total) :-
|
||||
edge(Start, Fin, Distance), reverse([Fin|CurrentLoc], Visited), len(Visited, Q),
|
||||
(Q\=7 -> Total is 100000; Total is Costn + Distance).
|
||||
|
||||
shortest_path(Path):-setof(Cost-Path, best_path(Path,Cost), Holder),pick(Holder,Path).
|
||||
|
||||
best(Cost-Holder,Bcost-_,Cost-Holder):- Cost<Bcost,!.
|
||||
best(_,X,X).
|
||||
|
||||
pick([Cost-Holder|R],X):- pick(R,Bcost-Bholder),best(Cost-Holder,Bcost-Bholder,X),!.
|
||||
pick([X],X).
|
36
Assignment2/A/tsp.dat
Normal file
36
Assignment2/A/tsp.dat
Normal file
|
@ -0,0 +1,36 @@
|
|||
let dist[1,1]:=99;
|
||||
let dist[1,2]:=2;
|
||||
let dist[1,3]:=3;
|
||||
let dist[1,4]:=1;
|
||||
let dist[1,5]:=99;
|
||||
let dist[1,6]:=99;
|
||||
let dist[2,1]:=99;
|
||||
let dist[2,2]:=99;
|
||||
let dist[2,3]:=99;
|
||||
let dist[2,4]:=2;
|
||||
let dist[2,5]:=2;
|
||||
let dist[2,6]:=4;
|
||||
let dist[3,1]:=3;
|
||||
let dist[3,2]:=99;
|
||||
let dist[3,3]:=99;
|
||||
let dist[3,4]:=2;
|
||||
let dist[3,5]:=2;
|
||||
let dist[3,6]:=99;
|
||||
let dist[4,1]:=1;
|
||||
let dist[4,2]:=2;
|
||||
let dist[4,3]:=99;
|
||||
let dist[4,4]:=99;
|
||||
let dist[4,5]:=99;
|
||||
let dist[4,6]:=99;
|
||||
let dist[5,1]:=99;
|
||||
let dist[5,2]:=99;
|
||||
let dist[5,3]:=2;
|
||||
let dist[5,4]:=2;
|
||||
let dist[5,5]:=99;
|
||||
let dist[5,6]:=1;
|
||||
let dist[6,1]:=99;
|
||||
let dist[6,2]:=4;
|
||||
let dist[6,3]:=3;
|
||||
let dist[6,4]:=99;
|
||||
let dist[6,5]:=1;
|
||||
let dist[6,6]:=99;
|
22
Assignment2/A/tsp.lp
Normal file
22
Assignment2/A/tsp.lp
Normal file
|
@ -0,0 +1,22 @@
|
|||
% % Generate
|
||||
{ cycle(X,Y) : path(X,Y) } = 1 :- node(X).
|
||||
{ cycle(X,Y) : path(X,Y) } = 1 :- node(Y).
|
||||
|
||||
% Display
|
||||
#show cycle/2.
|
||||
% Optimize
|
||||
#minimize { C,X,Y : cycle(X,Y), edge(X,Y,C) }.
|
||||
|
||||
% Nodes
|
||||
node(a;b;c;d;e;f).
|
||||
% (Directed) Edges
|
||||
path(a,(b;c;d)). path(b,(d;e;f)). path(c,(a;d;e)).
|
||||
path(d,(a;b)). path(e,(c;d;f)). path(f,(b;c;e)).
|
||||
|
||||
% Edge Costs
|
||||
edge(a,b,2). edge(a,c,3). edge(a,d,1).
|
||||
edge(b,d,2). edge(b,e,2). edge(b,f,4).
|
||||
edge(c,a,3). edge(c,d,2). edge(c,e,2).
|
||||
edge(d,a,1). edge(d,b,2).
|
||||
edge(e,c,2). edge(e,d,2). edge(e,f,1).
|
||||
edge(f,b,4). edge(f,c,3). edge(f,e,1).
|
26
Assignment2/A/tsp.mod
Normal file
26
Assignment2/A/tsp.mod
Normal file
|
@ -0,0 +1,26 @@
|
|||
param N := 6;
|
||||
|
||||
var m{1..N};
|
||||
|
||||
param dist{1..N,1..N} integer > 0;
|
||||
|
||||
var x{1..N,1..N} binary;
|
||||
|
||||
minimize Total:
|
||||
sum{ i in 1..N,j in 1..N: i<>j} dist[i,j]* x[i,j];
|
||||
|
||||
C1{k in 1..N}: sum{i in 1..N: i <> k} x[i,k] =1;
|
||||
|
||||
C2{k in 1..N}: sum{i in 1..N: i <> k} x[k,i] =1;
|
||||
|
||||
C3{i in 2..N, j in 2..N: i <> j}: m[i]-m[j]+N*x[i,j]<=N-1;
|
||||
|
||||
C4{i in 2..N}: m[i]<=N-1;
|
||||
|
||||
|
||||
data tsp.dat;
|
||||
option solver cplex;
|
||||
solve;
|
||||
display Total;
|
||||
display x;
|
||||
display m;
|
80
Assignment2/A/tsp.py
Normal file
80
Assignment2/A/tsp.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
"""Simple Travelling Salesperson Problem (TSP) between cities."""
|
||||
|
||||
from ortools.constraint_solver import routing_enums_pb2
|
||||
from ortools.constraint_solver import pywrapcp
|
||||
|
||||
|
||||
def create_data_model():
|
||||
"""Stores the data for the problem."""
|
||||
data = {}
|
||||
data["distance_matrix"] = [
|
||||
[99, 2, 3, 1, 99, 99],
|
||||
[99, 99, 99, 2, 2, 4],
|
||||
[3, 99, 99, 2, 2, 99],
|
||||
[1, 2, 99, 99, 99, 99],
|
||||
[99, 99, 2, 2, 99, 1],
|
||||
[99, 4, 3, 99, 1, 99],
|
||||
]
|
||||
data["num_vehicles"] = 1
|
||||
data["depot"] = 0
|
||||
return data
|
||||
|
||||
|
||||
def print_solution(manager, routing, solution):
|
||||
"""Prints solution on console."""
|
||||
print(f"Objective: {solution.ObjectiveValue()} miles")
|
||||
index = routing.Start(0)
|
||||
plan_output = "Route for vehicle 0:\n"
|
||||
route_distance = 0
|
||||
while not routing.IsEnd(index):
|
||||
plan_output += f" {manager.IndexToNode(index) + 1} ->"
|
||||
previous_index = index
|
||||
index = solution.Value(routing.NextVar(index))
|
||||
route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)
|
||||
plan_output += f" {manager.IndexToNode(index)}\n"
|
||||
plan_output += f"Route distance: {route_distance} miles\n"
|
||||
print(plan_output)
|
||||
|
||||
|
||||
def main():
|
||||
"""Entry point of the program."""
|
||||
# Instantiate the data problem.
|
||||
data = create_data_model()
|
||||
|
||||
# Create the routing index manager.
|
||||
manager = pywrapcp.RoutingIndexManager(
|
||||
len(data["distance_matrix"]), data["num_vehicles"], data["depot"]
|
||||
)
|
||||
|
||||
# Create Routing Model.
|
||||
routing = pywrapcp.RoutingModel(manager)
|
||||
|
||||
|
||||
def distance_callback(from_index, to_index):
|
||||
"""Returns the distance between the two nodes."""
|
||||
# Convert from routing variable Index to distance matrix NodeIndex.
|
||||
from_node = manager.IndexToNode(from_index)
|
||||
to_node = manager.IndexToNode(to_index)
|
||||
return data["distance_matrix"][from_node][to_node]
|
||||
|
||||
transit_callback_index = routing.RegisterTransitCallback(distance_callback)
|
||||
|
||||
# Define cost of each arc.
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
|
||||
|
||||
# Setting first solution heuristic.
|
||||
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
|
||||
search_parameters.first_solution_strategy = (
|
||||
routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
|
||||
)
|
||||
|
||||
# Solve the problem.
|
||||
solution = routing.SolveWithParameters(search_parameters)
|
||||
|
||||
# Print solution on console.
|
||||
if solution:
|
||||
print_solution(manager, routing, solution)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
10
Assignment2/B/data.lp
Normal file
10
Assignment2/B/data.lp
Normal file
|
@ -0,0 +1,10 @@
|
|||
task(0, 2).
|
||||
task(1, 3).
|
||||
task(2, 1).
|
||||
task(3, 9).
|
||||
task(4, 2).
|
||||
task(5, 8).
|
||||
task(6, 9).
|
||||
task(7, 8).
|
||||
task(8, 5).
|
||||
task(9, 8).
|
1
Assignment2/B/data.py
Normal file
1
Assignment2/B/data.py
Normal file
|
@ -0,0 +1 @@
|
|||
[2, 3, 1, 9, 2, 8, 9, 8, 5, 8]
|
10
Assignment2/B/data10.lp
Normal file
10
Assignment2/B/data10.lp
Normal file
|
@ -0,0 +1,10 @@
|
|||
task(0, 4).
|
||||
task(1, 1).
|
||||
task(2, 3).
|
||||
task(3, 9).
|
||||
task(4, 10).
|
||||
task(5, 7).
|
||||
task(6, 5).
|
||||
task(7, 10).
|
||||
task(8, 1).
|
||||
task(9, 3).
|
1
Assignment2/B/data10.py
Normal file
1
Assignment2/B/data10.py
Normal file
|
@ -0,0 +1 @@
|
|||
[4, 1, 3, 9, 10, 7, 5, 10, 1, 3]
|
20
Assignment2/B/data20.lp
Normal file
20
Assignment2/B/data20.lp
Normal file
|
@ -0,0 +1,20 @@
|
|||
task(0, 7).
|
||||
task(1, 6).
|
||||
task(2, 2).
|
||||
task(3, 17).
|
||||
task(4, 10).
|
||||
task(5, 19).
|
||||
task(6, 20).
|
||||
task(7, 17).
|
||||
task(8, 1).
|
||||
task(9, 12).
|
||||
task(10, 17).
|
||||
task(11, 6).
|
||||
task(12, 5).
|
||||
task(13, 7).
|
||||
task(14, 20).
|
||||
task(15, 17).
|
||||
task(16, 2).
|
||||
task(17, 3).
|
||||
task(18, 19).
|
||||
task(19, 11).
|
1
Assignment2/B/data20.py
Normal file
1
Assignment2/B/data20.py
Normal file
|
@ -0,0 +1 @@
|
|||
[7, 6, 2, 17, 10, 19, 20, 17, 1, 12, 17, 6, 5, 7, 20, 17, 2, 3, 19, 11]
|
30
Assignment2/B/data30.lp
Normal file
30
Assignment2/B/data30.lp
Normal file
|
@ -0,0 +1,30 @@
|
|||
task(0, 1).
|
||||
task(1, 19).
|
||||
task(2, 21).
|
||||
task(3, 8).
|
||||
task(4, 6).
|
||||
task(5, 24).
|
||||
task(6, 17).
|
||||
task(7, 23).
|
||||
task(8, 15).
|
||||
task(9, 22).
|
||||
task(10, 14).
|
||||
task(11, 2).
|
||||
task(12, 2).
|
||||
task(13, 10).
|
||||
task(14, 3).
|
||||
task(15, 17).
|
||||
task(16, 17).
|
||||
task(17, 19).
|
||||
task(18, 26).
|
||||
task(19, 9).
|
||||
task(20, 28).
|
||||
task(21, 16).
|
||||
task(22, 22).
|
||||
task(23, 19).
|
||||
task(24, 17).
|
||||
task(25, 15).
|
||||
task(26, 18).
|
||||
task(27, 15).
|
||||
task(28, 23).
|
||||
task(29, 27).
|
1
Assignment2/B/data30.py
Normal file
1
Assignment2/B/data30.py
Normal file
|
@ -0,0 +1 @@
|
|||
[1, 19, 21, 8, 6, 24, 17, 23, 15, 22, 14, 2, 2, 10, 3, 17, 17, 19, 26, 9, 28, 16, 22, 19, 17, 15, 18, 15, 23, 27]
|
15
Assignment2/B/randomgen.py
Normal file
15
Assignment2/B/randomgen.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
import random
|
||||
import sys
|
||||
if len(sys.argv) == 2: x = int(sys.argv[1])
|
||||
else: x = 10
|
||||
file1 = open("data" + str(x) + ".lp", "w")
|
||||
file2 = open("data" + str(x) + ".py", "w")
|
||||
file2.write('[')
|
||||
for i in range(x):
|
||||
j = random.randint(1,x)
|
||||
file1.write("task({}, {}).\n".format(i, j))
|
||||
file2.write(str(j))
|
||||
if i != x - 1: file2.write(", ")
|
||||
file2.write(']')
|
||||
file1.close()
|
||||
file2.close()
|
16
Assignment2/B/task.lp
Normal file
16
Assignment2/B/task.lp
Normal file
|
@ -0,0 +1,16 @@
|
|||
% Input facts
|
||||
#const deadline = 90.
|
||||
#const processors = 8.
|
||||
#include "data30.lp".
|
||||
|
||||
1 { start(T, Time) : Time = 0..deadline } 1 :- task(T, _).
|
||||
1 { end(T, Time) : Time = 0..deadline } 1 :- task(T, _).
|
||||
|
||||
:- start(T, Time), end(T, End), task(T, Length), End != Time + Length.
|
||||
|
||||
:- Time = 0..deadline, not #count{ T : start(T, StartTime), end(T, EndTime), StartTime <= Time, Time < EndTime } <= processors.
|
||||
|
||||
:- task(T, _), end(T, Time), Time > deadline.
|
||||
|
||||
#show start/2.
|
||||
#show end/2.
|
50
Assignment2/B/task.py
Normal file
50
Assignment2/B/task.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
"""Solves a simple assignment problem."""
|
||||
from ortools.sat.python import cp_model
|
||||
|
||||
|
||||
def main() -> None:
|
||||
# Data
|
||||
costs = [10,5,8,10,5,2,1]
|
||||
num_workers = 2
|
||||
deadline = 20
|
||||
num_tasks = len(costs)
|
||||
|
||||
# Model
|
||||
model = cp_model.CpModel()
|
||||
|
||||
# Variables
|
||||
x = {}
|
||||
for worker in range(num_workers):
|
||||
for task in range(num_tasks):
|
||||
x[worker, task] = model.new_bool_var(f"x[{worker},{task}]")
|
||||
|
||||
# Each task is assigned to exactly one worker.
|
||||
for task in range(num_tasks):
|
||||
model.add_exactly_one(x[worker, task] for worker in range(num_workers))
|
||||
|
||||
# Objective
|
||||
for worker in range(num_workers):
|
||||
objective_terms = []
|
||||
for task in range(num_tasks):
|
||||
objective_terms.append(costs[task] * x[worker, task])
|
||||
model.AddLinearConstraint(sum(objective_terms), 0, deadline)
|
||||
|
||||
# Solve
|
||||
solver = cp_model.CpSolver()
|
||||
status = solver.solve(model)
|
||||
|
||||
# Print solution.
|
||||
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
|
||||
print(f"Total cost = {solver.objective_value}\n")
|
||||
for worker in range(num_workers):
|
||||
for task in range(num_tasks):
|
||||
if solver.boolean_value(x[worker, task]):
|
||||
print(
|
||||
f"Worker {worker} assigned to task {task}."
|
||||
+ f" Cost = {costs[task]}"
|
||||
)
|
||||
else:
|
||||
print("No solution found.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
13
Assignment2/C/cut.dat
Normal file
13
Assignment2/C/cut.dat
Normal file
|
@ -0,0 +1,13 @@
|
|||
param: WIDTHS: orders:=
|
||||
6.77 10
|
||||
7.56 40
|
||||
17.46 33
|
||||
18.76 10 ;
|
||||
|
||||
param nPAT := 9 ;
|
||||
|
||||
param nbr: 1 2 3 4 5 6 7 8 9 :=
|
||||
6.77 0 1 1 0 3 2 0 1 4
|
||||
7.56 1 0 2 1 1 4 6 5 2
|
||||
17.46 0 1 0 2 1 0 1 1 1
|
||||
18.76 3 2 2 1 1 1 0 0 0 ;
|
66
Assignment2/C/cut.lp
Normal file
66
Assignment2/C/cut.lp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#const max = 10.
|
||||
#const size = 30.
|
||||
order(1, size).
|
||||
order(2, size).
|
||||
order(3, size).
|
||||
order(4, size).
|
||||
|
||||
width(1).
|
||||
width(2).
|
||||
width(3).
|
||||
width(4).
|
||||
|
||||
pattern(1, 1, 0).
|
||||
pattern(1, 2, 1).
|
||||
pattern(1, 3, 0).
|
||||
pattern(1, 4, 3).
|
||||
|
||||
pattern(2, 1, 1).
|
||||
pattern(2, 2, 0).
|
||||
pattern(2, 3, 1).
|
||||
pattern(2, 4, 2).
|
||||
|
||||
pattern(3, 1, 1).
|
||||
pattern(3, 2, 2).
|
||||
pattern(3, 3, 0).
|
||||
pattern(3, 4, 2).
|
||||
|
||||
pattern(4, 1, 0).
|
||||
pattern(4, 2, 1).
|
||||
pattern(4, 3, 2).
|
||||
pattern(4, 4, 1).
|
||||
|
||||
pattern(5, 1, 3).
|
||||
pattern(5, 2, 1).
|
||||
pattern(5, 3, 1).
|
||||
pattern(5, 4, 1).
|
||||
|
||||
pattern(6, 1, 2).
|
||||
pattern(6, 2, 4).
|
||||
pattern(6, 3, 0).
|
||||
pattern(6, 4, 1).
|
||||
|
||||
pattern(7, 1, 0).
|
||||
pattern(7, 2, 6).
|
||||
pattern(7, 3, 1).
|
||||
pattern(7, 4, 0).
|
||||
|
||||
pattern(8, 1, 1).
|
||||
pattern(8, 2, 5).
|
||||
pattern(8, 3, 1).
|
||||
pattern(8, 4, 0).
|
||||
|
||||
pattern(9, 1, 4).
|
||||
pattern(9, 2, 2).
|
||||
pattern(9, 3, 1).
|
||||
pattern(9, 4, 0).
|
||||
|
||||
|
||||
1 { cut(I, 0..max) } 1:- pattern(I, _, _).
|
||||
:- order(W, L), #sum { J * K: pattern(I, W, J), cut(I, K)} < L.
|
||||
|
||||
total(N) :- N = #sum {J, I : cut(I, J)}.
|
||||
#minimize {N: total(N)}.
|
||||
|
||||
#show cut/2.
|
||||
#show total/1.
|
20
Assignment2/C/cut.mod
Normal file
20
Assignment2/C/cut.mod
Normal file
|
@ -0,0 +1,20 @@
|
|||
set WIDTHS;
|
||||
param orders {WIDTHS} > 0;
|
||||
|
||||
param nPAT integer >= 0;
|
||||
param nbr {WIDTHS, 1..nPAT} integer >= 0;
|
||||
|
||||
var Cut {1..nPAT} integer >= 0;
|
||||
|
||||
minimize Number:
|
||||
sum {j in 1..nPAT} Cut[j];
|
||||
|
||||
subject to Fulfill {i in WIDTHS}:
|
||||
sum {j in 1..nPAT} nbr[i,j] * Cut[j] >= orders[i];
|
||||
|
||||
data cut.dat;
|
||||
option solver cplex;
|
||||
solve;
|
||||
option omit_zero_rows 1;
|
||||
option display_1col 0;
|
||||
display Cut;
|
36
Assignment2/README.md
Normal file
36
Assignment2/README.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Assignment 1
|
||||
|
||||
## Part A
|
||||
### clingo
|
||||
|
||||
|
||||
## Part B
|
||||
### clingo
|
||||
| size | processors | deadline | result | time |
|
||||
| ---- | ---------- | -------- |
|
||||
| 10 | 3 | 20 | yes | 0.031 |
|
||||
| 20 | 6 | 30 | no | 4.498 |
|
||||
| 20 | 8 | 30 | yes | 0.233 |
|
||||
| 30 | 6 | 60 | unknown | too long to solve |
|
||||
| 30 | 8 | 60 | yes | 2.961 |
|
||||
| 30 | 8 | 80 | yes | 6.701 |
|
||||
| 30 | 8 | 90 | yes | 9.245 |
|
||||
|
||||
With either too high or too low constrain, the runtime grows exponentially. If the constrain is too low, it must iterate through all answers to find one correct result. If it is too high, then it may waste too much time fill the first processor.
|
||||
|
||||
### Google OR-Tools
|
||||
|
||||
## Part C
|
||||
### clingo
|
||||
| size | ans | time |
|
||||
| ---- | --- | ------ |
|
||||
| 5 | 5 | 0.678 |
|
||||
| 10 | 9 | 0.866 |
|
||||
| 15 | 13 | 1.122 |
|
||||
| 20 | 17 | 1.902 |
|
||||
| 25 | 21 | 6.379 |
|
||||
| 30 | 25 | 34.466 |
|
||||
|
||||
One important factor of the runtime is the max number of cut to check. If we set max = 10 with size = 30, we get the time of 0.914. However, it is impossible to get the max size before running, I believe this time would be a great representation of the runtime of clingo.
|
||||
|
||||
### AMPL
|
Loading…
Reference in New Issue
Block a user