Known values for variables in a linear program written in Mathprog - linear-programming

I have a linear program written in MathProg. My unknown binary variable is a two-dimensional array defined as:
var x{i in V, l in L}, >=0, <=1;
where V and L are sets of integers.
The value of some variables, however, are known in advance and I would like to specify this for the solver in order to reduce the size of the ILP. For example I know that x[4,l] when l=2 is 1 and for any other values of l is zero. Currently, I specify this as as a constraint:
s.t. initial4{i in V: i=4}: sum{l in L}(l*x[i,l]) = 2;
I was wondering if this is the efficient way of specifying the values of a subset of unknowns in advance.
Ideally, I would like to place such information in a separate file together with the data section rather than in the model file.

Create an upper bound and lower bound for each variable:
var x{i in index_set}, >=x_L[i], <=x_U[i];
and adjust the lower and upper bounds for the known values.
Here is a MathProg snippet fixing x[2] to zero:
set index_set;
param x_L{index_set};
param x_U{index_set};
var x{i in index_set}, >=x_L[i], <=x_U[i];
s.t.
dummy:
sum{i in index_set} x[i] = 2;
solve;
display x;
data;
set index_set := 1, 2, 3;
param x_L default 0;
param x_U default 1 :=
2 0;
end;
From the (filtered) output it is clear that the preprocessor is smart enough to fix x[2] to 0:
glpsol --math test.mod
OPTIMAL SOLUTION FOUND BY LP PREPROCESSOR
x[1].val = 1
x[2].val = 0
x[3].val = 1

Related

Return a random object from a list based on proprieties

This is quite a strange issue for me because I can't visualize my problem correctly. Just so that you know, I'm not really asking for code but just for an idea to write an approriate alogirthm that would generate some weather based on their probability of occuring.
Here's what I want to achieve :
Let's say I have a WeatherClass, with a parameter called "Probability". I want to have different weather instances with their own probability of "happening".
enum Probability {
Never = -1,
Low = 0,
Normal = 1,
Always = 2
};
std::vector<WeatherClass> WeatherContainer;
WeatherClass Sunny = WeatherClass();
Sunny.Probability = Probability.Normal;
WeatherClass Rainy = WeatherClass();
Rainy.Probability = Probability.Low;
WeatherClass Cloudy = WeatherClass();
Cloudy.Probability = Probability.Normal;
WeatherContainer.push_back(Sunny);
WeatherContainer.push_back(Rainy);
WeatherContainer.push_back(Cloudy);
Now, my question is : what is the most clever way to return some weather based on its own probability of happening?
I don't know why but I can't figure this out.. My first guess would be to have some kind of "luck" variable and compare it with the probability of each element or something similar.
Any hint or advice would be really helpful.
Greets,
required
Generally speaking, assuming you have an integer sequence of numbers representing a linear increase in probability (starting from 1, not 0!):
1,2,3,4,5,6...n
Marking pn for some specific integer (weather in your scheme, say "6"), and the sum of all the enum integers Sn, a linear probability could easily be defined as:
pn/Sn
This of course means the weather associated with "1" is least likely, and the one with "n" is most likely. Other schemes are possible, such as exponential - just need to normalize properly. Also, if you forgot your math:
Sn=(1+n)*n/2
Now you need to roll from this probability. One option, disregarding efficiency, to help you think about this:
Make a giant set, where each weather (or integer) appears as many times as the associated integer. 1 appears once, ..., n appears n times. This list is of size Sn by definition. Now use the random library:
int choice = rand() % Sn; #index between 0 and Sn-1 - chosen probability indicator.
You could of course randomize the list as well for extra randomness.
An example: in our array we have probmap={1,2,2,3,3,3}. If choice==4, then probmap[4]==3. Suppose 3 corresponds to Sunny, then we have our result!. There are of course ways to make this better, choose different probability functions etc. but I think this is a good start.
You can generate a random number between 0 and 3, subtract 1, cast it to Probability and search your vector for a matching entry.
auto result = rand();
result %= 4;
--result;
auto prob = (Probability)result;
auto index = -1;
for( auto I = 0 ; I < WeatherContainer.size() ; ++I )
if( WeatherContainer [ I ].Probability == prob )
{
index = I;
break;
}
if( index != -1 )
{
// Do your thing
}

