Using indicator constraints in Julia - julia

JuMP provides a special syntax for creating indicator constraints.So, Which one is better, linearizing the indicator constraints and then write a code or using this feature?
In order to constrain the constraint x + y <= 2 to hold when z binary variable a is one:
#variable(model, x)
#variable(model, y)
#variable(model, z, Bin)
#constraint(model, z => {x + y <= 2})
Actually my question is which one is faster and more efficient, To linearize ourselves or to use code?

The answer is problem- and solver-dependent. You should try both approaches and time them to find out which is more efficient for your problem.
Some solvers (e.g., Gurobi) have special support for indicators, in which case it's probably faster to use the indicators directly. If you're using a solver that doesn't have special support for indicators, we convert the indicator constraint to a SOS-I constraint (https://jump.dev/MathOptInterface.jl/stable/submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.IndicatorSOS1Bridge).
The quality of a big-M type linearization will depend on using domain knowledge to select a good big-M. JuMP doesn't do big-M reformulations automatically.

Related

Integral basis nf.zk versus nfbasis in Pari GP

I have been using the database of lmfdb.org to find the integral basis of a number field. Now, I want to utilize PARI/GP in multiplying algebraic integers. However, I have encountered a problem. PARI/GP uses the integral basis "nf.zk" in its computations, which apparently is not always the same as the "nfbasis(f)", which is the integral basis that lmfdb.org provides.
For example, we have the following code from PARI/GP:
? f = x^3 - x^2 + 2*x + 8
nf = nfinit(f)
nf.zk
%1 = [1, x, 1/2*x^2 - 1/2*x + 1]
? nfbasis(f)
%2 = [1, x, 1/2*x^2 - 1/2*x]
Now, my questions are:
Why are nf.zk and nfbasis(f) different?
Why does PARI/GP use nf.zk instead of nfbasis(f)?
Lastly, can I tell PARI/GP to use nfbasis(f) instead of nf.zk?
When we take the trouble to initialize an nf structure with nfinit, we perform precomputations to speed up later work. Here, nfinit first computes the integer basis by calling nfbasis, which returns the (canonical) HNF basis, then LLL-reduces it with respect to the T2 norm. The LLL-reduced basis is usually different from the HNF one, but it usually has smaller elements.
This LLL reduction can be expensive (in particular when the degree is large) but it ensures that time complexities are bounded in terms of the field discriminant instead of the size of the input polynomial.
I believe all polynomials defining number fields in the lmfdb were run through polredabs which ensures their coefficients are small (in terms of the field discriminant), but the HNF integer basis may still be much larger than the LLL one. Additionally, if an algebraic integer has small T2 norm, its expression in terms of the LLL-reduced basis is guaranteed to have small coefficients, whereas it can have much larger coefficients on the HNF basis.
In pari-2.14 (which is not released yet but available via git or through nightly snapshots on the PARI/GP website), you can use nfinit(, 4), which removes the LLL reduction step. This speeds up the initialization, but usually slows down every operation involving the resulting nf.
? f = x^3 - x^2 + 2*x + 8
? nfinit(f,4).zk
%2 = [1, x, 1/2*x^2 - 1/2*x]

JuMP - multiple solutions in Integer and 0-1 Programming

In JuMP, Julia v1.3.1,
using JuMP, GLPK
function example_basic(n = 4)
model = Model(GLPK.Optimizer)
#variable(model, x1, Bin)
#variable(model, x2, Bin)
#variable(model, C <= 1)
#objective(model, Max, C)
#constraint(model, x1 + x2 <= C)
# if verbose
# print(model)
# end
JuMP.optimize!(model)
obj_value = JuMP.objective_value(model)
# num_results = 1
num_results = result_count(model)
#show num_results
end
Returns 1. I just don't understand the programming behind this result. Because there are clearly 2 optimal solutions for this tiny linear problem:
(x1,x2)=(0,1)=(1,0)
How come JuMP returns 1?
My best guess is that GLPK doesn't support multiple solutions for Integer Programming because the documentation says:
Some solvers support returning multiple solutions. You can check how many solutions are available to query using result_count.
Then I tried another solver: Cbc, but the result was the same. If my issue is that both solvers don't support multiple solutions, how could I have the list of JuMP solvers that do?
Traditionally MIP solvers just return one solution. Most (or even all) free solvers follow this approach and just return one solution. Some commercial solvers have something called a solution pool to hold multiple solutions.
There is a way to enumerate optimal or second best MIP solutions by adding a cut to the problem and resolve. See How to ask for second best solution to a MIP using JuMP.

