Report Modeling and Computational Practice
Report Modeling and Computational Practice
Task 1:
Using a depth first strategy for selecting the nodes on the Branch and Bound Algorithm, evaluat-
ing the node on the left first (i.e. the node correspondig to smaller values on the new constraint)
and using the Matlab solver linprog for the linear relaxations, the problem was solved. What
follows is an detailed explanation of the first steps of the algorithm followed by the data for
each iteration and the solution.
• The first step is solving the linear relaxation of the original problem, given by:
Which yelds:
– x = [2.5 0 0 0]
– z = 25
As the solution is not integer in x1 , a new upper bound z = 25 is obtained and two new
branches are generated: S1 : x1 ≤ 2 and S2 : x1 ≥ 3. Thus, the current list of active nodes
is given by L = {S1 , S2 }. The figure below represents the current tree.
1
Solving S1 yelds:
– x = [2 0.4 0 0]
– z = 24.8
As the solution is not integer in x2 , a new upper bound z = 24.8 is obtained and two new
branches are generated: S11 : x2 ≤ 0 and S12 : x2 ≥ 1. Thus, the current list of active
nodes is given by L = {S2 , S11 , S12 }.
– x = [2 0 0.667 0]
– z = 24.6
As the solution is not integer in x3 , a new upper bound z = 24.6 is obtained and two new
branches are generated: S111 : x3 = 0 and S112 : x3 = 1. Thus, the current list of active
nodes is given by L = {S2 , S12 , S111 , S112 }.
• Choosing node S111 , we add the constraint x1 = 0 to problem S11 , which gives:
– x = [2 0 0 1]
– z = 21.5
2
As the solution is integer in all variables, a new lower bound for all nodes z = 21.5 is
obtained and this branch is cut by optimality. The list of active nodes is then given by
L = {S2 , S12 , S112 }.
• As the algorithm continues, new nodes are cut by optimality or unfeasibility. The Table 1
shows the values for the decision variables and objective function for all evaluated nodes.
• The tree generated form the execution of the algorithm is shown in Figure 1.
• From all nodes cut by optimality, the node S1212 , with x = [0 2 0 0] has the highest
value for the objective function and thus is the optimal value for the original problem.
Task 2:
• Using the linprog solver form Matlab the following solution was obtained for the linear
relaxation (LiR) of the original problem
• The optimal solution for the lagrangian relaxation (LaR) of the original problem, obtained
from the best solution calculated by an simple implemetation of the subgradient method
in Matlab that was executed for 1000 iterations, is shown below:
– (x1 , x2 , x3 ) = (0, 1, 0)
– z = 14.5
– u = 3.5
• The bounds generated by both relaxations are equal because the convex hull of the set
of constraints not relaxed by the lagrangian function including the limitation that the
decision variables are integer is equal to the feasible region defined by these constraints,
ignoring that the decision variables are integer:
Co{x ∈ X : Cx ≤ d} = {x : Cx ≤ d}
In this example, the only constraint used on the lagrangian function is 3x1 + x2 + 4x3 ≤ 4,
thus the constraints left are the upper and lower bounds on the values of the decision
variables (0 ≤ {x1 , x2 , x3 } ≤ 1). As such, it is easy to see that the convex hull of these
constraints, considering that x1 , x2 , x3 are binary, is the same as the region defined by
these bounds when ignoring the constraint that x1 , x2 , x3 are binary. When this occurs,
it is said that the LaR has the Integrality Property.
3
Node x1 x2 x3 x4 z Note
S0 2.5 0 0 0 25 Res. not integer
S1 2 0.4 0 0 24.8 Res. not integer
S11 2 0 0.667 0 24.6 Res. not integer
S111 2 0 0 1 21.5 Cut by optimality
S112 1.75 0 1 0 24.5 Res. not integer
S1121 1 0 1 1 18.5 Cut by optimality
S1122 x x x x x Cut by infeasibility
S12 1.25 1 0 0 24.5 Res. not integer
S121 1 1.2 0 0 24.4 Res. not integer
S1211 1 1 0.334 0 24.334 Res. not integer
S12111 1 1 0 1 23.5 Cut by optimality
S12112 0.5 1 1 0 24 Res. not integer
S121121 0 1 1 1 20.5 Cut by optimalty
S121122 x x x x x Cut by infeasibility
S1212 0 2 0 0 24 Cut by optimalty
S122 x x x x x Cut by infeasibility
S2 x x x x x Cut by infeasibility
Table 1: Table summarizing the execution of the Branch and Bound algorithm.
Figure 1: Branch and Bound tree. The green and red nodes were cut by optimality and
infeasibility respectively.
4
Task 3:
In order to formulate this problem, we first define a square matrix β of size n of binary decision
variables, with n being the number of tasks. Each element β(i, j) represents the precedence of
task i over task j, meaning that if has value 1, task i should be executed sooner than task j.
We also define the array s of length n, in which each component s(i) will contain the starting
times of it’s respective task i.
In order to impose the precedence rules of the problem, one can organize the precedence pairs
of nodes in two arrays: P reclow containing the indices of nodes that have low precedence on the
precedence pairing, and P rechigh containing the incices of nodes that have higher precedence
(should be executed first) when compared to the respective node on the P reclow array. Both
arrays have length of m, which is given by the number of precedence pairs of the problem. For
this task, we have these arrrays defined as (m = 6):
Using the Big-M method, with M = nj=1 p(j) ∗ 10, the following formulation is proposed:
P
n
X
z = min w(j) x(j)
x
j=1
4 1 2 8 3 6 7 10 11 9 12 5
and J = 856.
Task 4:
In order to solve this problem, one can formulate it as a Maximal Flow Problem with unitary
capacities on all archs:
This way, the maximal capacity obtained will correspond to the maximal number of disjoint
paths possible and the optimal flow values correspond to one possibility for connections of nodes
that result on the maximal number of disjoint paths.
The proposed formulation can be represented as:
z = max v
x,v
X X v,
for i = s
subject to xi,j − xj,i = 0, for all i ∈ V − {s, t}
{j:(i,j)∈A} {j:(j,i)∈A}
−v, for i = t
0 ≤ xi,j ≤ ui,j for each(i, j) ∈ A
5
Figure 2: Representation of the graph with unitary capacities.
where v is the flow on node t, xi,j is the flow from node i to node j, and ui,j is the capacity
of this arch. As we established that the problem would have unitary capacities on the existing
archs, if exists an arch form i to j, the value of ui,j is set to 1, and set to 0 if this arch doesn’t
exist. The matrix ui,j for this problem is presented below:
0 1 0 1 0 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
u=
0
0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
As the capacities for all arches are integer, the Theorem of Flux Integrality states that the
result will be integer, thus we guarantee that the optimal solutions will be flux values of either
0 or 1. Using Matlab with Yalmip and the Gurobi solver, the proposed formulation resulted on
the following optimal values:
v=2
0 1 0 1 0 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
x=
0
0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
Which corresponds to the colored paths shown on the following figure:
Note that the paths that yeld the maximal number of disjointed paths are not unique. There
are other possibilites of paths, but as the maximal flow obtaied was v = 2, the maximal number
of disjointed paths is always 2.
6
Figure 3: Representation of the paths obtained.
Annex 1
mainT1.m
7
1 function [z optimal, x optimal, y optimal, tree, k] = branch and bound(n, m, ...
constraint handler, objective handler)
2 x = sdpvar(n, 1);
3 y = sdpvar(m, 1);
4
5 z upper = Inf;
6 z lower = -Inf;
7 x optimal = [];
8 y optimal = [];
9
10 i = 1; % starting index
11 k = 0; % iteration counter
12
13 original constraints = constraint handler(x, y);
14 objective = objective handler(x, y);
15
16 tree = {{1, original constraints, z lower, z upper, 0}}; % A cell of nodes,
17 % first element is its index, second is the constraints of that node, third
18 % and fourth are the bound at that time and the fifth is its parent node ...
index
19
20 valid nodes = [1]; %% valid nodes to solve tha optimization problem, when
21 % the problem is solved it gets out of this list and puts its leafs on
22 % this list if the node has any
23
24 while true
25 k = k + 1;
26
27 if isempty(valid nodes) == false
28 % if there are valid nodes to check, get the first on the ...
valid nodes
29 % list and remove it
30 i = valid nodes(1);
31 valid nodes(1) = [];
32 else
33 break;
34 end
35
36 node constraints = tree{i}{2};
37 opt result = optimize(node constraints, objective, ...
sdpsettings('verbose', false));
38
39 if opt result.problem == 0
40
41 z node = value(objective);
42 y node = value(y);
43
44 if i == 1
45 z lower = z node;
46 end
47
48 if sum(round(y node) == y node) == length(y node) %% if the ...
solution is integer, then
49 if z node ≤ z upper
50 z upper = z node;
51
52 x optimal = value(x);
53 y optimal = value(y);
54 end
55 end
8
56
57
58 tree{i}{3} = z node;
59 tree{i}{4} = z upper;
60
61 if z node < z upper % if the current node has a lower value then ...
the current upper bound, which
62 % is known to be feasible, than this branch ...
has a potential for finding a
63 % better solution and should be branched
64
65 for j = 1:m %% loop for finding a non integer solution
66 if floor(y node(j)) 6= y node(j)
67
68 parent node index = tree{i}{1};
69 parent node constraints = tree{i}{2};
70
71 tree length = length(tree);
72 tree{end + 1} = {tree length + 1, ...
[parent node constraints, y(j) ≤ ...
floor(y node(j))], z node, z upper, ...
parent node index};
73
74
75 tree length = length(tree);
76 tree{end + 1} = {tree length + 1, ...
[parent node constraints, y(j) ≥ ...
ceil(y node(j))], z node, z upper, ...
parent node index};
77
78 valid nodes = [tree length, tree length + +1, ...
valid nodes];
79
80 break; %% since we've found a non integer value we ...
can exit now
81 end
82 end
83 end
84 end
85 end
86
87 z optimal = z upper;
88 end
simplex22.m
1
2
3 constraints = @(x, y) [[4 5 3 1] * y ≤ 10, y ≥ 0, y(3:4) ≤ 1];
4
5 objective = @(x, y) -[10 12 7 3/2] * y;
6
7 n = 0; % continuous variables
9
8 m = 4; % integer variables
9
10
11 %%
12 [z, x, y, trees] = branch and bound(n, m, constraints, objective);
13
14 nodes = [];
15 for i = 1:length(trees)
16 nodes = [nodes, trees{i}{5}];
17 end
18
19 treeplot(nodes)
10
Annex 2
mainT2.m
1 %% Lagrangian relaxation
2 clc
3 clear all
4
5 binvar x1 x2 x3
6 g = 4-(3*x1+x2+4*x3);
7
8 u = 0;
9 mu = 0.1;
10 rho = 0.95;
11 bestz = inf;
12 for i = 2:1000
13
14 obj = 10*x1+4*x2+14*x3+u(i-1)*(4-(3*x1+x2+4*x3));
15 diagnostics = optimize(restr,-obj,sdpsettings('verbose',0));
16 X1(i-1) = value(x1);
17 X2(i-1) = value(x2);
18 X3(i-1) = value(x3);
19 z(i-1) = value(obj);
20 d(i-1) = value(g);
21 if(z(i-1)<bestz)
22 bestz = z(i-1);
23 bestx1 = value(x1);
24 bestx2 = value(x2);
25 bestx3 = value(x3);
26 end
27 if ...
((d(i-1)≥0)&&(floor(X1(end))==X1(end))&&(floor(X2(end))==X2(end))&&(floor(X3(end))==X3(
28 disp('Lagrangian converged');
29 break;
30 end
31 u(i) = u(i-1)-mu(i-1)*d(i-1);
32 mu(i) = rho*mu(i-1);
33
34 end
35
36 disp('Lagrangian relaxation -------------')
37 disp(['z=',num2str(z(end))])
38 disp(['x1=',num2str(X1(end))])
39 disp(['x2==',num2str(X2(end))])
40 disp(['x3=',num2str(X3(end))])
41 disp(['lambda=',num2str(u(end))])
42
43 %plot(z)
44
11
45 %% Linear relaxation
46
47 sdpvar x1 x2 x3
48 obj = 10*x1+4*x2+14*x3;
49 restr = [0≤x1≤1;0≤x2≤1;0≤x3≤1;(3*x1+x2+4*x3)≤4];
50 optimize(restr,-obj,sdpsettings('verbose',0));
51
52 disp('Linear relaxation -----------------')
53 disp(['z=',num2str(value(obj))])
54 disp(['x1=',num2str(value(x1))])
55 disp(['x2=',num2str(value(x2))])
56 disp(['x3==',num2str(value(x3))])
12
Annex 3
mainT3.m
1 clc
2 clear all
3
4 % Defining problem parameters
5
6 p = [3 2 6 2 5 4 4 3 10 1 8 7];
7 w = [5 3 7 6 1 2 8 4 7 1 6 2];
8
9 n = length(p);
10
11 M = sum(p) * 10;
12
13 % Precedence pairs
14 lowPrec = [3 12 7 7 6 12];
15 highPrec = [1 3 3 6 8 10];
16
17 npairs = length(lowPrec);
18
19 % Defining decision variables ---------------------------------------------
20
21 beta = binvar(n,n,'full');
22 x = sdpvar(1,n,'full');
23 % The lines are the execution instants while the collumns are the tasks
24
25 % Building the constraints ------------------------------------------------
26
27 constr = [];
28
29 % Adding constraints: Each task can only be executed once ---
30 for i = 1:n % For each task
31 constr = [constr; x(i)≥0];
32 for j = 1:n
33 if i < j
34 constr = [constr; beta(i, j) + beta(j, i) == 1];
35 end
36
37 if j == i
38 constr = [constr; beta(i, j) == 0];
39 continue
40 end
41
42 constr = [constr; x(j) - x(i) ≥ p(i) - M*(1-beta(i,j))];
43 end
44 end
45
13
46 for i = 1:npairs
47 constr = [constr; x(lowPrec(i)) ≥ x(highPrec(i)) + p(i) ];
48 end
49
50 % Building the objective --------------------------------------------------
51
52 aux = sdpvar;
53 constr = [constr;aux==0]; % Trick for inicializing sdpvar as zero
54
55 tStart(1) = aux;
56 obj = aux;
57
58 for i = 1:n % For all execution instants but the first
59 obj = obj + x(i)*w(i);
60 end
61
62
63 % Solving -----------------------------------------------------------------
64
65 % optimize(constr,obj,sdpsettings('solver','cplex'))
66 optimize(constr,obj)
67
68
69 % Showing the results -----------------------------------------------------
70
71 [Y,taskid] = sort(value(x));
72 %% todo: arrumar cumsum
73 disp('Ordem das tarefas:')
74 disp(taskid)
75
76 disp('Valor da FO:')
77 disp(value(obj));
78
79 % Ordem das tarefas:
80 % 2 1 10 4 3 5 8 6 7 11 12 9
81 % Valor da FO:
82 % 1285
14
Annex 4
mainT4.m
1 clc
2 clear all
3
4 u = [0 1 0 1 0 0 0 0; % node 1 (source)
5 0 0 1 0 0 1 0 0;
6 0 0 0 1 1 0 0 0;
7 0 0 0 0 0 0 1 0;
8 0 0 0 0 0 1 1 0;
9 0 0 0 0 0 0 0 1;
10 0 0 0 0 0 0 0 1;
11 0 0 0 0 0 0 0 0]; % node 8 (sink)
12
13 s = 1;
14 t = 8;
15
16 x = binvar(8,8,'full');
17 v = sdpvar;
18
19 constr = [];
20
21 aux = sdpvar;
22 constr = [constr;aux==0];
23
24 for i = 1:8
25 sumX(i) = aux;
26 for j = 1:8
27 sumX(i) = sumX(i) + x(i,j) - x(j,i);
28 constr = [constr;0≤x(i,j)≤u(i,j)];
29 end
30 if (i == s)
31 constr = [constr;sumX(i)== v];
32 elseif (i == t)
33 constr = [constr;sumX(i)==-v];
34 else
35 constr = [constr;sumX(i)== 0];
36 end
37 end
38
39 obj = v;
40
41 % optimize(constr,-obj,sdpsettings('solver','gurobi'))
42 optimize(constr,-obj)
43
44 value(v)
45
15
46 value(x)
16