Subset sum variant with a non-zero target sum

I have an array of integers and need to apply a variant of the subset sum algorithm on it, except that instead of finding a set of integers whose sum is 0 I am trying to find a set of integers whose sum is n. I am unclear as to how to adapt one of the standard subset sum algorithms to this variant and was hoping for any insight into the problem.
This is subset sum problem, which is NP-Complete (there is no known efficient solution to NP-Complete problems), but if your numbers are relatively small integers - there is an efficient pseudo polynomial solution to it that follows the recurrence:
D(x,i) = false x<0
D(0,i) = true
D(x,0) = false x != 0
D(x,i) = D(x,i-1) OR D(x-arr[i],i-1)
Later, you need to step back on your choices, see where you decided to "reduce" (take the element), and where you decided not to "reduce" (not take the element), on the generated matrix.
This thread and this thread discuss how to get the elements for similar problems.
Here is a python code (taken from the thread I linked to) that does the trick.
If you are not familiar with python - read it as pseudo code, it's pretty easy to understand python!.
arr = [1,2,4,5]
n = len(arr)
SUM = 6
#pre processing:
D = [[True] * (n+1)]
for x in range(1,SUM+1):
D.append([False]*(n+1))
#DP solution to populate D:
for x in range(1,SUM+1):
for i in range(1,n+1):
D[x][i] = D[x][i-1]
if x >= arr[i-1]:
D[x][i] = D[x][i] or D[x-arr[i-1]][i-1]
print D
#get a random solution:
if D[SUM][n] == False:
print 'no solution'
else:
sol = []
x = SUM
i = n
while x != 0:
possibleVals = []
if D[x][i-1] == True:
possibleVals.append(x)
if x >= arr[i-1] and D[x-arr[i-1]][i-1] == True:
possibleVals.append(x-arr[i-1])
#by here possibleVals contains 1/2 solutions, depending on how many choices we have.
#chose randomly one of them
from random import randint
r = possibleVals[randint(0,len(possibleVals)-1)]
#if decided to add element:
if r != x:
sol.append(x-r)
#modify i and x accordingly
x = r
i = i-1
print sol
You can solve this by using dynamic programming.
Lets assume that:
N - is the sum that required (your first input).
M - is the number of summands available (your second input).
a1...aM - are the summands available.
f[x] is true when you can reach the sum of x, and false otherwise
Now the solution:
Initially f[0] = true and f[1..N] = false - we can reach only the sum of zero without taking any summand.
Now you can iterate over all ai, where i in [1..M], and with each of them perform next operation:
f[x + ai] = f[x + ai] || f[x], for each x in [M..ai] - the order of processing is relevant!
Finally you output f[N].
This solution has the complexity of O(N*M), so it is not very useful when you either have large input numbers or large number of summands.

Algorithm for finding the maximum number of non-overlapping lines on the x axis

