Select a suitable set for a set - minizinc

I need some help with the following case.
let say I have the following code:
enum x= {p,k,m};
enum y= {t1,t2,t3,t4};
array[y] of set of int:against=[{1,3,6},{3,3,6},{6,1,1},{6,3,6}];
array[x] of set of int:attack=[{3,3,6},{6,2,2},{3,1,3}];
array[x] of set of y: NodesD=[{t2,t3},{t2,t3,t4},{t1,t4}];
array[x]of var y: Select;
constraint forall(p in x)(Select[p] in NodesD[p]);
So for each enum of x I should select only on enum of Y. Then I want to select the one that suitable for each set of attack in the following way:
let take the first enum of x {p} which have two possible chooses of y{t2,t3}, so I want to do like this: t2={1,1,6}, t3={6,3,3} so I want to subtract each value in x attack[] {3,3,6} from each value in y against[] and the sum up the results:
{1,1,6}-
{3,3,6}
-----------
{-2,-2,0} then sum them which is equal to -4
then do the same with t2
{6,3,3}-
{3,3,6}
------------
{3,0,-3} which is equal to 0
and in this case, t3 which is equal to 0 is better than t2=-4.
I want to do the same for each enum x and Maximize the power.
I tried to do it in the following way but it does not work
var int: power = sum(p in x)(card(against[Select[p]])-(card(attack[p])*Select[p]) );
solve maximize power ;
Any help or hint please,:)

If you want to make an element by element comparison a matrix is better suited for that than an array of sets, because that way you ensure that both matrixes have the same width and also the syntax is less cumbersome, so instead of summing with an index from 1 to the cardinality of the set you use a different set to sum over the columns of the matrix.
You could calculate the sum of the element wise difference of the sets with
sum(i in 1..min(card(set_A),card(set_B)))(set_A[i] - set_B[i]);
using the min to be sure that you only iterate over the smallest set and don't access elements that don't exist.
But written like this is cleaner in my opinion, basically, change the {} of sets for | to delimit the rows of the matrix in attack and against, and add a new variable that will index the columns of the matrix, I called it FRONTS in this example, so you pick an X and compare the difference of forces over the different battlefronts.
enum X = {p,k,m};
enum y = {t1,t2,t3,t4};
set of int : FRONTS = 1..3;
array[y,FRONTS] of int : against=[|1,3,6|3,3,6|6,1,1|6,3,6|];
array[X,FRONTS] of int : attack=[|3,3,6|6,2,2|3,1,3|];
array[X] of set of y : nodesD=[{t2,t3},{t2,t3,t4},{t1,t4}];
array[X] of var y : select;
var int: power;
constraint forall(p in X)(select[p] in nodesD[p]);
constraint power = sum(p in X)( sum(i in FRONTS)( against[ select[p], i] - attack[ p, i ] ) );
solve maximize power;
output [show(select) ++ " = " ++ show(power)];

Related

how to define an array with fractional index number

Like suppose that I need to create a function named pressure denoted by p (a 2-D matrix) which depends on 2 variables r and z.
u, v, w are linear matrices which also depend on 2 variables r and z.
r and z are linear matrix defined below take i={1,2,3,4,5,6,7,8,9,10}
r(i)=i/10
z(i)=i/10
u(i) = 2*r(i) + 3*z(i)
v(i) = 8*r(i) + 4*z(i)
w(i) = 3*r(i) + 2*z(i)
p = p(r,z) %, which is given as,
p(r(i),z(j)) = 2*v(i) - 4*u(i) + w(j)
Now suppose the value of p at a given location (r,z) say (0.4,0.8) is needed, I want that if I give the input p(0.4,0.8), I get the result.
In your case the easiest way is to convert the fractional numbers to integers by multiplying by 10.
This way the location (r,z) = (0.4, 0.8) will become (4,8).
If you don't want to remember every time to provide the locations multiplied by 10, just create a function that will do it for you, so you can call the function with the fractional location.
If your matrices are linear, you will always find a multiplying factor to get rid of the fractional coordinates.
Not entirely sure what you mean here, but if your matrix is only defined in the indices you give (i.e. you only want to draw values from the fixed set of indices you defined), then this should do it:
% the query indices
r_i = 0.4;
z_i = 0.8;
value = p(r_i*10,z_i*10);
if you want to look at values between the ones you defined, you need to look at interpolation:
% the query indices
r_i = 0.46;
z_i = 0.84;
value = interp2(r,z, p, r_i, z_i);
(I may have gotten r and z in that last function in the wrong order, try it out).

