Can this be expressed using Integer Programming or Constraint Programming? - math

Consider a fixed m by n matrix M, all of whose entries are 0 or 1. The question is whether there exists a non zero vector v, all of whose entries are -1, 0 or 1 for which Mv = 0. For example,
[0 1 1 1]
M_1 = [1 0 1 1]
[1 1 0 1]
In this example, there is no such vector v.
[1 0 0 0]
M_2 = [0 1 0 0]
[0 0 1 0]
In this example, the vector (0,0,0,1) gives M_2v = 0.
I am currently solving this problem by trying all different vectors v.
However, is it possible to express the problem as an integer
programming problem or constraint programming problem so I can use an
existing software package, such as SCIP instead which might be more
efficient.

It would help a little if you also give a positive example, not just a negative.
I might have missed something in the requirement/definitions, but here is a way of doing it in the Constraint Programming (CP) system MiniZinc (http://minizinc.org/). It don't use any specific constraints unique to CP systems - except perhaps for the function syntax, so it should be possible to translate it to other CP or IP systems.
% dimensions
int: rows = 3;
int: cols = 4;
% the matrix
array[1..rows, 1..cols] of int: M = array2d(1..rows,1..cols,
[0, 1, 1, 1,
1, 0, 1, 1,
1, 1, 0, 1,
] );
% function for matrix multiplication: res = matrix x vec
function array[int] of var int: matrix_mult(array[int,int] of var int: m,
array[int] of var int: v) =
let {
array[index_set_2of2(m)] of var int: res; % result
constraint
forall(i in index_set_1of2(m)) (
res[i] = sum(j in index_set_2of2(m)) (
m[i,j]*v[j]
)
)
;
} in res; % return value
solve satisfy;
constraint
% M x v = 0
matrix_mult(M, v) = [0 | j in 1..cols] /\
sum(i in 1..cols) (abs(v[i])) != 0 % non-zero vector
;
output
[
"v: ", show(v), "\n",
"M: ",
]
++
[
if j = 1 then "\n" else " " endif ++
show(M[i,j])
| i in 1..rows, j in 1..cols
];
By changing the definition of "M" to use decision variables with the domain 0..1 instead of constants:
array[1..rows, 1..cols] of var 0..1: M;
then this model yield 18066 different solutions, for example these two:
v: [-1, 1, 1, 1]
M:
1 0 0 1
1 1 0 0
1 0 0 1
----------
v: [-1, 1, 1, 1]
M:
0 0 0 0
1 0 1 0
1 0 0 1
Note: Generating all solutions is probably more common in CP systems than in traditional MIP systems (this is a feature that I really appreciate).

Related

Get a sequence number from 0 and alternate positive/negative incrementing every other time

I would like to be able to obtain a (non-convergent) sequence of numbers by a simple calculation that would look like this: 0, 1, -1, 2, -2, 3, -3, 4, -4 ...
By simple calculation I mean being able to do it with a single variable that would start from 1 (or 0) without having to rearrange this sequence.
I made several (unsuccessful) attempts in Lua, here is what it should look like in principle (this example only alternates 0s and 1s):
do
local n = 0
for i = 1, 10 do print(n)
n = n==0 and 1 or -n + (n/n)
end
end
Is this possible and how?
Update:
I just succeeded like this:
local n, j = 0, 2
for i = 1, 10 do print(n)
n = n==0 and 1 or j%2==0 and -(n+(n/math.abs(n))) or -n
j = j + 1
end
But I have to help myself with a second variable, I would have liked to know if with only n it would be possible to do it?
The whole numbers are enumerable. Thus there exists a mapping from the natural numbers to whole numbers. You'll now have to use a loop to loop over natural numbers, then compute a function that gives you a whole number:
-- 0, 1...10, -1...-10 -> 21 numbers total
for n = 1, 21 do
local last_bit = n % 2
local sign = 1 - (2 * last_bit)
local abs = (n - last_bit) / 2
print(sign * abs)
end
prints
-0
1
-1
2
-2
...
10
-10
on Lua 5.1; on newer Lua versions, you can use n // 2 instead of (n - last_bit) / 2 to (1) use ints and (2) make extracting the abs cheaper.
Simply "emit" both n and -n in each iteration:
for n = 0, 10 do
print(n)
print(-n)
end
My problem was solved by #EgorSkriptunoff in comment of my question, his approach is:
n = (n > 0 and 0 or 1) - n
The output of:
local n = 0
for i=1,10 do io.write(n..", ")
n = (n > 0 and 0 or 1) - n
end
Actually gives:
0, 1, -1, 2, -2, 3, -3, 4, -4, 5,

Create boolean vector of length n with k true values well dispersed

The problem is to create boolean vector of length n with k true entries (and n-k false entries) well dispersed in the vector.
If k = 5 and n = 8 manually created solutions are [1 0 1 1 0 1 0 1] or [1 0 1 0 1 0 1 1] etc.
An example for a vector with entries that are not well dispersed would be [1 1 1 1 1 0 0 0 0].
A possible criterium for "well-dispersedness" is having alternating blocks of zeros and ones of roughly the same length - specifically with one-blocks of size floor(n/k) or floor(n/k) + 1 and zero-blocks of size floor(n/(n-k)) or floor(n/(n-k)) + 1.
How to create such a vector?
Get the simplest implementation of Bresenham algorithm, and simulate drawing of line segment with end coordinates (0,0)-(ones,zeros). This is just error-propagation approach.
When algorithm generates change of X-coordinate (X-step), it corresponds to 1-entry, Y-step corresponds to zero bit.
def Distribute(ones, zeros):
leng = ones + zeros
err = leng // 2
res = []
for i in range(0, leng):
err = err - ones
if err < 0 :
res.append(1)
err = err + leng
else:
res.append(0)
print(res)
Distribute(5,3)
[1, 0, 1, 0, 1, 1, 0, 1]

How to determine the number of possible combinations of letters that contain a degenerate substring

I've been racking my brain for a couple of days to work out a series or closed-form equation to the following problem:
Specifically: given all strings of length N that draws from an alphabet of L letters (starting with 'A', for example {A, B}, {A, B, C}, ...), how many of those strings contain a substring that matches the pattern: 'A', more than 1 not-'A', 'A'. The standard regular expression for that pattern would be A[^A][^A]+A.
The number of possible strings is simple enough: L^N . For small values of N and L, it's also very practical to simply create all possible combinations and use a regular expression to find the substrings that match the pattern; in R:
all.combinations <- function(N, L) {
apply(
expand.grid(rep(list(LETTERS[1:L]), N)),
1,
paste,
collapse = ''
)
}
matching.pattern <- function(N, L, pattern = 'A[^A][^A]+A') {
sum(grepl(pattern, all.combinations(N, L)))
}
all.combinations(4, 2)
matching.pattern(4, 2)
I had come up with the following, which works for N < 7:
M <- function(N, L) {
sum(
sapply(
2:(N-2),
function(g) {
(N - g - 1) * (L - 1) ** g * L ** (N - g - 2)
}
)
)
}
Unfortunately, that only works while N < 7 because it's simply adding the combinations that have substrings A..A, A...A, A....A, etc. and some combinations obviously have multiple matching substrings (e.g., A..A..A, A..A...A), which are counted twice.
Any suggestions? I am open to procedural solutions too, so long as they don't blow up with the number of combinations (like my code above would). I'd like to be able to compute for values of N from 15 to 25 and L from 2 to 10.
For what it is worth, here's the number of combinations, and matching combinations for some values of N and L that are tractable to determine by generating all combinations and doing a regular expression match:
N L combinations matching
-- - ------------ --------
4 2 16 1
5 2 32 5
6 2 64 17
7 2 128 48
8 2 256 122
9 2 512 290
10 2 1024 659
4 3 81 4
5 3 243 32
6 3 729 172
7 3 2187 760
8 3 6561 2996
9 3 19683 10960
10 3 59049 38076
4 4 256 9
5 4 1024 99
6 4 4096 729
7 4 16384 4410
8 4 65536 23778
9 4 262144 118854
10 4 1048576 563499
It is possible to use dynamic programming approach.
For fixed L, let X(n) be number of strings of length n that contain given pattern, and let A(n) be number of strings of length n that contain given pattern and starts with A.
First derive recursion formula for A(n). Lets count all strings in A(n) by grouping them by first 2-3 letters. Number of strings in A(n) with:
"second letter A" is A(n-1),
"second letter non-A and third letter is A" is A(n-2),
"second and third letter non-A" is (L^(n-3) - (L-1)^(n-3)). That is because string 'needs' at least one A in remaining letters to be counted.
With that:
A(n) = A(n-1) + (L-1) * (A(n-2) + (L-1) * (L^(n-3) - (L-1)^(n-3)))
String of length n+1 can start with A or non-A:
X(n+1) = A(n+1) + (L-1) * X(n)
X(i) = A(i) = 0, for i <= 3
Python implementation:
def combs(l, n):
x = [0] * (n + 1) # First element is not used, easier indexing
a = [0] * (n + 1)
for i in range(4, n+1):
a[i] = a[i-1] + (l-1) * (a[i-2] + (l-1) * (l**(i-3) - (l-1)**(i-3)))
x[i] = a[i] + (l-1) * x[i-1]
return x[4:]
print(combs(2, 10))
print(combs(3, 10))
print(combs(4, 10))
This can be described as a state machine. (For simplicity, x is any letter other than A.)
S0 := 'A' S1 | 'x' S0 // ""
S1 := 'A' S1 | 'x' S2 // A
S2 := 'A' S1 | 'x' S3 // Ax
S3 := 'A' S4 | 'x' S3 // Axx+
S4 := 'A' S4 | 'x' S4 | $ // AxxA
Counting the number of matching strings of length n
S0(n) = S1(n-1) + (L-1)*S0(n-1); S0(0) = 0
S1(n) = S1(n-1) + (L-1)*S2(n-1); S1(0) = 0
S2(n) = S1(n-1) + (L-1)*S3(n-1); S2(0) = 0
S3(n) = S4(n-1) + (L-1)*S3(n-1); S3(0) = 0
S4(n) = S4(n-1) + (L-1)*S4(n-1); S4(0) = 1
Trying to reduce S0(n) to just n and L gives a really long expression, so it would be easiest to calculate the recurrence functions as-is.
For really large n, this could be expressed as a matrix expression, and be efficiently calculated.
n
[L-1 1 0 0 0 ]
[ 0 1 L-1 0 0 ] T
[0 0 0 0 1] × [ 0 1 0 L-1 0 ] × [1 0 0 0 0]
[ 0 0 0 L-1 1 ]
[ 0 0 0 0 L ]
In JavaScript:
function f(n, L) {
var S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 1;
var S1_tmp;
while (n-- > 0) {
S0 = S1 + (L - 1) * S0;
S1_tmp = S1 + (L - 1) * S2;
S2 = S1 + (L - 1) * S3;
S3 = S4 + (L - 1) * S3;
S4 = S4 + (L - 1) * S4;
S1 = S1_tmp;
}
return S0;
}
var $tbody = $('#resulttable > tbody');
for (var L = 2; L <= 4; L++) {
for (var n = 4; n <= 10; n++) {
$('<tr>').append([
$('<td>').text(n),
$('<td>').text(L),
$('<td>').text(f(n,L))
]).appendTo($tbody);
}
}
#resulttable td {
text-align: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="resulttable">
<thead>
<tr>
<th>N</th>
<th>L</th>
<th>matches</th>
</tr>
</thead>
<tbody>
</tbody>
</table>

Finding denominators of Farey tree fractions in constant time

Hello r masters.
I need to calculate Denominators of Farey tree fractions up to 2**30.
I came up with this C++ solution using this approach:
struct FareySB {
int num, den;
FareySB() : den(0) {}
int sum() {
return num + den;
}
};
const int LGMAX = 30;
const int MAX = 1 << LGMAX;
FareySB FTF[MAX];
void get_FTF() {
FTF[0].num = 0; FTF[0].den = 1;
FTF[1].num = 1; FTF[1].den = 1;
FTF[2].num = 1; FTF[2].den = 2;
int k = 3;
for (int i = 1; i < LGMAX; i++) {
int len = 1 << i;
int hlen = len >> 1;
for (int j=0; j<hlen; j++) {
FTF[k].num = FTF[k-hlen].num;
FTF[k].den = FTF[k-hlen].sum();
k++;
}
for (int j=0; j<hlen; j++) {
FTF[k].num = FTF[k-len].den;
FTF[k].den = FTF[k-1-(j<<1)].den;
k++;
}
}
}
To know the n-th term I need to know all [0..n-1] terms. Ok so far.
This has a problem: memory just explodes after about 2**27.
The denominators of Farey Tree Fractions are the OEIS-A007306:
1, 1, 2, 3, 3, 4, 5, 5, 4, 5, 7, 8, 7, 7, 8, 7, ...
In that OEIS page I found a code which seems to return the n-th term of the sequence in constant time. If thats true it would solve my Memory Limit Exceeded issue.
But the code is in R language:
(R)
# Given n, compute directly a(n)
# by taking into account the binary representation of n-1
aa <- function(n){
b <- as.numeric(intToBits(n))
l <- sum(b)
m <- which(b == 1)-1
d <- 1
if(l > 1) for(j in 1:(l-1)) d[j] <- m[j+1]-m[j]+1
f <- c(1, m[1]+2) # In A002487: f <- c(0, 1)
if(l > 1) for(j in 3:(l+1)) f[j] <- d[j-2]*f[j-1]-f[j-2]
return(f[l+1])
}
# a(0) = 1, a(1) = 1, a(n) = aa(n-1) n > 1
It may be really simple to you, but I don't know R language, and can't understand the above code.
Is it really a constant function? How does that function works?
If you could show me for a given n whats happening inside this function, then I could be able to code it in C++ myself.
Thanks in advance.
I'm not sure quite how it works, but here is what the R code is doing. Assume n=100.
b <- as.numeric(intToBits(n)) this produces a 32-element vector of a (reversed) binary representation of n. For n=100, b is 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
l <- sum(b) is the sum of the elements of b (i.e. the number of 1s). In this case l=3
m <- which(b == 1)-1 is a vector of the indices of the elements of b that are equal to 1, each reduced by 1. So for n=100, m= 2 5 6
d <- 1 just setting d equal to 1
if(l > 1) for(j in 1:(l-1)) d[j] <- m[j+1]-m[j]+1. If l is bigger than one, then d becomes a vector of length l-1, where each d is the differences between successive values of m, plus one. So for n=100, d= 4 2
f <- c(1, m[1]+2) sets f as a vector with the first value 1, second value the first element of m, plus 2. Here f is 1 4
if(l > 1) for(j in 3:(l+1)) f[j] <- d[j-2]*f[j-1]-f[j-2]. If l is bigger than one, this adds elements onto the end of f, according to that formula - e.g. f[3] is d[1]*f[2]-f[1] or 4*4-1=15. For n=100, f is 1 4 15 26.
return(f[l+1]) This returns the last element of f as the result.
I'm not sure whether it is constant, but it looks pretty quick as n increases. Good luck!

how to compute the original vector from a distance matrix?

I have a small question about vector and matrix.
Suppose a vector V = {v1, v2, ..., vn}. I generate a n-by-n distance matrix M defined as:
M_ij = | v_i - v_j | such that i,j belong to [1, n].
That is, each element M_ij in the square matrix is the absolute distance of two elements in V.
For example, I have a vector V = {1, 3, 3, 5}, the distance matrix will be
M=[
0 2 2 4;
2 0 0 2;
2 0 0 2;
4 2 2 0; ]
It seems pretty simple. Now comes to the question. Given such a matrix M, how to obtain the initial V?
Thank you.
Based on some answer for this question, it seems that the answer is not unique. So, now suppose that all the initial vector has been normalized to 0 mean and 1 variance. The question is: Given such a symmetric distance matrix M, how to decide the initial normalized vector?
You can't. To give you an idea of why, consider these two cases:
V1 = {1,2,3}
M1 = [ 0 1 2 ; 1 0 1 ; 2 1 0 ]
V2 = {3,4,5}
M2 = [ 0 1 2 ; 1 0 1 ; 2 1 0 ]
As you can see, a single M could be the result of more than one V. Therefore, you can't map backwards.
There is no way to determine the answer uniquely, since the distance matrix is invariant to adding a constant to all elements and to multiplying all the values by -1. Assuming that element 1 is equal to 0, and that the first nonzero element is positive, however, you can find an answer. Here is the pseudocode:
# Assume v[1] is 0
v[1] = 0
# e is value of first non-zero vector element
e = 0
# ei is index of first non-zero vector element
ei = 0
for i = 2...n:
# if all vector elements have been 0 so far
if e == 0:
# get the current distance from element 1 and its index
# this new element may still be 0
e = d[1,i]
ei = i
v[i] = e
elseif d[1,i] == d[ei,i] + v[ei]: # v[i] <= v[1]
# v[i] is to the left of v[1] (assuming v[ei] > v[1])
v[i] = -d[1,i]
else:
# some other case; v[i] is to the right of v[1]
v[i] = d[1,i]
I don't think it is possible to find the original vector, but you can find a translation of the vector by taking the first row of the matrix.
If you let M_ij = | v_i - v_j | and you translate all v_k for k\in [1,n] you will get
M_ij = | v-i + 1 - v_j + 1 |
= | v_i - v_j |
Hence, just take the first row as the vector and find one initial point to translate the vector to.
Correction:
Let v_1 = 0, and let l_k = | v_k | for k\in [2,n] and p_k the parity of v_k
Let p_1 = 1
for(int i = 2; i < n; i++)
if( | l_i - l_(i+1) | != M_i(i+1) )
p_(i+1) = - p_i
else
p_(i+1) = p_i
doing this for all v_k for k\in [2,n] in order will show the parity of each v_k in respect to the others
Then you can find a translation of the original vector with the same or opposite direction
Update (For Normalized vector):
Let d = Sqrt(v_1^2 + v_2^2 + ... + v_n^2)
Vector = {0, v_1 / d, v_2 / d, ... , v_n / d}
or
{0, -v_1 / d, -v_2 / d, ... , -v_n / d}

Resources