-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBB.js
118 lines (108 loc) · 4.12 KB
/
BB.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
* Add max or min constraint for a decision variable.
*
* @param A
* @param b
* @param cj
* @param x
* @param xB
* @param decVar Decision variable we're creating a max/min constraint for.
* @param val Max/min for variable.
* @param sign -1 if greater than constraint, 1 for less than constraint.
*/
function addBBConstr(A, b, cj, x, xB, decVar, val, sign) {
// Cols in A before constraint was added
var {mn} = getDims(A);
var loc = basisIndex(x, [decVar]); // Which column of x decVar is found in
// Create new row to add to A
var newARow = new Array(mn+1);
// Loop over elements in new A row
for (let i = 0; i < mn + 1; i++) {
// Element corresponding to decVar should equal sign (-1 for >=,
// 1 for <=)
if (i == loc[0]) {
newARow[i] = sign;
}
// Slack variable coefficient
else if (i == mn) {
newARow[i] = 1;
}
// All other elements should = 0
else {
newARow[i] = 0;
}
}
// new b row & c entry
var newARows = [newARow];
var newbRow = [sign*val];
var newcEnt = [0];
// Add constraint to A, b, cj, x and xB
[A, b, cj, x, xB] = addConstr(A, b, cj, x, xB, newARows, newbRow, newcEnt);
return [A, b, cj, x, xB];
}
/**
* Performs branch and bound to find solution.
*
* @param A Constraint coefficient array.
* @param b Solution array.
* @param cj Objective function coefficients array.
* @param x Decision variable array.
* @param xB Basis variable array.
* @param sign What the objective function has been multiplied by to
* make the problem a max problem, either -1 or 1.
* @param objVarName Name of the objective function (usually just a letter).
* @param intConds Integer conditions; there is one element for each
* decision variable. If equal to 1, that decision variable needs to be
* integer.
* @param maxz Maximium z value thus far found for an integer solution.
* @return [b, x, xB]
*/
function branchAndBound(A, b, cj, x, xB, sign, objVarName, intConds, maxz) {
// Mention what integer constraints the user has specified
for (let i = 0; i < x.length; i++) {
if (intConds[i] == 1) {
console.log(x[i] + " is required to be an integer.");
} else {
console.log(x[i] + " is not required to be an integer.");
}
}
// isOptim = false if not all integer constraints are satisfied
var [isOptim, branchVar, branchVal] = varNotInt(b, x, xB, intConds);
if (!isOptim) {
// Less than problem
var [ALt, bLt, cjLt, xLt, xBLt] = addBBConstr(A, b, cj, x, xB, branchVar, Math.floor(branchVal), 1);
var [ALt, bLt, cjLt, xLt, xBLt, zLt, isFeasLt] = simplexIterator(ALt, bLt,
cjLt, xLt, xBLt, sign, objVarName);
if (isFeasLt && zLt > maxz) {
var [isOptimLt, branchVarLt, branchValLt] = varNotInt(bLt, xLt, xBLt, intConds);
if (isOptimLt) {
maxz = zLt;
}
}
// Greater than problem
var [AGt, bGt, cjGt, xGt, xBGt] = addBBConstr(A, b, cj, x, xB, branchVar, Math.ceil(branchVal), 1);
var [AGt, bGt, cjGt, xGt, xBGt, zGt, isFeasGt] = simplexIterator(AGt, bGt,
cjGt, xGt, xBGt, sign, objVarName);
}
}
/**
* Determines whether the integer conditions are satisfied.
*
* @param b Solution array.
* @param x Decision variable array.
* @param xB Basis variable array.
* @param intConds Integer conditions. intConds[i] indicates whether x[i] is
* meant to be an integer. If it is equal to 1 the answer is yes, otherwise no.
* @return If conditions are satisfied, true, otherwise [false, first
* basis variable that doesn't satisfy integer conditions and solution value
* for that variable]
*/
function varNotInt(b, x, xB, intConds) {
var loc = basisIndex(x, xB);
for (let i = 0 ; i < b.length; i++) {
if ( (intConds[loc[i]] == 1) && (!isInt(b[i]))){
return [false, xB[i], b[i]];
}
}
return true;
}