Formulating a binary sequence with shift in MILP - constraint-programming

I would like to know if it's actually possible to encode a (binary) sequence with rotations in MILP/MIP.
Given a binary sequence (0,1,1,0,0,0,0,1) and variables x0,x1,x2,x3,x4,x5,x6,x7,
I want to restrict my MILP program such that it takes up one of the following:
(x0,x1,x2,x3,x4,x5,x6,x7) = (0,1,1,0,0,0,0,1) or
(x7,x0,x1,x2,x3,x4,x5,x6) = (0,1,1,0,0,0,0,1) or
...
(x1,x2,x3,x4,x5,x6,x7,x0) = (0,1,1,0,0,0,0,1)
I understand that the rotation can be easily solved by just extending the sequence. But I find myself creating multiple MILP instances, each instance corresponding to exactly one of the cases. If this is infeasible, why?

There are many approaches one could design and it's not really clear in what context you will use it.
Here is a relatively simple one:
A: Introduce n new binary variables: These describe the "root / first zero" decision
s_x0, s_x1, s_x2, s_x3, s_x4, s_x5, s_x6, s_x7
B: Add a simplex-constraint / make those add up to 1: We do want a unique root!
s_x0 + s_x1 + s_x2 + s_x3 + s_x4 + s_x5 + s_x6 + s_x7 = 1
C: Encode all implications for all possible roots which can be chosen
for: s_x0
logic-form | milp-form
s_x0 -> x0 (1-s_x0) + x0 >= 1
s_x0 -> x1 (1-s_x0) + x1 >= 1
s_x0 -> !x2 (1-s_x0) + (1-x2) >= 1
s_x0 -> !x3 (1-s_x0) + (1-x3) >= 1
s_x0 -> !x4 (1-s_x0) + (1-x4) >= 1
s_x0 -> !x5 (1-s_x0) + (1-x5) >= 1
s_x0 -> x6 (1-s_x0) + x6 >= 1
s_x0 -> !x7 (1-s_x0) + (1-x7) >= 1
for: s_x1
s_x1 -> !x0 (1-s_x1) + (1-x0) >= 1
s_x1 -> x1 (1-s_x1) + x1 >= 1
s_x1 -> x2 (1-s_x1) + x2 >= 1
s_x1 -> !x3 (1-s_x1) + (1-x3) >= 1
s_x1 -> !x4 (1-s_x1) + (1-x4) >= 1
s_x1 -> !x5 (1-s_x1) + (1-x5) >= 1
s_x1 -> !x6 (1-s_x1) + (1-x6) >= 1
s_x1 -> x7 (1-s_x1) + x7 >= 1
for ......
This:
Basically exploits the core structure behind the problem:
We need to chose between n different patterns and must enforce the effects
Will get big (at least for human-consumption)
Is rather simple / easy to understand and implement
But also should provide a nice LP-relaxation
This (non-compact) formulation also exploits some strengths of MILP-solvers (e.g. clique-tables)

Related

Get If (condition), then (assign value), else (assign other value) statement in Linear Programming

I'm looking for a linear programming equation that satisfied the conditions;
Given that all variables here are binary variables
if A+B = 2; then C = 1; else C = 0
Also,
if A+B+D = 3; then E = 1; else E = 0
How would one phrase this and satisfy these conditions as well as linearity conditions?
I've tried
A + B - 2 <= M(1-y) and 1 - C <= My
for the first constraint but it doesn't seem to work
For the first equation, you can use:
C + 1 >= A + B
2C <= A + B
If there is a natural sense (max/min) for C in the problem, one of those is sufficient.
Similarly for the second:
E + 2 >= A + B + D
3E <= A + B + D

Mathematics - Distribute a list of numbers over an interval

My problem is simple.
I am searching a mathematical function to distribute number over an interval.
For example I have this list :
[2; 4; 9; 14]
And in my case I wish
2 -> 1 = f(2)
14 -> 20 = f(14)
4 -> f(4) = ?
9 -> f(9) = ?
This is just an example I am searching for f(x).
Someone would have any idea ?
Thanks for advance ! :)
If you want a linear function, then:
f(x) = lowerFunc + (x - lowerX) * (upperFunc - lowerFunc) / (upperX - lowerX),
where:
lowerFunc: function value at the lower end
upperFunc: function value at the upper end
lowerX: x parameter at the lower end
upperX: x parameter at the upper end.
For your example:
f(x) = 1 + (x - 2) * (20 - 1) / (14 - 2)
= 1 + (x - 2) * 19/12
f(2) = 1
f(4) = 4.1666
f(9) = 12.08333
f(14) = 20