MIP/LP - Modelling "if b=1 then x=y" constraint

I have a Mixed Integer Programming (MIP) problem, currently modelled in Python's PuLP library. My issue is however very generic, syntax doesn't play a role here.
I want to add a constraint to my model that works like this:
if b=1 then x=y
The variable b is a binary variable taking values 0 or 1. x and y are variables that represent the current stock level. x as a continuous variable, y as an integer variable.
I know constraints can only be modelled in the following format:
a*x+c <= y # a, c are constants, x, y variables
I hope there is some workaround how I can model the above described if b then x equals y constraint.
Here are my approaches so far:
b*y <= x
y >= x*b # works in theory, but multiplication of 2 variables is not allowed
For 2 binary variables x and y the following is true:
M*y > x # represents: if x then y (M is a sufficient large constant)
I guess the solution involves a large M constant, maybe even further helper variables.
A little background: I want to model an inventory problem, with continuous stock levels. However, order decisions should only be possible in integer numbers. I therefore need the stock level to be modelled with float numbers. At the point of order (b==1) however in integer.
I hope someone can help here, even if this is rather theoretic than directly coding related. Hints to further resources that might help are also highly appreciated.
b=1 => x=y
can be modeled as:
y-M(1-b) <= x <= y+M(1-b)

Get branch points of equation

