# How can lazy constraints be written in a \*.lp file?

**URL:** <https://discourse.julialang.org/t/how-can-lazy-constraints-be-written-in-a-lp-file/85324>\
**Category:** Optimization (Mathematical)\
**Tags:** question\
**Created:** [August 5, 2022, 5:14am UTC](https://discourse.julialang.org/t/how-can-lazy-constraints-be-written-in-a-lp-file/85324 "2022-08-05T05:14:29Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Somayeh\_Esmaeili](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/somayeh_esmaeili/32/10955_2.png) [@Somayeh\_Esmaeili](https://discourse.julialang.org/u/Somayeh_Esmaeili)\
**Post date:** [August 5, 2022, 5:14am UTC](https://discourse.julialang.org/t/how-can-lazy-constraints-be-written-in-a-lp-file/85324/1 "2022-08-05T05:14:30Z")

</div>

I need to convert the codes in \*.lp file. But the lazy constraints can not be converted. Would you please help me? Thanks very much

```julia
using JuMP,CPLEX
T=Model(solver=CplexSolver());
#Sets-------------------------------------------------------------------------
totalu=4;
U=1:4;
totalV=5;
V=1:totalV;
#Parameters-------------------------------------------------------------------
d=[100	10	8	9	7;10	100	10	5	6;8	10	100	8	9;9	5	8	100	6;7	6	9	6	100];
#variables---------------------------------------------------------------------
@variable(T,x[V,V],Bin);
@variable(T,u[V]>=0);
#constrains---------------------------------------------------------------------
@constraint(T,c1[i in V], sum(x[i,j] for j in V )==1);
@constraint(T,c2[j in V], sum(x[i,j] for i in V )==1);
#lazyconstraint----------------------------------------------------------------
function sbt(cb)
	v=zeros(Int64,N)
	n=zeros(Int64,N)
	for i=1:totalV
		v[i]=0
		n[i]=round(sum(j*getvalue(x[i,j]) for j in 1:totalV))
	end
	sd=0
	for i=1:totalV
		if v[i]==0
			t=[]
			ff=i
			global t
			condition=false
			while condition==false
				push!(t,ff)
				v[ff]=1
				ff=n[ff]
				if ff==i
					condition=true
				end
			end
			sze=length(t)
			if sze<totalV
				@lazyconstraint(cb, sum(x[j,k] for j in t, k in t)<=sze-1)
				sd=sd+1
			end
		end
	end
end
addlazycallback(T, sbt)
# objective function------------------------------------------------------------
ff=sum(d[i,j]*x[i,j] for i in V,j in V);
@objective(T, Min, ff);
solve(T)

```

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [August 5, 2022, 9:55pm UTC](https://discourse.julialang.org/t/how-can-lazy-constraints-be-written-in-a-lp-file/85324/2 "2022-08-05T21:55:46Z")

</div>

JuMP does not support writing lazy constraints to a LP file, and there are no work-arounds. Why do you need this?

---

<div class="post-metadata">

**Author:** ![Somayeh\_Esmaeili](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/somayeh_esmaeili/32/10955_2.png) [@Somayeh\_Esmaeili](https://discourse.julialang.org/u/Somayeh_Esmaeili)\
**Post date:** [August 6, 2022, 4:25am UTC](https://discourse.julialang.org/t/how-can-lazy-constraints-be-written-in-a-lp-file/85324/3 "2022-08-06T04:25:49Z")

</div>

Thanks very much,  
I have to compare my model which is solved with an exact bi objective method with a valuable branch and bound method that its codes is available in github .But the model codes should be in \*.lp files that it be possible to use those codes. 🥲

---

<div class="post-metadata">

**Author:** ![mike\_k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike_k/32/211864_2.png) [@mike\_k](https://discourse.julialang.org/u/mike_k)\
**Post date:** [August 7, 2022, 2:21pm UTC](https://discourse.julialang.org/t/how-can-lazy-constraints-be-written-in-a-lp-file/85324/4 "2022-08-07T14:21:07Z")

</div>

You could try to write an \*.lp file of the model before solving it. In the callback in this if statement:

```julia
if sze<totalV
   @lazyconstraint(cb, sum(x[j,k] for j in t, k in t)<=sze-1)
   sd=sd+1
end

```

open the \*.lp file, and append the cut to the file using the `print()` function; then close the file. This is probably not very efficient but it should work.

Note: I think in older JuMP versions there was no guarantee that the cuts you try to add are really accepted by CPLEX. If this is also the current case it means that your \*.lp file may contain cuts which you tried to add but which have not been accepted by CPLEX.

---

<div class="post-metadata">

**Author:** ![mtanneau](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mtanneau/32/17787_2.png) [@mtanneau](https://discourse.julialang.org/u/mtanneau)\
**Post date:** [August 7, 2022, 3:03pm UTC](https://discourse.julialang.org/t/how-can-lazy-constraints-be-written-in-a-lp-file/85324/5 "2022-08-07T15:03:52Z")

</div>

Another possibility is to keep a copy of the original model, and to modify your callback so that, every time you submit a lazy constraint to the original model (which is being solved), you add it as a “regular” constraint to the copy.

Once the optimization is done, the copied model contains all the constraints that were added within a callback, and you can write it to an `.lp` file. This might be more efficient and less error-prone than dynamically modifying the `.lp` file within the callback.

As pointed out above: CPLEX may or may not accept your lazy constraints. The only guarantee is that, if a solution is rejected, it will not be visited again. In particular, there is no guarantee that CPLEX will keep the lazy constraints in the linear relaxation.

---

<div class="post-metadata">

**Author:** ![Somayeh\_Esmaeili](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/somayeh_esmaeili/32/10955_2.png) [@Somayeh\_Esmaeili](https://discourse.julialang.org/u/Somayeh_Esmaeili)\
**Post date:** [August 10, 2022, 3:53am UTC](https://discourse.julialang.org/t/how-can-lazy-constraints-be-written-in-a-lp-file/85324/6 "2022-08-10T03:53:10Z")

</div>

Thanks very much for your kindly help.  
If the version of JuMP is changed, this problem will be solved?

---

<div class="post-metadata">

**Author:** ![Somayeh\_Esmaeili](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/somayeh_esmaeili/32/10955_2.png) [@Somayeh\_Esmaeili](https://discourse.julialang.org/u/Somayeh_Esmaeili)\
**Post date:** [August 10, 2022, 4:03am UTC](https://discourse.julialang.org/t/how-can-lazy-constraints-be-written-in-a-lp-file/85324/7 "2022-08-10T04:03:40Z")

</div>

I’m really grateful.  
As you mentioned, It is not possible use the lazy constraint for elimination subtours? I used this for an inventory routing problem to solve the model with more nodes as well as faster, the model worked, but it has many instances with different nodes, vehicles and periods. then, is it possible that the constraints not added completely when the instances are solving? and gives wrong solutions?

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [August 10, 2022, 12:11pm UTC](https://discourse.julialang.org/t/how-can-lazy-constraints-be-written-in-a-lp-file/85324/8 "2022-08-10T12:11:19Z")

</div>

The only guarantee is that the final solution returned by the solver will respect all lazy constraints that have been added.

This is the case in all versions of JuMP.

---

<div class="post-metadata">

**Author:** ![Somayeh\_Esmaeili](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/somayeh_esmaeili/32/10955_2.png) [@Somayeh\_Esmaeili](https://discourse.julialang.org/u/Somayeh_Esmaeili)\
**Post date:** [August 10, 2022, 12:35pm UTC](https://discourse.julialang.org/t/how-can-lazy-constraints-be-written-in-a-lp-file/85324/9 "2022-08-10T12:35:59Z")

</div>

I’m very thankful,  
How is t possible? is the following sentence correct?  
the model with lazy constraints works in small scale consequently it works in large scales too.

---

<div class="post-metadata">

**Author:** ![mtanneau](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mtanneau/32/17787_2.png) [@mtanneau](https://discourse.julialang.org/u/mtanneau)\
**Post date:** [August 10, 2022, 2:21pm UTC](https://discourse.julialang.org/t/how-can-lazy-constraints-be-written-in-a-lp-file/85324/10 "2022-08-10T14:21:17Z")

</div>

> How is t possible?

This is how most MIP solvers deal with lazy constraints.

> The only guarantee is that the final solution returned by the solver will respect all lazy constraints that have been added.

The small print is even more specific: the [Gurobi docs](https://www.gurobi.com/documentation/9.5/refman/c_cblazy.html) state that

> Your callback should be prepared to cut off solutions that violate any of your lazy constraints, including those that have already been added. Node solutions will usually respect previously added lazy constraints, **but not always.**

(I added the emphasis on the “not always”). In fact, the only thing that Gurobi really guarantees is that it will give you the opportunity to reject a solution before it is accepted as incumbent, by providing Gurobi with a violated constraint. As far as I know, CPLEX works in a similar way.

In other words, if you submit a violated constraint, Gurobi guarantees that it will not accept the solution. However, Gurobi gives you no guarantee that the next incumbent candidate will satisfy that constraint. This is why the docs state that _your callback should […] cut off solutions that violate any of your lazy constraints, including those that have already been added_.

How does all this impact you? Say you record all the lazy constraints added by your callback, and save `.lp` file that contains the original model + all the lazy constraints. Then,

- If you load that `.lp` file afterwards and solve it (without any callback), the resulting solution may violate _other_ constraints that were not seen in the initial run.  
For instance, if you’re solving TSP with adding sub-tour elimination constraints in a callback, you have no guarantee that the solution from solving the `.lp` file (and just the `.lp` file) will statisfy _all_ sub-tour elimination constraints: only the ones that were seen in the initial solve and showed up in the `.lp` file.
- Loading the `.lp` file and solving it directly may be much slower than the initial solve (because of all the additional constraints that stay in the formulation), or it may be much faster (because those constraints take you straight to the optimum). There’s no telling until you’ve run it.
- Intermediate results like the LP relaxation may be drastically different. In general, adding more constraints to the problem will strengthen the LP relaxation, but it will also affect presolve, cut-generation, heuristics, etc… with unclear effects in terms of performance.