Python Bit Summation Algorithm

I am trying to implement a function that will be used to judge whether a generator's output is continuous. The method I am gravitating towards is to iterate through the generator. For each value, I right justify the bits of the value (disregarding the 0b), count the number of ones, and shift the number of ones.
#!/usr/bin/python3
from typing import Tuple
def find_bit_sum(top: int, pad_length: int) -> int :
"""."""
return pad_length * (top + 1)
def find_pad_length(top: int) -> int :
"""."""
return len(bin(top)) - 2 # -"0b"
def guess_certain(top: int, pad_length: int) -> Tuple[int, int, int] :
"""."""
_both: int = find_bit_sum(top, pad_length)
_ones: int = sum(sum(int(_i_in) for _i_in in bin(_i_out)[2 :]) for _i_out in range(1, top + 1))
return _both - _ones, _ones, _both # zeros, ones, sum
def guess(top: int, pad_length: int) -> Tuple[int, int, int] : # zeros then ones then sum
"""."""
_bit_sum: int = find_bit_sum(top, pad_length) # number of bits in total
_zeros: int = _bit_sum # ones are deducted
_ones: int = 0 # _bit_sum - _zeros
# detect ones
for _indexed in range(pad_length) :
_ones_found: int = int(top // (2 ** (_indexed + 1))) # HELP!!!
_zeros -= _ones_found
_ones += _ones_found
#
return _zeros, _ones, _bit_sum
def test_the_guess(max_value: int) -> bool : # the range is int [0, max_value + 1)
pad: int = find_pad_length(max_value)
_zeros0, _ones0, _total0 = guess_certain(max_value, pad)
_zeros1, _ones1, _total1 = guess(max_value, pad)
return all((
_zeros0 == _zeros1,
_ones0 == _ones1,
_total0 == _total1
))
if __name__ == '__main__' : # should produce a lot of True
for x in range(3000) :
print(test_the_guess(x))
For the life of me, I cannot make guess() agree with guess_certain(). The time complexity of guess_certain() is my problem: it works for small ranges [0, top], but one can forget 256-bit numbers (tops). The find_bit_sum() function works perfectly. The find_pad_length() function also works.
top // (2 ** (_indexed + 1))
I've tried 40 or 50 variations of the guess() function. It has thoroughly frustrated me. The guess() function is probabilistic. In its finished state: if it returns False, then the Generator definitely isn't producing every value in range(top + 1); however, if it returns True, then the Generator could be. We already know that the generator range(top + 1) is continuous because it does produce each number between 0 and top inclusively; so, test_the_guess() should be returning True.
I sincerely do apologise for the chaotic explanation. If you have anny questions, please don't hesitate to ask.
I adjusted your ones_found assignment statement to account for the number of powers of two per int(top // (2 ** (_indexed + 1))), as well as a additional "rollover" ones that occur before the next power of two. Here is the resulting statement:
_ones_found: int = int(top // (2 ** (_indexed + 1))) * (2 ** (_indexed)) + max(0, (top % (2 ** (_indexed + 1))) - (2 ** _indexed) + 1)
I also took the liberty of converting the statement to bitwise operators for both clarity and speed, as shown below:
_ones_found: int = ((top >> _indexed + 1) << _indexed) + max(0, (top & (1 << _indexed + 1) - 1) - (1 << _indexed) + 1)

How to Find a Point Where a Circle and Line with 1/0 Slope Intersect

I'm writing a simple 2D top-down game in Python 3 using tkinter. All the collidable objects are either circles/arcs or lines. I wrote the following method to detect when a circle hits a line:
I am using the formulas y = mx + b and r^2 = (x-h)^2 + (y-k)^2
def CheckHitCToL(self, LX0, LY0, LX1, LY1, CX0, CX1, Tab):
try:
H = self.Creatures[Tab].X
K = self.Creatures[Tab].Y
R = abs((CX0 - CX1) / 2)
M = (LY0 - LY1) / (LX0 - LX1)
B = M * (-LX1) + LY1
QA = (M * M) + 1
QB = (-H - H) + (((B - K) * M) * 2)
QC = (H * H) + ((B - K) * (B - K)) - (R * R)
X = (- QB + sqrt((QB * QB) - (4 * QA * QC))) / (2 * QA)
Y = (M * X) + B
if ((X <= LX0 and X >= LX1) or (X >= LX0 and X <= LX1)) and ((Y <= LY0 and Y >= LY1) or (Y >= LY0 and Y <= LY1)):
return True
else:
return False
except:
return False
My problem is when you have a vertical line, M (Or the slope) is (LY0 - LY1) / 0. (This is because the slope is equal to rise/run, and vertical lines don't have a run, just a rise) Which of course returns an error, caught by try except, which then informs my movement method that no collision has taken place. Of course I can simply move the "try:" down a few lines, but it's still going to throw an error. How can I adapt this program to not throw an error when working with a vertical line?
Well, the most obvious method would involve using if( (LX0 - LX1)==0 ) and doing this case separately. In such cases, you need to check whether distance between LX0 and CX0 is equal to the radius of circle.
You can use another forms of line equation -
implicit A*x + B*y + C = 0
or parametric x = LX0 + t * (LX1 - LX0), y = LY0 + t *(LY1 - LY0)
with appropriate modification of calculations

How can I find the general form equation of a line from two points?

Given the input:
double x1,y1,x2,y2;
How can I find the general form equation (double a,b,c where ax + by + c = 0) ?
Note: I want to be able to do this computationally. So the equivalent for slope-intercept form would be something like:
double dx, dy;
double m, b;
dx = x2 - x1;
dy = y2 - y1;
m = dy/dx;
b = y1;
Obviously, this is very simple, but I haven't been able to find the solution for the general equation form (which is more useful since it can do vertical lines). I already looked in my linear algebra book and two books on computational geometry (both too advanced to explain this).
If you start from the equation y-y1 = (y2-y1)/(x2-x1) * (x-x1) (which is the equation of the line defined by two points), through some manipulation you can get (y1-y2) * x + (x2-x1) * y + (x1-x2)*y1 + (y2-y1)*x1 = 0, and you can recognize that:
a = y1-y2,
b = x2-x1,
c = (x1-x2)*y1 + (y2-y1)*x1.
Get the tangent by subtracting the two points (x2-x1, y2-y1). Normalize it and rotate by 90 degrees to get the normal vector (a,b). Take the dot product with one of the points to get the constant, c.
If you start from the equation of defining line from 2 points
(x - x1)/(x2 - x1) = (y - y1)/(y2 - y1)
you can end up with the next equation
x(y2 - y1) - y(x2 - x1) - x1*y2 + y1*x2 = 0
so the coefficients will be:
a = y2 - y1
b = -(x2 - x1) = x1 - x2
c = y1*x2 - x1*y2
My implementation of the algorithm in C
inline v3 LineEquationFrom2Points(v2 P1, v2 P2) {
v3 Result;
Result.A = P2.y - P1.y;
Result.B = -(P2.x - P1.x);
Result.C = P1.y * P2.x - P1.x * P2.y;
return(Result);
}
Shortcut steps:
"Problem : (4,5) (3,-7)"
Solve:
m=-12/1 then
12x-y= 48
"NOTE:m is a slope"
COPY THE NUMERATOR, AFFIX "X"
Positive fraction Negative sign on between.
(tip: simmilar sign = add + copy the sign)
1.Change the second set into opposite signs,
2.ADD y1 to y2 (means add or subtract them depending of the sign),
3.ADD x1 to x2 (also means add or subtract them depending of the sign),
4.Then Multiply 12 and 1 to any of the problem set.
After that "BOOM" Tada!, you have your answer
#include <stdio.h>
main()
{
int a,b,c;
char x,y;
a=5;
b=10;
c=15;
x=2;
y=3;
printf("the equation of line is %dx+%dy=%d" ,a,b,c);
}

Resources