Minizinc - Implementing count constraint - minizinc

I am working on this problem. I have two decision variables x and y. For same values in x, and corresponding same values in y, I have to count the occurences of this value in y.
I have tried to implement it. But I have doubts that the functionality is as expected.
My code
set of int: x = 1..4;
set of int: y = 1..3;
set of int: a = 1..10;
set of int: b = 1..5;
%Decision variables
array[x, y] of var a: recordA;
array[x, y] of var b: recordB;
constraint forall(i in x ) (
alldifferent([recordB[i,j] | j in y])
);
constraint forall(i in x ) (
alldifferent([recordA[i,j] | j in y])
);
%constraint forall(i,k in x, j in y where i<k /\ recordB[i,j]=recordB[k,j]) (
% forall(i,k in x,j in y where recordA[i,j]=recordA[k,j])(
% count(recordA, recordA[i,j])
%);
OR
%Maybe something like this
%constraint forall(i in x, j in y, m in b)(
% count(col(recordA, j),count(col(recordB,j),m))
% );
The idea is for every recorB and every recordA, to go through all the y (for all the x) and count how many values occur the same recordB at corresponding the same recordA.
For Example- for a value r1 in recordB->count of number of values r2 occuring in recordA.
In this case, recordB has three occurences of value 4 at recordB[1], recordB[6] and recordB[11]
correspondingly recordA has two occurrences of value 5 at recordA[1], recordA[6] but at recordA[11] the value is 1.
I want to count these occurrences of same values in recordA corresponding wuth recordB.
And each row of recordA is unique
And each row of recordB is unique
Thanks for suggestions

Related

How to do a toeplitz matrix efficiently matlab

Let's suppose I have a vector x and 2 constants initialized as follows:
x = [ones(1,21) zeros(1,79)]; %step of 100 components
p = 2; q = 0;
Now, I want to build this matrix:
But in this case for example x(q-1) = x(-1) doesn't exist, so I want it to be 0, and I was wondering if there is a way to do it with the minimum lines of code. Note that the matrix can be written with the function toeplitz(), but I don't know how to replace nonexistent position of my vector x with zeros.
I hope someone can help me. Thank you for your answers.
You need to be careful about zero-based or one-based indexing.
In your question, you state that negative indices are invalid - in MATLAB the index 0 is also invalid. The below code assumes your x(q) is zero-based as described, but I do a +1 conversion. Be aware of this if q+p-1 is near numel(x).
x = [ones(1,21) zeros(1,79)]; %step of 100 components
p = 2; q = 0;
% Set up indexing matrix using implicit expansion (R2016b or newer)
m = ( q:-1:q-p+1 ) + ( 0:1:q+p-1 ).';
% Convert from 0-based to 1-based for MATLAB
m = m + 1;
% Set up output matrix, defaulting to zero
M = zeros( size( m ) );
% Put elements where 'm' is valid from 'x' into output 'M'
M( m > 0 ) = x( m( m > 0 ) );
The output is a (q+p) * p matrix.

Solve a system of boolean equations in Matlab

I have a set of boolean equations, i.e.
var1 = x AND y
var2 = x OR z
var3 = ...
var4 = ...
And the constraint that every output vari should equal 1.
I want every corresponding combination of input variables (x, y ,z ...) which satisfies these equations.
For example, the first two equations would allow [x y z] = [1 1 0] or [1 1 1] as solutions.
You can do this pretty easily if you don't have too many variables.
This method will stall if you do have many variables, because it uses use a matrix of size K*(2^K), where K is the number of variables, and combvec gets pretty slow for large K too.
Whilst you have to be wary of the number of variables, this method is pretty capable of handling many logical 'equations' with little overhead.
In the x, y, z example:
% Get all combinations of x/y/z, where each is true or false
opts = repmat( {[true, false]}, 1, 3 );
xyz = combvec( opts{:} )
% Assign each row to a named variable
x = xyz(1,:); y = xyz(2,:); z = xyz(3,:);
% Get the combinations which satisfy your conditions
results = xyz( :, (x & y) & (x | z) );
% Each column of results is a solution
>> results
results =
1 1
1 1
1 0
Written more generally, it might look something like this:
K = 3; % K variables (previously x, y and z so K = 3)
% Create all true/false combinations
opts = repmat( {[true, false]}, 1, K );
combs = combvec( opts{:} );
% Shorthand so we can write in(i) not combs(i,:)
in = #(k) combs(k,:);
% Apply conditions
results = combs( :, (in(1) & in(2)) ...
& (in(1) | in(3)) );
Note: if you don't have the Neural Network Toolbox, you won't have combvec. There are many alternatives for getting all the combinations.

find x values (randomly generated) that gives certain y values

I've found some guidance on how to find x values corresponding to y values on plots, but I'm dealing with something slightly different.
Below is the code for what I've been trying to do:
a = 1 + (2-1).*rand(1,10);
b = 5 + (10-5).*rand(1,10);
c = linspace(0, 100, 10);
y = (c-a)./b
x = linspace(0, 10, 10);
scatter(x,y,'b.')
idx = (5 <= y & y <= 10);
hold on, plot(x(idx), y(idx), 'r.')
hold off
So my y values (coming from a and b) are random, and I want to find what range of a and b will give me 5 < y < 10. I introduced x to visualize possible ranges of y values so trying to find range of x that gives certain range of y wouldn't be useful for me. Would there be an easier way to approach this problem? Any advice will be appreciated!
As you know find(y >= 5 && y <= 10) find the indexes which you expect. In this way, if you find indexes of y, you can apply these for a and b. As value of each element of y is defined exactly by the respective equivalent index in a, b and c, so you found the related index of a and b to get the specified range in y.

How to check whether vector b is in Col A?

How do I determine whether b∈Col A or b∉Col A in matlab? A being an m x n matrix where m >= n, and b being a vector. Is there a built in function for this already, or would I need to create one? If b∈Col A, how would I go about determining whether matrix A has orthonormal columns/is orthogonal?
You can use ismember as explained in a previous answer.
// some sample data
A = [eye(3); zeros(3)];
v = [0; 1; 0; 0; 1; 0];
ismember(A', v', 'rows')
To check orthogonality, you could do the following
// A scalar initialised outside the for-loop. It stores sums of inner products.
dp = 0;
// Take the columns of A one by one and compute the inner product with all subsequent columns. If A is orthogonal, all the inner products have to be zero and, hence, their sum has to be zero.
for i = 1:size(A, 2)
dp = dp + sum(A(:, i)'*A(:, i+1:end));
end
if (dp == 0)
disp('The columns are orthogonal')
else
disp('The columns are not orthogonal')
end
To have orthonormal columns, the norm of each column has to be 1, so:
// Check each column for unit length
M = mat2cell(A, size(A, 1), ones(size(A, 2), 1));
if find(cellfun(#(x)norm(x,2), M) ~= 1)
disp('Columns are not of unit length')
else
disp('Columns are of unit length')
end
Note that all these operations become simpler and faster if m=n (since you allow this case).
Say you have a matrix A that is nxm and a vector b that is nx1, and you want to see if b is a column in A.
You can do this by taking the transpose of both A and b, and then looking to see if the vector b is a member of A. This is the code:
member = ismember(A',b','rows');
Here is an example;
A =
1 5
2 2
3 3
4 4
b =
1
2
3
4
member = ismember(A',b','rows')
member =
1
0
So the first column of A and b are a match but the second column of A and b are not the same. If you want to check the orthogonality of the columns you can do this:
orthcheck = triu(A'*A);
if there are any zeros on the upper triangular matrix then the columns are orthogonal. The A'*A checks the dot product of all the columns and you only need the upper triagular part since the matrix is symmetric.
Another way of testing if v is a column of A:
any(all(bsxfun(#eq,A,v))) %// gives 1 if it is; 0 otherwise
To test if A is orthogonal:
product = A*A'; %'// I'm using ' in case you have complex numbers
product(1:size(A,1)+1:end) = 0; %// remove diagonal
all(product(:)==0) %// gives 1 if it is; 0 otherwise

Looping with two variables from a vector

I have a 30-vector, x where each element of x follows a standardised normal distribution.
So in Matlab,
I have:
for i=1:30;
x(i)=randn;
end;
Now I want to create 30*30=900 elements from vector, x to make a 900-vector, C defined as follows:
I am unable to do the loop for two variables (k and l) properly. I have:
for k=1:30,l=1:30;
C(k,l)=(1/30)*symsum((x(i))*(x(i-abs(k-l))),1,30+abs(k-l));
end
It says '??? Undefined function or method 'symsum' for input arguments of type
'double'.'
I hope to gain from this a 900-vector, C which I will then rewrite as a matrix. The reason I have using two indices k and l instead of one is because I eventually want these indices to denote the (k,l)-entry of such a matrix so it is important that that my 900-vector will be in the form of C = [ row 1 row 2 row 3 ... row 30 ] so I can use the reshape tool i.e.
C'=reshape(C,30,30)
Could anyone help me with the code for the summation and getting such a 900 vector.
Let's try to make this a bit efficient.
n = 30;
x = randn(n,1);
%# preassign C for speed
C = zeros(n);
%# fill only one half of C, since it's symmetric
for k = 2:n
for l = 1:k-1
%# shift the x-vector by |k-l| and sum it up
delta = k-l; %# k is always larger than l
C(k,l) = sum( x(1:end-delta).*x(1+delta:end) );
end
end
%# fill in the other half of C
C = C + C';
%# add the diagonal (where delta is 0, and thus each
%# element of x is multiplied with itself
C(1:n+1:end) = sum(x.^2);
It seems to me that you want a matrix C of 30x30 elements.
Given the formula that you provided I would do
x = randn(1,30)
C = zeros(30,30)
for k=1:30
for l=1:30
v = abs(k-l);
for i =1:30-v
C(k,l) = C(k,l) + x(i)*x(i+v);
end
end
end
if you actually need the vector you can obtain it from the matrix.