Create an increasing integer alternating sequence in MATLAB / Octave

I'm trying to find a way to create a number pattern like the one below
0,1,-2,3,-4,5....
Please note: it needs to go to 200000, but I will be splitting them up into groups of 2000.
I found a formula that looks like it would work on http://oeis.org/A181983, but when I create the formula in MATLAB / Octave, the numbers don't match up:
f_num= #(x) x / (1 + x)^2;
numval = f_num(1)
numval = 0.25000
Is there another way I should be doing this?
Method #1 - Using (-1)^x
Just use a linear increment operator to go from 0 to 200000 and multiply the sequence by (-1)^(x+1) to allow the sign of the sequence to alternate:
x = 0:200000;
y = ((-1).^(x+1)) .* x;
The addition of the +1 is important so that the even positions get a positive sign while the odd positions get a negative sign.
Method #2 - Using indexing
Alternatively, you can declare the same array from 0 to 200000, index into every even position and negate the sign:
x = 0:200000;
x(2:2:end) = -x(2:2:end);
Method #3 - Using trigonometry and integers
One more to throw into the mix. You know that for cos(x*pi), the output is -1 when x is odd and the output is 1 when x is even. We need to flip this for your case and ultimately use this alternating sequence to multiply with the same array going from 0 to 200000, and therefore:
x = 0:200000;
y = (-cos(x*pi)).*x;
Aside
Interestingly enough, (-1)^x is also equal to exp(i*pi*x) for all values of x that are integer. We can verify this by using Euler's formula where: exp(i*pi*x) = cos(pi*x) + i*sin(pi*x). Since i*sin(pi*x) = 0 for all x belonging to an integer, we really get exp(i*pi*x) = cos(pi*x). Substituting even numbers of x will give us 1 while odd numbers of x will give us -1, and hence exp(i*pi*x) = cos(pi*x) = (-1)^x for all x belonging to integers.
Also, (-1)^(x+1) = -(-1)^x = -cos(x*pi) for all x belonging to integers and so the first method is really equal to the third method anyway!
try
f_num= #(x) x * (-1)^(x+1);

Permuting n elements by swapping each element by no more than k positions

What I have is a vector (n = 4 in the example):
x = '0123';
What I want is a vector y of the same size of x and with the same elements as in x in different order:
y = ['0123'; '0132'; '0213'; '0231'; '0312'; '0321'; '1023'; '1032'; '1203'; '1302'; '2013'; '2031'; '2103'; '2301'];
y(ceil(rand * numel(y(:, 1))), :)
i.e. a permutation such that each element in y is allowed to randomly change no more than k positions with respect to its original position in x (k = 2 in the example). The probability distribution must be uniform (i.e. each permutation must be equally likely to occur).
An obvious but inefficient way to do it is of course to find a random unconstrained permutation and check ex post whether or not this happens to respect the constraint. For small vectors you can find all the permutations, delete those that are not allowed and randomly pick among the remaining ones.
Any idea about how to do the same more efficiently, for example by actually swapping the elements?
Generating all the permutations can be done easily using constraint programming. Here is a short model using MiniZinc for the above example (note that we assume that x will contain n different values here):
include "globals.mzn";
int: k = 2;
int: n = 4;
array[1..n] of int: x = [0, 1, 2, 3];
array[1..n] of var int: y;
constraint forall(i in 1..n) (
y[i] in {x[i + offset] | offset in -min(k, i-1)..min(k, n-i)}
);
constraint all_different(y);
solve :: int_search(y, input_order, indomain_min, complete)
satisfy;
output [show(y)];
In most cases, constraint programming systems have the possibility to use a random search. However, this would not give you a uniform distribution of the results. Using CP will however generate all valid permutations more efficiently than the naive method (generate and test for validity).
If you need to generate a random permutation of your kind efficiently, I think that it would be possible to modify the standard Fisher-Yates shuffle to handle it directly. The standard algorithm uses the rest of the array to choose the next value from, and chooses the value with a probability distribution that is uniform. It should be possible to keep a list of only the currently valid choices, and to change the probability distribution of the values to match the desired output.
I don't see any approach other than the rejection method that you mention. However, instead of listing all allowed permutations and then picking one, it's more efficient to avoid that listing. Thus, you can randomly generate a permutation, check if it's valid, and repeat if it's not:
x = '0123';
k = 2;
n = numel(x);
done = 0;
while ~done
perm = randperm(n);
done = all( abs(perm-(1:n)) <= k ); %// check condition
end
y = x(perm);