If I have a general function,f(z,a), z and a are both real, and the function f takes on real values for all z except in some interval (z1,z2), where it becomes complex. How do I determine z1 and z2 (which will be in terms of a) using Mathematica (or is this possible)? What are the limitations?
For a test example, consider the function f[z_,a_]=Sqrt[(z-a)(z-2a)]. For real z and a, this takes on real values except in the interval (a,2a), where it becomes imaginary. How do I find this interval in Mathematica?
In general, I'd like to know how one would go about finding it mathematically for a general case. For a function with just two variables like this, it'd probably be straightforward to do a contour plot of the Riemann surface and observe the branch cuts. But what if it is a multivariate function? Is there a general approach that one can take?
What you have appears to be a Riemann surface parametrized by 'a'. Consider the algebraic (or analytic) relation g(a,z)=0 that would be spawned from this branch of a parametrized Riemann surface. In this case it is simply g^2 - (z - a)*(z - 2*a) == 0. More generally it might be obtained using Groebnerbasis, as below (no guarantee this will always work without some amount of user intervention).
grelation = First[GroebnerBasis[g - Sqrt[(z - a)*(z - 2*a)], {x, a, g}]]
Out[472]= 2 a^2 - g^2 - 3 a z + z^2
A necessary condition for the branch points, as functions of the parameter 'a', is that the zero set for 'g' not give a (single valued) function in a neighborhood of such points. This in turn means that the partial derivative of this relation with respect to g vanishes (this is from the implicit function theorem of multivariable calculus). So we find where grelation and its derivative both vanish, and solve for 'z' as a function of 'a'.
Solve[Eliminate[{grelation == 0, D[grelation, g] == 0}, g], z]
Out[481]= {{z -> a}, {z -> 2 a}}
Daniel Lichtblau
Wolfram Research
For polynomial systems (and some class of others), Reduce can do the job.
E.g.
In[1]:= Reduce[Element[{a, z}, Reals]
&& !Element[Sqrt[(z - a) (z - 2 a)], Reals], z]
Out[1]= (a < 0 && 2a < z < a) || (a > 0 && a < z < 2a)
This type of approach also works (often giving very complicated solutions for functions with many branch cuts) for other combinations of elementary functions I checked.
To find the branch cuts (as opposed to the simple class of branch points you're interested in) in general, I don't know of a good approach. The best place to find the detailed conventions that Mathematica uses is at the functions.wolfram site.
I do remember reading a good paper on this a while back... I'll try to find it....
That's right! The easiest approach I've seen for branch cut analysis uses the unwinding number. There's a paper "Reasoning about the elementary functions of complex analysis" about this the the journal "Artificial Intelligence and Symbolic Computation". It and similar papers can be found at one of the authors homepage: http://www.apmaths.uwo.ca/~djeffrey/offprints.html.
For general functions you cannot make Mathematica calculate it.
Even for polynomials, finding an exact answer takes time.
I believe Mathematica uses some sort of quantifier elimination when it uses Reduce,
which takes time.
Without any restrictions on your functions (are they polynomials, continuous, smooth?)
one can easily construct functions which Mathematica cannot simplify further:
f[x_,y_] := Abs[Zeta[y+0.5+x*I]]*I
If this function is real for arbitrary x and any -0.5 < y < 0 or 0<y<0.5,
then you will have found a counterexample to the Riemann zeta conjecture,
and I'm sure Mathematica cannot give a correct answer.

How to find which subset of bitfields xor to another bitfield?

I have a somewhat math-oriented problem. I have a bunch of bitfields and would like to calculate what subset of them to xor together to achieve a certain other bitfield, or if there isn't a way to do it discover that no such subset exists.
I'd like to do this using a free library, rather than original code, and I'd strongly prefer something with Python bindings (using Python's built-in math libraries would be acceptable as well, but I want to port this to multiple languages eventually). Also it would be good to not take the memory hit of having to expand each bit to its own byte.
Some further clarification: I only need a single solution. My matrices are the opposite of sparse. I'm very interested in keeping the runtime to an absolute minimum, so using algorithmically fancy methods for inverting matrices is strongly preferred. Also, it's very important that the specific given bitfield be the one outputted, so a technique which just finds a subset which xor to 0 doesn't quite cut it.
And I'm generally aware of gaussian elimination. I'm trying to avoid doing this from scratch!
cross-posted to mathoverflow, because it isn't clear what the right place for this question is - https://mathoverflow.net/questions/41036/how-to-find-which-subset-of-bitfields-xor-to-another-bitfield
Mathematically speaking, XOR of two bits can be treated as addition in F_2 field.
You want to solve a set of equations in a F_2 field. For four bitfiels with bits (a_0, a_1, ... a_n), (b_0, b_1, ..., b_n), (c_0, c_1, ..., c_n), (r_0, r_1, ..., r_n), you get equations:
x * a_0 + y * b_0 + z * c_0 = r_0
x * a_1 + y * b_1 + z * c_1 = r_1
...
x * a_n + y * b_n + z * c_n = r_n
(where you look for x, y, z).
You could program this as a simple integer linear problem with glpk, probably lp_solve (but I don't remember if it will fit). These might work very slowly though, as they are trying to solve much more general problem.
After googling for a while, it seems that this page might be a good start looking for code. From descriptions it seems that Dixon and LinBox could be a good fit.
Anyway, I think asking at mathoverflow might give you more precise answers. If you do, please link your question here.
Update: Sagemath uses M4RI for solving this problem. This makes it (for me) a very good recommendation.
For small instances that easily fit in memory, this is just solving a linear system over F_2, so try mod-2 Gaussian elimination. For very large sparse instances, like those that occur in factoring (sieve) algorithms, look up the Wiedemann algorithm.
It's possible to have multiple subsets xor to the same value; do you care about finding all subsets?
A perhaps heavy-handed approach would be to filter the powerset of bitfields. In Haskell:
import Data.Bits
xorsTo :: Int -> [Int] -> [[Int]]
xorsTo target fields = filter xorsToTarget (powerset fields)
where xorsToTarget f = (foldl xor 0 f) == target
powerset [] = [[]]
powerset (x:xs) = powerset xs ++ map (x:) (powerset xs)
Not sure if there is a way to do this without generating the powerset. (In the worst case, it is possible for the solution to actually be the entire powerset).
expanding on liori's answer above we have a linear system of equations (in modulo 2):
a0, b0, c0 ...| r0
a1, b1, c1 ...| r1
... |
an, bn, cn ...| rn
Gaussian elimination can be used to solve the system. In modulo 2, the add row operation becomes an XOR operation. It is much simpler computationally to do this than to use a generic linear systems solver.
So, if a0 is zero we swap up a row that has a 1 in the a position. Then perform an XOR (using row 0) on any other row whos "a" bit is a 1. Then repeat using row 1 and column b, then row 2 col c, etc.
If you get a row of zeroes with a non-zero in the r column then the subset DNE.

Resources