in OPL Filter and read k for a set of i,j from a tuple having i,j,k - linear-programming

I have a model reading data from an excel file. Below is part of the model.
I use the below code to read data as below
tuple blockType {
string id;
int i;
int j;
int k;
};
{blockType} PitBlocksType = ...; // Read from excel table which contains several rows, a short example below
/*
Example below
Block Id Bench(i) Strip(j) Block(k)
P1 1 1 1
P2 1 1 2
P3 1 1 3
P7 3 1 1
P8 3 1 2
P9 3 1 3
P10 1 2 1
P11 1 2 2
P12 1 2 3
P16 3 2 1
P17 3 2 2
P18 3 2 3
P19 1 3 1
P20 1 3 2
P21 1 3 3
P22 2 3 1
P23 2 3 2
P24 2 3 3
P25 3 3 1
P26 3 3 2
P27 3 3 3
*/
tuple jk {
string ids;
int j;
int k;
}
{jk} jks=...; // from the above table reading only the j,k : There are multiple occurrences of the same j,k - Not sure if this is the best method
{int} BenchPerjk[jks]= ?????? ; // Here I want to read all i for each set of jks
//int succ3=next(BenchPerjk[<id, 5,3>],3); // I want to use something like this below
{blockType} OntopPit[b1 in PitBlocksType] =
{b | b in PitBlocksType: b1.i == next(BenchPerjk[b.id, b.j ,b.k],b.i) && // This is giving an error
((b1.k == b.k-1 ) ||
(b1.k == b.k+1 ) ||
(b1.k == b.k ) ) &&
((b1.j == b.j-1 ) ||
(b1.j == b.j+1 ) ||
(b1.j == b.j ) ) };
There are 2 issues above - One is How to read the BenchPerjk[jks] by filtering data from the table for each set of jk.
The second issue is the implementation of the Next command in the code - What is the best way.
Looking forward for your help please,

You cannot filter things while reading, so you always have to read everything. Once you have everything you should be able extract the jks as follows:
tuple jk {
int j;
int k;
}
{jk} jks = { <t.j, t.k> | t in PitBlocksType };
execute { writeln(jks); }
{int} BenchPerjk[v in jks] = { t.i | t in PitBlocksType : t.j == v.j && t.k == v.k };
execute { writeln(BenchPerjk); }

Related

A many-to-one mapping in the natural domain using discrete input variables?

I would like to find a mapping f:X --> N, with multiple discrete natural variables X of varying dimension, where f produces a unique number between 0 to the multiplication of all dimensions. For example. Assume X = {a,b,c}, with dimensions |a| = 2, |b| = 3, |c| = 2. f should produce 0 to 12 (2*3*2).
a b c | f(X)
0 0 0 | 0
0 0 1 | 1
0 1 0 | 2
0 1 1 | 3
0 2 0 | 4
0 2 1 | 5
1 0 0 | 6
1 0 1 | 7
1 1 0 | 8
1 1 1 | 9
1 2 0 | 10
1 2 1 | 11
This is easy when all dimensions are equal. Assume binary for example:
f(a=1,b=0,c=1) = 1*2^2 + 0*2^1 + 1*2^0 = 5
Using this naively with varying dimensions we would get overlapping values:
f(a=0,b=1,c=1) = 0*2^2 + 1*3^1 + 1*2^2 = 4
f(a=1,b=0,c=0) = 1*2^2 + 0*3^1 + 0*2^2 = 4
A computationally fast function is preferred as I intend to use/implement it in C++. Any help is appreciated!
Ok, the most important part here is math and algorythmics. You have variable dimensions of size (from least order to most one) d0, d1, ... ,dn. A tuple (x0, x1, ... , xn) with xi < di will represent the following number: x0 + d0 * x1 + ... + d0 * d1 * ... * dn-1 * xn
In pseudo-code, I would write:
result = 0
loop for i=n to 0 step -1
result = result * d[i] + x[i]
To implement it in C++, my advice would be to create a class where the constructor would take the number of dimensions and the dimensions itself (or simply a vector<int> containing the dimensions), and a method that would accept an array or a vector of same size containing the values. Optionaly, you could control that no input value is greater than its dimension.
A possible C++ implementation could be:
class F {
vector<int> dims;
public:
F(vector<int> d) : dims(d) {}
int to_int(vector<int> x) {
if (x.size() != dims.size()) {
throw std::invalid_argument("Wrong size");
}
int result = 0;
for (int i = dims.size() - 1; i >= 0; i--) {
if (x[i] >= dims[i]) {
throw std::invalid_argument("Value >= dimension");
}
result = result * dims[i] + x[i];
}
return result;
}
};