I'm not exactly sure how to ask this, but I'll try to be as specific as possible.
Imagine a tetris screen with only rectangles, of different shapes, falling to the bottom.
I want to compute the maximum number of rectangles that I can fit one next to the other without any overlapping ones. I've named them lines in the title because I'm actually only interested in the length of the rectangle when computing, or the line parallel to the x axis that it's falling towards.
So basically I have a custom type with a start and end, both integers between 0 and 100. Say we have a list of these rectangles ranging from 1 to n. rectangle_n.start (unless it's the rectangle closest to the origin) has to be > rectangle_(n-1).end so that they will never overlap.
I'm reading the rectangle coordinates (both are x axis coordinates) from a file with random numbers.
As an example:
consider this list of rectangle type objects
rectangle_list {start, end} = {{1,2}, {3,5}, {4,7} {9,12}}
We can observe that the 3rd object has its start coordinate 4 < the previous rectangle's end coordinate which is 5. So in sorting this list, I would have to remove the 2nd or the 3rd object so that they don't overlap.
I'm not sure if there is a type for this kind of problem so I didn't know how else to name it. I'm interested in an algorithm that can be applied on a list of such objects and would sort them out accordingly.
I've tagged this with c++ because the code I'm writing is c++ but any language would do for the algorithm.
You are essentially solving the following problem. Suppose we have n intervals {[x_1,y_1),[x_2,y_2),...,[x_n,y_n)} with x_1<=x_2<=...<=x_n. We want to find a maximal subset of these intervals such that there are no overlaps between any intervals in the subset.
The naive solution is dynamic programming. It guarantees to find the best solution. Let f(i), 0<=i<=n, be the size of the maximal subset up to interval [x_i,y_i). We have equation (this is latex):
f(i)=\max_{0<=j<i}{f(j)+d(i,j)}
where d(i,j)=1 if and only if [x_i,y_i) and [x_j,y_j) have no overlaps; otherwise d(i,j) takes zero. You can iteratively compute f(i), starting from f(0)=0. f(n) gives the size of the maximal subset. To get the actual subset, you need to keep a separate array s(i)=\argmax_{0<=j<i}{f(j)+d(i,j)}. You then need to backtrack to get the 'path'.
This is an O(n^2) algorithm: you need to compute each f(i) and for each f(i) you need i number of tests. I think there should be a O(nlogn) algorithm, but I am not so sure.
EDIT: an implementation in Lua:
function find_max(list)
local ret, f, b = {}, {}, {}
f[0], b[0] = 0, 0
table.sort(list, function(a,b) return a[1]<b[1] end)
-- dynamic programming
for i, x in ipairs(list) do
local max, max_j = 0, -1
x = list[i]
for j = 0, i - 1 do
local e = j > 0 and list[j][2] or 0
local score = e <= x[1] and 1 or 0
if f[j] + score > max then
max, max_j = f[j] + score, j
end
end
f[i], b[i] = max, max_j
end
-- backtrack
local max, max_i = 0, -1
for i = 1, #list do
if f[i] > max then -- don't use >= here
max, max_i = f[i], i
end
end
local i, ret = max_i, {}
while true do
table.insert(ret, list[i])
i = b[i]
if i == 0 then break end
end
return ret
end
local l = find_max({{1,2}, {4,7}, {3,5}, {8,11}, {9,12}})
for _, x in ipairs(l) do
print(x[1], x[2])
end
The name of this problem is bin packing, it is usually considered as a hard problem but can be computed reasonably well for small number of bins.
Here is a video explaining common approaches to this problem
EDIT : By hard problem, I mean that some kind of brute force has to be employed. You will have to evaluate a lot of solutions and reject most of them, so usually you need some kind of evaluation mechanism. You need to be able to compare solution, such as "This solution packs 4 rectangles with area of 15" is better than "This solution packs 3 rectangles with area of 16".
I can't think of a shortcut, so you may have to enumerate the power set in descending order of size and stop on the first match.
The straightforward way to do this is to enumerate combinations of decreasing size. You could do something like this in C++11:
template <typename I>
std::set<Span> find_largest_non_overlapping_subset(I start, I finish) {
std::set<Span> result;
for (size_t n = std::distance(start, finish); n-- && result.empty();) {
enumerate_combinations(start, finish, n, [&](I begin, I end) {
if (!has_overlaps(begin, end)) {
result.insert(begin, end);
return false;
}
return true;
});
}
return result;
}
The implementation of enumerate_combination is left as an exercise. I assume you already have has_overlap.

Efficient method for finding the middle k-combination of n sorted elements

Suppose that I have a sorted array, N, consisting of n elements. Now, given k, I need a highly efficient method to generate the k-combination that would be the middle combination (if all the k-combinations were lexicographically sorted).
Example:
N = {a,b,c,d,e} , k = 3
1: a,b,c
2: a,b,d
3: a,b,e
4: a,c,d
5: a,c,e
6: a,d,e
7: b,c,d
8: b,c,e
9: b,d,e
10: c,d,e
I need the algorithm to generate combination number 5.
The Wikipedia page on the combinatorial number system explains how this can be obtained (in a greedy way). However, since n is very large and I need to find the middle combination for all k's less than n, I need something much more efficient than that.
I'm hoping that since the combination of interest always lies in the middle, there is some sort of a straightforward method for finding it. For example, the first k-combination in the above list is always given by the first k elements in N, and similarly the last combination is always given by the last k elements. Is there such a way to find the middle combination as well?
http://en.wikipedia.org/wiki/Combinatorial_number_system
If you are looking for a way to obtain the K-indexes from the lexicographic index or rank of a unique combination, then your problem falls under the binomial coefficient. The binomial coefficient handles problems of choosing unique combinations in groups of K with a total of N items.
I have written a class in C# to handle common functions for working with the binomial coefficient. It performs the following tasks:
Outputs all the K-indexes in a nice format for any N choose K to a file. The K-indexes can be substituted with more descriptive strings or letters.
Converts the K-indexes to the proper lexicographic index or rank of an entry in the sorted binomial coefficient table. This technique is much faster than older published techniques that rely on iteration. It does this by using a mathematical property inherent in Pascal's Triangle and is very efficient compared to iterating over the set.
Converts the index in a sorted binomial coefficient table to the corresponding K-indexes. The technique used is also much faster than older iterative solutions.
Uses Mark Dominus method to calculate the binomial coefficient, which is much less likely to overflow and works with larger numbers.
The class is written in .NET C# and provides a way to manage the objects related to the problem (if any) by using a generic list. The constructor of this class takes a bool value called InitTable that when true will create a generic list to hold the objects to be managed. If this value is false, then it will not create the table. The table does not need to be created in order to use the 4 above methods. Accessor methods are provided to access the table.
There is an associated test class which shows how to use the class and its methods. It has been extensively tested with several cases and there are no known bugs.
To read about this class and download the code, see Tablizing The Binomial Coeffieicent.
The following tested code will calculate the median lexicographic element for any N Choose K combination:
void TestMedianMethod()
{
// This test driver tests out the GetMedianNChooseK method.
GetMedianNChooseK(5, 3); // 5 choose 3 case.
GetMedianNChooseK(10, 3); // 10 choose 3 case.
GetMedianNChooseK(10, 5); // 10 choose 5 case.
}
private void GetMedianNChooseK(int N, int K)
{
// This method calculates the median lexicographic index and the k-indexes for that index.
String S;
// Create the bin coeff object required to get all
// the combos for this N choose K combination.
BinCoeff<int> BC = new BinCoeff<int>(N, K, false);
int NumCombos = BinCoeff<int>.GetBinCoeff(N, K);
// Calculate the median value, which in this case is the number of combos for this N
// choose K case divided by 2.
int MedianValue = NumCombos / 2;
// The Kindexes array holds the indexes for the specified lexicographic element.
int[] KIndexes = new int[K];
// Get the k-indexes for this combination.
BC.GetKIndexes(MedianValue, KIndexes);
StringBuilder SB = new StringBuilder();
for (int Loop = 0; Loop < K; Loop++)
{
SB.Append(KIndexes[Loop].ToString());
if (Loop < K - 1)
SB.Append(" ");
}
// Print out the information.
S = N.ToString() + " choose " + K.ToString() + " case:\n";
S += " Number of combos = " + NumCombos.ToString() + "\n";
S += " Median Value = " + MedianValue.ToString() + "\n";
S += " KIndexes = " + SB.ToString() + "\n\n";
Console.WriteLine(S);
}
Output:
5 choose 3 case:
Number of combos = 10
Median Value = 5
KIndexes = 4 2 0
10 choose 3 case:
Number of combos = 120
Median Value = 60
KIndexes = 8 3 1
10 choose 5 case:
Number of combos = 252
Median Value = 126
KIndexes = 9 3 2 1 0
You should be able to port this class over fairly easily to the language of your choice. You probably will not have to port over the generic part of the class to accomplish your goals. Depending on the number of combinations you are working with, you might need to use a bigger word size than 4 byte ints.

How to auto-generate and assign variables corresponding to elements in a matrix?

I am working on a binary linear program problem.
I am not really familiar with any computer language(just learned Java and C++ for a few months), but I may have to use computer anyway since the problem is quite complicated.
The first step is to declare variables m_ij for every entry in (at least 8 X 8) a matrix M.
Then I assign corresponding values of each element of a matrix to each of these variables.
The next is to generate other sets of variables, x_ij1, x_ij2, x_ij3, x_ij4, and x_ij5, whenever the value of m_ij is not 0.
The value of x_ijk variable is either 0 or 1, and I do not have to assign values for x_ijk variables.
Probably the simplest way to do it is to declare and assign a value to each variable, e.g.
int* m_11 = 5, int* m_12 = 2, int* m_13 = 0, ... int* m_1n = 1
int* m_21 = 3, int* m_12 = 1, int* m_13 = 2, ... int* m_2n = 3
and then pick variables, the value of which is not 0, and declare x_ij1 ~ x_ij5 accordingly.
But this might be too much work, especially since I am going to consider many different matrices for this problem.
Is there any way to do this automatically?
I know a little bit of Java and C++, and I am considering using lp_solve package in C++(to solve binary integer linear program problem), but I am willing to use any other language or program if I could do this easily.
I am sure there must be some way to do this(probably using loops, I guess?), and this is a very simple task, but I just don't know about it because I do not have much programming language.
One of my cohort wrote a program for generating a random matrix satisfying some condition we need, so if I could use that matrix as my input, it might be ideal, but just any way to do this would be okay as of now.
Say, if there is a way to do it with MS excel, like putting matrix entries to the cells in an excel file, and import it to C++ and automatically generate variables and assign values to them, then this would simplify the task by a great deal!
Matlab indeed seems very suitable for the task. Though the example offered by #Dr_Sam will indeed create the matrices on the fly, I would recommend you to initialize them before you assign the values. This way your code still ends up with the right variable if something with the same name already existed in the workspace and also your variable will always have the expected size.
Assuming you want to define a square 8x8 matrix:
m = zeros(8)
Now in general, if you want to initialize a three dimensional matrixh of size imax,jmax,kmax:
imax = 8;
jmax = 8;
kmax = 5;
x = zeros(imax,jmax,kmax);
Now assigning to or reading from these matrices is very easy, note that length and with of m have been chosen the same as the first dimensions of x:
m(3,4) = 4; %Assign a value
myvalue = m(3,4) %read the value
m(:,1) = 1:8 *Assign the values 1 through 8 to the first column
x(2,4,5) = 12; %Assign a single value to the three dimensional matrix
x(:,:,2) = m+1; Assign the entire matrix plus one to one of the planes in x.
In C++ you could use a std::vector of vectors, like
std::vector<std::vector<int>> matrix;
You don't need to use separate variables for the matrix values, why would you when you have the matrix?
I don't understand the reason you need to get all values where you evaluate true or false. Instead just put directly into a std::vector the coordinates where your condition evaluates to true:
std::vector<std::pair<int, int> true_values;
for (int i = 0; i < matrix.size(); i++)
{
for (int j = 0; j < matrix[i].size(); j++)
{
if (some_condition_for_this_matrix_value(matrix[i][j], i, j) == true)
true_values.emplace_back(std::make_pair(i, j));
}
}
Now you have a vector of all matrix coordinates where your condition is true.
If you really want to have both true and false values, you could use a std::unordered_map with a std::pair containing the matrix coordinates as key and bool as value:
// Create a type alias, as this type will be used multiple times
typedef std::map<std::pair<int, int>, bool> bool_map_type;
bool_map_type bool_map;
Insert into this map all values from the matrix, with the coordinates of the matrix as the key, and the map value as true or false depending on whatever condition you have.
To get a list of all entries from the bool_map you can remove any false entries with std::remove_if:
std::remove_if(bool_map.begin(), bool_map.end(),
[](const bool_map_type::value_type& value) {
return value.second == false;
};
Now you have a map containing only entries with their value as true. Iterate over this map to get the coordinates to the matrix
Of course, I may totally have misunderstood your problem, in which case you of course are free to disregard this answer. :)
I know both C++ and Matlab (not Python) and in your case, I would really go for Matlab because it's way easier to use when you start programming (but don't forget to come back to C++ when you will find the limitations to Matlab).
In Matlab, you can define matrices very easily: just type the name of the matrix and the index you want to set:
m(1,1) = 1
m(2,2) = 1
gives you a 2x2 identity matrix (indices start with 1 in Matlab and entries are 0 by default). You can also define 3d matrices the same way:
x(1,2,3) = 2
For the import from Excel, it is possible if you save your excel file in CSV format, you can use the function dlmread to read it in Matlab. You could also try later to implement your algorithm directly in Matlab.
Finally, if you want to solve your binary integer programm, there is already a built-in function in Matlab, called bintprog which can solve it for you.
Hope it helps!