# source:trunk/OS/doc/chapters/codesamples.tex@4520

Last change on this file since 4520 was 4520, checked in by Gassmann, 20 months ago

Edits to user manuals

File size: 24.4 KB
Line
1\division{Code samples to illustrate the OS Project}\label{section:examples}
2
3\ifdevelop
4These example executable files are not built by running {\tt configure} and {\tt make}.
5Windows users are advised to download a binary distribution and use the solution file {\tt examples.sln} provided there in the
6\begin{verbatim}
7examples\MSVisualStudio
8\end{verbatim}
9directory.
10
11In order to build the examples in a {\bf unix environment}\index{unix} the user must first run
12%
13\index{make install@{\tt make install}}
14\begin{verbatim}
15make install
16\end{verbatim}
17in the COIN-OS project root directory (the discussion in this section assumes that the project root directory is
18{\tt COIN-OS}).  Running {\tt make install}  will  place all the header files required by the examples in the directory
19\begin{verbatim}
20COIN-OS/include
21\end{verbatim}
22and all of the libraries required by the examples in the directory
23\begin{verbatim}
24COIN-OS/lib
25\end{verbatim}
26In addition the folder {\tt pkgconfig} is placed in the {\tt lib} directory as well. Unix must then be informed of the location of this folder as follows:
27\begin{verbatim}
28export PKG_CONFIG_PATH=<path to pkgconfig directory>
29\end{verbatim}
30The source code for the examples is in the {\tt COIN-OS/OS/examples} hierarchy.  For instance, the {\tt osModDemo}
31example of section~\ref{section:exampleOSModDemo} is in the directory
32\begin{verbatim}
33COIN-OS/OS/examples/osModDemo
34\end{verbatim}
35
36Next, the user should connect to the appropriate example directory and run {\tt make}.
37If the user has done a VPATH\index{VPATH} build, the makefiles\index{makefile|(} will be in each respective example directory under
38\begin{verbatim}
39vpath_root/OS/examples
40\end{verbatim}
41otherwise, the makefiles will be in each respective example directory under
42\begin{verbatim}
43COIN-OS/OS/examples
44\end{verbatim}
45\else
46The binary distribution contains a number of sample applications that illustrate the use of the
47OS libraries and other aspects of the OS project. The sample code is found in the {\tt examples}
48folder. Each application contains a makefile for unix users; there are also MS Visual Studio project files
49for Windows users. At present only MS Visual Studio 2008 is supported.
50
51Under Windows, connect to the {\tt MSVisualStudio-v9} directory and open {\tt examples.sln} in Visual Studio. All examples can then be built simply by pushing F7 (Build solution). To build only selected examples it is necessary to open the Configuration Manager from the Build menu and select the projects desired to be built.
52
53To build any of the examples under unix, it is at present necessary to set the environment variable
54{\tt PKG\_CONFIG\_PATH} to point to the folder {\tt lib/pkgconfig}. Unless some directories were
56
57\begin{verbatim}
58export PKG_CONFIG_PATH=../../lib/pkgconfig
59\end{verbatim}
60
61After that, connect to the appropriate directory for the desired project and run {\tt make}.
62For instance, the code and makefile for the {\tt osModDemo}
63example of section~\ref{section:exampleOSModDemo} is in the directory
64\begin{verbatim}
65examples/osModDemo
66\end{verbatim}
67
68
69\fi
70
71The {\tt Makefile} in each example directory is fairly simple and is designed to be easily modified
72by the user if necessary.  The part of the Makefile to be adjusted, if necessary, is
73
74\begin{verbatim}
75##########################################################################
76#    You can modify this example makefile to fit for your own program.   #
77#    Usually, you only need to change the five CHANGEME entries below.   #
78##########################################################################
79
80# CHANGEME: This should be the name of your executable
81EXE = OSModDemo
82# CHANGEME: Here is the name of all object files corresponding to the source
83#           code that you wrote in order to define the problem statement
84OBJS =  OSModDemo.o
87# CHANGEME: Additional flags for compilation (e.g., include flags)
88ADDINCFLAGS =  -I${prefix}/include 89# CHANGEME: SRCDIR is the path to the source code; VPATH is the path to 90# the executable. It is assumed that the lib directory is in prefix/lib 91# and the header files are in prefix/include 92SRCDIR = /Users/kmartin/Documents/files/code/cpp/OScpp/COIN-OS/OS/examples/osModDemo 93VPATH = /Users/kmartin/Documents/files/code/cpp/OScpp/COIN-OS/OS/examples/osModDemo 94prefix = /Users/kmartin/Documents/files/code/cpp/OScpp/vpath 95\end{verbatim} 96 97 98Developers can use the Makefiles as a starting point for building applications that use the 99OS project libraries\index{makefile|)}. 100 101 102 103 104\subdivision{Algorithmic Differentiation: Using the OS Algorithmic Differentiation Methods}\label{section:cppad} 105 106\index{Algorithmic differentiation|(} 107In the {\tt OS/examples/algorithmicDiff} folder is test code {\tt OSAlgorithmicDiffTest.cpp}. This code 108illustrates the key methods in the {\tt OSInstance}\index{OSInstance@{\tt OSInstance}} API that are used for 109algorithmic differentiation. These methods are described in Section~\ref{section:ad}. 110 111 112 113\subdivision{Instance Generator: Using the OSInstance API to Generate Instances}\label{section:exampleOSInstanceGeneration} 114 115This example is found in the {\tt instanceGenerator} folder in the {\tt examples} folder. This example illustrates 116how to build a complete in-memory model instance using the {\tt OSInstance}\index{OSInstance@{\tt OSInstance}} API. 117See the code {\tt OSInstanceGenerator.cpp} for the complete example. Here we provide a few highlights to illustrate 118the power of the API. 119 120The first step is to create an {\tt OSInstance} object. 121\begin{verbatim} 122OSInstance *osinstance; 123osinstance = new OSInstance(); 124\end{verbatim} 125 126The instance has two variables,$x_{0}$and$x_{1}$. Variable$x_{0}$is a continuous variable with lower bound of$-100$and upper bound of$100$. Variable$x_{1}$is a binary variable. First declare the instance to have two variables. 127\begin{verbatim} 128osinstance->setVariableNumber( 2); 129\end{verbatim} 130Next, add each variable. There is an {\tt addVariable} method with the signature 131\begin{verbatim} 132addVariable(int index, string name, double lowerBound, double upperBound, char type); 133\end{verbatim} 134Then the calls for these two variables are 135\begin{verbatim} 136osinstance->addVariable(0, "x0", -100, 100, 'C'); 137osinstance->addVariable(1, "x1", 0, 1, 'B'); 138\end{verbatim} 139There is also a method {\tt setVariables} for adding more than one variable simultaneously. The objective function(s) and constraints are added through similar calls. 140 141Nonlinear terms are also easily added. The following code illustrates how to add a nonlinear term 142$x_{0}*x_{1}\$ in the {\tt <nonlinearExpressions>} section of  OSiL. This term is part of constraint~1
143and is the second of six constraints contained in the instance.
144\begin{verbatim}
145osinstance->instanceData->nonlinearExpressions->numberOfNonlinearExpressions = 6;
146osinstance->instanceData->nonlinearExpressions->nl = new Nl*[ 6 ];
147osinstance->instanceData->nonlinearExpressions->nl[ 1] = new Nl();
148osinstance->instanceData->nonlinearExpressions->nl[ 1]->idx = 1;
149osinstance->instanceData->nonlinearExpressions->nl[ 1]->osExpressionTree =
150new OSExpressionTree();
151// the nonlinear expression is stored as a vector of nodes in postfix format
152// create a variable nl node for x0
153nlNodeVariablePoint = new OSnLNodeVariable();
154nlNodeVariablePoint->idx=0;
155nlNodeVec.push_back( nlNodeVariablePoint);
156// create the nl node for x1
157nlNodeVariablePoint = new OSnLNodeVariable();
158nlNodeVariablePoint->idx=1;
159nlNodeVec.push_back( nlNodeVariablePoint);
160// create the nl node for *
161nlNodePoint = new OSnLNodeTimes();
162nlNodeVec.push_back( nlNodePoint);
163// now the expression tree
164osinstance->instanceData->nonlinearExpressions->nl[ 1]->osExpressionTree->m_treeRoot =
165nlNodeVec[ 0]->createExpressionTreeFromPostfix( nlNodeVec);
166\end{verbatim}
167\index{Algorithmic differentiation|)}
168
169%\subdivision{Excel:  Using VBA To Generate OSiL}\label{section:exampleExcel}
170
171%\subdivision{Matlab:  Using  MATLAB To Generate OSiL}\label{section:exampleMatlab}
172
173\subdivision{branchCutPrice:  Using Bcp}\label{section:examplebranchCutPrice}
174
175This example illustrates the use of the COIN-OR Bcp (Branch-cut-and-price) project.
176This project offers the user with the ability to have control over each node in the branch and process.
177This makes it possible to add user-defined cuts and/or user-defined variables. At each node in the tree,
178a call is made to the method {\tt process\_lp\_result()}. In the example problem we illustrate 1) adding COIN-OR Cgl cuts,
1792) a user-defined cut, and 3) a user-defined variable.
180
181
182\subdivision{OSModificationDemo: Modifying an In-Memory {\tt OSInstance} Object}\label{section:exampleOSModDemo}
183
184The {\tt osModificationDemo} folder holds the file {\tt OSModificationDemo.cpp}.
185This is similar to the {\tt instanceGenerator} example. In this case, a simple
186linear program is generated. However, this example also illustrates how to
187modify an in-memory OSInstance object. In particular, we illustrate how to
188modify an objective function coeffient. Note the dual occurrence of the
189following code
190
191\begin{verbatim}
192solver->osinstance->bObjectivesModified = true;
193\end{verbatim}
194
195in the {\tt OSModificationDemo.cpp} file (lines 177 and 187).
196This line is critical, since otherwise changes made to the OSInstance object
197will not be passed to the solver.
198
199This example also illustrates calling a COIN-OR solver,
200in this case {\tt Clp}\index{COIN-OR projects!Clp@{\tt Clp}}.
201
202\vskip 8pt
203
204{\bf Important:} the ability to modify a problem instance is still extremely limited in this release.
205A better API for problem modification will come with a later release of OS.
206
207
208
209\subdivision{OSSolverDemo: Building In-Memory Solver and Option Objects}\label{section:exampleOSSolverDemo}
210
211The code in the  example file {\tt OSSolverDemo.cpp} in the folder {\tt osSolverDemo}  illustrates  how to build solver interfaces and  an in-memory {\tt OSOption} object. In this example we  illustrate building a solver interface and corresponding {\tt OSOption} object for the solvers {\tt Clp}, {\tt Cbc}, {\tt SYMPHONY}, {\tt Ipopt},   {\tt Bonmin}, and {\tt Couenne}.   Each solver class inherits from a virtual {\tt OSDefaultSolver} class. Each solver class has the string data members
212
213\begin{itemize}
214\item {\tt osil --} this string conforms to the OSiL standard and holds the model instance.
215
216\item {\tt osol --} this string conforms to the OSoL standard and holds an instance with the
217solver options (if there are any); this string can be empty.
218
219\item {\tt osrl --} this string conforms to the OSrL standard and holds the solution instance;
220each solver interface produces an osrl string.
221\end{itemize}
222
223Corresponding to each string there is an in-memory object data member, namely
224
225\begin{itemize}
226\item {\tt osinstance --}  an in-memory {\tt OSInstance} object containing the model instance
227and get() and set() methods to access various parts of the model.
228
229
230\item {\tt osoption --} an in-memory {\tt OSOption} object; solver options can be accessed or
231set using get() and set() methods.
232
233
234\item {\tt osresult --}  an in-memory {\tt OSResult} object; various parts of the model solution
235are accessible through get() and set() methods.
236\end{itemize}
237
238
239For each solver we detail five steps:
240
241\begin{itemize}
242\item[Step 1:]  Read a model instance from a file  and create the corresponding {\tt OSInstance} object.
243For four of the solvers we read a file with the model instance in OSiL format. For the Clp example
244we read an MPS file and convert to OSiL. For the Couenne example we read an AMPL nl file and convert
245to OSiL.
246
247\item[Step 2:]  Create an {\tt OSOption} object and set options appropriate for the given solver.
248This is done by defining
249
250\begin{verbatim}
251OSOption* osoption = NULL;
252osoption = new OSOption();
253\end{verbatim}
254
255A key method in the {\tt OSOption} interface is {\tt setAnotherSolverOption()}.  This method
256takes the following arguments in order.
257
258\begin{itemize}
259\item[] {\tt std::string name} -- the option name;
260\item[] {\tt std::string value}  -- the value of the option;
261\item[] {\tt std::string solver} -- the name of the solver to which the option applies;
262\item[] {\tt std::string category} -- options may fall into categories. For example, consider the
263Couenne solver.  This solver is also linked to the Ipopt and Bonmin solvers and  it is possible
264to set options for these solvers through the Couenne API. In order to set an Ipopt option
265you would set the {\tt solver} argument to {\tt couenne} and set the {\tt category} option
266to {\tt ipopt}.
267
268\item[] {\tt std::string type} -- many solvers require knowledge of the data type, so you can set
269the type to {\tt double}, {\tt integer}, {\tt boolean} or {\tt string}, depending on the solver
270requirements. Special types defined by the solver, such as the type {\tt numeric} used by the
271Ipopt solver, can also be accommodated. It is the user's responsibility to verify the type
272expected by the solver.
273
274
275\item[] {\tt std::string  description} -- this argument is used to provide any detail or
277information is not needed.
278\end{itemize}
279
280For excellent documentation that details solver options for Bonmin, Cbc, and Ipopt  we recommend
281
282\begin{center}
284\end{center}
285
286
287\item[Step 3:] Create the solver object. In the OS project there is a {\it virtual} solver that
288is declared by
289
290\begin{verbatim}
291DefaultSolver *solver  = NULL;
292\end{verbatim}
293
294The Cbc, Clp and SYMPHONY solvers as well as other solvers of linear and integer linear programs
295are all invoked by creating a {\tt CoinSolver().} For example, the following is used to invoke Cbc.
296
297\begin{verbatim}
298solver = new CoinSolver();
299solver->sSolverName ="cbc";
300\end{verbatim}
301
302%Then to declare a specific, for example, an {\tt Ipopt} solver, simply write
303Other solvers, particularly Ipopt, Bonmin and Couenne are implemented separately. So to declare,
304for example, an Ipopt solver, one should write
305
306\begin{verbatim}
307solver = new IpoptSolver();
308\end{verbatim}
309
310The syntax is the same regardless of solver.
311
312\item[Step 4:] Import the {\tt OSOption} and {\tt OSInstance} into the solver and solve the model.
313This process is identical regardless of which solver is used. The syntax is:
314
315\begin{verbatim}
316solver->osinstance = osinstance;
317solver->osoption = osoption;
318solver->solve();
319\end{verbatim}
320
321\item[Step 5:] After optimizing the instance,  each of the OS solver interfaces uses the underlying solver API to get the solution result and write the result to a string
322named {\tt osrl} which is a string representing the solution instance in the {\tt OSrL} XML standard.
323This string is accessed by
324
325\begin{verbatim}
326solver->osrl
327\end{verbatim}
328
329
330In the example code {\tt OSSolverDemo.cpp} we have written a method,
331
332\begin{verbatim}
333void getOSResult(std::string osrl)
334\end{verbatim}
335
336that takes the {\tt osrl} string and creates an {\tt OSResult} object.
337We then illustrate several of the {\tt OSResult} API methods
338
339\begin{verbatim}
340double getOptimalObjValue(int objIdx, int solIdx);
341std::vector<IndexValuePair*>  getOptimalPrimalVariableValues(int solIdx);
342\end{verbatim}
343to get and write out the optimal objective function value, and optimal primal values.  See also Section \ref{section:exampleOSResultDemo}.
344
345\end{itemize}
346
347We now highlight some of the features illustrated by each of the solver examples.
348
349\begin{itemize}
350\item {\bf Clp --}  In this example we read in a problem instance in MPS format.  The class
351{\tt OSmps2osil}  has a method {\tt mps2osil} that is used to convert the MPS instance contained
352in a file into an in-memory {\tt OSInstance} object. This example also illustrates how to
353set options using the Osi interface. In particular we turn on intermediate output which is
354turned off by default in the Coin Solver Interface.
355
356\item {\bf Cbc --}  In this example we read a problem instance that is in OSiL format and create
357an in-memory {\tt OSInstance} object.  We then create an {\tt OSOption} object.  This is quite trivial.
358A  plain-text XML file conforming to the OSiL schema is read into a string {\tt osil} which is then
359converted into the in-memory {\tt OSInstance} object by
360
361\begin{verbatim}
363OSInstance *osinstance = NULL;
366\end{verbatim}
367
368
369 We set the linear programming algorithm to be the primal simplex method and then set the option
370on the pivot selection to be Dantzig rule.  Finally, we set the print level to be 10.
371
372\item {\bf SYMPHONY --}   In this example we also read a problem instance that is in OSiL format and
373create an in-memory {\tt OSInstance} object.  We then create an {\tt OSOption} object and
374illustrate setting the {\tt verbosity} option.
375
376\item {\bf Ipopt --}   In this example we also read a problem instance that is in OSiL format.
377However, in this case we do  not create an {\tt OSInstance} object. We read the OSiL file into
378a string {\tt osil}.  We then feed the {\tt osil} string directly into the Ipopt solver by
379\begin{verbatim}
380solver->osil = osil;
381\end{verbatim}
382The user always has the option of providing the OSiL to the solver as either a string or in-memory object.
383
384Next we create an {\tt OSOption} object. For Ipopt, we illustrate setting the maximum iteration limit
385and also provide the name of the output file. In addition, the OSOption object can hold initial solution
386values. We illustrate how to initialize all of the variable to 1.0.
387
388\begin{verbatim}
389numVar = 2; //rosenbrock mod has two variables
390xinitial = new double[numVar];
391for(i = 0; i < numVar; i++){
392    xinitial[ i] = 1.0;
393}
394osoption->setInitVarValuesDense(numVar, xinitial);
395\end{verbatim}
396
397
398
399\item {\bf Bonmin --}  In this example we read a problem instance that is in OSiL format and create
400an in-memory {\tt OSInstance} object just as was done in the Cbc and SYMPHONY examples.
401We then create an {\tt OSOption} object.  In setting the  {\tt OSOption} object we intentionally
402set an option that will cause the Bonmin solver to terminate early.  In particular we set the
403{\tt node\_limit} to zero.
404
405\begin{verbatim}
406osoption->setAnotherSolverOption("node_limit","0","bonmin","","integer","");
407\end{verbatim}
408
409This results in early termination of the algorithm. The {\tt OSResult} class API has a method
410\begin{verbatim}
411std::string getSolutionStatusDescription(int solIdx);
412\end{verbatim}
413
414For this example, invoking
415\begin{verbatim}
416osresult->getSolutionStatusDescription( 0)
417\end{verbatim}
418gives the result:
419\begin{verbatim}
420LIMIT_EXCEEDED[BONMIN]: A resource limit was exceeded, we provide the current solution.
421\end{verbatim}
422
423
424\item {\bf Couenne --}   In this example we read in a problem instance in AMPL nl format.
425The class {\tt OSnl2osil}  has a method {\tt nl2osil} that is used to convert the nl instance
426contained in a file into an in-memory {\tt OSInstance} object. This is done as follows:
427
428\begin{verbatim}
429// convert to the OS native format
430OSnl2osil *nl2osil = NULL;
431nl2osil = new OSnl2osil( nlFileName);
432// create the first in-memory OSInstance
433nl2osil->createOSInstance() ;
434osinstance =  nl2osil->osinstance;
435\end{verbatim}
436\end{itemize}
437
438This part of the example also illustrates setting options in one solver from another.
439Couenne uses Bonmin which uses Ipopt.  So for example,
440
441\begin{verbatim}
442osoption->setAnotherSolverOption("max_iter","100","couenne","ipopt","integer","");
443\end{verbatim}
444identifies the solver as {\tt couenne}, but the category of value of {\tt ipopt}  tells the solver
445interface to set the iteration limit on the Ipopt algorithm that is solving the continuous relaxation
446of the problem.  Likewise, the setting
447\begin{verbatim}
448osoption->setAnotherSolverOption("num_resolve_at_node","3","couenne","bonmin","integer","");
449\end{verbatim}
450identifies the solver as {\tt couenne}, but the category of value of {\tt bonmin}  tells the solver
451interface to tell the Bonmin solver to try three starting points at each node.
452
453
454
455\subdivision{OSResultDemo: Building In-Memory Result Object to Display Solver Result}\label{section:exampleOSResultDemo}
456
457The OS protocol for representing an optimization result is {\tt OSrL}. Like the {\tt OSiL} and {\tt OSoL} protocol, this protocol has an associated in-memory {\tt OSResult} class with corresponding API.  The use of the API is demonstrated in the code {\tt OSResultDemo.cpp} in the folder {\tt OS/examples/OSResultDemo}.  In the code we solve a linear program with the {\tt Clp} solver.  The OS solver interface builds an {\tt OSrL} string that we read into the {\tt OSrLReader} class and create and {\tt OSResult} object. We then use the {\tt OSResult} API to get the optimal primal and dual solution. We also use the API to get the reduced cost values.
458
459
460\subdivision{OSCglCuts: Using the OSInstance API to Generate Cutting Planes}\label{section:exampleOSAddCuts}
461
462In this example, we show how to add cuts to tighten an LP using COIN-OR
463{\tt Cgl} (Cut Generation Library)\index{COIN-OR projects!Cgl@{\tt Cgl}}.
464A file ({\tt p0033.osil}) in OSiL format is used to create an OSInstance object. The linear programming relaxation
465is solved. Then, Gomory, simple rounding, and knapsack cuts are added using {\tt Cgl}.  The model is then optimized
466using {\tt Cbc}.
467
468\subdivision{OSRemoteTest:  Calling a Remote Server}\label{section:exampleOSRemoteTest}
469
470This example illustrates the API for the six service methods described in Section~\ref{section:servicemethods}.
471The file {\tt osRemoteTest.cpp} in folder {\tt osRemoteTest} first builds a small linear
472example, solves it remotely in synchronous mode and displays the solution.
473The asynchronous mode is also tested by submitting the problem to a remote solver,
474checking the status and either retrieving the answer or killing the process if it has not
475yet finished.
476
477{\bf Windows users should note}
478that this project links to {\tt wsock32.lib}, which is not part of the Visual Studio  Express Package.  It is necessary
479to also download and install the Windows Platform SDK\index{Windows Platform SDK}, which can be found at
480
481\medskip
482\noindent{\scriptsize\tt\UrlSdk}.
483\medskip
484
485\ifdevelop
487\else
488\noindent Further information is provided in the OS User's Manual.
489\fi
490
491\subdivision{OSJavaInstanceDemo:  Building an OSiL Instance in
493\index{Java|(}
494
495In this example we demonstrate how to build an OSiL instance using the Java
496OSInstance API.  The example code also  illustrates calling the {\tt
497OSSolverService} executable from Java. In order to use this example, the user should do an svn
498checkout:
499
500\begin{verbatim}
501svn co https://projects.coin-or.org/svn/OS/branches/OSjava OSjava
502\end{verbatim}
503
504The {\tt OSjava} folder contains the file {\tt INSTALL.txt}. Please follow the
505instructions in {\tt  INSTALL.txt} under the heading:
506\begin{verbatim}
507== Install Without a Web Server==
508\end{verbatim}
509
510These instructions assume that the user has installed the Eclipse IDE. See
512user get {\tt Eclipse Classic}.  In addition, the user should also have a copy of the
513{\tt OSSolverService} executable that is compatible with his or her platform.
514The {\tt OSSolverService} executable for several different platforms is
516The user can also build the executable as described in this Manual.  See Section
517\ref{section:build}. The code base for this example is in the folder:
518\begin{verbatim}
519OSjava/OSJavaExamples/src/OSJavaInstanceDemo.java
520\end{verbatim}
521The code in the file {\tt OSJavaInstanceDemo.java} demonstrates how the
522Java OSInstance API that is in {\tt OSCommon} can be used to generate a linear
523program and then call the C++ {\tt OSSolverService} executable
524to solve the problem.\index{Java|)}  Running this example in Eclipse will
525generate in the folder
526\begin{verbatim}
527OSjava/OSJavaExamples
528\end{verbatim}
529two files. It will generate {\tt parincLinear.osil} which is a linear program in
530the OS OSiL format, it will also call the {\tt OSSolverService} executable which
531generates the result file {\tt result.osrl} in the OS OSrL format.
532
533
Note: See TracBrowser for help on using the repository browser.