Ordering an array based on 2D array of relations (higher, lower, doesn't matter)

I have been stuck with this problem for two days and I still can't get it right.
Basically, I have a 2D array with relations between certain numbers (in given range):
0 = the order doesn't matter
1 = the first number (number in left column) should be first
2 = the second number (number in upper row) should be first
So, I have some 2D array, for example this:
0 1 2 3 4 5 6
0 0 0 1 0 0 0 2
1 0 0 2 0 0 0 0
2 2 1 0 0 1 0 0
3 0 0 0 0 0 0 0
4 0 0 2 0 0 0 0
5 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0
And my goal is to create a new array of given numbers (0 - 6) in such a way that it is following the rules from the 2D array (e.g. 0 is before 2 but it is after 6). I probably also have to check if such array exists and then create the array. And get something like this:
6 0 2 1 4 5
My Code
(It doesn't really matter, but I prefer c++)
So far I tried to start with ordered array 0123456 and then swap elements according to the table (but that obviously can't work). I also tried inserting the number in front of the other number according to the table, but it doesn't seem to work either.
// My code example
// I have:
// relArr[n][n] - array of relations
// resArr = {1, 2, ... , n} - result array
for (int i = 0; i < n; i++) {
for (int x = 0; x < n; x++) {
if (relArr[i][x] == 1) {
// Finding indexes of first (i) and second (x) number
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
// Placing the (i) before (x) and shifting array
int tmp, insert = iX+1;
if (iX < iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert < iI+1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert++;
}
}
} else if (relArr[i][x] == 2) {
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
int tmp, insert = iX-1;
if (iX > iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert > iI-1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert--;
}
}
}
}
}
I probably miss correct way how to check whether or not it is possible to create the array. Feel free to use vectors if you prefer them.
Thanks in advance for your help.
You seem to be re-ordering the output at the same time as you're reading the input. I think you should parse the input into a set of rules, process the rules a bit, then re-order the output at the end.
What are the constraints of the problem? If the input says that 0 goes before 1:
| 0 1
--+----
0 | 1
1 |
does it also guarantee that it will say that 1 comes after 0?
| 0 1
--+----
0 |
1 | 2
If so you can forget about the 2s and look only at the 1s:
| 0 1 2 3 4 5 6
--+--------------
0 | 1
1 |
2 | 1 1
3 |
4 |
5 |
6 | 1
From reading the input I would store a list of rules. I'd use std::vector<std::pair<int,int>> for this. It has the nice feature that yourPair.first comes before yourPair.second :)
0 before 2
2 before 1
2 before 4
6 before 0
You can discard any rules where the second value is never the first value of a different rule.
0 before 2
6 before 0
This list would then need to be sorted so that "... before x" and "x before ..." are guaranteed to be in that order.
6 before 0
0 before 2
Then move 6, 0, and 2 to the front of the list 0123456, giving you 6021345.
Does that help?
Thanks for the suggestion.
As suggested, only ones 1 are important in 2D array. I used them to create vector of directed edges and then I implemented Topological Sort. I decide to use this Topological Sorting Algorithm. It is basically Topological Sort, but it also checks for the cycle.
This successfully solved my problem.

Permutating a vector

I am trying to get every permutation of a vector but also with a divider that indicates sub-permutations. It seems there is a mistake in my code as you can see from my results the ending permutation.
0 1 3 2 | and 0 2 3 1 | and 0 3 2 1 | are all duplicated.
I am also curious if there is a way to do what I am trying to do that can accept a reference to the vector rather than making a copy.
IDEONE: http://ideone.com/fork/2v0wk3
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void permute(vector<int> v, int path_length) {
do {
for(int i=0; i<=3; ++i) {
cout << v[i] << " ";
if(i == path_length-1)
cout << "| ";
}
cout << endl;
if(path_length == v.size()) {
cout << "====="<< endl;
return;
}
permute(v, path_length+1);
} while(next_permutation(v.begin()+path_length-1,v.end()));
}
int main() {
vector<int> v;
for(int i=0;i<=3;++i)
v.push_back(i);
int path_length = 2;
permute(v, path_length);
return 0;
}
Results:
0 1 | 2 3
0 1 2 | 3
0 1 2 3 |
=====
0 1 3 | 2
0 1 3 2 |
=====
0 1 | 3 2
0 1 3 | 2
0 1 3 2 |
=====
0 2 | 1 3
0 2 1 | 3
0 2 1 3 |
=====
0 2 3 | 1
0 2 3 1 |
=====
0 2 | 3 1
0 2 3 | 1
0 2 3 1 |
=====
0 3 | 1 2
0 3 1 | 2
0 3 1 2 |
=====
0 3 2 | 1
0 3 2 1 |
=====
0 3 | 2 1
0 3 2 | 1
0 3 2 1 |
=====
Expected Results:
0 1 | 2 3
0 1 2 | 3
0 1 2 3 |
=====
0 1 3 | 2
0 1 3 2 |
=====
0 2 | 1 3
0 2 1 | 3
0 2 1 3 |
=====
0 2 3 | 1
0 2 3 1 |
=====
0 3 | 1 2
0 3 1 | 2
0 3 1 2 |
=====
0 3 2 | 1
0 3 2 1 |
=====
Consider another way to generate every sequence you need.
We will have a vector <int> cur to store the current sequence, and a vector <bool> used to track which integers are used and which are not.
In a recursive function with a depth argument, find another unused integer, put it as cur[depth] and proceed considering the next position, which is depth + 1.
Print the result anytime the depth is in the required bounds.
#include <iostream>
#include <vector>
using namespace std;
int const n = 3;
void generate (vector <int> & cur, vector <bool> & used, int depth) {
if (depth >= 2) {
for (int i = 0; i < depth; i++) {
cout << cur[i] << ' ';
}
cout << endl;
}
for (int i = 0; i <= n; i++) {
if (!used[i]) {
used[i] = true;
cur[depth] = i;
generate (cur, used, depth + 1);
used[i] = false;
}
}
}
int main () {
vector <int> cur (n);
vector <bool> used (n, false);
cur[0] = 0;
used[0] = true;
generate (cur, used, 1);
return 0;
}
And the output is:
0 1
0 1 2
0 1 2 3
0 1 3
0 1 3 2
0 2
0 2 1
0 2 1 3
0 2 3
0 2 3 1
0 3
0 3 1
0 3 1 2
0 3 2
0 3 2 1
You can add the ===== part, too, if you print it when depth > n.
Your question is not very clear to me. You can use the not so well known next permutation from the STL :
std::vector<int> my_vector = { 1 , 5 , 7 , 2 , 3 , 10};
std::sort(my_vector.begin(), my_vector.end());
do {
std::copy(my_vector.begin(), my_vector.end(), ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
} while(std::next_permutation(my_vector.begin(), my_vector.end()));
1 - Sort the vector
2 - Iterate over the permutations
(the do while just print it with a copy to the cout)
I'm not wure of what you call "sub" permutations, are you just moving the "|" inside each permutation ?

calculate different combination of numbers with different number of columns in C++?

I would really appreciate it if someone can point me to the right direction with this problem. I am trying to find all the different combinations of various numbers each with a different number of columns (in C++). for example consider the number 2:
two columns:
2 = { 2 , 0 }
{ 0 , 2 }
{ 1 , 1 }
three columns :
2 = { 0 , 0 , 2 }
{ 0 , 2 , 0 }
{ 2 , 0 , 0 }
{ 1 , 1 , 0 }
{ 0 , 1 , 1 }
{ 1 , 0 , 1 }
four columns:
2 = { 0 , 0 , 0 , 2 }
{ 0 , 0 , 2 , 0 }
{ 0 , 2 , 0 , 0 }
{ 2 , 0 , 0 , 0 }
{ 1 , 1 , 0 , 0 }
{ 0 , 0 , 1 , 1 }
{ 0 , 1 , 1 , 0 }
{ 1 , 0 , 0 , 1 }
{ 1 , 0 , 1 , 0 }
{ 0 , 1 , 0 , 1 }
thanks in advance!
Here's my attempt:
void combinations(int n, int columns, std::vector<int>& soFar)
{
if (columns == 1)
{
for (auto e : soFar)
std::cout << e << " ";
std::cout << n << '\n';
return;
}
for (int i = 0; i <= n; ++i)
{
soFar.push_back(i);
combinations(n - i, columns - 1, soFar);
soFar.pop_back();
}
}
void combinations(int n, int columns)
{
std::vector<int> soFar;
combinations(n, columns, soFar);
}
Basically, you keep dividing the number into two subparts, till you reach your depth limit (the number of columns in your case).
To keep printing the previous numbers on the way back up, I store them in the soFar vector, pushing and popping them accordingly.
Here's the output for combinations(2, 4):
0 0 0 2
0 0 1 1
0 0 2 0
0 1 0 1
0 1 1 0
0 2 0 0
1 0 0 1
1 0 1 0
1 1 0 0
2 0 0 0
This is a straight combinatorics question. If you have m columns, then you have m-1 dividers between columns. With the number n, you want all the ways to order m-1 dividers and n elements. For example, with n=5 and m=3, one possible arrangement is xx,x,xx -- and you are looking at 7 choose 2.
So the general solution is m+n-1 choose m-1, or equivalently, m+n-1 choose n.
The formula for x choose y is x! / [y! * (x-y)!]
Consider splitting the problem into two subproblems:
1) Find all the combinations of numbers that add to your number:
i.e: 2-column case for "3": (2,1) and (3,0)
2) Permute all the combinations you've found:
i.e: (2,1) -> (2,1), (1,2) and (3,0) -> (3,0), (0,3)
For part 1), you get the problem of big numbers and many columns, say 5 with 4 columns (i know, they're unfathomably huge numbers):
5 = 4 + 1
5 = 3 + 2
5 = 3 + 1 + 1
5 = 2 + 1 + 1 + 1
5 = 1 + 1 + 1 + 1 + 1
If you look carefully, you have a possibility for recursion. As in, for 5 = 3 + 2: find the combinations for 3 and the combinations for 2 and so on... until you get to 1
As soon as you say recursion, tree structures start to sound interesting. This is how I'd approach the problem.

Dynamic programming algorithm

Hi I have a question on an existing algo problem.
Existing problem description: Generate 10-digit number using a phone keypad
1 2 3
4 5 6
7 8 9
0
Though this question has a tag of C++, consider this pseudo-code to express the algorithm (which conveniently happens to be written in ruby.)
# Where the knight can jump to
$m = {
0 => [4,6], 1 => [6,8], 2 => [7,9], 3 => [4,8], 4 => [0,3,9],
5 => [], 6 => [0,1,7], 7 => [2,6], 8 => [1,3], 9 => [2,4]
}
$cache = Hash.new
# return count
def nseq( k, n, e=0 )
e += 1 if k.even?
return 0 if 3 < e
return 1 if n == 1
key = "#{k}:#{n}:#{e}" # for the memoization
return $cache[key] if $cache.has_key? key
# Sum nseq(j,n-1,e) for j in $m[k]
return $cache[key] = $m[k].inject(0) { |sum,j| sum + nseq( j, n-1, e ) }
end
0.upto(9) do |k|
2.upto(8) do |n|
count = nseq(k,n)
puts "k=#{k},n=#{n}: #{count}"
break if count.zero?
end
end
This outputs
k=0,n=2: 2
k=0,n=3: 6
k=0,n=4: 8
k=0,n=5: 16
k=0,n=6: 0
k=1,n=2: 2
k=1,n=3: 5
k=1,n=4: 10
k=1,n=5: 24
k=1,n=6: 32
k=1,n=7: 64
k=1,n=8: 0
k=2,n=2: 2
k=2,n=3: 4
k=2,n=4: 10
k=2,n=5: 16
k=2,n=6: 32
k=2,n=7: 0
k=3,n=2: 2
k=3,n=3: 5
k=3,n=4: 10
k=3,n=5: 24
k=3,n=6: 32
k=3,n=7: 64
k=3,n=8: 0
k=4,n=2: 3
k=4,n=3: 6
k=4,n=4: 14
k=4,n=5: 16
k=4,n=6: 32
k=4,n=7: 0
k=5,n=2: 0
k=6,n=2: 3
k=6,n=3: 6
k=6,n=4: 14
k=6,n=5: 16
k=6,n=6: 32
k=6,n=7: 0
k=7,n=2: 2
k=7,n=3: 5
k=7,n=4: 10
k=7,n=5: 24
k=7,n=6: 32
k=7,n=7: 64
k=7,n=8: 0
k=8,n=2: 2
k=8,n=3: 4
k=8,n=4: 10
k=8,n=5: 16
k=8,n=6: 32
k=8,n=7: 0
k=9,n=2: 2
k=9,n=3: 5
k=9,n=4: 10
k=9,n=5: 24
k=9,n=6: 32
k=9,n=7: 64
k=9,n=8: 0
The result is the number of all n-length sequences starting on key k, which have no more than 3 even digits in them. For example, the last entry is k=9,n=8: 0. This means that all sequences of length 8 starting on key 9 include more than 3 even digits.
EDIT: Here it is translated into C++. It produces identical output as above.
#include<iostream>
#include<map>
using namespace std;
const int MAX_EVENS = 3; // Assume < 8
// Where the knight can jump to
const int jumpto[][3] = { {4,6}, // 0
{6,8}, {7,9}, {4,8}, // 1 2 3
{0,3,9}, {}, {0,1,7}, // 4 5 6
{2,6}, {1,3}, {2,4} }; // 7 8 9
const int jumpto_size[] = { 2, // 0
2, 2, 2, // 1 2 3
3, 0, 3, // 4 5 6
2, 2, 2 }; // 7 8 9
typedef map<unsigned,int> cachetype;
cachetype cache;
int nseq( int k, int n, int e=0 )
{
e += k&1^1; // increment e if k is even.
if( MAX_EVENS < e ) return 0;
if( n <= 1 ) return 1;
unsigned key = (n << 4 | k) << 3 | e; // n is left with 32-7=25 bits
cachetype::const_iterator it = cache.find(key);
if( it != cache.end() ) return it->second;
int sum = 0;
for( int i=0 ; i<jumpto_size[k] ; ++i ) sum += nseq( jumpto[k][i], n-1, e );
return cache[key] = sum;
}
int main()
{
for( int k=0 ; k<=9 ; ++k )
for( int n=2 ; n<=8 ; ++n )
{
int count = nseq(k,n);
cout << "k="<<k<<",n="<<n<<": "<<count<<endl;
if( count == 0 ) break;
}
return 0;
}