1% BEGIN LICENSE BLOCK
2% Version: CMPL 1.1
3%
4% The contents of this file are subject to the Cisco-style Mozilla Public
5% License Version 1.1 (the "License"); you may not use this file except
6% in compliance with the License.  You may obtain a copy of the License
7% at www.eclipse-clp.org/license.
8% 
9% Software distributed under the License is distributed on an "AS IS"
10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11% the License for the specific language governing rights and limitations
12% under the License. 
13% 
14% The Original Code is  The ECLiPSe Constraint Logic Programming System. 
15% The Initial Developer of the Original Code is  Cisco Systems, Inc. 
16% Portions created by the Initial Developer are
17% Copyright (C) 2006 Cisco Systems, Inc.  All Rights Reserved.
18% 
19% Contributor(s): 
20% 
21% END LICENSE BLOCK
22
23\chapter{The Eplex Library}
24\label{chapeplex}
25%HEVEA\cutdef[1]{section}
26
27\section{Introduction}
28
29The eplex library allows an external Mathematical Programming solver to be
30used by {\eclipse}. It is designed to allow the external solver to be seen
31as another solver for {\eclipse}, possibly in co-operation with
32the existing `native' solvers of {\eclipse} such as the {\it ic\/} solver. It is
33not specific to a given external solver, with the differences between
34different solvers (largely) hidden from the user, so that the user can
35write the same code and it will run on the different solvers.
36
37The exact types of problems that can be solved (and methods to solve them)
38are solver dependent, but currently linear programming, mixed integer
39programming and quadratic programming problems can be solved.
40
41The rest of this chapter is organised as follows: the remainder of this
42introduction gives a very brief description of Mathematical Programming, which
43can be skipped if the reader is familiar with the concepts. 
44Section~\ref{mpmodelling} demonstrates the modelling of an MP problem, and the
45following section discusses some of the more advanced features of the library
46that are useful for hybrid techniques.
47
48\subsection{What is Mathematical Programming?}
49\label{whatmp}
50
51\index{Mathematical Programming (MP)}
52\index{Linear Programming (LP)}
53\index{Mixed Integer Programming (MIP)}
54\index{optimisation (numerical)}
55\index{objective function}
56
57Mathematical Programming (MP) (also known as numerical optimisation) is the study of optimisation using
58mathematical/numerical techniques. A problem is modelled
59by a set of simultaneous equations: an
60objective function that is to be minimised or maximised, subject to a set of
61constraints on the problem variables, expressed as equalities and
62inequalities. 
63
64Many subclasses of MP problems have found important practical
65applications. In particular, Linear Programming (LP)
66problems and Mixed Integer Programming (MIP) problems are perhaps the most
67important. LP problems have both a linear objective function and linear
68constraints.  MIP problems are LP problems where some or all of the
69variables are constrained to take on only integer values. 
70
71It is beyond the scope of this chapter to cover MP in
72any more detail. However, for most usages of the eplex library, the user
73need not know the details of MP -- it can be treated as a black-box
74solver.
75
76\See{For more information on Mathematical Programming, you can read a
77textbook on the subject such as H.~P.~Williams'  {\it Model Building in
78Mathematical Programming} \cite{Williams99}.}
79
80\quickref{Classification of MP problems}{
81
82\begin{itemize}
83\item Linear Programming (LP) problems: linear constraints and objective
84function, continuous variables.
85\item Mixed Integer Programming (MIP) problems: LP problems with some or
86all variables restricted to taking integral values.
87\end{itemize}
88
89}
90
91\subsection{Why interface to Mathematical Programming solvers?}
92\label{whymp}
93
94Much research effort has been devoted to developing efficient ways of
95solving the various subclasses of MP problems for over 50 years. The
96external solvers are state-of-the-art implementations of some of these
97techniques. The eplex library allows the user to model an MP problem in
98ECLiPSe, and then solve the problem using the best available MP tools.
99
100In addition, the eplex library allows for the user to write programs that
101combines MP's global algorithmic solving techniques with the local
102propagation techniques of Constraint Logic
103Programming. 
104
105\subsection{Example formulation of an MP Problem} 
106\begin{figure}
107\begin{center}
108\resizebox{0.5\textwidth}{!}{\includegraphics{tpprob.ps}}
109\end{center}
110\caption{An Example MP Problem}
111\label{tpprob}
112\end{figure}
113
114Figure~\ref{tpprob} shows an example of an MP problem.
115It is a transportation problem where 
116several plants (1-3) have varying product producing capacities that must
117be transported to various clients (A-D), each requiring various amounts of
118the product. The per-unit cost of transporting the product to
119the clients also varies. The problem is to minimise the transportation
120cost whilst satisfying the demands of the clients. 
121
122To formulate the problem, we define the amount of product transported from
123a plant $N$ to a client $p$ as the variable $Np$, e.g.\ $A1$
124represents the cost of transporting to plant $A$ from client $1$. There are
125two kinds of constraints:
126
127\begin{itemize}
128\item The amount of product delivered from all the plants to a client must be equal to the
129client's demand, e.g.\ for client A, which can recieve products from plants
1301-3: \( A1 + A2 + A3 = 21 \)
131
132
133\item The amount of product sent by a plant must not be more than its
134capacity, e.g. for plant 1, which can send products to plants A-D:
135\(A1 + B1 + C1 + D1 \leq 50 \)
136
137\end{itemize}
138
139The objective is to minimise the transportation cost, thus the objective
140function is to minimise the combined costs of transporting the product to
141all 4 clients from the 3 plants.
142
143
144Putting everything
145together, we have the following formulation of the problem:
146
147Objective function:
148{\small
149\[
150\min (10A1 + 7A2 + 200A3 + 8B1 + 5B2 + 10B3 + 5C1 + 5C2 + 8C3 + 9D1 + 3D2 + 7D3) 
151\]
152}
153
154Constraints:
155
156\begin{eqnarray*}
157A1 + A2 + A3 & = & 21\\
158B1 + B2 + B3 & = & 40\\
159C1 + C2 + C3 & = & 34\\
160D1 + D2 + D3 & = & 10\\
161A1 + B1 + C1 + D1 & \leq & 50\\
162A2 + B2 + C2 + D2 & \leq & 30\\
163A3 + B3 + C3 + D3 & \leq & 40\\
164\end{eqnarray*}
165
166\section{How to load the library}
167
168To use the library, you must have an MP solver that eplex can use. This
169can be an open-source solver such as the COIN-OR project's CLP/CBC solvers,
170which is distributed with ECLiPSe, or a commercial solver such as 
171XPRESS-MP or CPLEX. Your {\eclipse} should be configured to load in a
172`default' solver if there is more than one available. 
173
174\See{See the library
175manual's Eplex chapter for details for how to install the solver.} 
176
177When configured properly, the library can be loaded with the directive:
178
179\begin{code}
180:- lib(eplex).
181\end{code}
182
183\noindent
184This will load the library with the default external MP solver.
185
186You probably need a valid license in order to use an external commercial solver.
187
188\section{Modelling MP problems in {\eclipse}}
189\label{mpmodelling}
190
191\subsection{Eplex instance}
192
193The simplest way to model an eplex problem is through an {\it eplex
194instance}. Abstractly, it can be viewed as a solver module that is
195dedicated to one MP problem. MP constraints can be posted to the instance 
196and the problem solved with respect to an objective function by the
197external solver.
198
199Declaratively, an eplex instance can be
200seen as a compound constraint consisting of all the variables and
201constraints of its eplex problem. Like normal constraints, different eplex
202instances can share variables, although the individual MP constraints in
203an eplex instance do not necessarily have to be consistent with those in
204another. 
205
206\quickref{Eplex Instance}{
207
208An {\bf eplex instance} represents a single MP problem in a
209module. Constraints for the problem are posted to the module. The
210problem is solved with respect to an objective function.
211}
212
213\subsection{Example modelling of an MP problem in {\eclipse}}
214
215\index{modelling, LP problem}
216The following code models (and solves) the transportation problem of
217Figure~\ref{tpprob}, using an eplex instance:
218
219{\small
220\begin{code}
221:- lib(eplex).
222
223:- eplex_instance(prob).  % a. declare an eplex instance
224
225main1(Cost, Vars) :-
226        % b. create the problem variables and set their range
227        Vars = [A1,A2,A3,B1,B2,B3,C1,C2,C3,D1,D2,D3], 
228        prob: (Vars \$:: 0.0..1.0Inf),
229
230        % c. post the constraints for the problem to the eplex instance
231        prob: (A1 + A2 + A3 \$= 21),
232        prob: (B1 + B2 + B3 \$= 40),
233        prob: (C1 + C2 + C3 \$= 34),
234        prob: (D1 + D2 + D3 \$= 10),
235
236        prob: (A1 + B1 + C1 + D1 \$=< 50),
237        prob: (A2 + B2 + C2 + D2 \$=< 30),
238        prob: (A3 + B3 + C3 + D3 \$=< 40),
239
240        % d. set up the external solver with the objective function
241        prob: eplex_solver_setup(min(
242                10*A1 + 7*A2 + 200*A3 + 
243                 8*B1 + 5*B2 + 10*B3 +
244                 5*C1 + 5*C2 +  8*C3 + 
245                 9*D1 + 3*D2 +  7*D3)),
246
247        %------------------------------- End of Modelling code
248
249        prob: eplex_solve(Cost).  % e. Solve problem using external solver
250
251\end{code}
252}
253
254To use an eplex instance, it must first be declared with \verb'eplex_instance/1'. 
255This is usually done with a directive, as in line \verb'a'.
256Once
257declared, an eplex instance can be referred to using its name like a module
258qualifier.
259
260We first create the problem
261variables and set their range to be non-negative, as is conventional in MP.
262Note that the bounds are posted to our eplex instance, using \verb'$::/2'.
263\Note{The default bounds for variables is -1.0Inf..1.0Inf. Bounds posted to
264  an eplex instance are specific to that eplex instance.}
265
266Next, we set up the MP constraints for the
267problem by posting them to the eplex instance. 
268The MP constraints accepted by eplex are the arithmetic equalities and 
269inequalities:
270\verb'$=/2', \verb'$=</2' and \verb'$>=/2'.
271\Note{The arithmetic constraints can be linear expressions on both
272sides. The restriction to linear
273expressions originates from the external solver.}
274\index{\$=/2!eplex}
275\index{\$>=/2!eplex}
276\index{\$=</2!eplex}
277\index{eplex\_solver\_setup/1}
278\index{eplex\_instance/1}
279\index{eplex\_solve/1}
280
281We need to setup the external solver with the eplex instance, so
282that the problem can be solved by the external solver. This is done by
283\verb'eplex_solver_setup/1', with the objective
284function given as the argument, enclosed by either \verb'min(...)' or \verb'max(...)'. In this case, we are minimising.
285Note that
286generally the setup of the solver and the posting of the MP constraints can be
287done in any order.
288
289Having set up the problem, we can solve it
290by calling \verb'eplex_solve/1' in line \verb'e'. 
291
292When an instance gets solved, the external solver takes into account all
293constraints posted to that instance, the current variable bounds for the
294problem variables, and the objective specified during setup.
295
296In this case, there is an optimal solution of 710.0:
297
298\begin{quote}\begin{verbatim}
299?-  main1(Cost, Vars).
300
301Cost = 710.0
302Vars = [A1{0.0 .. 1e+20 @ 0.0}, A2{0.0 .. 1e+20 @ 21.0}, ....]
303\end{verbatim}\end{quote}
304Note that the problem variables are not
305instantiated by the solver. However, the `solution' values, i.e.\ the
306values that the variable are given by the solver, are available in the
307eplex attribute. The eplex attribute is shown as \verb'Lo..Hi @ Sol' where
308\verb'Lo' is the lower bound, \verb'Hi' the upper bound, and \verb'Sol' the
309solution value for the variable (e.g., \verb'A2' has the solution value of
31021.0 in the example above). Note also that the external solver may not
311allow very large floats, hence \verb'1e+20', this external solver's
312representation of infinity, is the upper bound of the
313variables, even though we specified \verb'1.0Inf' in our code. 
314
315One reason the problem variables are not assigned their solution values is
316so that the eplex problem can be solved again, after it has been modified.
317A problem can be modified by the addition of more constraints, and/or
318changes in the bounds of the problem variables.
319
320\subsection{Getting more solution information from the solver}
321
322The solution values of the problem variables can be obtained by
323\verb'eplex_var_get/3'. The example program in the
324previous section can be modified to return the solution values:
325
326{\small
327\begin{code}
328main2(Cost, Vars) :-
329        ....  % same as previous example up to line e
330        prob: eplex_solve(Cost),  % e. Solve problem using external solver
331        (foreach(V, Vars) do
332            % f. set the problem variables to their solution values
333            prob: eplex_var_get(V, typed_solution, V) 
334        ).
335\end{code}}
336\index{eplex_var_get/3}
337
338In line \verb'f', \verb'eplex_var_get/3' is used to obtain the solution
339value for a problem variable. The second argument, set to \verb'typed_solution', 
340 specifies that we want the solution value for the variable to be returned.
341Here, we instantiate the problem variable itself to the solution value
342with the third argument:
343
344\begin{quote}\begin{verbatim}
345?- main2(Cost, Vars).
346
347
348Cost = 710.0
349Vars = [0.0, 21.0, 0.0, 16.0, 9.0, 15.0, 34.0, 0.0, 0.0, 0.0, 0.0, 10.0]
350\end{verbatim}\end{quote}
351
352Note that, in general, an MP problem can have many optimal solutions, i.e.\
353different solutions which give the optimal value for the objective function.
354As a result, the above
355instantiations for \verb'Vars' might not be what is returned by the solver
356used.
357
358
359\subsection{Adding integrality constraints}
360\index{modelling, MIP}
361
362In general, a problem variable is not restricted to taking integer
363values. However, for some problems, there may be a requirement that some or
364all of the variable values be strictly integral (for example, in the previous
365transportation problem, it may be that only whole units of the
366products can be transported; also variables may often be used to model
367booleans by allowing them to take on the values of 0 or 1 only). 
368This can be specified  by
369posting an additional \verb'integers/1' constraint on the
370variables. 
371
372\index{integers/1!eplex}
373Consider the example problem again, where it so happens that the
374optimal value for the objective function can be satisfied with integral
375values for the variables. To show the differences
376that imposing integer constraints might make, we add the constraint that
377client A must receive an equal amount of products from plants 1 and 2. Now
378the problem (without the integer constraints) can be written as:
379
380{\small
381\begin{code}
382:- lib(eplex).
383
384:- eplex_instance(prob).  
385
386main3(Cost, Vars) :-
387        Vars = [A1,A2,A3,B1,B2,B3,C1,C2,C3,D1,D2,D3], 
388        prob: (Vars \$:: 0.0..1.0Inf),
389        prob: (A1 + A2 + A3 \$= 21),
390        prob: (B1 + B2 + B3 \$= 40),
391        prob: (C1 + C2 + C3 \$= 34),
392        prob: (D1 + D2 + D3 \$= 10),
393
394        prob: (A1 + B1 + C1 + D1 \$=< 50),
395        prob: (A2 + B2 + C2 + D2 \$=< 30),
396        prob: (A3 + B3 + C3 + D3 \$=< 40),
397
398        prob: eplex_solver_setup(min(
399                10*A1 + 7*A2 + 200*A3 + 
400                 8*B1 + 5*B2 + 10*B3 +
401                 5*C1 + 5*C2 +  8*C3 + 
402                 9*D1 + 3*D2 +  7*D3)),
403
404        prob: (A1 \$= A2), % g. the new constraint, added after setup
405
406        %------------------------------- End of Modelling code
407
408        prob: eplex_solve(Cost),  
409        (foreach(V, Vars) do
410            prob: eplex_var_get(V, typed_solution, V) 
411        ).
412\end{code}}
413
414In this example, the new constraint in line \verb'g' is imposed after the
415solver setup. In fact it can be imposed anytime before
416\verb'eplex_solve(Cost)' is called.
417
418This problem also has an optimal \verb'Cost' of 710, the same as the original
419problem. However, the solution values are not integral:
420
421\begin{quote}\begin{verbatim}
422?- main3(Cost, Vars).
423
424Cost = 710.0
425Vars = [10.5, 10.5, 0.0, 5.5, 19.5, 15.0, 34.0, 0.0, 0.0, 0.0, 0.0, 10.0]
426\end{verbatim}\end{quote}
427
428Now, to impose the constraints that only whole units of the products can be
429transported, we modify the program as follows:
430
431{\small
432\begin{code}
433main4(Cost, Vars) :-
434        Vars = [A1,A2,A3,B1,B2,B3,C1,C2,C3,D1,D2,D3], 
435        prob: (Vars \$:: 0.0..1.0Inf),
436        prob: integers(Vars),  % h. impose the integrality constraint
437        ....% Rest is the same as main3
438\end{code}}
439
440In line \verb'h', we added the \verb'integers/1' constraint. This imposes
441the integrality constraint on \verb'Vars' for the eplex instance
442\verb'prob'. Now,
443the external solver will only assign integer solution values to the
444variables in the list. \Note{In fact, with the integer
445constraints, the problem is solved
446as a MIP problem rather than an LP problem, which involves different
447(and generally computationally more expensive) techniques. This difference
448is hidden from the eplex user.}
449
450Running this program, we get:
451
452\begin{quote}\begin{verbatim}
453
454?- main4(Cost,Vars).
455
456Cost = 898.0
457Vars = [10, 10, 1, 6, 20, 14, 34, 0, 0, 0, 0, 10]
458
459\end{verbatim}\end{quote}
460
461In this case, \verb'A1' and \verb'A2' are now integers. In fact, notice
462that all the values returned are now integers rather than floats. This is
463because the  \verb'typed_solution' option of \verb'eplex_var_get/3'
464returns the solution values taking into account if the variables have been
465declared as integers for the eplex instance.
466\Note{Posting an integers/1 constraint to an eplex instance only
467  inform the external solver to treat those variables as integers (in fact
468  the external solver will still represent the variables as floats, but
469  will only assign intergral solution values to them), but does
470  not constrain the variable itself to be of type integer.}
471
472
473
474\quickref{Modelling an MP Problem}{
475\begin{itemize}
476\item Declare an eplex instance using {\bf eplex_instance(+Instance)}.
477\item Post the constraints ({\bf \$=/2, \$>=/2, \$=</2, integers/1,
478  \$::/2}) for the problem to the eplex instance.
479\item Setup the solver with the objective function using 
480\newline{\bf Instance: eplex_solver_setup(+ObjFunc)}.
481\end{itemize}
482
483}
484
485\section{Repeated Solving of an Eplex Problem}
486
487Part of the power of using the eplex library comes from being able to solve
488an eplex problem repeatedly after modification.
489For example, we can solve the original transportation
490problem, add the extra constraint, and resolve the problem.
491Remember that as \verb'eplex_solve/1' instantiates its argument, we
492need to use a new variable for each call:
493
494{\small
495\begin{code}
496        .... % setup the constraints for the original problem as before
497        prob: (A3 + B3 + C3 + D3 =< 40),
498
499        prob: eplex_solver_setup(min(....)), % as before
500
501        prob: eplex_solve(Cost1),     % h. solve original problem
502        prob: (A1 \$= A2),
503        prob: eplex_solve(Cost2),     % i. solve modified problem
504        .....
505\end{code}}
506
507Note that posted constraints behave logically: they are added to an eplex
508instance when posted, and removed when they are backtracked over.
509
510In the examples so far, the solver has been invoked explicitly.
511However, the solver can also behave like a normal constraint, i.e.\ it is
512automatically invoked when certain conditions are met. 
513
514As an example, we implement the standard branch-and-bound method of
515solving a MIP problem, using the external solver as an LP solver only.
516Firstly we outline how this can be
517implemented with the facilities we have already encountered. We then show
518how this can be improved usin more advanced features of \texttt{lib(eplex)}.
519
520With the branch-and-bound approach, a search-tree is formed, and at each node a
521`relaxed' version of the MIP problem is solved as an LP problem.
522Starting at the root, the problem solved is the original MIP problem, but
523without any of the integrality constraints:
524{\small
525\begin{code}
526:- eplex_instance(mip).
527
528main5(Cost, Vars) :-
529      % set up variables and constraints, but no integers/1 constraints
530      ....
531      % assume minimise for simplicity
532      mip: eplex_solver_setup(min(Obj)), 
533      mip: eplex_solve(RelaxedCost),
534      mip: (Cost \$>= RelaxedCost),  % RelaxedCost is lower bound 
535\end{code}}
536\begin{figure}
537\begin{center}
538\resizebox{0.35\textwidth}{!}{\includegraphics{mipnode.ps}}
539\end{center}
540\caption{Labelling a variable at a MIP tree node}
541\label{mipnode}
542\end{figure}
543In general, this initial LP solution contains non-integer assignments
544to integer variables. The objective value of this LP is a lower bound on
545the actual MIP objective value.
546The task of the search is to find integer assignments
547for the integer variables that optimises the objective function. 
548Each node of the
549search-tree solves the problem with extra bound constraints on these
550variables. At each node, a particular variable is `labelled' as shown in
551Figure~\ref{mipnode}. The integer variable in this case has been assigned
552the non-integer value of 4.2. In the subsequent nodes of the tree, we
553consider two  alternate problems, which creates two branches in the search. In one
554problem, we impose the bound constraint $X \leq 4$, and in the other, $X
555\geq 5$: these are the two nearest integer values to 4.2. In each branch,
556the problem is  solved
557again as an LP problem with its new bound for the variable:
558
559{\small
560\begin{code}
561branching(IntVars) :-
562      ....
563      % for each integer variable X which violates the integer constraint
564      mip: eplex_var_get(X, solution, XVal),
565      ...
566      Split is floor(XVal),
567      % choice: branch on the two ranges for X
568      (mip: (X \$=< Split) ; mip: (X \$>= Split + 1)),
569      mip: eplex_solve(RelaxedCost),
570      ...% repeat until there are no integer violations
571\end{code}}
572
573A choice-point for the two alternative branchings is created in the above
574code, the problem is solved with one of the branchings (\verb'X $=< Split').
575The program then proceeds to further labelling of the variables. The
576alternative branch is left to be tried on backtracking.
577
578
579Eventually, if the problem has a solution, all the integer
580variables will be `labelled' with integer values, resulting in a solution to the
581MIP problem. However, this will generally not be optimal, and so the program
582needs to backtrack into the tree to search for a better solution by trying
583the other branches for the variables, using the
584existing solution value as a bound.
585This `branch-and-bound' search technique is implemented in {\tt
586lib(branch_and_bound)}.
587
588\quickref{Reminder: use {\eclipse} libraries!}{Remember that {\eclipse} provides
589libraries that make some programming tasks much easier. There is no
590need to write your own code when you can use what is
591provided by an {\eclipse} library.}
592
593\begin{sloppypar}
594In the code, the external solver is invoked explicitly at every node. This
595however may not be necessary as the imposed bound may already be satisfied.
596As stated at the start of this section, the invocation of the solver could be done in a
597data-driven way, more like a normal constraint.
598This is done with \verb'eplex_solver_setup/4':
599\verb'eplex_solver_setup(+Obj,-ObjVal,+Options,+Trigs)', a more
600powerful version of \verb'eplex_solver_setup/1' for setting up a
601solver. The \verb'Trigs' argument specifies a list of `trigger
602modes' for triggering the solver. \See{See the {\eclipse} reference manual for a
603complete  description of the predicate.}
604\end{sloppypar}
605
606\index{eplex\_solver\_setup/4}
607For our example, we add a bound constraint at each node to exclude a
608fractional solution value for a variable. The criterion we want to use is
609to invoke the solver only if this old solution value is excluded by the new
610bounds (otherwise the external solver will solve the same problem
611redundantly). This is done by
612specifying \verb'deviating_bounds' in the trigger modes.
613The full code that
614implements a MIP solution for the
615example transportation problem is given below: 
616{\small
617\begin{code}
618:- lib(eplex).
619:- lib(branch_and_bound).
620
621:- eplex_instance(mip).
622
623main6(Cost, Vars) :-
624        % b. create the problem variables and set their range
625        Vars = [A1,A2,A3,B1,B2,B3,C1,C2,C3,D1,D2,D3], 
626        mip: (Vars :: 0.0..1.0Inf),
627
628        % c. post the constraints for the problem to the eplex instance
629        mip: (A1 + A2 + A3 \$= 21),
630        mip: (B1 + B2 + B3 \$= 40),
631        mip: (C1 + C2 + C3 \$= 34),
632        mip: (D1 + D2 + D3 \$= 10),
633
634        mip: (A1 + B1 + C1 + D1 \$=< 50),
635        mip: (A2 + B2 + C2 + D2 \$=< 30),
636        mip: (A3 + B3 + C3 + D3 \$=< 40),
637        mip: (A1 \$= A2),
638
639        % j. post the objective function as a constraint 
640        ObjFunc = 10*A1 + 7*A2 + 200*A3 + 
641                   8*B1 + 5*B2 + 10*B3 +
642                   5*C1 + 5*C2 +  8*C3 + 
643                   9*D1 + 3*D2 +  7*D3,
644        mip: (ObjFunc  \$= Cost),
645
646        % k. this is a more flexible method for setting up a solver.
647        %    [deviating_bounds] specifies that the external solver should be
648        %    invoked when any solution value is outside the variable bounds 
649        mip: eplex_solver_setup(min(ObjFunc), Cost, [], [deviating_bounds]),
650
651        % l. Use the branch_and_bound library to do the branch and bound
652        bb_min(( branching(Vars), 
653                 mip: eplex_get(cost, Cost)
654                 (foreach(V, Vars) do mip: eplex_var_get(V,solution,V))
655               ), Cost, _).
656
657branching(IntVars) :-
658        % Find a variable X which does not have an integer solution value
659        (integer_violation(IntVars, X, XVal) ->
660            % m. try the closer integer range first
661            Split is round(XVal),
662            (Split > XVal ->
663                (mip: (X \$>= Split) ;  mip: (X \$=< Split - 1))
664            ;
665                (mip: (X \$=< Split) ; mip:  (X \$>= Split + 1))
666            ),
667            branching(IntVars)
668        ;
669            % cannot find any integer violations; found a solution
670            true
671        ).
672
673% returns Var with solution value Val which violates the integer constraint
674integer_violation([X|Xs], Var, Val) :-
675        mip: eplex_var_get(X, solution, RelaxedSol),
676        % m. we are dealing with floats here, so need some `margin' for a
677        %    float value to be considered integer (1e-5 on either side)
678        (abs( RelaxedSol - round(RelaxedSol) ) >= 1e-5 ->
679            Var = X, Val = RelaxedSol
680        ;
681            integer_violation(Xs, Var, Val)
682        ).
683
684\end{code}}
685
686The setup of the solver is done in line \verb'k', with the use of the
687\verb'deviating_bounds' trigger mode. There are no explicit calls to trigger the
688solver -- it is triggered automatically. In addition, the first call to
689\verb'eplex_solve/1' for an initial solution
690is also not required, because when trigger modes are specified, then
691by default, \verb'eplex_solver_setup/4' will invoke the solver once the
692problem is setup. 
693
694\begin{sloppypar}
695Besides the \verb'deviating_bounds'
696trigger condition, the other argument of interest in our use of
697\verb'eplex_solver_setup/4' is the second argument,
698the objective value of the problem (\verb'Cost' in the example): 
699recall that this was returned previously by \verb'eplex_solve/1'.
700Unlike in \verb'eplex_solve/1', the variable is {\it not\/}
701instantiated when the solver returns. Instead, one of the bounds (lower
702bound in the case of minimise) is updated
703to the optimal value, reflecting the range the objective value can take,
704from suboptimal to the `best' value at optimal. The variable is therefore
705made a problem variable by posting of the objective as a constraint in line
706\verb'j'. This informs the external solver needs to be informed
707that the \verb'Cost' variable is the objective value.
708
709\end{sloppypar}
710
711In line \verb'm', the branch choice is created by the posting of the bound
712constraint, which may trigger the external solver. Here, we use a
713simple heuristic to decide which of the two branches to try first: the
714branch with the integer range closer to the relaxed solution value.
715For example, in the situation of Figure~\ref{mipnode}, the branch with
716\verb'X $=< 4' is tried first since the solution value of 4.2 is
717closer to 4 than 5.
718
719By using {\it lib(branch_and_bound)\/}'s \verb'bb_min/3' predicate in \verb'm',  
720there is no need to explicitly write our own branch-and-bound routine. However, 
721this predicate requires the cost variable to be instantiated, so we call
722\verb'eplex_get(cost, Cost)' to instantiate \verb'Cost' at the end of
723each labelling of the variables. We also get the solution values for the
724variables, so that the branch-and-bound routine will remember it.
725The final value returned in \verb'Cost' (and {\tt Vars} for the solution
726values) 
727is the optimal value after the branch-and-bound search, i.e.\ the
728optimal value for the MIP problem.
729
730\quickref{More advanced modelling in eplex}{
731\begin{itemize}
732\item Use {\bf
733Instance:eplex_solver_setup(+Obj,-ObjVal,+Opts,+Trigs)} to
734set up an external solver state for instance Instance. Trigs specifies a
735list of trigger conditions to automatically trigger the external solver.
736\item {\bf Instance:eplex_var_get(+Var,+What,-Value)} can be used to obtain
737information for the variable {\bf Var} in the eplex instance.
738\item {\bf Instance:eplex_get(+Item, -Value)} can be used to  retrieve
739information about the eplex instance's solver state.
740\end{itemize}
741}
742\index{eplex\_get/2}
743
744Of course, in practice, we do not write our own MIP solver, but 
745use the MIP solver provided with the external solvers instead. These
746solvers are highly optimised and tightly coupled to their own LP solvers. 
747The techniques of solving relaxed subproblems described here are however
748very useful for combining the external solver with other solvers in a
749hybrid fashion. \See{See chapter~\ref{chaphybrid} for more details on hybrid techniques.}
750
751\section{Exercise}
752
753A company produces two types of products T1 and T2, which requires the
754following resources to produce each unit of the product:
755
756\vspace{3mm}
757\begin{center}
758\begin{tabular}{|r||r|r|}\hline
759Resource & T1 & T2\\ \hline
760Labour (hours) & 9 & 6\\ \hline
761Pumps (units) & 1 & 1\\ \hline
762Tubing (m) & 12 & 16\\ \hline
763\end{tabular}
764\end{center}
765\vspace{3mm}
766
767The amount of profit per unit of products are:
768
769\begin{description}
770\item[T1] \pounds350
771\item[T2] \pounds300
772\end{description}
773
774They have the following resources available: 1566 hours of labour, 200
775pumps, and 2880 metres of tubing.
776
777
778
779\begin{enumerate}
780\item Write a program to maximise the profit for the company, using eplex
781as a black box solver.   Write a predicate that returns the profit and the
782    values for T1 and T2.
783
784\item What program change is required to answer this question:
785    What profit can be achieved if exactly 150 units of T1 are required?
786
787\item What would the profit be if fractional numbers of refrigerators could
788    be produced?
789
790\item Rewrite the program from (1) without optimize/2, using
791    eplex_solver_setup/1, eplex_solve/1, and eplex_var_get/3.
792
793\item In the program from (4), remove the integrality constraints (so that eplex
794    only sees an LP problem).  Solve the integer problem by interleaving
795    solving of the LP problem with a rounding heuristic:
796
797\begin{itemize}
798    \item solve the continuous relaxation
799    \item round the solution for T1 to the nearest integer and instantiate it
800Initially just return the maximum profit value.
801    \item re-solve the new continuous relaxation
802    \item round the solution for T2 to the nearest integer and instantiate it
803    \item re-solve the new continuous relaxation
804\end{itemize}
805
806    What is the result in terms of T1, T2 and Profit?
807 
808\item Rewrite the program from (5) using eplex_solver_setup/4 and automatic
809    triggering of the solver instead of explicit calls to eplex_solve/1.
810    The solver should be triggered whenever variables get instantiated.
811\end{enumerate}
812
813%HEVEA\cutend
814
815