Pull out values and associated strings of at least a certain value

I am trying to write code to pull out of a vector of data, 1x1000, the values that are a fold change of 2 or more. A fold change of 2 is equivalent to -1. I want to pull out the names of my genes (coded in vector C) and the values (coded in vector fcsites). This is what I have come up with so far but one of my issues is that I don't know what to specify as the length of the new vector. Does anyone know a better way to approach this?
atleast = {C,fcsites}
Z = zeros(length(C),1);
for i2=1:length(C)
Z(i2)=C(fcsites<=-1);
end
I get the error:
atleast =
{602x1 cell} [602x1 double]
The following error occurred converting from cell to double:
Error using double
Conversion to double from cell is not possible.
Find the desired elements in fcsites, and use their corresponding indices as a subscript for C:
idx = (fcsites <= -1);
X = C(idx)
or shorter:
X = C(fcsites <= -1)
Now X contains all the names from C that correspond to values in fcsites that are less than or equal to -1.

Set all nonzero matrix elements to 1 (while keeping the others 0)

I have a mesh grid defined as
[X, Y, Z] = meshgrid(-100:100, -100:100, 25); % z will have more values later
and two shapes (ovals, in this case):
x_offset_1 = 40;
x_offset_2 = -x_offset_1;
o1 = ((X-x_offset_1).^2./(2*Z).^2+Y.^2./Z.^2 <= 1);
o2 = ((X-x_offset_2).^2./(2*Z).^2+Y.^2./Z.^2 <= 1);
Now, I want to find all points that are nonzero in either oval. I tried
union = o1+o2;
but since I simply add them, the overlapping region will have a value of 2 instead of the desired 1.
How can I set all nonzero entries in the matrix to 1, regardless of their previous value?
(I tried normalized_union = union./union;, but then I end up with NaN in all 0 elements because I'm dividing by zero...)
Simplest solution: A=A~=0;, where A is your matrix.
This just performs a logical operation that checks if each element is zero. So it returns 1 if the element is non-zero and 0 if it is zero.
First suggestion: don't use union as a variable name, since that will shadow the built-in function union. I'd suggest using the variable name inEitherOval instead since it's more descriptive...
Now, one option you have is to do something like what abcd suggests in which you add your matrices o1 and o2 and use the relational not equal to operator:
inEitherOval = (o1+o2) ~= 0;
A couple of other possibilities in the same vein use the logical not operator or the function logical:
inEitherOval = ~~(o1+o2); % Double negation
inEitherOval = logical(o1+o2); % Convert to logical type
However, the most succinct solution is to apply the logical or operator directly to o1 and o2:
inEitherOval = o1|o2;
Which will result in a value of 1 where either matrix is non-zero and zero otherwise.
There is another simple solution, A=logical(A)