How can we use constraint in every individual element in an array in cplex? - constraints

Why is my forall loop not working to apply an constraint to all the individual values stored in my variable. For eg: if there are 100 values stored under a variable k, how can I apply the constraint where each value is less than a certain constant.

range r=1..100;
int value[i in r]=2*i;
dvar int k[r];
maximize sum(i in r) k[i];
subject to
{
forall(i in r) k[i]<=value[i];
}
assert forall(i in r) k[i]==2*i;
works fine

Related

Need review of scheduling model logic, suggestions for constraint creation and fixes for syntax errors

I am creating a scheduling model for a blending facility in Mini Zinc. I have asked a similar question earlier but I have since progressed. I will summarize what I think my existing model should do, it would be super helpful if someone could correct any logical or syntax errors I have made. The model currently errors, with several instances of "expecting end of file". It seems way to simplistic in comparison to several other sequence dependent scheduling models I have found. Below you will find the model code commented with my understanding of each line.
Besides an overview of the logic and syntax, I am looking for help with the "missing constraint" in this model, which needs to require that the array of blends [y] contain no more than the declared integer quantity of each blend.
Notable future goals for this model include automatic generation of the blendcost matrix, output the schedule array given a starting day into a 5 column matrix representing weekdays, and showing the blend name as opposed to blend number.
enum Blends = { A, B, C, D, E, F};
%Establish names for each blend and link them to their order number.
int: nb = count([Blends])
%Count the number of blends, plan to use later.
int: qA; %Error: syntax error, unexpected int, expecting end of file
int: qB;
int: qC;
int: qD;
int: qE;
int: qF;
int: sb;
%Call for inputs of the quantity of each of the blends needed, as well as the number/letter of the blend currently in the machine.
int: mc = qA + qB + qC + qD + qE + qF;
%Sum the blend quantities to determine total number of blends
[Blendcost] : [|1,2,2,2,2,2,|1,1,1,1,1,1,|1,1,1,1,1,1,|2,2,2,1,2,2,|1,1,1,1,1,1,|1,1,1,1,1,1,|]; %Error: syntax error, unexpected [|, expecting identifier
%Establishes a blend cost matrix, 6X6 depicting the transition costs from any blend A-F to any other blend A-F
array [Blends] of int: 1..6;
%Is this line needed to establish the link between A/1, B/2, C/3 etc;? Or is that taken care of when Blends is enumerated?
array [0..mc] of var 1..6: y;
%Create an array from 0 to the number of blends with potential values from 1-6, corresponding to the blend numbers.
%Missing constraint: [y] can contain no more than the quantity of each blend declared above, except for the blend declared in the starting blend, which will be allowed that blend quantity + 1
constraint y(0) = sb
%y(0) is set equal to the starting blend Letter/Number Defined earlier, used to determine the first transitionary cost.
array [1..mc] of int: x(i); %Error: syntax error, unexpected array, expecting end of file
%Create an array from 1 to number of blends, which will be filled with the transition costs in response to variations in y
constraint forall(i in x)(x(i) = Blendcost(y(i-1),y(i)))
%For each space in x, x will equal the blend cost value obtained from the previous blend in the y array vs the next blend in the y array
solve minimize sum (x); %Error: syntax error, unexpected solve, expecting end of file
%Solves this model attempting to minimize the sum of the x array, which should be filled with the transition costs.
show(y):
%Print the final array of blend numbers that has minimized blend cost transition.
%Error: unexpected end of file, expecting identifier.
Here is a basic version of your CP-model that runs (assuming some demand q):
enum BLEND = { A, B, C, D, E, F};
array[BLEND] of int: q = [1, 2, 4, 6, 8, 1];
array[BLEND, BLEND] of int: Blendcost =
[|1,2,2,2,2,2|1,1,1,1,1,1|1,1,1,1,1,1|2,2,2,1,2,2|1,1,1,1,1,1|1,1,1,1,1,1|];
int: mc = sum(q);
array[1..mc] of var BLEND: y;
include "global_cardinality.mzn";
constraint global_cardinality(y, BLEND, q);
var int: obj = sum(p in 1..mc-1)(Blendcost[y[p],y[p+1]]) + 1;
array[int] of var opt BLEND: day = [y[p] | p in 1..mc-1, q in 1..max(Blendcost) where q <= Blendcost[y[p],y[p+1]]] ++ [y[mc]];
array[int] of var opt int: wash = [bool2int(q > 1) | p in 1..mc-1, q in 1..max(Blendcost) where q <= Blendcost[y[p],y[p+1]]] ++ [0];
solve minimize obj;
output ["obj=\(obj)\n"] ++
["day=\n"] ++ [
show(day[d]) ++ if fix(wash[d]) > 0 then "W" else "" endif ++ " " ++
if d mod 5 = 0 then "\n" else "" endif | d in 1..length(day)
] ++ ["\nmc=\(mc)\n"] ++ ["y=\(y)\n"] ++ ["wash=\(wash)\n"]
Have a look at https://www.minizinc.org/doc-2.2.3/en/lib-globals.html#counting-constraints for alternative versions of the counting constraint.
For larger instances a MIP-model might show better performance.

Recursive method to finding the k element subsets of a set with n elements

Consider the problem of finding the k element subsets of a set with n elements. Write a recursive function that takes an array of integers representing the set, the number of integers in the set (n), and the required subset size (k) as input, and displays all subsets with k elements on the screen. You may assume that the elements in the array have unique values. For example, if the array (set) contains the elements [ 8 2 6 7 ], n is 4, and k is 2, then the output is 82 86 87 26 27 67.
Can you help me with this, at least tell what way should I follow?
The type of thing you're talking about is a **combination&&.
There's a recursive definition of the calculation tucked in the middle of the Wikipedia page.
$$\binom{n}{k}=\binom{n-1}{k-1}+\binom{n-1}{k}$$
Figuring out what your base cases are might be tricky, but I think everything you need is there.
I would've right something like this:
subset ( numbers, n, k, index)
{
if (index < n) // end for the recursion. passed through all elements
{
if (k == 0) // end for the recursion. no more elements needed
print ' '
else
{
print numbers[index]
subset(numbers, n, k-1, index+1) // uses the number in the current index
subset(numbers, n, k, index+1) // doesn't use the number in the current index
}
}
call subset(numbers, n, k, 0) to start
notice that because order doesn't play a role in sets, its enough to pass over the elements in one direction

Sum 2D array in constraints in system verilog

I'm trying to create constraint using a 2d array filled with 1's and 0's.
I want every row to have a total sum of either 0,1,2,4 and every column sums to 1. Moreover, I want the entire sum of the matrix to be equal to 8 (which worked using sum function).
I tried using the function .sum() to constraint of every row and column to the value I demanded, but I keep getting syntax error. What am I doing wrong?
rand bit MAT[8][8];
constraint range {
MAT.sum() with (32' (item)) == 8;
foreach (MAT[j]){
foreach(MAT[j][i]){
MAT[j][].sum() with (32' (item)) == 1;
MAT[][i].sum() with (32' (item)) inside {0,1,2,4};
}
}
Section 7.12.3 Array reduction methods of the IEEE 1800-2012 standard states that
[array] reduction methods may be applied to any unpacked array of integral values to reduce the array to a
single value.
While MAT[0].sum() or MAT[1].sum() is allowed (apply sum on line 0 and 1 respectively of MAT), MAT.sum() is not. A line in MAT is an array of bit and bit is an integral type, but MAT is an array of unpacked array of bit which is not an integral type.
Also, it's not possible to select a single column from an array. You can only slice row-wise. This is a bit trickier to implement, but doable.
Let's look at each constraint. First, constraining the sum of each row is easily done with the sum() function:
constraint sum_on_row {
foreach (MAT[i])
MAT[i].sum() with (32'(item)) inside { 0, 1, 2, 4 };
}
To constraint the sum on a column you'll need to transpose the array (rows become columns, columns become rows) and constrain that. First, let's define the transpose of MAT:
rand bit MAT_transp[8][8];
constraint construct_MAT_transp {
foreach (MAT[i,j])
MAT_transp[j][i] == MAT[i][j];
}
We allocate another array and keep its contents in sync with those of MAT. Any constraints on MAT_transp will indirectly affect MAT. As before, we can constrain the rows of MAT_transp, which will effectively constrain the columns of MAT:
constraint sum_on_col {
foreach (MAT_transp[i])
MAT_transp[i].sum() with (32'(item)) == 1;
}
And lastly, you want the sum of all elements in the array to be 8. This is the trickiest to do. While we can't constrain the array sum directly, we can split the problem into two parts. First, we can compute the sum for each row in MAT and store them all in an array:
rand int unsigned row_sums[8];
constraint compute_row_sums {
foreach (row_sums[i])
row_sums[i] == MAT[i].sum() with (32'(item));
}
Now that we have the sum on each row, it's easy to constrain the sum of the entire array by constraining the sum of all row sums:
constraint sum_of_matrix {
row_sums.sum() == 8;
}
The cool thing is that with this one problem we've covered a lot of the usual "tricks" we can apply when constraining arrays. You can find more array constraint idioms in an old post I wrote.
Actually, array2d.sum() works with VCS.
For sum along 2nd index:
Instead of
MAT[j][].sum() with (32'(item))
Use
MAT[j].sum() with (32'(item))
For sum along 1st index:
Instead of
MAT[][i].sum() with (32'(item))
Use
MAT.sum() with (32'(item[i]))
Note: For sum along any index of a multi-dimensional array, specify the higher dimension indices and then reduce the sub array obtained, using with clause for lower dimension indices.
Example:
bit bit_array [n0][n1][n2][n3][n4];
int sum_0 = bit_array.sum() with (int'(item[i1][i2][i3][i4]));
int sum_1 = bit_array[i0].sum() with (int'(item[i2][i3][i4]));
int sum_2 = bit_array[i0][i1].sum() with (int'(item[i3][i4]));
int sum_3 = bit_array[i0][i1][i2].sum() with (int'(item[i4]));
int sum_4 = bit_array[i0][i1][i2][i3].sum() with (int'(item));

Sum of roots of binary search trees of height ≤H with N nodes

Consider all Binary Search Trees of height ≤H that can be created using the first N natural numbers. Find the sum of the roots of those Binary Search Trees.
For example, for N = 3, H = 3: There are 2 trees with 1 as root, 1 tree with 2 as root and 2 trees with 3 as root.
Hence, Sum = 2∗(1)+1∗(2)+2∗(3)=10
I am trying to solve this problem by writing a function f(n,h) which is related to f(n−1,h−1) and f(n−1,h) in some way, but unable to find the solution.
Note: All numbers [1,N] must be present in the tree and the height should be ≤H
Ok let us start with basics.
The number of BST that can be created using first N natural numbers can be very easily calculated using the following algorithm.
natural_number compute_no_of_BST(N)
{
if(N<=1)
return 1;
else
{
left=0,right=0,sum=0;
for(root = 1 to N)
{
left = compute_no_of_BST(root-1);
right = compute_no_of_BST(N-root);
sum = sum + (left*right);
}
return sum;
}
}
Explanation:
The key to understand this algorithm is this:
No matter what the distinct keys are, the number of BST only depends on number of distinct keys
So, this is what we use in recursion.For the left subtree number of distinct values are root-1 and for the right subtree the number of distinct values are N-root.Also we give every key the chance of being the root using the for loop.
Now, let us handle the constraint of height H.I am assuming the height to be the number of edges from root to leaf path. This can also be handled by focusing on the above algorithm and the trick is:
We will not call the recursive function calls for height > H and for this we must keep track of the number of edges traversed from root, which initially is 0.
So that kind of narrows it down to what are new function call will look like.
natural_number compute_no_of_BST(N,H,0);
And every time we make a recursive call, we increment the third variable to indicate an edge traversal.
We will also use an extra data structure, which is an array of length N where
arr[i] = number of BST with root i+1.
Here goes the algorithm for this
natural_number compute_no_of_BST(N,H,l)
{
if(N<=1)
return 1;
else
{
left=0,right=0,sum=0;
for(root = 1 to N)
{
if(l+1<=H)
{
left = compute_no_of_BST(root-1,H,l+1);
right = compute_no_of_BST(N-root,H,l+1);
if(l==0)
arr[root-1] = (left*right);
sum = sum + (left*right);
}
}
return sum;
}
}
Now sum can be easily computed as
arr[0]*1 + arr[1]*2 + ..... arr[N-1]*N.
Here is just a DP conversion of the above recursive algorithm.
int bottom_up_specific_height(int n,int h){
int i,j,l;
for(l=0;l<=h;l++){
dp[0][l]=1;
dp[1][l]=1;
}
int s=0;
for(i=2;i<=n;i++){
for(j=1;j<=i;j++){
for(l=h;l>=0;l--){
if(l==h)
dp[i][l]=0;
else
dp[i][l]+=(dp[j-1][l+1]*dp[i-j][l+1]);
if(l==0 && i==n)
s+=(j)*(dp[j-1][l+1]*dp[i-j][l+1]);
}
}
}
return s;
}
Here complexity reduces to O(h*n^2).
Is it possible to optimize it further!!

Finding if binary matrix exists given the row and column sums

How to find out if it is possible to contruct a binary matrix with given row and column sums.
Input :
The first row of input contains two numbers 1≤m,n≤1000, the number of rows and columns of the matrix. The next row contains m numbers 0≤ri≤n – the sum of each row in the matrix. The third row contains n numbers 0≤cj≤m – the sum of each column in the matrix.
Output:
Output “YES” if there exists an m-by-n matrix A, with each element either being 0 or 1. Else "NO".
I tried reading about Tomography algorithms but could not figure out an answer as all the papers related to Tomography algorithm is very complicated.
Can someone please help me..
I've successfully implemented randomly generating such matrices for R using a modeling based on network flow. I intend to write up those ideas one day, but haven't found the time yet. Reasearching for that, I read in Randomization of Presence–absence Matrices: Comments and New Algorithms by Miklós and Podani:
The Havel-Hakimi theorem (Havel 1955, Hakimi 1962) states that there exists a matrix Xn,m of 0’s and 1’s with row totals a0=(a1, a2,… , an) and column totals b0=(b1, b2,… , bm) such that bi ≥ bi+1 for every 0 < i < m if and only if another matrix Xn−1,m of 0’s and 1’s with row totals a1=(a2, a3,… , an) and column totals b1=(b1−1, b2−1,… ,ba1−1, ba1+1,… , bm) also exists.
I guess that should be the best method to recursively decide your question.
Phrased in my own words: Choose any row, remove it from the list of totals. Call that removed number k. Also subtract one from the k columns with larges sums. You obtain a description of a smaller matrix, and recurse. If at any point you don't have k columns with non-zero sums, then no such matrix can exist. Otherwise you can recursively build a matching matrix using the reverse process: take the matrix returned by the recursive call, then add one more row with k ones, placed in the columns from whose counts you originally subtracted one.
Implementation
bool satisfiable(std::vector<int> a, std::vector<int> b) {
while (!a.empty()) {
std::sort(b.begin(), b.end(), std::greater<int>());
int k = a.back();
a.pop_back();
if (k > b.size()) return false;
if (k == 0) continue;
if (b[k - 1] == 0) return false;
for (int i = 0; i < k; i++)
b[i]--;
}
for (std::vector<int>::iterator i = b.begin(); i != b.end(); i++)
if (*i != 0)
return false;
return true;
}

Resources