doc/0000755000175000017500000000000011247522375010277 5ustar renerenedoc/get_working_objective.htm0000644000175000017500000000607710237215410015357 0ustar renerene get_working_objective

get_working_objective

Returns the value of the objective function.

REAL get_working_objective(lprec *lp);

Return Value

get_working_objective returns the current value of the objective while solving the model.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_working_objective function returns the current value of the objective while solving the model.
This value can be retrieved while solving in a callback function.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int msgfunction(lprec *lp, void *userhandle, char *buf)
{

 printf("%f\n", get_working_objective(lp));

 return(0);
}

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  put_msgfunc(lp, msgfunction, NULL, 0);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_working_objective, is_feasible, get_variables, get_ptr_variables, get_constraints, get_ptr_constraints, get_constr_value, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex

doc/LGPL.htm0000644000175000017500000006516210056375074011560 0ustar renerene GNU LESSER GENERAL PUBLIC LICENSE

GNU LESSER GENERAL PUBLIC LICENSE

		       Version 2.1, February 1999

 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL.  It also counts
 as the successor of the GNU Library Public License, version 2, hence
 the version number 2.1.]

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.

  This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it.  You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.

  When we speak of free software, we are referring to freedom of use,
not price.  Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.

  To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights.  These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.

  For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you.  You must make sure that they, too, receive or can get the source
code.  If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it.  And you must show them these terms so they know their rights.

  We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.

  To protect each distributor, we want to make it very clear that
there is no warranty for the free library.  Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.

  Finally, software patents pose a constant threat to the existence of
any free program.  We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder.  Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.

  Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License.  This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License.  We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.

  When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library.  The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom.  The Lesser General
Public License permits more lax criteria for linking other code with
the library.

  We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License.  It also provides other free software developers Less
of an advantage over competing non-free programs.  These disadvantages
are the reason we use the ordinary General Public License for many
libraries.  However, the Lesser license provides advantages in certain
special circumstances.

  For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard.  To achieve this, non-free programs must be
allowed to use the library.  A more frequent case is that a free
library does the same job as widely used non-free libraries.  In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.

  In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software.  For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.

  Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.

  The precise terms and conditions for copying, distribution and
modification follow.  Pay close attention to the difference between a
"work based on the library" and a "work that uses the library".  The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.

		  GNU LESSER GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".

  A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.

  The "Library", below, refers to any such software library or work
which has been distributed under these terms.  A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language.  (Hereinafter, translation is
included without limitation in the term "modification".)

  "Source code" for a work means the preferred form of the work for
making modifications to it.  For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.

  Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it).  Whether that is true depends on what the Library does
and what the program that uses the Library does.

  1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.

  You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.

  2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) The modified work must itself be a software library.

    b) You must cause the files modified to carry prominent notices
    stating that you changed the files and the date of any change.

    c) You must cause the whole of the work to be licensed at no
    charge to all third parties under the terms of this License.

    d) If a facility in the modified Library refers to a function or a
    table of data to be supplied by an application program that uses
    the facility, other than as an argument passed when the facility
    is invoked, then you must make a good faith effort to ensure that,
    in the event an application does not supply such function or
    table, the facility still operates, and performs whatever part of
    its purpose remains meaningful.

    (For example, a function in a library to compute square roots has
    a purpose that is entirely well-defined independent of the
    application.  Therefore, Subsection 2d requires that any
    application-supplied function or table used by this function must
    be optional: if the application does not supply it, the square
    root function must still compute square roots.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.

In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library.  To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License.  (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.)  Do not make any other change in
these notices.

  Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.

  This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.

  4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.

  If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.

  5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library".  Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.

  However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library".  The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.

  When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library.  The
threshold for this to be true is not precisely defined by law.

  If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work.  (Executables containing this object code plus portions of the
Library will still fall under Section 6.)

  Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.

  6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.

  You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License.  You must supply a copy of this License.  If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License.  Also, you must do one
of these things:

    a) Accompany the work with the complete corresponding
    machine-readable source code for the Library including whatever
    changes were used in the work (which must be distributed under
    Sections 1 and 2 above); and, if the work is an executable linked
    with the Library, with the complete machine-readable "work that
    uses the Library", as object code and/or source code, so that the
    user can modify the Library and then relink to produce a modified
    executable containing the modified Library.  (It is understood
    that the user who changes the contents of definitions files in the
    Library will not necessarily be able to recompile the application
    to use the modified definitions.)

    b) Use a suitable shared library mechanism for linking with the
    Library.  A suitable mechanism is one that (1) uses at run time a
    copy of the library already present on the user's computer system,
    rather than copying library functions into the executable, and (2)
    will operate properly with a modified version of the library, if
    the user installs one, as long as the modified version is
    interface-compatible with the version that the work was made with.

    c) Accompany the work with a written offer, valid for at
    least three years, to give the same user the materials
    specified in Subsection 6a, above, for a charge no more
    than the cost of performing this distribution.

    d) If distribution of the work is made by offering access to copy
    from a designated place, offer equivalent access to copy the above
    specified materials from the same place.

    e) Verify that the user has already received a copy of these
    materials or that you have already sent this user a copy.

  For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it.  However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.

  It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system.  Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.

  7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:

    a) Accompany the combined library with a copy of the same work
    based on the Library, uncombined with any other library
    facilities.  This must be distributed under the terms of the
    Sections above.

    b) Give prominent notice with the combined library of the fact
    that part of it is a work based on the Library, and explaining
    where to find the accompanying uncombined form of the same work.

  8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License.  Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License.  However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.

  9. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Library or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.

  10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.

  11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all.  For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.

If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded.  In such case, this License incorporates the limitation as if
written in the body of this License.

  13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number.  If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation.  If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.

  14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission.  For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this.  Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.

			    NO WARRANTY

  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.

		     END OF TERMS AND CONDITIONS

           How to Apply These Terms to Your New Libraries

  If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change.  You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).

  To apply these terms, attach the following notices to the library.  It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.

    <one line to give the library's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the
  library `Frob' (a library for tweaking knobs) written by James Random Hacker.

  <signature of Ty Coon>, 1 April 1990
  Ty Coon, President of Vice

That's all there is to it!
doc/set_sense.htm0000644000175000017500000000453110237176664013010 0ustar renerene set_sense

set_sense

Set objective function sense.

void set_sense(lprec *lp, unsigned char maximize);

Return Value

set_sense has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

maximize

Set sense to minimize (FALSE) or maximize (TRUE).

Remarks

The set_sense function sets the objective sense. The default of lp_solve is to minimize, except for read_lp, read_LP where the default is to maximize.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_sense(lp, TRUE); /* set object sense to maximize */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_minim, set_maxim, is_maxim

doc/write_basis.htm0000644000175000017500000000711610617377062013332 0ustar renerene write_basis

write_basis

Writes current basis to a file.

unsigned char write_basis(lprec *lp, char *filename);

Return Value

Returns TRUE if basis could be written to filename and FALSE if not.
A FALSE return value indicates an error. Specifically file could not be opened or not able to write in file.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

filename

Filename to write the basis to.

Remarks

The write_basis function writes the current basis to filename.
This basis can later be reused by read_basis to reset a basis. Setting an initial basis can speed up the solver considerably. It is the starting point from where the algorithm continues to find an optimal solution.
When a restart is done, lp_solve continues at the last basis, except if set_basis, default_basis, guess_basis or read_basis is called.

The basis in the file is written in MPS bas file format.

When filename is NULL, then output is written to output set by set_outputstream, set_outputfile. By default this is stdout.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;

  /* Read LP model */
  lp = read_LP("model.lp", NORMAL, "test model");
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  ret = solve(lp);

  ret = write_basis(lp, "model.bas", NULL);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_basis, set_basis, default_basis, read_basis, guess_basis, get_basiscrash, set_basiscrash

doc/make_lp.htm0000644000175000017500000000562110351333702012412 0ustar renerene make_lp

make_lp

Create and initialise a new lprec structure.

lprec *make_lp(int rows, int columns);

Return Value

Returns a pointer to a new lprec structure. This must be provided to almost all lp_solve functions.
A NULL return value indicates an error. Specifically not enough memory available to setup an lprec structure.

Parameters

rows

Initial number of rows. Can be 0 as new rows can be added via add_constraint, add_constraintex, str_add_constraint

columns

Initial number of columns. Can be 0 as new columns can be added via add_column, add_columnex, str_add_column

Remarks

The make_lp function constructs a new LP. Sets all variables to initial values.
The LP has rows rows and columns columns. The matrix contains no values, but space for one value. All arrays that depend on rows and columns are allocated.

It is advised not to read/write the lprec structure. Instead, use the function interface to communicate with the lp_solve library. This because the structure can change over time. The function interface will be more stable.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /*
  .
  .
  .
  */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also copy_lp, delete_lp, free_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, resize_lp

doc/formulate.htm0000644000175000017500000014212211235624407013005 0ustar renerene Formulation of an lp problem in lpsolve

Formulation of an lp problem in lpsolve

We shall illustrate the method of linear programming by means of a simple example, giving a combination graphical/numerical solution, and then solve the problem in lpsolve in different ways. This via ASCII files and from different programming languages.

Suppose a farmer has 75 acres on which to plant two crops: wheat and barley. To produce these crops, it costs the farmer (for seed, fertilizer, etc.) $120 per acre for the wheat and $210 per acre for the barley.The farmer has $15000 available for expenses. But after the harvest, the farmer must store the crops while awaiting favourable market conditions. The farmer has storage space for 4000 bushels.Each acre yields an average of 110 bushels of wheat or 30 bushels of barley. If the net profit per bushel of wheat (after all expenses have been subtracted) is $1.30 and for barley is $2.00, how should the farmer plant the 75 acres to maximize profit?

We begin by formulating the problem mathematically. First we express the objective, that is the profit, and the constraints algebraically, then we graph them, and lastly we arrive at the solution by graphical inspection and a minor arithmetic calculation.

Let x denote the number of acres allotted to wheat and y the number of acres allotted to barley. Then the expression to be maximized, that is the profit, is clearly

P = (110)(1.30)x + (30)(2.00)y = 143x + 60y.

There are three constraint inequalities, specified by the limits on expenses, storage and acreage. They are respectively:

120x + 210y <= 15000
110x + 30y <= 4000
x + y <= 75

Strictly speaking there are two more constraint inequalities forced by the fact that the farmer cannot plant a negative number of acres, namely:

x >= 0,y >= 0.

Next we graph the regions specified by the constraints. The last two say that we only need to consider the first quadrant in the x-y plane. Here's a graph delineating the triangular region in the first quadrant determined by the first inequality.

Source

Now let's put in the other two constraint inequalities.

Source

The black area is the solution space that holds valid solutions. This means that any point in this area fulfils the constraints.

Now let's superimpose on top of this picture a contour plot of the objective function P.

Source

The lines give a picture of the objective function. All solutions that intersect with the black area are valid solutions, meaning that this result also fulfils the set constraints. The more the lines go to the right, the higher the objective value is. The optimal solution or best objective is a line that is still in the black area, but with an as large as possible value.

It seems apparent that the maximum value of P will occur on the level curve (that is, level line) that passes through the vertex of the polygon that lies near (22,53).
It is the intersection of x + y = 75 and 110*x + 30*y = 4000
This is a corner point of the diagram. This is not a coincidence. The simplex algorithm, which is used by lpsolve, starts from a theorem that the optimal solution is such a corner point.
In fact we can compute the result:

x + y = 75          (1)
110*x + 30*y = 4000 (2)

From (1), y can be expressed in function of x:

y = 75 - x (3)

This equation can be substituted in (2):

110*x + 30*(75 - x) = 4000

Or:

80*x = 1750

Or:

x = 21.875

From (3), y can be derived:

y = 75 - 21.875 = 53.125

The acreage that results in the maximum profit is 21.875 for wheat and 53.125 for barley. In that case the profit is:

P = 143*x + 60*y

Or:

P = 143*21.875 + 60*53.125 = 6326.625

That is, $6315.625.

Now, lpsolve comes into the picture to solve this linear programming problem more generally.

First let us show this problem in its mathematical format:

max(143x + 60y)
s.t.
120x + 210y <= 15000
110x + 30y <= 4000
x + y <= 75
x >= 0
y >= 0

Formulate an lp problem with lpsolve

There are several ways to model a linear problem via lpsolve:

Read the model from an ASCII file.

There exist a lot of formats to model an lp problem into. Almost each solver has its format on its own.

MPS file format

The MPS format is supported by most lp solvers and thus very universal. The model is provided to the solver via an ASCII file. This format is very old and difficult to read by humans. See MPS file format for a complete description about the format. This problem is formulated as follows in MPS format:

* model.mps
NAME
ROWS
 N  R0
 L  R1
 L  R2
 L  R3
COLUMNS
    x         R0        143.00000000   R1        120.00000000
    x         R2        110.00000000   R3        1.0000000000
    y         R0        60.00000000    R1        210.00000000
    y         R2        30.000000000   R3        1.0000000000
RHS
    RHS       R1        15000.000000   R2        4000.0000000
    RHS       R3        75.000000000
ENDATA

Save this as ASCII file with name model.mps

To read this format in lpsolve, the API functions read_mps, read_freemps, read_MPS, read_freeMPS can be used. The lpsolve distribution comes with two applications that use this API call to read a model:

lp_solve command line program

To read this MPS model via the lp_solve command line program and calculate the solution, enter the following command:

lp_solve -max -mps model.mps

This gives:

Value of objective function: 6315.63

Actual values of the variables:
x                          21.875
y                          53.125

The lp_solve program has a lot of options that can be set. See lp_solve command

IDE

Under Windows, there is also a graphical IDE that can read an MPS file. See LPSolve IDE for more information.

lp file format

The lp format is the native lpsolve format to provide LP models via an ASCII file to the solver. It is very readable and its syntax is very similar to the Mathematical formulation. See LP file format for a complete description about the format. This model is formulated as follows in lp-format:

/* model.lp */

max: 143 x + 60 y;

120 x + 210 y <= 15000;
110 x + 30 y <= 4000;
x + y <= 75;

Save this as ASCII file with name model.lp

To read this format in lpsolve, the API functions read_lp, read_LP can be used. The lpsolve distribution comes with two applications that use this API call to read a model:

lp_solve command line program

To read this lp model via the lp_solve command line program and calculate the solution, enter the following command:

lp_solve model.lp

This gives:

Value of objective function: 6315.63

Actual values of the variables:
x                          21.875
y                          53.125

The lp_solve program has a lot of options that can be set. See lp_solve command

IDE

Under Windows, there is also a graphical IDE that can read an lp-file. See LPSolve IDE for more information.

CPLEX lp file format

The CPLEX lp format is another format to provide LP models via an ASCII file to the solver. It is very readable and its syntax is very similar to the Mathematical formulation. It is a format used by the CPLEX solver. See CPLEX lp files for a complete description about the format. This model is formulated as follows in CPLEX lp format:

\* model.lpt *\

Maximize
 +143 x +60 y

Subject To
 +120 x +210 y <= 15000
 +110 x +30 y <= 4000
 +x +y <= 75

End

Save this as ASCII file with name model.lpt

lpsolve doesn't has an API call to read/write this format. However, the lpsolve distribution has an XLI that can do this. See External Language Interfaces for a description about XLIs. This uses the API call read_XLI. The xli to read/write this format is xli_CPLEX. The lpsolve distribution comes with two applications that use this API call to read a model:

lp_solve command line program

To read this CPLEX lp model via the lp_solve command line program and calculate the solution, enter the following command:

lp_solve -rxli xli_CPLEX model.lpt

This gives:

Value of objective function: 6315.63

Actual values of the variables:
x                          21.875
y                          53.125

The lp_solve program has a lot of options that can be set. See lp_solve command

IDE

Under Windows, there is also a graphical IDE that can read a CPLEX lp file via an XLI. See LPSolve IDE for more information.

LINDO lp file format

The LINDO FILE format is another format to provide LP models via an ASCII file to the solver. It is very readable and its syntax is very similar to the Mathematical formulation. It is a format used by the LINDO solver. See LINDO lp files for a complete description about the format. This model is formulated as follows in LINDO FILE format:

! model.lnd

MAXIMIZE
 +143 x +60 y

SUBJECT TO
 +120 x +210 y <= 15000
 +110 x +30 y <= 4000
 +x +y <= 75

END

Save this as ASCII file with name model.lpt

lpsolve doesn't has an API call to read/write this format. However, the lpsolve distribution has an XLI that can do this. See External Language Interfaces for a description about XLIs. This uses the API call read_XLI. The xli to read/write this format is xli_LINDO. The lpsolve distribution comes with two applications that use this API call to read a model:

lp_solve command line program

To read this LINDO lp model via the lp_solve command line program and calculate the solution, enter the following command:

lp_solve -rxli xli_LINDO model.lnd

This gives:

Value of objective function: 6315.63

Actual values of the variables:
x                          21.875
y                          53.125

The lp_solve program has a lot of options that can be set. See lp_solve command

IDE

Under Windows, there is also a graphical IDE that can read a LINDO lp file via an XLI. See LPSolve IDE for more information.

GNU MathProg file format

The GNU MathProg format is another format to provide LP models via an ASCII file to the solver. It is very readable and its syntax is very similar to the Mathematical formulation. It is a format used by the GLPK solver and a subset of AMPL. It has also the possibility to use loops. See Modeling Language GNU MathProg This model is formulated as follows in GNU MathProg format:

/* model.mod */

var x >= 0;
var y >= 0;

maximize obj: +143*x +60*y;

R1: +120*x +210*y <= 15000;
R2: +110*x +30*y <= 4000;
R3: +x +y <= 75;

Save this as ASCII file with name model.mod

lpsolve doesn't has an API call to read/write this format. However, the lp_solve distribution has an XLI that can do this. See External Language Interfaces for a description about XLIs. This uses the API call read_XLI. The xli to read/write this format is xli_MathProg. The lpsolve distribution comes with two applications that use this API call to read a model:

lp_solve command line program

To read this GNU MathProg model via the lp_solve command line program and calculate the solution, enter the following command:

lp_solve -rxli xli_MathProg model.mod

This gives:

Value of objective function: 6315.63

Actual values of the variables:
x                          21.875
y                          53.125

The lp_solve program has a lot of options that can be set. See lp_solve command

IDE

Under Windows, there is also a graphical IDE that can read a GNU MathProg file via an XLI. See LPSolve IDE for more information.

LPFML XML file format

The LPFML XML format is another format to provide LP models via an ASCII file to the solver. This format is very recent and uses XML layout. It is not very readable by us, but because of the XML structure very flexible. See LPFML: A W3C XML Schema for Linear Programming for more information. This model is formulated as follows in LPFML XML format:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<mathProgram xmlns="http://FML/lpfml.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://FML/lpfml.xsd lpfml.xsd">

  <linearProgramDescription>
    <source></source>
    <maxOrMin>max</maxOrMin>
    <numberRows>3</numberRows>
    <numberVars>2</numberVars>
  </linearProgramDescription>

  <linearProgramData>
    <rows>
      <row rowName="R1" rowUB="15000"/>
      <row rowName="R2" rowUB="4000"/>
      <row rowName="R3" rowUB="75"/>
    </rows>
    <columns>
      <col colName="x" colType="C" objVal="143"/>
      <col colName="y" colType="C" objVal="60"/>
    </columns>
    <amatrix>
      <sparseMatrix>
        <pntANonz>
          <el>3</el>
          <el>6</el>
        </pntANonz>
        <rowIdx>
          <el>0</el>
          <el>1</el>
          <el>2</el>
          <el>0</el>
          <el>1</el>
          <el>2</el>
        </rowIdx>
        <nonz>
          <el>120</el>
          <el>110</el>
          <el>1</el>
          <el>210</el>
          <el>30</el>
          <el>1</el>
        </nonz>
      </sparseMatrix>
    </amatrix>
  </linearProgramData>

</mathProgram>

Save this as ASCII file with name model.xml

lpsolve doesn't has an API call to read/write this format. However, the lp_solve distribution has an XLI that can do this. See External Language Interfaces for a description about XLIs. This uses the API call read_XLI. The xli to read/write this format is xli_LPFML. The lpsolve distribution comes with two applications that use this API call to read a model:

lp_solve command line program

To read this LPFML XML model via the lp_solve command line program and calculate the solution, enter the following command:

lp_solve -rxli xli_LPFML model.xml

This gives:

Value of objective function: 6315.63

Actual values of the variables:
x                          21.875
y                          53.125

The lp_solve program has a lot of options that can be set. See lp_solve command

IDE

Under Windows, there is also a graphical IDE that can read a LPFML XML file via an XLI. See LPSolve IDE for more information.

Construct the model from a Mathematical Programming Language.

There are several commercial and free Mathematical programming applications out there which can be used to solve lp problems. An lpsolve driver is made for several of them:

Construct the model from a Programming Language.

In several cases it is required that the solver is called from within the programming language in which an application is build. All the data is in memory and no files are created to provide data to the solver. lpsolve has a very rich, yet easy, API to do this. See lp_solve API reference for an overview of the API. lpsolve is a library of API routines. This library is called from the programming language. See Calling the lpsolve API from your application for more information. Above example is now formulated in several programming languages:

C/C++

The example model can be formulated as follows in C:

/* demo.c */

#include "lp_lib.h"

int demo()
{
  lprec *lp;
  int Ncol, *colno = NULL, j, ret = 0;
  REAL *row = NULL;

  /* We will build the model row by row
     So we start with creating a model with 0 rows and 2 columns */
  Ncol = 2; /* there are two variables in the model */
  lp = make_lp(0, Ncol);
  if(lp == NULL)
    ret = 1; /* couldn't construct a new model... */

  if(ret == 0) {
    /* let us name our variables. Not required, but can be useful for debugging */
    set_col_name(lp, 1, "x");
    set_col_name(lp, 2, "y");

    /* create space large enough for one row */
    colno = (int *) malloc(Ncol * sizeof(*colno));
    row = (REAL *) malloc(Ncol * sizeof(*row));
    if((colno == NULL) || (row == NULL))
      ret = 2;
  }

  if(ret == 0) {
    set_add_rowmode(lp, TRUE);  /* makes building the model faster if it is done rows by row */

    /* construct first row (120 x + 210 y <= 15000) */
    j = 0;

    colno[j] = 1; /* first column */
    row[j++] = 120;

    colno[j] = 2; /* second column */
    row[j++] = 210;

    /* add the row to lpsolve */
    if(!add_constraintex(lp, j, row, colno, LE, 15000))
      ret = 3;
  }

  if(ret == 0) {
    /* construct second row (110 x + 30 y <= 4000) */
    j = 0;

    colno[j] = 1; /* first column */
    row[j++] = 110;

    colno[j] = 2; /* second column */
    row[j++] = 30;

    /* add the row to lpsolve */
    if(!add_constraintex(lp, j, row, colno, LE, 4000))
      ret = 3;
  }

  if(ret == 0) {
    /* construct third row (x + y <= 75) */
    j = 0;

    colno[j] = 1; /* first column */
    row[j++] = 1;

    colno[j] = 2; /* second column */
    row[j++] = 1;

    /* add the row to lpsolve */
    if(!add_constraintex(lp, j, row, colno, LE, 75))
      ret = 3;
  }

  if(ret == 0) {
    set_add_rowmode(lp, FALSE); /* rowmode should be turned off again when done building the model */

    /* set the objective function (143 x + 60 y) */
    j = 0;

    colno[j] = 1; /* first column */
    row[j++] = 143;

    colno[j] = 2; /* second column */
    row[j++] = 60;

    /* set the objective in lpsolve */
    if(!set_obj_fnex(lp, j, row, colno))
      ret = 4;
  }

  if(ret == 0) {
    /* set the object direction to maximize */
    set_maxim(lp);

    /* just out of curioucity, now show the model in lp format on screen */
    /* this only works if this is a console application. If not, use write_lp and a filename */
    write_LP(lp, stdout);
    /* write_lp(lp, "model.lp"); */

    /* I only want to see important messages on screen while solving */
    set_verbose(lp, IMPORTANT);

    /* Now let lpsolve calculate a solution */
    ret = solve(lp);
    if(ret == OPTIMAL)
      ret = 0;
    else
      ret = 5;
  }

  if(ret == 0) {
    /* a solution is calculated, now lets get some results */

    /* objective value */
    printf("Objective value: %f\n", get_objective(lp));

    /* variable values */
    get_variables(lp, row);
    for(j = 0; j < Ncol; j++)
      printf("%s: %f\n", get_col_name(lp, j + 1), row[j]);

    /* we are done now */
  }

  /* free allocated memory */
  if(row != NULL)
    free(row);
  if(colno != NULL)
    free(colno);

  if(lp != NULL) {
    /* clean up such that all used memory by lpsolve is freed */
    delete_lp(lp);
  }

  return(ret);
}

int main()
{
  demo();
}

When this is run, the following is shown on screen:

/* Objective function */
max: +143 x +60 y;

/* Constraints */
+120 x +210 y <= 15000;
+110 x +30 y <= 4000;
+x +y <= 75;
Objective value: 6315.625000
x: 21.875000
y: 53.125000

Note that this example is very limited. It is also possible to set bounds on variables, ranges on constraints, define variables as integer, get more result information, changing solver options and parameters and much more. See lp_solve API reference for an overview of the API to do this.

Java

The example model can be formulated as follows in Java:

/* demo.java */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import lpsolve.*;

public class Demo {

	public Demo() {
	}

	public int execute() throws LpSolveException {
          LpSolve lp;
          int Ncol, j, ret = 0;

          /* We will build the model row by row
             So we start with creating a model with 0 rows and 2 columns */
          Ncol = 2; /* there are two variables in the model */

          /* create space large enough for one row */
          int[] colno = new int[Ncol];
          double[] row = new double[Ncol];

          lp = LpSolve.makeLp(0, Ncol);
          if(lp.getLp() == 0)
            ret = 1; /* couldn't construct a new model... */

          if(ret == 0) {
            /* let us name our variables. Not required, but can be useful for debugging */
            lp.setColName(1, "x");
            lp.setColName(2, "y");

            lp.setAddRowmode(true);  /* makes building the model faster if it is done rows by row */

            /* construct first row (120 x + 210 y <= 15000) */
            j = 0;

            colno[j] = 1; /* first column */
            row[j++] = 120;

            colno[j] = 2; /* second column */
            row[j++] = 210;

            /* add the row to lpsolve */
            lp.addConstraintex(j, row, colno, LpSolve.LE, 15000);
          }

          if(ret == 0) {
            /* construct second row (110 x + 30 y <= 4000) */
            j = 0;

            colno[j] = 1; /* first column */
            row[j++] = 110;

            colno[j] = 2; /* second column */
            row[j++] = 30;

            /* add the row to lpsolve */
            lp.addConstraintex(j, row, colno, LpSolve.LE, 4000);
          }

          if(ret == 0) {
            /* construct third row (x + y <= 75) */
            j = 0;

            colno[j] = 1; /* first column */
            row[j++] = 1;

            colno[j] = 2; /* second column */
            row[j++] = 1;

            /* add the row to lpsolve */
            lp.addConstraintex(j, row, colno, LpSolve.LE, 75);
          }

          if(ret == 0) {
            lp.setAddRowmode(false); /* rowmode should be turned off again when done building the model */

            /* set the objective function (143 x + 60 y) */
            j = 0;

            colno[j] = 1; /* first column */
            row[j++] = 143;

            colno[j] = 2; /* second column */
            row[j++] = 60;

            /* set the objective in lpsolve */
            lp.setObjFnex(j, row, colno);
          }

          if(ret == 0) {
            /* set the object direction to maximize */
            lp.setMaxim();

            /* just out of curioucity, now generate the model in lp format in file model.lp */
            lp.writeLp("model.lp");

            /* I only want to see important messages on screen while solving */
            lp.setVerbose(LpSolve.IMPORTANT);

            /* Now let lpsolve calculate a solution */
            ret = lp.solve();
            if(ret == LpSolve.OPTIMAL)
              ret = 0;
            else
              ret = 5;
          }

          if(ret == 0) {
            /* a solution is calculated, now lets get some results */

            /* objective value */
            System.out.println("Objective value: " + lp.getObjective());

            /* variable values */
            lp.getVariables(row);
            for(j = 0; j < Ncol; j++)
              System.out.println(lp.getColName(j + 1) + ": " + row[j]);

            /* we are done now */
          }

          /* clean up such that all used memory by lpsolve is freed */
          if(lp.getLp() != 0)
            lp.deleteLp();

          return(ret);
        }

	public static void main(String[] args) {
		try {
			new Demo().execute();
		}
		catch (LpSolveException e) {
			e.printStackTrace();
		}
	}
}

When this is run, the following is shown on screen:

Objective value: 6315.625
x: 21.875000000000007
y: 53.12499999999999

And a file model.lp is created with the following contents:

/* Objective function */
max: +143 x +60 y;

/* Constraints */
+120 x +210 y <= 15000;
+110 x +30 y <= 4000;
+x +y <= 75;

Note that this example is very limited. It is also possible to set bounds on variables, ranges on constraints, define variables as integer, get more result information, changing solver options and parameters and much more. See lp_solve API reference for an overview of the API to do this.

Also note that the API names in Java are a bit different than in the native lpsolve API and the lp argument is not there. See the lpsolve Java wrapper documentation for more details.

Delphi, Free Pascal

The example model can be formulated as follows in Delphi or Free Pascal:

program demo;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  lpsolve;

var
  Ncol, j, ret: integer;
  colno: PIntArray;
  row: PFloatArray;
  lp: THandle;

begin
  ret := 0;
  colno := nil;
  row := nil;

  (* We will build the model row by row
     So we start with creating a model with 0 rows and 2 columns *)
  Ncol := 2; (* there are two variables in the model *)
  lp := make_lp(0, Ncol);
  if (lp = 0) then
    ret := 1; (* couldn't construct a new model... *)
  (* let us name our variables. Not required, but can be usefull for debugging *)
  set_col_name(lp, 1, 'x');
  set_col_name(lp, 2, 'y');

  if (ret = 0) then
  begin
    (* create space large enough for one row *)
    GetMem(colno, SizeOf(integer) * Ncol);
    GetMem(row, SizeOf(double) * Ncol);
    if ((colno = nil) or (row = nil)) then
      ret := 2;
  end;

  if (ret = 0) then
  begin
    set_add_rowmode(lp, true);  (* makes building the model faster if it is done rows by row *)

    (* construct first row (120 x + 210 y <= 15000) *)
    j := 0;

    colno^[j] := 1; (* first column *)
    row^[j] := 120;
    j := j + 1;

    colno^[j] := 2; (* second column *)
    row^[j] := 210;
    j := j + 1;

    (* add the row to lp_solve *)
    if (not add_constraintex(lp, j, row, colno, LE, 15000)) then
      ret := 3;
  end;

  if (ret = 0) then
  begin
    (* construct second row (110 x + 30 y <= 4000) *)
    j := 0;

    colno^[j] := 1; (* first column *)
    row^[j] := 110;
    j := j + 1;

    colno^[j] := 2; (* second column *)
    row^[j] := 30;
    j := j + 1;

    (* add the row to lp_solve *)
    if (not add_constraintex(lp, j, row, colno, LE, 4000)) then
      ret := 3;
  end;

  if (ret = 0) then
  begin
    (* construct third row (x + y <= 75) *)
    j := 0;

    colno^[j] := 1; (* first column *)
    row^[j] := 1;
    j := j + 1;

    colno^[j] := 2; (* second column *)
    row^[j] := 1;
    j := j + 1;

    (* add the row to lp_solve *)
    if (not add_constraintex(lp, j, row, colno, LE, 75)) then
      ret := 3;
  end;

  if (ret = 0) then
  begin
    set_add_rowmode(lp, false); (* rowmode should be turned off again when done building the model *)

    (* set the objective function (143 x + 60 y) *)
    j := 0;

    colno^[j] := 1; (* first column *)
    row^[j] := 143;
    j := j + 1;

    colno^[j] := 2; (* second column *)
    row^[j] := 60;
    j := j + 1;

    (* set the objective in lp_solve *)
    if (not set_obj_fnex(lp, j, row, colno)) then
      ret := 4;
  end;

  if (ret = 0) then
  begin
    (* set the object direction to maximize *)
    set_maxim(lp);

    (* just out of curioucity, now show the model in lp format *)
    write_lp(lp, 'model.lp');

    (* I only want to see importand messages on screen while solving *)
    set_verbose(lp, IMPORTANT);

    (* Now let lp_solve calculate a solution *)
    ret := solve(lp);
    if (ret = OPTIMAL) then
      ret := 0
    else
      ret := 5;
  end;

  if (ret = 0) then
  begin
    (* a solution is calculated, now lets get some results *)

    (* objective value *)
    writeln(format('Objective value: %f', [get_objective(lp)]));

    (* variable values *)
    get_variables(lp, row);
    for j := 0 to Ncol-1 do
      writeln(format('%s: %f', [get_col_name(lp, j + 1), row^[j]]));

    (* we are done now *)
  end;

  (* free allocated memory *)
  if (row <> nil) then
    FreeMem(row);
  if (colno <> nil) then
    FreeMem(colno);

  if(lp <> 0) then
  begin
    (* clean up such that all used memory by lp_solve is freeed *)
    delete_lp(lp);
  end;
end.

When this is run, the following is shown:

Objective value: 6315.63
x: 21.88
y: 53.12

And a file model.lp is created with the following contents:

/* Objective function */
max: +143 x +60 y;

/* Constraints */
+120 x +210 y <= 15000;
+110 x +30 y <= 4000;
+x +y <= 75;

Note that a unit lpsolve.pas+lpsolve.inc is needed for this to work. This is available via the Delphi example.

Note that this example is very limited. It is also possible to set bounds on variables, ranges on constraints, define variables as integer, get more result information, changing solver options and parameters and much more. See lp_solve API reference for an overview of the API to do this.

VB, VBScript

The example model can be formulated as follows in VB or VBScript:

Option Explicit

'demo

Private lpsolve As lpsolve55

Sub Main()

    Set lpsolve = New lpsolve55

    lpsolve.Init "."

    Demo

    Set lpsolve = Nothing

End Sub

Private Function Demo() As Integer
    Dim lp As Long
    Dim Ncol As Long, colno() As Long
    Dim j As Integer, ret As Integer
    Dim row() As Double

    With lpsolve
        ' We will build the model row by row
        ' So we start with creating a model with 0 rows and 2 columns
        Ncol = 2 ' there are two variables in the model
        lp = .make_lp(0, Ncol)
        If lp = 0 Then
            ret = 1 ' couldn't construct a new model...
        End If

        If ret = 0 Then
            ' let us name our variables. Not required, but can be useful for debugging
            .set_col_name lp, 1, "x"
            .set_col_name lp, 2, "y"
            ' create space large enough for one row
            ReDim colno(0 To Ncol - 1)
            ReDim row(0 To Ncol - 1)
        End If

        If ret = 0 Then
            .set_add_rowmode lp, True  ' makes building the model faster if it is done rows by row

            ' construct first row (120 x + 210 y <= 15000)
            j = 0

            colno(j) = 1  ' first column
            row(j) = 120
            j = j + 1

            colno(j) = 2 ' second column
            row(j) = 210
            j = j + 1

            ' add the row to lpsolve
            If .add_constraintex(lp, j, row(0), colno(0), LE, 15000) = False Then
                ret = 3
            End If
        End If

        If ret = 0 Then
            ' construct second row (110 x + 30 y <= 4000)
            j = 0

            colno(j) = 1 ' first column
            row(j) = 110
            j = j + 1

            colno(j) = 2 ' second column
            row(j) = 30
            j = j + 1

            ' add the row to lpsolve
            If .add_constraintex(lp, j, row(0), colno(0), LE, 4000) = False Then
                ret = 3
            End If
        End If

        If ret = 0 Then
            ' construct third row (x + y <= 75)
            j = 0

            colno(j) = 1 ' first column
            row(j) = 1
            j = j + 1

            colno(j) = 2 ' second column
            row(j) = 1
            j = j + 1

            ' add the row to lpsolve
            If .add_constraintex(lp, j, row(0), colno(0), LE, 75) = False Then
                ret = 3
            End If
        End If

        If ret = 0 Then
            .set_add_rowmode lp, False ' rowmode should be turned off again when done building the model

            ' set the objective function (143 x + 60 y)
            j = 0

            colno(j) = 1 ' first column
            row(j) = 143
            j = j + 1

            colno(j) = 2 ' second column
            row(j) = 60
            j = j + 1

            ' set the objective in lpsolve
            If .set_obj_fnex(lp, j, row(0), colno(0)) = False Then
                ret = 4
            End If
        End If

        If ret = 0 Then
            ' set the object direction to maximize
            .set_maxim lp

            ' just out of curioucity, now show the model in lp format on screen
            ' this only works if this is a console application. If not, use write_lp and a filename
            .write_lp lp, "model.lp"

            ' I only want to see important messages on screen while solving
            .set_verbose lp, 3

            ' Now let lpsolve calculate a solution
            ret = .solve(lp)
            If ret = OPTIMAL Then
                ret = 0
            Else
                ret = 5
            End If
        End If

        If ret = 0 Then
            ' a solution is calculated, now lets get some results

            ' objective value
            Debug.Print "Objective value: " & .get_objective(lp)

            ' variable values
            .get_variables lp, row(0)
            For j = 1 To Ncol
                Debug.Print .get_col_name(lp, j) & ": " & row(j - 1)
            Next

            ' we are done now
        End If

        ' free allocated memory
        Erase row
        Erase colno

        If lp <> 0 Then
            ' clean up such that all used memory by lpsolve is freed
            .delete_lp lp
        End If

        Demo = ret
    End With

End Function

When this is run, the following is shown in the debug window:

Objective value: 6315.625
x: 21.875
y: 53.125

And a file model.lp is created with the following contents:

/* Objective function */
max: +143 x +60 y;

/* Constraints */
+120 x +210 y <= 15000;
+110 x +30 y <= 4000;
+x +y <= 75;

Note that a class lpsolve55.cls or the lpsolve55 COM object is needed for this to work. The class is available via the VB example and the COM object is also available.

Note that this example is very limited. It is also possible to set bounds on variables, ranges on constraints, define variables as integer, get more result information, changing solver options and parameters and much more. See lp_solve API reference for an overview of the API to do this.

VB.NET

The example model can be formulated as follows in VB.NET:

Option Strict Off
Option Explicit On
Module Module1

  'demo

  Private lpsolve As lpsolve55

  Public Sub Main()

    lpsolve = New lpsolve55

    lpsolve.Init(".")

    Demo()

    lpsolve = Nothing

  End Sub

  Private Function Demo() As Integer
    Dim lp As Integer
    Dim Ncol As Integer
    Dim colno() As Integer
    Dim j, ret As Short
    Dim row() As Double

    With lpsolve
      ' We will build the model row by row
      ' So we start with creating a model with 0 rows and 2 columns
      Ncol = 2 ' there are two variables in the model
      lp = .make_lp(0, Ncol)
      If lp = 0 Then
        ret = 1 ' couldn't construct a new model...
      End If

      If ret = 0 Then
        ' let us name our variables. Not required, but can be useful for debugging
        .set_col_name(lp, 1, "x")
        .set_col_name(lp, 2, "y")
        ' create space large enough for one row
        ReDim colno(Ncol - 1)
        ReDim row(Ncol - 1)
      End If

      If ret = 0 Then
        .set_add_rowmode(lp, True) ' makes building the model faster if it is done rows by row

        ' construct first row (120 x + 210 y <= 15000)
        j = 0

        colno(j) = 1 ' first column
        row(j) = 120
        j = j + 1

        colno(j) = 2 ' second column
        row(j) = 210
        j = j + 1

        ' add the row to lpsolve
        If .add_constraintex(lp, j, row(0), colno(0), lpsolve55.lpsolve_constr_types.LE, 15000) = False Then
          ret = 3
        End If
      End If

      If ret = 0 Then
        ' construct second row (110 x + 30 y <= 4000)
        j = 0

        colno(j) = 1 ' first column
        row(j) = 110
        j = j + 1

        colno(j) = 2 ' second column
        row(j) = 30
        j = j + 1

        ' add the row to lpsolve
        If .add_constraintex(lp, j, row(0), colno(0), lpsolve55.lpsolve_constr_types.LE, 4000) = False Then
          ret = 3
        End If
      End If

      If ret = 0 Then
        ' construct third row (x + y <= 75)
        j = 0

        colno(j) = 1 ' first column
        row(j) = 1
        j = j + 1

        colno(j) = 2 ' second column
        row(j) = 1
        j = j + 1

        ' add the row to lpsolve
        If .add_constraintex(lp, j, row(0), colno(0), lpsolve55.lpsolve_constr_types.LE, 75) = False Then
          ret = 3
        End If
      End If

      If ret = 0 Then
        .set_add_rowmode(lp, False) ' rowmode should be turned off again when done building the model

        ' set the objective function (143 x + 60 y)
        j = 0

        colno(j) = 1 ' first column
        row(j) = 143
        j = j + 1

        colno(j) = 2 ' second column
        row(j) = 60
        j = j + 1

        ' set the objective in lpsolve
        If .set_obj_fnex(lp, j, row(0), colno(0)) = False Then
          ret = 4
        End If
      End If

      If ret = 0 Then
        ' set the object direction to maximize
        .set_maxim(lp)

        ' just out of curioucity, now show the model in lp format on screen
        ' this only works if this is a console application. If not, use write_lp and a filename
        .write_lp(lp, "model.lp")

        ' I only want to see important messages on screen while solving
        .set_verbose(lp, 3)

        ' Now let lpsolve calculate a solution
        ret = .solve(lp)
        If ret = lpsolve55.lpsolve_return.OPTIMAL Then
          ret = 0
        Else
          ret = 5
        End If
      End If

      If ret = 0 Then
        ' a solution is calculated, now lets get some results

        ' objective value
        System.Diagnostics.Debug.WriteLine("Objective value: " & .get_objective(lp))

        ' variable values
        .get_variables(lp, row(0))
        For j = 1 To Ncol
          System.Diagnostics.Debug.WriteLine(.get_col_name(lp, j) & ": " & row(j - 1))
        Next

        ' we are done now
      End If

      ' free allocated memory
      Erase row
      Erase colno

      If lp <> 0 Then
        ' clean up such that all used memory by lpsolve is freed
        .delete_lp(lp)
      End If

      Demo = ret
    End With

  End Function
End Module

When this is run, the following is shown in the debug window:

Objective value: 6315.625
x: 21.875
y: 53.125

And a file model.lp is created with the following contents:

/* Objective function */
max: +143 x +60 y;

/* Constraints */
+120 x +210 y <= 15000;
+110 x +30 y <= 4000;
+x +y <= 75;

Note that a class lpsolve55.vb is needed for this to work. The class is available via the VB.NET example.

Note that this example is very limited. It is also possible to set bounds on variables, ranges on constraints, define variables as integer, get more result information, changing solver options and parameters and much more. See lp_solve API reference for an overview of the API to do this.

C#.NET

The example model can be formulated as follows in C#.NET:

using System.Windows.Forms;
using lpsolve55;

/* demo.cs */

namespace demo
{
  public class demo
  {
    public static void Main()
    {
      lpsolve.Init(".");

      Demo();
    }

    private static int Demo()
    {
      int lp;
      int Ncol;
      int[] colno;
      int j, ret = 0;
      double[] row;

      /* We will build the model row by row */
      /* So we start with creating a model with 0 rows and 2 columns */
      Ncol = 2; /* there are two variables in the model */
      lp = lpsolve.make_lp(0, Ncol);
      if (lp == 0)
        ret = 1; /* couldn't construct a new model... */

      if (ret == 0) {
        /* let us name our variables. Not required, but can be useful for debugging */
        lpsolve.set_col_name(lp, 1, "x");
        lpsolve.set_col_name(lp, 2, "y");
      }

      /* create space large enough for one row */
      colno = new int[Ncol];
      row = new double[Ncol];

      if (ret == 0) {
        lpsolve.set_add_rowmode(lp, true); /* makes building the model faster if it is done rows by row */

        /* construct first row (120 x + 210 y <= 15000) */
        j = 0;

        colno[j] = 1; /* first column */
        row[j++] = 120;

        colno[j] = 2; /* second column */
        row[j++] = 210;

        /* add the row to lpsolve */
        if (lpsolve.add_constraintex(lp, j, ref row[0], ref colno[0], lpsolve.lpsolve_constr_types.LE, 15000) == false)
          ret = 3;
      }

      if (ret == 0) {
        /* construct second row (110 x + 30 y <= 4000) */
        j = 0;

        colno[j] = 1; /* first column */
        row[j++] = 110;

        colno[j] = 2; /* second column */
        row[j++] = 30;

        /* add the row to lpsolve */
        if (lpsolve.add_constraintex(lp, j, ref row[0], ref colno[0], lpsolve.lpsolve_constr_types.LE, 4000) == false)
          ret = 3;
      }

      if (ret == 0) {
        /* construct third row (x + y <= 75) */
        j = 0;

        colno[j] = 1; /* first column */
        row[j++] = 1;

        colno[j] = 2; /* second column */
        row[j++] = 1;

        /* add the row to lpsolve */
        if (lpsolve.add_constraintex(lp, j, ref row[0], ref colno[0], lpsolve.lpsolve_constr_types.LE, 75) == false)
          ret = 3;
      }

      if (ret == 0) {
        lpsolve.set_add_rowmode(lp, false); /* rowmode should be turned off again when done building the model */

        /* set the objective function (143 x + 60 y) */
        j = 0;

        colno[j] = 1; /* first column */
        row[j++] = 143;

        colno[j] = 2; /* second column */
        row[j++] = 60;

        /* set the objective in lpsolve */
        if (lpsolve.set_obj_fnex(lp, j, ref row[0], ref colno[0]) == false)
          ret = 4;
      }

      if (ret == 0) {
        lpsolve.lpsolve_return s;

        /* set the object direction to maximize */
        lpsolve.set_maxim(lp);

        /* just out of curioucity, now show the model in lp format on screen */
        /* this only works if this is a console application. If not, use write_lp and a filename */
        lpsolve.write_lp(lp, "model.lp");

        /* I only want to see important messages on screen while solving */
        lpsolve.set_verbose(lp, 3);

        /* Now let lpsolve calculate a solution */
        s = lpsolve.solve(lp);
        if (s == lpsolve.lpsolve_return.OPTIMAL)
          ret = 0;
        else
          ret = 5;
      }

      if (ret == 0) {
        /* a solution is calculated, now lets get some results */

        /* objective value */
        System.Diagnostics.Debug.WriteLine("Objective value: " + lpsolve.get_objective(lp));

        /* variable values */
        lpsolve.get_variables(lp, ref row[0]);
        for(j = 0; j < Ncol; j++)
          System.Diagnostics.Debug.WriteLine(lpsolve.get_col_name(lp, j + 1) + ": " + row[j]);

        /* we are done now */
      }

      /* free allocated memory */

      if (lp != 0) {
        /* clean up such that all used memory by lpsolve is freed */
        lpsolve.delete_lp(lp);
      }

      return(ret);
    } //Demo
  }
}

When this is run, the following is shown in the debug window:

Objective value: 6315.625
x: 21.875
y: 53.125

And a file model.lp is created with the following contents:

/* Objective function */
max: +143 x +60 y;

/* Constraints */
+120 x +210 y <= 15000;
+110 x +30 y <= 4000;
+x +y <= 75;

Note that a class lpsolve55.cs is needed for this to work. The class is available via the CS.NET example.

Note that this example is very limited. It is also possible to set bounds on variables, ranges on constraints, define variables as integer, get more result information, changing solver options and parameters and much more. See lp_solve API reference for an overview of the API to do this.

doc/is_lag_trace.htm0000644000175000017500000000436510237176660013435 0ustar renerene is_lag_trace

is_lag_trace

Returns a flag if Lagrangian progression must be printed while solving.

unsigned char is_lag_trace(lprec *lp);

Return Value

is_lag_trace returns TRUE or FALSE. Print or do not print.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_lag_trace function returns a flag if Lagrangian progression must be printed while solving. This function is mend for debugging purposes. The default is not to print (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char lag_trace;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  lag_trace = is_lag_trace(lp); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_lag_trace

doc/FAQ.htm0000644000175000017500000006325611235624134011425 0ustar renerene lp_solve Frequently Asked Questions

lp_solve Frequently Asked Questions

- Where can I find the latest version of lp_solve?
There is a yahoo group (http://groups.yahoo.com/group/lp_solve/) that bundles all activities of the lp_solve community. You have to register but this is for free. You will find there the latest sources, examples and manuals.

- Can I use lp_solve in commercial code?
Yes you can. However read the GNU LESSER GENERAL PUBLIC LICENSE which you can find in LGPL.txt

- Please explain what this LGPL license exactly means. I don't understand it.
The LGPL is as clear as fog on what is allowed, what is not, and what is commercial. We use the following structure for determining the applicability of LGPL for a particular setting (which nobody has disagreed with yet):

The LGPL "decision tree/truth table" essentially consists of the following structure:

               lp_solve used
                as compiled
                 library?
                 Yes    No
                -----------
lp_solve   Yes |  B1 |  B2 |
code was       |-----|-----|
modified?   No |  A  |  B3 |
                -----------

A: "Work that uses the library"
B: "Work based on the library"

Case A: Since no lp_solve code has been changed and it is used purely as a library based on distributed original code, only conspicuously placed copyright/citation information and the reference to where the source may be obtained is necessary. No part of your own code has to be provided and it can be protected and licensed as you wish.

Case B1: The full code of the modified lp_solve library has to be distributed or made very easily available with full credits and license information (optionally LGPL or GPL). Your own source code does *not* have to be included and it can be protected and licensed as you wish.

Case B2: The full code of the modified lp_solve library has to be distributed or made very easily available with full credits and license information (optionally LGPL or GPL). Your own code *has* to be made public/reverse engineer-able and be licensed under either LGPL or GPL.

Case B3: Since no lp_solve code has been changed and it is used as a linked-in library based on distributed original code, only conspicuously placed copyright information and the reference to where the source may be obtained is necessary. Your own code *has* to be made public/reverse engineer-able and be licensed under either LGPL or GPL.

You have to make a judicious determination based on this. If your code falls under the categories B2 or B3, and the terms are unacceptable to you (or the company you represent), then our interpretation of the LGPL is that you have to find a suitable commercial arrangement/licensing with the copyright holders of lp_solve. If this is applicable to you, then you can address any mail about licensing/copyrights to us we will resolve this.

- But how much does lp_solve costs me?

lp_solve is totally free - gratis - if you follow the rules of the LGPL. You may of course ask money for code you have developed or added, but only for that part, and the openness provisions of the LGPL have to be respected. If you are not willing to respect this, then the only recourse is that you seek an agreement with the copyright holders of the appropriate parts of lp_solve.

- How should lp_solve be cited when I use it?

lpsolve citation data
----------------------
Description     : Open source (Mixed-Integer) Linear Programming system
Language        : Multi-platform, pure ANSI C / POSIX source code, Lex/Yacc based parsing
Official name   : lp_solve (alternatively lpsolve)
Release data    : Version 5.1.0.0 dated 1 May 2004
Co-developers   : Michel Berkelaar, Kjell Eikland, Peter Notebaert
Licence terms   : GNU LGPL (Lesser General Public Licence)
Citation policy : General references as per LGPL
                  Module specific references as specified therein
This text is also in citations.txt

- What are the default bounds on variables?
As all (at least, simplex) lp solvers, the default lower bound on a variable is 0 and the default upper bound is unlimited.

- Is it possible to set negative bounds on variables?
Yes, this is perfectly possible.

- Is it possible to set a minus infinite lower bound on a variable?
Yes, this is possible. In the lp format, use as lower bound -Inf. In the mps format, in the BOUNDS section use FR
If you use the API interface, use get_infinite(lp)
Note that lp_solve splits this variable in 2 if there is a positive or no upper bound. This is done automatically by lp_solve. Because of this, the model becomes larger and thus can take some more time to solve, so only put a minus infinity lower bound on a variable when it is needed.

- What is the layout of the lp/mps/CPLEX format?
See the help file

- When I call the API call solve(), several messages are printed on screen. How can I disable those messages?
Use the set_verbose API call. The default is NORMAL (4). Changing this to IMPORTANT (3) already disables a lot of messages.

- lp_solve fails to solve my model or it takes a very long time to solve my model. What can I do?
lp_solve has a lot of options. Consider to use the following:

  1. Use the LUSOL bfp. See Basis Factorization Packages. This will improve speed and numerical stability considerably. This bfp will probably be the default in a later lp_solve version.
  2. Use scaling. See scaling and set_scaling. This will improve numerical stability and even performance considerably.
  3. Use presolve. Presolve eliminates variables and constraints where possible. This makes the model smaller so that it is solved faster. But presolve also takes some time, so it depends on the model if the total time is faster or even slower.
  4. If the model has integer variables, look at branching options and tolerance gaps. Especially, look at the following API calls: set_mip_gap, set_break_at_first set_break_at_value set_bb_floorfirst set_bb_depthlimit set_solutionlimit set_bb_rule
If you use the lp_solve command line program, each of these options can be set via a command line option. See lp_solve -h or lp_solve command.

- Can lp_solve handle non-linear equations?
No, lp_solve can only handle linear constraints. However it also supports integer and semi-continuous variables and special ordered sets. This can be a help to simulate non-linearity.

- Can lp_solve handle ratios?
Ratios can be converted to linear equations. See the help file.

- I get a parse error on my lp-file, but I don't see any error in the formulation I have done. What is wrong here?
Have you entered your model via Word? Then the problem will probably be that some characters have ascii codes that are not recognised by lp_solve. For example, Word changes the minus sign (-) to another character that also looks like a minus sign, but it is a bit longer. The ascii code of this character is different from the ascii code of the real minus sign and lp_solve has problem with it. However you see a - on screen. The solution is not to use Word to enter your lp-model. Notepad should be ok. Better is to use the LPSolve IDE.

- lp_solve prints the output on screen. Can I have the output also in a file?
Yes, you can use standard redirection for that. Use the > before the filename to do that.
For example:
lp_solve input.lp >output.txt

- I have a constraint saying that x < 2, but lp_solve comes with a solution of 2, how comes?
< is the same as as <=
also > is the same as >=
This makes more than sense. Mathematically, 1.99999999999999999999999999999999999999999999999999 is smaller than 2, but what is the practical difference with 2? You always have to consider rounding errors also... If the variable is defined as integer then just say x <= 1

- When I solve my model, I get a stack overflow error/core dump/protection error. What is wrong?
If your model has integer/binary/semi-cont/SOS variables then version 5 can solve your problem. In version 4, the implemented branch-and-bound algorithm puts its branches on the stack and that can result in a stack overflow when it is a tough model. Version 5 doesn't put the branches on the stack anymore and because of that, this error is solved.

- Version 4 solves my models slower than version 3 did. What can I do?
Some models are indeed slower with version 4. Version 5 has several enhancements and is faster and more stable. Also version 4 always calculates the sensitivity information while older versions did not have this feature. This also takes some time. Version 5 only calculates the sensitivity when this information is specifically asked that makes it again faster.

- It takes a long time to build the model via the API interface. Especially add_constraint, add_constraintex, str_add_constraint seems to be slow. How can it be made faster?
Version 5 has a new API call set_add_rowmode that makes add_constraint, str_add_constraint spectacular faster.
If the model is build column by column, then it is strongly suggested to use add_columnex instead of add_column because add_columnex gives the possibility to only supply the non-zero elements and that speeds up building the model considerably, especially if the matrix is sparse (a lot of zero elements).
If the model is build row by row, then it is strongly suggested to use add_constraintex instead of add_constraint because add_constraintex gives the possibility to only supply the non-zero elements and that speeds up building the model considerably, especially if the matrix is sparse (a lot of zero elements).

- Can lp_solve give me the 'simplex tableau' of the model?
Version 5 has a new routine (print_tableau) to give you this information.

- Is there documentation about the API interface?
Yes, there are html (help) files. See the Files section in the yahoo group.

- What is the maximum number of rows/columns that lp_solve can handle?
There is no fixed limit. Only available memory is a limit.

- I use a programming language that is not listed as supported or for which there are no examples. Can lp_solve be called from this language?
If this language allows calling functions from a C-dll, then it is possible. It is not because there is no example provided (yet) that it is not possible. The lp_solve community is always interested in your interface to call the lp_solve library. It doesn't have to be perfect.

- The Windows examples don't work. I get an error running them. Some dll cannot be found.
The examples call a dll that contains the lp_solve routines. This dll is called lpsolve*.dll and must be on the system either in the directory of the application or somewhere in the path.
This dll is contained in the windows binaries archive in the files section.

- Does lp_solve supports the mps free format?
This is possible from version 5.0.10.0. Before it was not possible. See read_freeMPS or the -fmps and -wfmps options to the lp_solve program. There is also a utility LPx2D that allows to convert this format. See the Files section.

- Does the lp_solve lp format support comments?
Yes it does. Put the comments between /* */
It can be anywhere in the text, even over multiple lines. Just like in C
lp_solve 4.0.1.11 and newer also supports the C++ line comment //

- I want to compile lp_solve myself, but I get link errors. Also what should I do with lp.y, lex.l, lp_rlp.y, lp_rlp.l?
The .y files are yacc files. They can be translated to C via the bison or yacc commands.
The .l files are lex files. They can be translated to C via the flex or lex commands.
lp.y/lex.l were used in version 4. Version 5 use the names lp_rlp.y/lp_rlp.l All unix environments have these commands. There are also windows versions available.
For example at http://unxutils.sourceforge.net/
Also only include lp.c in your compile project, not lex.c. lex.c is automatically #included by lp.c
Version 5 doesn't use the .c extension for the translated lex file. Instead it uses the .h extension. That way there is no confusion. So you don't have to (and may not) include it yourself again in the project.
To compile lp_solve, you must use make or gmake and a Makefile. There are several example makefiles in the source included like Makefile.linux, Makefile.msc. Enter make or gmake -f makefile. Note that for WINDOWS, you must use gnu make because MS make hasn't enough functionality. You can find gmake at http://unxutils.sourceforge.net/

- I compile lp_solve myself, but I get link errors saying that main (or _main) is already defined.
demo.c, mps2lp.c, lp2mps.c, lp_solve.c may never be in the same project. You must use one of these with the other C source files (except lex.c, see above) to make either demo.exe, mps2lp.exe, lp2mps.exe, lp_solve.exe

- I want to use the lpsolve dll, but when I compile my C/C++ program, I get link errors. He doesn't find any of the lpsolve API routines. What am I doing wrong?
Each function that you use in a C/C++ application must be defined. The compiler gives a warning if he doesn't find a definition of a function and the linker gives an error if he doesn't find an implementation for each used function. The implementation of a function can be in your source code, in another source file or in a library. If the function is in the same source code and defined before it is called, then you get no compiler warning because it is declared implicitly. If the function is after you call it, in another source file or in a library, then your source code must have a definition of this function or the compiler will give a warning. This is because the compiler wants to check if the function is correctly called (correct number of arguments, correct return code, should there be done some implicit conversion, ...). It is common to define these declarations in a header (.h) file. That is the reason why you include stdio.h, stdlib.h, string.h, windows.h and so on. For lpsolve, this library is lp_lib.h (lpkit.h in version 4 and before). Because lp_lib.h and lpkit.h also include other header files, you need these also. Including these source files do not guarantee that the linker will not give an error. This because the linker not only wants the definition of the functions, it also needs the implementation of it. So all routine calls that you do must be found somewhere by the linker. These can be in one of your source files and if they are not static defined then it is ok for the linker, or they are in a library. For example the function printf is a function from a library. This library can be linked statically or dynamically with your program. In Visual C, for the standard libraries this is defined via one of the compiler options /MT, /MD, /ML (in .NET via project, properties, C/C++, Code generation, Runtime Library. In VC6 via Project, settings, C/C++, category code generation, use runtime library). This results in using one of the libraries LIBC*.lib or MSVCRT*.lib. If you use static linking, then these routines are linked at link time with your program so that this program runs without the need of any other file. So these routines are then in LIBC.lib (the static libraries). If you use dynamic linking (MSVCRT.lib), then this library contains minimal code (not the implementation of this function) to call a library (a dll) at runtime. For example MSVCRT.DLL. So this dll must be on the system when you *run* the application. You will see that the resulting exe is smaller when dynamically linked compared to statically linked. This is logical because the implementation of the routine is in the DLL. The advantage of a DLL is that you can have a new implementation of it and use it in your application without having to rebuild your application. This because the DLL is linked at runtime with your program. Off course, the interface should stay the same for that. Also see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_c_run.2d.time_libraries.asp for an explanation on the VC runtime libraries.
Now besides the standard libraries there are also additional libraries. For example odbc32.lib is one that provides an API to access ODBC, or ws2_32.lib that contains the winsock/TCP/IP API calls and so on. These are all dynamic linked libraries, so the implementation is in a DLL. You must specify the library to the linker so that he knows how to call the implemented DLL (how it is called, ...).

Now if you want to use the lpsolve dll, you must also specify the lpsolve library to the linker so that you don't get the link errors. For version 5, this library is called lpsolve51.lib. You must specify it via Project, Properties, Linker, Input, Additional Dependencies (.NET) or Project, Settings, Link, Category General, Object Library Modules (VC6). There you add lpsolve51.lib (if there are already other libraries, just add at the end, separated via a space). You can specify the path where this file is located or you can specify via Project, Properies, Linker, General, Additional Library Directories (.NET) or Project, Settings, Link, Category Input, Additional library path, the paths where libraries can be found (separated by ,). Basically that is it. Also see Calling the lpsolve API from your application for more information.

- lp.c and lex.c that are generated on my system are different from the versions that can be found in the support folder in the files section. Are the latest versions of these files on your site?
Depending on the platform, the command used and the version of the command, these files are indeed different. That is not a problem. You can compare this with a compiler. The same source code generates totally different binaries, depending on the compiler used and its version, but the programs react the same (at least, they should ...).

- When I start the lp_solve program, nothing happens. I just get a blinking cursor. If I enter a command like lp1 = make_lp(0,4), I get a parse error. What is wrong here? How do I use the program?
lp_solve is a library with a set of routines with purpose to solve a MIP model. These routines are sometimes referred as the API (Application Programming Interface). These routines can be used in a C-program to solve MIP models. This is for example demonstrated in the demo program. Under Windows there is also a dll available that can be used by other programming languages to call the API functions. There are demos in VB and .NET available, but the principle is the same. The lp_solve program is basically another 'demo' program of this api. This program reads the MIP model from standard input or from a file and outputs the result back to the console or to a file. There are two possible input formats: the 'lp' format and the 'mps' format. This has nothing to do with the API. So lp1 = make_lp(0,4) is a totally wrong input for the lp_solve program. The lp-format is a 'readable' format of a MIP model.
For example:

max: -x1 + 2 x2;
C1: 2x1 + x2 <= 5;
-4 x1 + 4 x2 <= 5;

int x2,x1;

This lp-format is the default format of the lp_solve program.

The other format is mps format. This is a totally different format and used by many MIP solvers. This format is not very readable for us humans. The same example as above in mps format looks like this:

ROWS
 N  r_0
 L  C1
 L  r_2
COLUMNS
    MARK0000  'MARKER'                 'INTORG'
    x1        r_0                  1   C1                   2
    x1        r_2                 -4
    x2        r_0                 -2   C1                   1
    x2        r_2                  4
    MARK0001  'MARKER'                 'INTEND'
RHS
    RHS       C1                   5   r_2                  5
ENDATA

To enable this input format in the lp_solve program, use the -mps option.

The lp_solve program has many other options to control many other things like the amount of data to output, if scaling must be used and so on.

There are two other 'demo' programs: lp2mps and mps2lp. They convert model files from one format to the other.

The lp_solve, lp2mps and mps2lp programs all use API calls of the lp_solve library to perform their actions.

If lp_solve is started without an input file, then it gives a blinking cursor and waits for input. It is now possible to enter the model in the specified format (lp by default). But this is not very handy. You must enter the whole model each time you want to solve it and must be careful that you don't type any errors. To stop input mode, press Ctrl Z.
However it is much better to write your model in a disk file with your favourite editor (make sure it is in text format) and then provide this file to lp_solve. For example:

lp_solve input.lp

It is also possible to use input redirection:

lp_solve <input.lp

Or more sophisticated constructs like:

gen_model | lp_solve

gen_model is here a user written program that outputs the model to standard output and via the pipe character (|) this output is redirected to lp_solve. So no intermediate file is needed in this case.

- Is there no more user-friendly interface than the lp_solve command line program?
Yes there is, thanks to Henri Gourvest. For version 5 there is now the LPSolve IDE, a Windows interface to the lpsolve library. See LPSolve IDE for more information.

doc/has_XLI.htm0000644000175000017500000000426610237176656012315 0ustar renerene has_XLI

has_XLI

Returns if there is an external language interface (XLI) set.

unsigned char has_XLI(lprec *lp);

Return Value

has_XLI returns TRUE if there is an XLI set, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

See External Language Interfaces for a complete description on XLIs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char hasXLI;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  hasXLI = has_XLI(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_XLI, is_nativeXLI, set_XLI

doc/put_bb_branchfunc.htm0000644000175000017500000000703710311110422014435 0ustar renerene put_bb_branchfunc

put_bb_branchfunc

Specifies a user function to select a B&B branching, given the column to branch on.

void put_bb_branchfunc(lprec *lp, lphandleint_intfunc newbranch, void *bb_branchhandle);

Return Value

put_bb_branchfunc has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

newbranch

The branch routine.

typedef int (__WINAPI lphandleint_intfunc)(lprec *lp, void *bb_branchhandle, int column);

The routine must return TRUE if first the floor branch must be taken and FALSE if first the ceiling branch must be taken for the specified column.
Note the __WINAPI attribute. This is important under Windows. It ensures __stdcall calling convention which is required.

bb_branchhandle

A parameter that will be provided to the branch routine.

Remarks

Specifies a user function to select a B&B branching, given the column to branch on. With this function you can specify which branch must be taken first in the B&B algorithm. The floor or the ceiling. This overrules the setting of set_bb_floorfirst.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int __WINAPI branchfunction(lprec *lp, void *bb_branchhandle, int column)
{
 int branch;

 /* set branch to TRUE or FALSE to specify to branch first on the floor or ceiling branch */

 return(branch);
}

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  put_bb_branchfunc(lp, branchfunction, NULL);

  solve(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_bb_floorfirst, get_bb_floorfirst, set_var_branch, get_var_branch, set_var_weights, get_var_priority

doc/set_BFP.htm0000644000175000017500000000560710237176662012305 0ustar renerene set_BFP

set_BFP

Set basis factorization package.

unsigned char set_BFP(lprec *lp, char *filename);

Return Value

set_BFP returns TRUE if the call has succeeded, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

filename

The name of the BFP package. Currently following BFPs are implemented:

"bfp_etaPFI" original lp_solve product form of the inverse.
"bfp_LUSOL" LU decomposition.
"bfp_GLPK" GLPK LU decomposition.
NULL The default BFP package.
However the user can also build his own BFP packages ...

Remarks

The set_BFP function sets the basis factorization package (BFP). See Basis Factorization Packages for a complete description on BFPs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_BFP(lp, "bfp_LUSOL");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, has_BFP, is_nativeBFP

doc/open.gif0000644000175000017500000000107211034166173011721 0ustar renereneGIF89a   0 00 @80`H PH@^YY`X@vgIp`Ph p x pPx``kp̙А 000ШPаp@@PPPf`ppúƷȀЀ؀؀Р!, DD.4:BBA?-5-@??'*++>?9%*>00,,+(+ Absolute values

Absolute values

Constraints

Linear constraints are of the form:

a1 x1 + a2 x2 + a3 x3 + ... <= maximum
a1 x1 + a2 x2 + a3 x3 + ... >= minimum

Where minimum and maximum are constants.

lp_solve can only handle these kind of Linear equations. So what if absolute values must be formulated:

abs(a1 x1 + a2 x2 + a3 x3) = 0
abs(a1 x1 + a2 x2 + a3 x3) <= maximum
abs(a1 x1 + a2 x2 + a3 x3) >= minimum

= 0 (or <= 0)

This is the easiest case. If abs(X) must be equal to zero, then this can only be fulfilled if X is zero. So the condition can also be written as:

a1 x1 + a2 x2 + a3 x3 = 0

<= maximum

This is a bit more complicated, but still quite easy.

Let's first represent a1 x1 + a2 x2 + a3 x3 by X. So the condition becomes:

abs(X) <= maximum

What is in fact abs(X) ?

It is X if X is positive or 0 and it is -X if X is negative.

This also implies that maximum is always bigger than or equal to zero. Else the constraint would always be impossible (mathematical impossible with real numbers).

The geometric representation of this is:

----+===============+----
-maximum    0    +maximum

The section between -maximum and +maximum fulfils the constraint.

So if X is positive, the restriction becomes:

 X <= maximum

If X is negative, the restriction becomes:

-X <= maximum

And the fortunate thing is that if we need the one restriction that the other is always redundant. If X is positive, then -X is negative and thus always less than maximum (which is always positive, remember) and thus the second equation is then redundant. If X is negative, then it is always less than maximum (which is always positive, remember) and thus the first equation is then redundant. This can also be seen easily from the graphical representation. So just add the following two equations:

 X <= maximum
-X <= maximum

And the abs(X) <= maximum condition is fulfilled.

And what if the condition is

abs(X) + Y <= maximum

With Y any linear combination.

It is easy to see that the same reasoning can be used to become:

 X + Y <= maximum
-X + Y <= maximum

With the original definition of X this becomes:

 a1 x1 + a2 x2 + a3 x3 + Y <= maximum
-a1 x1 - a2 x2 - a3 x3 + Y <= maximum
Special case 1
abs(x1) + abs(x2) + ... <= maximum;
First consider each abs(xi) value. From above, consider the following:
xiabs >= xi;
xiabs >= -xi;
This makes xiabs >= abs(xi)
Greater than or equal, but as is, not for sure equal.
However, in combination with other constraints, this can become equal. If following constraint is added, and when active, then each xiabs will represent the absolute value of xi:
x1abs + x2abs + ... <= maximum;
So, for each abs(xi) variable in the constraint, add a new variable xiabs and add two extra constraints for it. Then replace abs(xi) by xiabs in the constraint and the condition is fulfilled.
Note that the objective may be minimization or maximization, it doesn't matter.
Note that the variables may have an extra coefficient, but not negative! If the sign would be negative, then xiabs will not have the intention to become as small as possible, but as large as possible and the result would be that xiabs would not be equal to abs(xi). It could become larger.

Example:
max: x1 + 2x2 - 4x3 -3x4;
x1 + x2 <= 5;
2x1 - x2 >= 0;
-x1 + 3x2 >= 0;
x3 + x4 >= .5;
x3 >= 1.1;
x3 <= 10;

abs(x2) + abs(x4) <= 1.5; /* Note that this is not a valid expression. It will be converted. */

free x2, x4;
The converted model becomes:
max: x1 + 2x2 - 4x3 -3x4;
x1 + x2 <= 5;
2x1 - x2 >= 0;
-x1 + 3x2 >= 0;
x3 + x4 >= .5;
x3 >= 1.1;
x3 <= 10;

x2abs >= x2;
x2abs >= -x2;

x4abs >= x4;
x4abs >= -x4;

x2abs + x4abs <= 1.5;

free x2, x4;
The result is:
Value of objective function: 2.6

Actual values of the variables:
x1                           3.75
x2                           1.25
x3                            1.1
x4                          -0.25
x2abs                        1.25
x4abs                        0.25

>= minimum

Let's first represent a1 x1 + a2 x2 + a3 x3 by X. So the condition becomes:

abs(X) >= minimum

What is in fact abs(X) ?

It is X if X is positive or 0 and it is -X if X is negative.

This also implies that minimum should always be bigger than zero. Else the constraint would always be fulfilled and there is no point in having the constraint.

The geometric representation of this is:

====+---------------+====
-minimum    0    +minimum

The section not between -minimum and +minimum fulfils the constraint.

So if X is positive, the restriction becomes:

 X >= minimum

If X is negative, the restriction becomes:

-X >= minimum

Unfortunately, the trick as for a maximum cannot be used here. If X is positive, then -X is not greater than minimum, in contrary ...

It can also be seen from the graphical representation that this restriction is discontinue. This has as effect that it is not possible to convert this into a set of linear equations.

A possible approach to overcome this is making use of integer variables. In particular by using a binary variable B:

 X + M * B >= minimum
-X + M * (1 - B) >= minimum

M is a large enough constant. See later.
The binary variable B takes care of the discontinuity. It can be either 0 or 1. With M large enough, this makes one or the other constraint obsolete.

If B is 0, then the equations can be written as:

 X >= minimum
-X + M >= minimum

So in this case, the restriction X >= minimum is active. X must be positive and larger than minimum. With M large enough, the second constraint is always fulfilled.

If B is 1, then the equations can be written as:

 X + M >= minimum
-X >= minimum

So in this case, the restriction -X >= minimum is active. X must be negative and -X be larger than minimum. With M large enough, the first constraint is always fulfilled.

It is important to use a realistic value for M. Don't use for example 1e30 for it. This creates numerical instabilities and even if not then tolerances will give problem. Because of tolerances, B may not be zero, but actually for example 1e-20. This multiplied with 1e30 gives not zero, but 1e10! This results in X + 1e10 >= minimum instead of X >= minimum. Not what was mathematically formulated!

So how big must M be?
Well, we can make a prediction.
Either -X + M >= minimum (X >= minimum) or X + M >= minimum (X <= -minimum) must always be TRUE.
That comes to -abs(X) + M >= minimum.
Or M >= minimum + abs(X)

If we can predict how large X can become (absolutely), then we can predict a maximum value needed for M for this to work. If abs(X) cannot be larger than maximum, then M can be minimum+maximum.

In most cases, it is possible to determine a reasonable upper bound for X.

In lp-format, the needed equations are:

X + M * B >= minimum;
X + M * B <= M - minimum;

B <= 1;

int B;

And what if the condition is

abs(X) + Y >= minimum

With Y any linear combination.

It is easy to see that the same reasoning can be used to become:

 X + M * B + Y >= minimum
-X + M * (1 - B) + Y >= minimum

With M >= minimum - Y + abs(X)

In lp-format:

X + M * B + Y >= minimum;
X + M * B - Y <= M - minimum

B <= 1;

int B;

Objective function

The objective function is of the form:

min or max: a1 x1 + a2 x2 + a3 x3 + ...

What if there is an absolute value in the objective:

abs(a1 x1 + a2 x2 + a3 x3) + a4 x4 + a5 x5

Let's first represent a1 x1 + a2 x2 + a3 x3 by X and a4 x4 + a5 x5 by Y. Then the objective becomes:

abs(X) + Y

Depending on the sign before the abs and the objective direction, there is an easy and a harder way to solve this.

minimization and sign is positive or maximization and sign is negative.

min: abs(X) + Y
or
max: -abs(X) + Y

In these two situations, abs(X) will be as small as possible, ideally zero. We can use that fact. Add one variable X' and two constraints to the model:

 X <= X'
-X <= X'

And replace in the objective abs(X) with X':

min: X' + Y
or
max: -X' + Y

That is all. So how does this work? There are 3 cases to consider:

X > 0

In this case, -X is negative and the second constraint -X <= X' is always fulfilled because X' is implicitly >= 0. The first constraint X <= X' is however different. Because X is positive, X' must be at least as large as X. But because X' is in the objective in such a way that is tends to be as small as possible, X' will be equal to X. So X' is abs(X) in this case.

X < 0

In this case, X is negative and the first constraint X <= X' is always fulfilled because X' is implicitly >= 0. The second constraint -X <= X' is however different. Because X is negative (-X positive), X' must be at least as large as -X. But because X' is in the objective in such a way that is tends to be as small as possible, X' will be equal to -X. So X' is abs(X) in this case.

X = 0

In this case, both constraints are always fulfilled because X' is implicitly >= 0. Because X' is in the objective in such a way that is tends to be as small as possible, X' will be equal to X, in this case 0. So X' is abs(X).

So in all cases, X' equals abs(X)

With the original definition of X and Y this becomes:

min: X' + a4 x4 + a5 x5
or
max: -X' + a4 x4 + a5 x5

 a1 x1 + a2 x2 + a3 x3 <= X'
-a1 x1 - a2 x2 - a3 x3 <= X'

minimization and sign is negative or maximization and sign is positive.

min: -abs(X) + Y
or
max: abs(X) + Y

This is a different story. abs(X) now tends to be as large as possible. So the previous trick cannot be used now.

A possible approach to overcome this is making use of integer variables. In particular by using a binary variable B and adding a variable X'. Add following constraints to the model:

 X + M * B >= X'
-X + M * (1 - B) >= X'
 X <= X'
-X <= X'

And replace in the objective abs(X) with X':

min: -X' + Y
or
max: X' + Y

That is all. So how does this work? In fact this is a combination of a maximum and minimum constraint on an absolute expression. X' represents the absolute expression and is used in the objective.

M is a large enough constant. See later.
The binary variable B can be either 0 or 1. With M large enough, this makes one or the other constraint obsolete.

If B is 0, then the equations can be written as:

 X >= X'
-X + M >= X'
 X <= X'
-X <= X'

So in this case, the restriction X >= X' is active. X must be positive and larger than X'. With M large enough, the second constraint is always fulfilled. The third constraint says that X <= X'. The forth constraint is always fulfilled. In fact the first and third constraint have as result that X' equals X, which is positive in this case.

If B is 1, then the equations can be written as:

 X + M >= X'
-X >= X'
 X <= X'
-X <= X'

So in this case, the restriction -X >= X' is active. X must be negative and -X be larger than X'. With M large enough, the first constraint is always fulfilled. The third constraint is always fulfilled. The forth constraint says that -X < X'. In fact the second and forth constraint have as result that X' equals -X, which is positive in this case.

It is important to use a realistic value for M. Don't use for example 1e30 for it. This creates numerical instabilities and even if not then tolerances will give problem. Because of tolerances, B may not be zero, but actually for example 1e-20. This multiplied with 1e30 gives not zero, but 1e10! This results in X + 1e10 >= X' instead of X >= X'. Not what was mathematically formulated!

So how big must M be?
Well, we can make a prediction.
Either -X + M >= X' (X >= X') or X + M >= X' (X <= -X') must always be TRUE.
That comes to -abs(X) + M >= X'.
or -abs(X) + M >= abs(X).
Or M >= 2 * abs(X)

If we can predict how large X can become (absolutely), then we can predict a maximum value needed for M for this to work. If abs(X) cannot be larger than maximum, then M can be 2 * maximum.

In most cases, it is possible to determine a reasonable upper bound for X.

In lp-format, the needed equations are:

max: X' + Y;

 X + M * B - X' >= 0;
 X + M * B + X' <= M;
 X <= X'
-X <= X'

B <= 1;

int B;
doc/set_rh_vec.htm0000644000175000017500000000677510242131666013142 0ustar renerene set_rh_vec, str_set_rh_vec

set_rh_vec, str_set_rh_vec

Set the right hand side (RHS) vector (column 0).

void set_rh_vec(lprec *lp, REAL *rh);

unsigned char str_set_rh_vec(lprec *lp, char *rh_string);

Return Value

set_rh_vec has no return value. str_set_rh_vec returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

rh

An array with row elements that contains the values of the RHS.

rh_string

A string with row elements that contains the values of the RHS. Each element must be separated by space(s).

Remarks

The set_rh_vec, str_set_rh_vec functions set all values of the RHS vector (column 0) at once.
Note that element 0 of the array is not considered (i.e. ignored). Row 1 is element 1, row 2 is element 2, ...
If the initial value of the objective function must also be set, use set_rh.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL rhs[1+2]; /* must be 1 more then number of rows ! */

  /* Create a new LP model */
  lp = make_lp(2, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  rhs[1] = 1.0;
  rhs[2] = 2.0;
  set_rh_vec(lp, rhs);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_rh, get_rh, add_constraint, add_constraintex, str_add_constraint, add_column, add_columnex, str_add_column, get_mat, get_column, get_columnex, set_column, set_columnex, get_row, get_rowex, set_row, set_rowex

doc/is_debug.htm0000644000175000017500000000444210237176660012576 0ustar renerene is_debug

is_debug

Returns a flag if all intermediate results and the branch-and-bound decisions must be printed while solving.

unsigned char is_debug(lprec *lp);

Return Value

is_debug returns TRUE or FALSE. Debug or do not debug.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_debug function returns a flag if all intermediate results and the branch-and-bound decisions must be printed while solving. This function is mend for debugging purposes. The default is not to debug (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char dodebug;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  dodebug = is_debug(lp); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_debug

doc/get_scalelimit.htm0000644000175000017500000000510310237176656014002 0ustar renerene get_scalelimit

get_scalelimit

Sets the relative scaling convergence criterion for the active scaling mode.

REAL get_scalelimit(lprec *lp);

Return Value

get_scalelimit returns the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

scalelimit

maximum number of iterations

Remarks

The get_scalelimit function the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations (default is 5).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL scalelimit;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  scalelimit = get_scalelimit(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_scalelimit, set_scaling, get_scaling, is_integerscaling

doc/set_basisvar.htm0000644000175000017500000000357310311116376013475 0ustar renerene set_basisvar

set_basisvar

This is an internal function that has been published for special purposes. It should generally not be used.

int set_basisvar(lprec *lp, int basisPos, int enteringCol);

Return Value

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

basisPos

enteringCol

Remarks

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

doc/Java/0000755000175000017500000000000011137710501011144 5ustar renerenedoc/Java/docs/0000755000175000017500000000000010762600107012077 5ustar renerenedoc/Java/docs/api/0000755000175000017500000000000011230412604012642 5ustar renerenedoc/Java/docs/api/overview-tree.html0000644000175000017500000001326610257560740016360 0ustar renerene Class Hierarchy (Using lp_solve in Java programs)

Hierarchy For All Packages

Package Hierarchies:
lpsolve

Class Hierarchy

Interface Hierarchy



Copyright 2004 - Juergen Ebert doc/Java/docs/api/constant-values.html0000644000175000017500000015677011230412605016677 0ustar renerene Constant Field Values (Using lp_solve in Java programs)

Constant Field Values


Contents
lpsolve.*

lpsolve.LpSolve
public static final int ANTIDEGEN_BOUNDFLIP 512
public static final int ANTIDEGEN_COLUMNCHECK 2
public static final int ANTIDEGEN_DURINGBB 128
public static final int ANTIDEGEN_DYNAMIC 64
public static final int ANTIDEGEN_FIXEDVARS 1
public static final int ANTIDEGEN_INFEASIBLE 32
public static final int ANTIDEGEN_LOSTFEAS 16
public static final int ANTIDEGEN_NONE 0
public static final int ANTIDEGEN_NUMFAILURE 8
public static final int ANTIDEGEN_RHSPERTURB 256
public static final int ANTIDEGEN_STALLING 4
public static final int AUTOMATIC 2
public static final int BRANCH_AUTOMATIC 2
public static final int BRANCH_DEFAULT 3
public static final int BRANCH_CEILING 0
public static final int BRANCH_FLOOR 1
public static final int CRASH_MOSTFEASIBLE 2
public static final int CRASH_NOTHING 0
public static final int CRITICAL 1
public static final int DATAIGNORED -4
public static final int DEGENERATE 4
public static final int DETAILED 5
public static final int DYNAMIC 4
public static final int EQ 3
public static final int FALSE 0
public static final int FEASFOUND 12
public static final int FR 0
public static final int FULL 6
public static final int PRESOLVED 9
public static final int GE 2
public static final int IMPORTANT 3
public static final int IMPROVE_BBSIMPLEX 8
public static final int IMPROVE_DUALFEAS 2
public static final int IMPROVE_NONE 0
public static final int IMPROVE_SOLUTION 1
public static final int IMPROVE_THETAGAP 4
public static final int INFEASIBLE 2
public static final int LE 1
public static final int MSG_INITPSEUDOCOST 8192
public static final int MSG_INVERT 4
public static final int MSG_ITERATION 2
public static final int MSG_LPBETTER 64
public static final int MSG_LPEQUAL 32
public static final int MSG_LPFEASIBLE 8
public static final int MSG_LPOPTIMAL 16
public static final int MSG_MILPBETTER 512
public static final int MSG_MILPEQUAL 256
public static final int MSG_MILPFEASIBLE 128
public static final int MSG_MILPOPTIMAL 2048
public static final int MSG_MILPSTRATEGY 1024
public static final int MSG_NONE 0
public static final int MSG_PERFORMANCE 4096
public static final int MSG_PRESOLVE 1
public static final int NEUTRAL 0
public static final int NOBFP -3
public static final int NODE_AUTOORDER 8192
public static final int NODE_BRANCHREVERSEMODE 16
public static final int NODE_BREADTHFIRSTMODE 4096
public static final int NODE_DEPTHFIRSTMODE 128
public static final int NODE_DYNAMICMODE 1024
public static final int NODE_FIRSTSELECT 0
public static final int NODE_FRACTIONSELECT 3
public static final int NODE_GAPSELECT 1
public static final int NODE_GREEDYMODE 32
public static final int NODE_PSEUDOCOSTMODE 64
public static final int NODE_PSEUDOCOSTSELECT 4
public static final int NODE_PSEUDONONINTSELECT 5
public static final int NODE_PSEUDORATIOSELECT 6
public static final int NODE_RANDOMIZEMODE 256
public static final int NODE_RANGESELECT 2
public static final int NODE_RCOSTFIXING 16384
public static final int NODE_RESTARTMODE 2048
public static final int NODE_STRONGINIT 32768
public static final int NODE_USERSELECT 7
public static final int NODE_WEIGHTREVERSEMODE 8
public static final int NOFEASFOUND 13
public static final int NOMEMORY -2
public static final int NORMAL 4
public static final int NOTRUN -1
public static final int NUMFAILURE 5
public static final int OF 4
public static final int OPTIMAL 0
public static final int PRESOLVE_BOUNDS 262144
public static final int PRESOLVE_COLDOMINATE 16384
public static final int PRESOLVE_COLFIXDUAL 131072
public static final int PRESOLVE_COLS 2
public static final int PRESOLVE_DUALS 524288
public static final int PRESOLVE_ELIMEQ2 256
public static final int PRESOLVE_IMPLIEDFREE 512
public static final int PRESOLVE_IMPLIEDSLK 65536
public static final int PRESOLVE_KNAPSACK 128
public static final int PRESOLVE_LINDEP 4
public static final int PRESOLVE_MERGEROWS 32768
public static final int PRESOLVE_NONE 0
public static final int PRESOLVE_PROBEFIX 2048
public static final int PRESOLVE_PROBEREDUCE 4096
public static final int PRESOLVE_REDUCEGCD 1024
public static final int PRESOLVE_REDUCEMIP 64
public static final int PRESOLVE_ROWDOMINATE 8192
public static final int PRESOLVE_ROWS 1
public static final int PRESOLVE_SENSDUALS 1048576
public static final int PRESOLVE_SOS 32
public static final int PRICE_ADAPTIVE 32
public static final int PRICE_AUTOPARTIAL 512
public static final int PRICE_HARRISTWOPASS 4096
public static final int PRICE_HYBRID 64
public static final int PRICE_LOOPALTERNATE 2048
public static final int PRICE_LOOPLEFT 1024
public static final int PRICE_METHODDEFAULT 0
public static final int PRICE_MULTIPLE 8
public static final int PRICE_PARTIAL 16
public static final int PRICE_PRIMALFALLBACK 4
public static final int PRICE_RANDOMIZE 128
public static final int PRICE_TRUENORMINIT 16384
public static final int PRICER_DANTZIG 1
public static final int PRICER_DEVEX 2
public static final int PRICER_FIRSTINDEX 0
public static final int PRICER_STEEPESTEDGE 3
public static final int PROCBREAK 11
public static final int PROCFAIL 10
public static final int RUNNING 8
public static final int SCALE_COLSONLY 1024
public static final int SCALE_CURTISREID 7
public static final int SCALE_DYNUPDATE 256
public static final int SCALE_EQUILIBRATE 64
public static final int SCALE_EXTREME 1
public static final int SCALE_GEOMETRIC 4
public static final int SCALE_INTEGERS 128
public static final int SCALE_LINEAR 0
public static final int SCALE_LOGARITHMIC 16
public static final int SCALE_MEAN 3
public static final int SCALE_NONE 0
public static final int SCALE_POWER2 32
public static final int SCALE_QUADRATIC 8
public static final int SCALE_RANGE 2
public static final int SCALE_ROWSONLY 512
public static final int SCALE_USERWEIGHT 31
public static final int SEVERE 2
public static final int SIMPLEX_DEFAULT 6
public static final int SIMPLEX_DUAL_DUAL 10
public static final int SIMPLEX_DUAL_PRIMAL 6
public static final int SIMPLEX_PRIMAL_DUAL 9
public static final int SIMPLEX_PRIMAL_PRIMAL 5
public static final int SUBOPTIMAL 1
public static final int TIMEOUT 7
public static final int TRUE 1
public static final int UNBOUNDED 3
public static final int UNKNOWNERROR -5
public static final int USERABORT 6



Copyright 2004 - Juergen Ebert doc/Java/docs/api/allclasses-noframe.html0000644000175000017500000000234210257560736017326 0ustar renerene All Classes (Using lp_solve in Java programs) All Classes
AbortListener
BbListener
LogListener
LpSolve
LpSolveException
MsgListener
VersionInfo
doc/Java/docs/api/index.html0000644000175000017500000000145610257560736014667 0ustar renerene Using lp_solve in Java programs <H2> Frame Alert</H2> <P> This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. <BR> Link to<A HREF="lpsolve/package-summary.html">Non-frame version.</A> doc/Java/docs/api/resources/0000755000175000017500000000000010762557140014672 5ustar renerenedoc/Java/docs/api/resources/inherit.gif0000644000175000017500000000007110257560736017025 0ustar renereneGIF89a, DrjԐ;߀Q@N;doc/Java/docs/api/stylesheet.css0000644000175000017500000000231710257560736015572 0ustar renerene/* Javadoc style sheet */ /* Define colors, fonts and other style attributes here to override the defaults */ /* Page background color */ body { background-color: #FFFFFF } /* Headings */ h1 { font-size: 145% } /* Table colors */ .TableHeadingColor { background: #CCCCFF } /* Dark mauve */ .TableSubHeadingColor { background: #EEEEFF } /* Light mauve */ .TableRowColor { background: #FFFFFF } /* White */ /* Font used in left-hand frame lists */ .FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif } .FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif } .FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif } /* Navigation bar fonts and colors */ .NavBarCell1 { background-color:#EEEEFF;} /* Light mauve */ .NavBarCell1Rev { background-color:#00008B;} /* Dark Blue */ .NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;} .NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;} .NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;} .NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;} doc/Java/docs/api/serialized-form.html0000644000175000017500000001230010257560736016642 0ustar renerene Serialized Form (Using lp_solve in Java programs)

Serialized Form


Package lpsolve

Class lpsolve.LpSolveException extends java.lang.Exception implements Serializable



Copyright 2004 - Juergen Ebert doc/Java/docs/api/allclasses-frame.html0000644000175000017500000000255610257560736017000 0ustar renerene All Classes (Using lp_solve in Java programs) All Classes
AbortListener
BbListener
LogListener
LpSolve
LpSolveException
MsgListener
VersionInfo
doc/Java/docs/api/deprecated-list.html0000644000175000017500000001076510257560736016634 0ustar renerene Deprecated List (Using lp_solve in Java programs)

Deprecated API



Copyright 2004 - Juergen Ebert doc/Java/docs/api/packages.html0000644000175000017500000000160510257560736015332 0ustar renerene (Using lp_solve in Java programs)


The front page has been relocated.Please see:
          Frame version
          Non-frame version.
doc/Java/docs/api/help-doc.html0000644000175000017500000001722710257560736015256 0ustar renerene API Help (Using lp_solve in Java programs)

How This API Document Is Organized

This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.

Package

Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain four categories:

Class/Interface

Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:

Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.

Tree (Class Hierarchy)

There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with java.lang.Object. The interfaces do not inherit from java.lang.Object.

Deprecated API

The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.

Index

The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.

Prev/Next

These links take you to the next or previous class, interface, package, or related page.

Frames/No Frames

These links show and hide the HTML frames. All pages are available with or without frames.

Serialized Form

Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.

This help file applies to API documentation generated using the standard doclet.



Copyright 2004 - Juergen Ebert doc/Java/docs/api/package-list0000644000175000017500000000001110257560736015143 0ustar renerenelpsolve doc/Java/docs/api/lpsolve/0000755000175000017500000000000011230412770014332 5ustar renerenedoc/Java/docs/api/lpsolve/package-frame.html0000644000175000017500000000352510257560736017726 0ustar renerene lpsolve (Using lp_solve in Java programs) lpsolve
Interfaces 
AbortListener
BbListener
LogListener
MsgListener
Classes 
LpSolve
VersionInfo
Exceptions 
LpSolveException
doc/Java/docs/api/lpsolve/LogListener.html0000644000175000017500000002131210257560736017464 0ustar renerene LogListener (Using lp_solve in Java programs)

lpsolve
Interface LogListener


public interface LogListener

Classes that implement this interface may be passed to the putLogfunc method of the LpSolve class.

Author:
Juergen Ebert
See Also:
LpSolve.putLogfunc(lpsolve.LogListener, java.lang.Object), "lp_solve documentation for 'put_logfunc'"

Method Summary
 void logfunc(LpSolve problem, java.lang.Object userhandle, java.lang.String buf)
          When set, the log routine is called when lp_solve has someting to report (error conditions or so).
 

Method Detail

logfunc

public void logfunc(LpSolve problem,
                    java.lang.Object userhandle,
                    java.lang.String buf)
             throws LpSolveException
When set, the log routine is called when lp_solve has someting to report (error conditions or so).

Parameters:
problem - the problem this Listener was defined for
userhandle - the userhandle object that was passed to putLogfunc
buf - the log message
Throws:
LpSolveException


Copyright 2004 - Juergen Ebert doc/Java/docs/api/lpsolve/AbortListener.html0000644000175000017500000002103710257560736020016 0ustar renerene AbortListener (Using lp_solve in Java programs)

lpsolve
Interface AbortListener


public interface AbortListener

Classes that implement this interface may be passed to the putAbortfunc method of the LpSolve class.

Author:
Juergen Ebert
See Also:
LpSolve.putAbortfunc(lpsolve.AbortListener, java.lang.Object), "lp_solve documentation for 'put_abortfunc'"

Method Summary
 boolean abortfunc(LpSolve problem, java.lang.Object userhandle)
          When set, the abort routine is called regularly during solve().
 

Method Detail

abortfunc

public boolean abortfunc(LpSolve problem,
                         java.lang.Object userhandle)
                  throws LpSolveException
When set, the abort routine is called regularly during solve(). The user can do whatever he wants in this routine.

Parameters:
problem - the problem this Listener was defined for
userhandle - the userhandle object that was passed to putAbortfunc
Returns:
if true, then lp_solve aborts the solver and returns with an appropriate code
Throws:
LpSolveException


Copyright 2004 - Juergen Ebert doc/Java/docs/api/lpsolve/LpSolve.html0000644000175000017500000105223211230413006016602 0ustar renerene LpSolve (Using lp_solve in Java programs)

lpsolve
Class LpSolve

java.lang.Object
  extended bylpsolve.LpSolve

public class LpSolve
extends java.lang.Object

Object wrapper for a problem structure of the lp_solve library. Offers access to all lp_solve methods.

Author:
Juergen Ebert

Field Summary
static int ANTIDEGEN_BOUNDFLIP
           
static int ANTIDEGEN_COLUMNCHECK
           
static int ANTIDEGEN_DURINGBB
           
static int ANTIDEGEN_DYNAMIC
           
static int ANTIDEGEN_FIXEDVARS
           
static int ANTIDEGEN_INFEASIBLE
           
static int ANTIDEGEN_LOSTFEAS
           
static int ANTIDEGEN_NONE
           
static int ANTIDEGEN_NUMFAILURE
           
static int ANTIDEGEN_RHSPERTURB
           
static int ANTIDEGEN_STALLING
           
static int AUTOMATIC
           
static int BRANCH_AUTOMATIC
           
static int BRANCH_CEILING
           
static int BRANCH_FLOOR
           
static int BRANCH_DEFAULT
           
static int CRASH_MOSTFEASIBLE
           
static int CRASH_NOTHING
           
static int CRITICAL
           
static int DATAIGNORED
           
static int DEGENERATE
           
static int DETAILED
           
static int DYNAMIC
           
static int EQ
           
static int FALSE
           
static int FEASFOUND
           
static int FR
           
static int FULL
           
static int PRESOLVED
           
static int GE
           
static int IMPORTANT
           
static int IMPROVE_BBSIMPLEX
           
static int IMPROVE_DUALFEAS
           
static int IMPROVE_NONE
           
static int IMPROVE_SOLUTION
           
static int IMPROVE_THETAGAP
           
static int INFEASIBLE
           
static int LE
           
static int MSG_INITPSEUDOCOST
           
static int MSG_INVERT
           
static int MSG_ITERATION
           
static int MSG_LPBETTER
           
static int MSG_LPEQUAL
           
static int MSG_LPFEASIBLE
           
static int MSG_LPOPTIMAL
           
static int MSG_MILPBETTER
           
static int MSG_MILPEQUAL
           
static int MSG_MILPFEASIBLE
           
static int MSG_MILPOPTIMAL
           
static int MSG_MILPSTRATEGY
           
static int MSG_NONE
           
static int MSG_PERFORMANCE
           
static int MSG_PRESOLVE
           
static int NEUTRAL
           
static int NOBFP
           
static int NODE_AUTOORDER
           
static int NODE_BRANCHREVERSEMODE
           
static int NODE_BREADTHFIRSTMODE
           
static int NODE_DEPTHFIRSTMODE
           
static int NODE_DYNAMICMODE
           
static int NODE_FIRSTSELECT
           
static int NODE_FRACTIONSELECT
           
static int NODE_GAPSELECT
           
static int NODE_GREEDYMODE
           
static int NODE_PSEUDOCOSTMODE
           
static int NODE_PSEUDOCOSTSELECT
           
static int NODE_PSEUDONONINTSELECT
           
static int NODE_PSEUDORATIOSELECT
           
static int NODE_RANDOMIZEMODE
           
static int NODE_RANGESELECT
           
static int NODE_RCOSTFIXING
           
static int NODE_RESTARTMODE
           
static int NODE_STRONGINIT
           
static int NODE_USERSELECT
           
static int NODE_WEIGHTREVERSEMODE
           
static int NOFEASFOUND
           
static int NOMEMORY
           
static int NORMAL
           
static int NOTRUN
           
static int NUMFAILURE
           
static int OF
           
static int OPTIMAL
           
static int PRESOLVE_BOUNDS
           
static int PRESOLVE_COLDOMINATE
           
static int PRESOLVE_COLFIXDUAL
           
static int PRESOLVE_COLS
           
static int PRESOLVE_DUALS
           
static int PRESOLVE_ELIMEQ2
           
static int PRESOLVE_IMPLIEDFREE
           
static int PRESOLVE_IMPLIEDSLK
           
static int PRESOLVE_KNAPSACK
           
static int PRESOLVE_LINDEP
           
static int PRESOLVE_MERGEROWS
           
static int PRESOLVE_NONE
           
static int PRESOLVE_PROBEFIX
           
static int PRESOLVE_PROBEREDUCE
           
static int PRESOLVE_REDUCEGCD
           
static int PRESOLVE_REDUCEMIP
           
static int PRESOLVE_ROWDOMINATE
           
static int PRESOLVE_ROWS
           
static int PRESOLVE_SENSDUALS
           
static int PRESOLVE_SOS
           
static int PRICE_ADAPTIVE
           
static int PRICE_AUTOPARTIAL
           
static int PRICE_HARRISTWOPASS
           
static int PRICE_HYBRID
           
static int PRICE_LOOPALTERNATE
           
static int PRICE_LOOPLEFT
           
static int PRICE_METHODDEFAULT
           
static int PRICE_MULTIPLE
           
static int PRICE_PARTIAL
           
static int PRICE_PRIMALFALLBACK
           
static int PRICE_RANDOMIZE
           
static int PRICE_TRUENORMINIT
           
static int PRICER_DANTZIG
           
static int PRICER_DEVEX
           
static int PRICER_FIRSTINDEX
           
static int PRICER_STEEPESTEDGE
           
static int PROCBREAK
           
static int PROCFAIL
           
static int RUNNING
           
static int SCALE_COLSONLY
           
static int SCALE_CURTISREID
           
static int SCALE_DYNUPDATE
           
static int SCALE_EQUILIBRATE
           
static int SCALE_EXTREME
           
static int SCALE_GEOMETRIC
           
static int SCALE_INTEGERS
           
static int SCALE_LINEAR
           
static int SCALE_LOGARITHMIC
           
static int SCALE_MEAN
           
static int SCALE_NONE
           
static int SCALE_POWER2
           
static int SCALE_QUADRATIC
           
static int SCALE_RANGE
           
static int SCALE_ROWSONLY
           
static int SCALE_USERWEIGHT
           
static int SEVERE
           
static int SIMPLEX_DEFAULT
           
static int SIMPLEX_DUAL_DUAL
           
static int SIMPLEX_DUAL_PRIMAL
           
static int SIMPLEX_PRIMAL_DUAL
           
static int SIMPLEX_PRIMAL_PRIMAL
           
static int SUBOPTIMAL
           
static int TIMEOUT
           
static int TRUE
           
static int UNBOUNDED
           
static int UNKNOWNERROR
           
static int USERABORT
           
 
Method Summary
 void addColumn(double[] column)
          Add a column to the problem.
 void addColumnex(int count, double[] column, int[] rowno)
          Add a column to the problem.
 void addConstraint(double[] row, int constrType, double rh)
          Add a constraint to the problem.
 void addConstraintex(int count, double[] row, int[] colno, int constrType, double rh)
          Add a constraint to the problem.
 void addLagCon(double[] row, int constrType, double rh)
          Add a Lagrangian constraint to the problem.
 void addSOS(java.lang.String name, int sostype, int priority, int count, int[] sosvars, double[] weights)
          Add a SOS constraint.
 int columnInLp(double[] column)
          Check if a column is already present in the problem.
 LpSolve copyLp()
          Copy an existing lprec structure to a new lprec structure.
 void defaultBasis()
          Sets the starting base to an all slack basis (the default simplex starting basis).
 void delColumn(int columnnr)
          Remove a column from the problem.
 void delConstraint(int rownr)
          Remove a constraint from the problem.
 void deleteLp()
          Frees all resources allocated to this problem.
 void dualizeLp()
          Create the dual of the current model.
protected  void finalize()
           
 int getAntiDegen()
          Returns the used degeneracy rule.
 void getBasis(int[] bascolumn, boolean nonbasic)
          Returns the basis of the lp.
 int getBasiscrash()
          Returns which basis crash mode must be used.
 int getBbDepthlimit()
          Returns the maximum branch-and-bound depth.
 int getBbFloorfirst()
          Returns which branch to take first in branch-and-bound algorithm.
 int getBbRule()
          Returns the branch-and-bound rule.
 boolean getBoundsTighter()
          Returns if set bounds may only be tighter or also less restrictive.
 double getBreakAtValue()
          Returns the value at which the branch-and-bound algorithm stops when the object value is better than this value.
 java.lang.String getColName(int colnr)
          Gets the name of a column in the problem.
 void getColumn(int colnr, double[] column)
          Get all column elements from the matrix.
 int getColumnex(int colnr, double[] column, int[] nzrows)
          Get the non-zero column elements from the matrix.
 void getConstraints(double[] var)
          Returns the values of the constraints.
 short getConstrType(int rownr)
          Get the type of a constraint.
 double getConstrValue(int rownr, int count, double[] primsolution, int[] nzindex)
          Gets the value of a constraint according to provided variable values.
 void getDualSolution(double[] duals)
          Returns the sensitivity of the constraints and the variables.
 double getEpsb()
          Returns the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.
 double getEpsd()
          Returns the value that is used as a tolerance for the reduced costs to determine whether a value should be considered as 0.
 double getEpsel()
          Returns the value that is used as a tolerance for rounding values to zero.
 double getEpsint()
          Returns the tolerance that is used to determine whether a floating-point number is in fact an integer
 double getEpsperturb()
          Returns the value that is used as perturbation scalar for degenerative problems.
 double getEpspivot()
          Returns the value that is used as a tolerance pivot element to determine whether a value should be considered as 0.
 int getImprove()
          Returns the iterative improvement level.
 double getInfinite()
          Returns the value of "infinite".
 void getLambda(double[] lambda)
          Returns the Lamdba vectors (Lagrangian optimization).
 double getLowbo(int colnr)
          Get the lower bound of a variable.
 long getLp()
          Return the value of the lp attribute.
 int getLpIndex(int index)
          Returns the index in the lp of the original row/column.
 java.lang.String getLpName()
          Get the name of the problem.
 int getLrows()
          Returns the number of Lagrangian rows in the lp.
 double getMat(int row, int column)
          Get a single element from the matrix.
 int getMaxLevel()
          Returns the deepest Branch-and-bound level of the last solution.
 int getMaxpivot()
          Returns the maximum number of pivots between a reinversion of the matrix.
 double getMipGap(boolean absolute)
          Returns the MIP gap value.
 int getNameindex(java.lang.String name, boolean isRow)
          Gets the index of a given column or row name in the lp.
 int getNcolumns()
          Returns the number of columns (variables) in the problem.
 double getNegrange()
          Returns the negative value below which variables are split into a negative and a positive part.
 int getNonzeros()
          Returns the number of non-zero elements in the matrix.
 int getNorigColumns()
          Returns the number of original columns (variables) in the problem.
 int getNorigRows()
          Returns the number of original rows (constraints) in the problem.
 int getNrows()
          Returns the number of rows (constraints) in the problem.
 double getObjBound()
          Returns initial "at least better than" guess for objective function.
 double getObjective()
          Returns the value of the objective function.
 java.lang.String getOrigcolName(int colnr)
          Gets the name of a column in the problem.
 int getOrigIndex(int index)
          Returns the original row/column where a constraint/variable was before presolve.
 java.lang.String getOrigrowName(int rownr)
          Gets the name of a constraint (row) in the problem.
 int getPivoting()
          Returns the pivot rule.
 int getPresolve()
          Returns the current presolve setting.
 int getPresolveloops()
          Returns the number of times presolve is done.
 void getPrimalSolution(double[] pv)
          Returns the solution of the model.
 int getPrintSol()
          Returns a flag if all intermediate valid solutions must be printed while solving.
 double[] getPtrColumn(int columnrnr)
          Get all column elements from the matrix.
 double[] getPtrConstraints()
          Returns the values of the constraints.
 double[] getPtrDualSolution()
          Returns the sensitivity of the constraints and the variables.
 double[] getPtrLambda()
          Returns the Lamdba vectors (Lagrangian optimization).
 double[] getPtrPrimalSolution()
          Returns the solution of the model.
 double[] getPtrRow(int rownr)
          Get all row elements from the matrix.
 double[][] getPtrSensitivityObj()
          Returns the sensitivity of the objective function.
 double[][] getPtrSensitivityObjex()
          Returns the sensitivity of the objective function.
 double[][] getPtrSensitivityRhs()
          Returns the sensitivity of the constraints and the variables.
 double[] getPtrVariables()
          Returns the values of the variables.
 double getRh(int row)
          Get the value of the right hand side (RHS) vector (column 0) for one row.
 double getRhRange(int rownr)
          Gets the range on a constraint.
 void getRow(int rownr, double[] row)
          Get all row elements from the matrix.
 int getRowex(int rownr, double[] row, int[] nzcols)
          Get the non-zero row elements from the matrix.
 java.lang.String getRowName(int rownr)
          Gets the name of a constraint (row) in the problem.
 double getScalelimit()
          Returns the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations.
 int getScaling()
          Specifies which scaling algorithm is used.
 void getSensitivityObj(double[] objfrom, double[] objtill)
          Returns the sensitivity of the objective function.
 void getSensitivityObjex(double[] objfrom, double[] objtill, double[] objfromvalue, double[] objtillvalue)
          Returns the sensitivity of the objective function.
 void getSensitivityRhs(double[] duals, double[] dualsfrom, double[] dualstill)
          Returns the sensitivity of the constraints and the variables.
 int getSimplextype()
          Returns the desired combination of primal and dual simplex algorithms.
 int getSolutioncount()
          Returns the number of equal solutions.
 int getSolutionlimit()
          Returns the solution number that must be returned.
 int getStatus()
          Returns an extra status after a call to a function.
 java.lang.String getStatustext(int statuscode)
          Returns the description of a returncode of the solve function.
 long getTimeout()
          Gets the timout.
 long getTotalIter()
          Returns the total number of iterations with Branch-and-bound of the last solution.
 long getTotalNodes()
          Returns the total number of nodes processed in branch-and-bound.
 double getUpbo(int colnr)
          Get the upper bound of a variable.
 int getVarBranch(int colnr)
          Returns, for the specified variable, which branch to take first in branch-and-bound algorithm.
 double getVarDualresult(int index)
          Returns the sensitivity of the constraints and the variables.
 void getVariables(double[] var)
          Returns the values of the variables.
 double getVarPrimalresult(int index)
          Returns the solution of the model.
 int getVarPriority(int colnr)
          Returns, for the specified variable, the priority the variable has in the branch-and-bound algorithm.
 int getVerbose()
          Returns the verbose level.
 double getWorkingObjective()
          Returns the value of the objective function.
 void guessBasis(double[] guessvector, int[] basisvector)
          Guess a basis for the lp.
 boolean hasBFP()
          Returns if there is a basis factorization package (BFP) available.
 boolean hasXLI()
          Returns if there is an external language interface (XLI) set.
 boolean isAddRowmode()
          Returns a flag which of the add routines perform best.
 boolean isAntiDegen(int testmask)
          Returns if the degeneracy rule specified in testmask is active.
 boolean isBinary(int colnr)
          Gets the type of the variable.
 boolean isBreakAtFirst()
          Returns if the branch-and-bound algorithm stops at first found solution.
 boolean isConstrType(int row, int mask)
          Returns if constraint type specified in mask is active.
 boolean isDebug()
          Returns a flag if all intermediate results and the branch-and-bound decisions must be printed while solving.
 boolean isFeasible(double[] values, double threshold)
          Checks if provided solution is a feasible solution.
 boolean isInfinite(double value)
          Checks if the provided absolute of the value is larger or equal to "infinite".
 boolean isInt(int colnr)
          Get the type of the variable.
 boolean isIntegerscaling()
          Specifies which scaling algorithm is used.
 boolean isLagTrace()
          Returns a flag if Lagrangian progression must be printed while solving.
 boolean isMaxim()
          Returns objective function direction.
 boolean isNativeBFP()
          Returns if the native (build-in) basis factorization package (BFP) is used, or an external package.
 boolean isNativeXLI()
          Returns if a build-in External Language Interfaces (XLI) is available or not.
 boolean isNegative(int colnr)
          Returns if the variable is negative.
 boolean isPivMode(int testmask)
          Returns if pivot strategy specified in testmask is active.
 boolean isPivRule(int rule)
          Checks if the specified pivot rule is active.
 boolean isPresolve(int testmask)
          Returns if presolve level specified in testmask is active.
 boolean isScalemode(int testmask)
          Returns if scaling mode specified in testmask is active.
 boolean isScaletype(int scaletype)
          Returns if scaling type specified in scaletype is active.
 boolean isSemicont(int colnr)
          Get the type of the variable. semi-continious or not.
 boolean isSOSVar(int colnr)
          Returns if the variable is SOS or not.
 boolean isTrace()
          Returns a flag if pivot selection must be printed while solving.
 boolean isUnbounded(int colnr)
          Returns if the variable is free.
 boolean isUseNames(boolean isRow)
          Returns if variable or constraint names are used.
static VersionInfo lpSolveVersion()
          Returns the full version number of the underlying lp_solve library.
static LpSolve makeLp(int rows, int columns)
          Creates a new problem.
 void printConstraints(int columns)
          Prints the values of the constraints of the lp.
 void printDebugdump(java.lang.String filename)
          Do a generic readable data dump of key lp_solve model variables; principally for run difference and debugging purposes.
 void printDuals()
          Prints the values of the duals of the lp.
 void printLp()
          Prints the lp model.
 void printObjective()
          Prints the objective value of the lp.
 void printScales()
          Prints the scales of the lp.
 void printSolution(int columns)
          Prints the solution (variables) of the lp.
 void printStr(java.lang.String str)
          Prints a string.
 void printTableau()
          Prints the tableau.
 void putAbortfunc(AbortListener listener, java.lang.Object userhandle)
          Register an AbortListener for callback.
 void putBbBranchfunc(BbListener listener, java.lang.Object userhandle)
          Register an BbBranchListener for callback.
 void putBbNodefunc(BbListener listener, java.lang.Object userhandle)
          Register an BbNodeListener for callback.
 void putLogfunc(LogListener listener, java.lang.Object userhandle)
          Register an LogListener for callback.
 void putMsgfunc(MsgListener listener, java.lang.Object userhandle, int mask)
          Register an MsgListener for callback.
 java.lang.String readBasis(java.lang.String filename)
          Read basis from a file and set as default basis.
static LpSolve readFreeMps(java.lang.String filename, int verbose)
          Read a model in free MPS format from file and create a new problem.
static LpSolve readLp(java.lang.String filename, int verbose, java.lang.String lpName)
          Read an lp model from file and create a new problem.
static LpSolve readMps(java.lang.String filename, int verbose)
          Read an mps model from file and create a new problem.
 void readParams(java.lang.String filename, java.lang.String options)
          Read settings from a parameter file.
static LpSolve readXLI(java.lang.String xliname, java.lang.String modelname, java.lang.String dataname, java.lang.String options, int verbose)
          Read a model via the External Language Interface and create a new problem.
 void resetBasis()
          Resets the basis to the initial basis.
 void resetParams()
          Resets parameters back to their default values.
 boolean resizeLp(int rows, int columns)
          Allocate memory for the specified size.
 boolean setAddRowmode(boolean turnon)
          Specifies which add routine performs best.
 void setAntiDegen(int antiDegen)
          Specifies if special handling must be done to reduce degeneracy/cycling while solving.
 void setBasis(int[] bascolumn, boolean nonbasic)
          Sets an initial basis of the lp.
 void setBasiscrash(int mode)
          Specifies which basis crash mode must be used.
 int setBasisvar(int basisPos, int enteringCol)
          This is an internal function that has been published for special purposes. It should generally not be used.
 void setBbDepthlimit(int bbMaxlevel)
          Sets the maximum branch-and-bound depth.
 void setBbFloorfirst(int floorFirst)
          Specifies which branch to take first in branch-and-bound algorithm.
 void setBbRule(int bbRule)
          Specifies the branch-and-bound rule.
 void setBFP(java.lang.String filename)
          Set basis factorization package.
 void setBinary(int colnr, boolean mustBeBin)
          Set the type of the variable.
 void setBounds(int colnr, double lower, double upper)
          Set the upper and lower bound of a variable.
 void setBoundsTighter(boolean tighten)
          Specifies if set bounds may only be tighter or also less restrictive.
 void setBreakAtFirst(boolean breakAtFirst)
          Specifies if the branch-and-bound algorithm stops at first found solution.
 void setBreakAtValue(double breakAtValue)
          Specifies if the branch-and-bound algorithm stops when the object value is better than a given value.
 void setColName(int colnr, java.lang.String name)
          Set the name of a column in the problem.
 void setColumn(int colno, double[] column)
          Set a column in the lp.
 void setColumnex(int colno, int count, double[] column, int[] rowno)
          Set a column in the lp.
 void setConstrType(int rownr, int constrType)
          Set the type of a constraint.
 void setDebug(boolean debug)
          Sets a flag if all intermediate results and the branch-and-bound decisions must be printed while solving.
 void setEpsb(double value)
          Specifies the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0
 void setEpsd(double value)
          Specifies the value that is used as a tolerance for reduced costs to determine whether a value should be considered as 0.
 void setEpsel(double value)
          Specifies the value that is used as a tolerance for rounding values to zero.
 void setEpsint(double value)
          Specifies the tolerance that is used to determine whether a floating-point number is in fact an integer.
 void setEpslevel(int epslevel)
          This is a simplified way of specifying multiple eps thresholds that are "logically" consistent.
 void setEpsperturb(double value)
          Specifies the value that is used as perturbation scalar for degenerative problems.
 void setEpspivot(double value)
          Specifies the value that is used as a tolerance pivot element to determine whether a value should be considered as 0.
 void setImprove(int improve)
          Specifies the iterative improvement level.
 void setInfinite(double value)
          Specifies the practical value for "infinite".
 void setInt(int colnr, boolean mustBeInteger)
          Set the type of the variable.
 void setLagTrace(boolean lagTrace)
          Sets a flag if Lagrangian progression must be printed while solving.
 void setLowbo(int colnr, double value)
          Set the lower bound of a variable.
 void setLpName(java.lang.String name)
          Set the name of the problem.
 void setMat(int row, int column, double value)
          Set a single element in the matrix.
 void setMaxim()
          Set objective function to maximize.
 void setMaxpivot(int maxNumInv)
          Sets the maximum number of pivots between a reinversion of the matrix.
 void setMinim()
          Set objective function to minimize.
 void setMipGap(boolean absolute, double value)
          Specifies the MIP gap value.
 void setNegrange(double negRange)
          Set negative value below which variables are split into a negative and a positive part.
 void setObj(int column, double value)
          Set the objective function (row 0) of the matrix.
 void setObjBound(double objBound)
          Set initial "at least better than" guess for objective function.
 void setObjFn(double[] row)
          Set the objective function (row 0) of the matrix.
 void setObjFnex(int count, double[] row, int[] colno)
          Set the objective function (row 0) of the matrix.
 void setOutputfile(java.lang.String filename)
          Defines the output for the print_* functions.
 void setPivoting(int pivRule)
          Specifies the pivot rule.
 void setPreferdual(boolean dodual)
          Sets the desired combination of primal and dual simplex algorithms.
 void setPresolve(int doPresolve, int maxloops)
          Specifies if a presolve must be done before solving.
 void setPrintSol(int printSol)
          Sets a flag if all intermediate valid solutions must be printed while solving.
 void setRh(int row, double value)
          Set the value of the right hand side (RHS) vector (column 0) for one row.
 void setRhRange(int rownr, double range)
          Set the range on a constraint.
 void setRhVec(double[] rh)
          Set the right hand side (RHS) vector (column 0).
 void setRow(int rowno, double[] row)
          Set a constraint in the lp.
 void setRowex(int rowno, int count, double[] row, int[] colno)
          Set a constraint in the lp.
 void setRowName(int rownr, java.lang.String name)
          Set the name of a constraint (row) in the problem.
 void setScalelimit(double scalelimit)
          Sets the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations.
 void setScaling(int scalemode)
          Specifies which scaling algorithm must be used.
 void setSemicont(int colnr, boolean mustBeSc)
          Set the type of the variable. semi-continious or not.
 void setSense(boolean maximize)
          Set objective function sense.
 void setSimplextype(int simplextype)
          Sets the desired combination of primal and dual simplex algorithms.
 void setSolutionlimit(int limit)
          Sets the solution number that must be returned.
 void setTimeout(long timeout)
          Set a timeout.
 void setTrace(boolean trace)
          Sets a flag if pivot selection must be printed while solving.
 void setUnbounded(int colnr)
          Sets if the variable is free.
 void setUpbo(int colnr, double value)
          Set the upper bound of a variable.
 void setUseNames(boolean isRow, boolean useNames)
          Sets if variable or constraint names are used.
 void setVarBranch(int colnr, int branchMode)
          Specifies, for the specified variable, which branch to take first in branch-and-bound algorithm.
 void setVarWeights(double[] weights)
          Set the weights on variables.
 void setVerbose(int verbose)
          Set the verbose level.
 void setXLI(java.lang.String filename)
          Set External Language Interfaces package.
 int solve()
          Solve the model.
 void strAddColumn(java.lang.String column)
          Add a column to the problem.
 void strAddConstraint(java.lang.String row, int constrType, double rh)
          Add a constraint to the problem.
 void strAddLagCon(java.lang.String row, int constrType, double rh)
          Add a Lagrangian constraint to the problem.
 void strSetObjFn(java.lang.String row)
          Set the objective function (row 0) of the matrix.
 void strSetRhVec(java.lang.String rh)
          Set the right hand side (RHS) vector (column 0).
 double timeElapsed()
          Gets the time elapsed since start of solve.
 void unscale()
          Unscales the model.
 void writeBasis(java.lang.String filename)
          Writes current basis to a file.
 void writeFreeMps(java.lang.String filename)
          Write a model in free MPS format to a file.
 void writeLp(java.lang.String filename)
          Write an lp model to a file.
 void writeMps(java.lang.String filename)
          Write an mps model to a file.
 void writeParams(java.lang.String filename, java.lang.String options)
          Write settings to a parameter file.
 void writeXLI(java.lang.String filename, java.lang.String options, boolean results)
          Write a model to a file via the External Language Interface.
 
Methods inherited from class java.lang.Object
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

FALSE

public static final int FALSE
See Also:
Constant Field Values

TRUE

public static final int TRUE
See Also:
Constant Field Values

AUTOMATIC

public static final int AUTOMATIC
See Also:
Constant Field Values

DYNAMIC

public static final int DYNAMIC
See Also:
Constant Field Values

FR

public static final int FR
See Also:
Constant Field Values

LE

public static final int LE
See Also:
Constant Field Values

GE

public static final int GE
See Also:
Constant Field Values

EQ

public static final int EQ
See Also:
Constant Field Values

OF

public static final int OF
See Also:
Constant Field Values

SIMPLEX_PRIMAL_PRIMAL

public static final int SIMPLEX_PRIMAL_PRIMAL
See Also:
Constant Field Values

SIMPLEX_DUAL_PRIMAL

public static final int SIMPLEX_DUAL_PRIMAL
See Also:
Constant Field Values

SIMPLEX_PRIMAL_DUAL

public static final int SIMPLEX_PRIMAL_DUAL
See Also:
Constant Field Values

SIMPLEX_DUAL_DUAL

public static final int SIMPLEX_DUAL_DUAL
See Also:
Constant Field Values

SIMPLEX_DEFAULT

public static final int SIMPLEX_DEFAULT
See Also:
Constant Field Values

PRESOLVE_NONE

public static final int PRESOLVE_NONE
See Also:
Constant Field Values

PRESOLVE_ROWS

public static final int PRESOLVE_ROWS
See Also:
Constant Field Values

PRESOLVE_COLS

public static final int PRESOLVE_COLS
See Also:
Constant Field Values

PRESOLVE_LINDEP

public static final int PRESOLVE_LINDEP
See Also:
Constant Field Values

PRESOLVE_SOS

public static final int PRESOLVE_SOS
See Also:
Constant Field Values

PRESOLVE_REDUCEMIP

public static final int PRESOLVE_REDUCEMIP
See Also:
Constant Field Values

PRESOLVE_KNAPSACK

public static final int PRESOLVE_KNAPSACK
See Also:
Constant Field Values

PRESOLVE_ELIMEQ2

public static final int PRESOLVE_ELIMEQ2
See Also:
Constant Field Values

PRESOLVE_IMPLIEDFREE

public static final int PRESOLVE_IMPLIEDFREE
See Also:
Constant Field Values

PRESOLVE_REDUCEGCD

public static final int PRESOLVE_REDUCEGCD
See Also:
Constant Field Values

PRESOLVE_PROBEFIX

public static final int PRESOLVE_PROBEFIX
See Also:
Constant Field Values

PRESOLVE_PROBEREDUCE

public static final int PRESOLVE_PROBEREDUCE
See Also:
Constant Field Values

PRESOLVE_ROWDOMINATE

public static final int PRESOLVE_ROWDOMINATE
See Also:
Constant Field Values

PRESOLVE_COLDOMINATE

public static final int PRESOLVE_COLDOMINATE
See Also:
Constant Field Values

PRESOLVE_MERGEROWS

public static final int PRESOLVE_MERGEROWS
See Also:
Constant Field Values

PRESOLVE_IMPLIEDSLK

public static final int PRESOLVE_IMPLIEDSLK
See Also:
Constant Field Values

PRESOLVE_COLFIXDUAL

public static final int PRESOLVE_COLFIXDUAL
See Also:
Constant Field Values

PRESOLVE_BOUNDS

public static final int PRESOLVE_BOUNDS
See Also:
Constant Field Values

PRESOLVE_DUALS

public static final int PRESOLVE_DUALS
See Also:
Constant Field Values

PRESOLVE_SENSDUALS

public static final int PRESOLVE_SENSDUALS
See Also:
Constant Field Values

CRASH_NOTHING

public static final int CRASH_NOTHING
See Also:
Constant Field Values

CRASH_MOSTFEASIBLE

public static final int CRASH_MOSTFEASIBLE
See Also:
Constant Field Values

ANTIDEGEN_NONE

public static final int ANTIDEGEN_NONE
See Also:
Constant Field Values

ANTIDEGEN_FIXEDVARS

public static final int ANTIDEGEN_FIXEDVARS
See Also:
Constant Field Values

ANTIDEGEN_COLUMNCHECK

public static final int ANTIDEGEN_COLUMNCHECK
See Also:
Constant Field Values

ANTIDEGEN_STALLING

public static final int ANTIDEGEN_STALLING
See Also:
Constant Field Values

ANTIDEGEN_NUMFAILURE

public static final int ANTIDEGEN_NUMFAILURE
See Also:
Constant Field Values

ANTIDEGEN_LOSTFEAS

public static final int ANTIDEGEN_LOSTFEAS
See Also:
Constant Field Values

ANTIDEGEN_INFEASIBLE

public static final int ANTIDEGEN_INFEASIBLE
See Also:
Constant Field Values

ANTIDEGEN_DYNAMIC

public static final int ANTIDEGEN_DYNAMIC
See Also:
Constant Field Values

ANTIDEGEN_DURINGBB

public static final int ANTIDEGEN_DURINGBB
See Also:
Constant Field Values

ANTIDEGEN_RHSPERTURB

public static final int ANTIDEGEN_RHSPERTURB
See Also:
Constant Field Values

ANTIDEGEN_BOUNDFLIP

public static final int ANTIDEGEN_BOUNDFLIP
See Also:
Constant Field Values

NEUTRAL

public static final int NEUTRAL
See Also:
Constant Field Values

CRITICAL

public static final int CRITICAL
See Also:
Constant Field Values

SEVERE

public static final int SEVERE
See Also:
Constant Field Values

IMPORTANT

public static final int IMPORTANT
See Also:
Constant Field Values

NORMAL

public static final int NORMAL
See Also:
Constant Field Values

DETAILED

public static final int DETAILED
See Also:
Constant Field Values

FULL

public static final int FULL
See Also:
Constant Field Values

MSG_NONE

public static final int MSG_NONE
See Also:
Constant Field Values

MSG_PRESOLVE

public static final int MSG_PRESOLVE
See Also:
Constant Field Values

MSG_ITERATION

public static final int MSG_ITERATION
See Also:
Constant Field Values

MSG_INVERT

public static final int MSG_INVERT
See Also:
Constant Field Values

MSG_LPFEASIBLE

public static final int MSG_LPFEASIBLE
See Also:
Constant Field Values

MSG_LPOPTIMAL

public static final int MSG_LPOPTIMAL
See Also:
Constant Field Values

MSG_LPEQUAL

public static final int MSG_LPEQUAL
See Also:
Constant Field Values

MSG_LPBETTER

public static final int MSG_LPBETTER
See Also:
Constant Field Values

MSG_MILPFEASIBLE

public static final int MSG_MILPFEASIBLE
See Also:
Constant Field Values

MSG_MILPEQUAL

public static final int MSG_MILPEQUAL
See Also:
Constant Field Values

MSG_MILPBETTER

public static final int MSG_MILPBETTER
See Also:
Constant Field Values

MSG_MILPSTRATEGY

public static final int MSG_MILPSTRATEGY
See Also:
Constant Field Values

MSG_MILPOPTIMAL

public static final int MSG_MILPOPTIMAL
See Also:
Constant Field Values

MSG_PERFORMANCE

public static final int MSG_PERFORMANCE
See Also:
Constant Field Values

MSG_INITPSEUDOCOST

public static final int MSG_INITPSEUDOCOST
See Also:
Constant Field Values

IMPROVE_NONE

public static final int IMPROVE_NONE
See Also:
Constant Field Values

IMPROVE_SOLUTION

public static final int IMPROVE_SOLUTION
See Also:
Constant Field Values

IMPROVE_DUALFEAS

public static final int IMPROVE_DUALFEAS
See Also:
Constant Field Values

IMPROVE_THETAGAP

public static final int IMPROVE_THETAGAP
See Also:
Constant Field Values

IMPROVE_BBSIMPLEX

public static final int IMPROVE_BBSIMPLEX
See Also:
Constant Field Values

SCALE_NONE

public static final int SCALE_NONE
See Also:
Constant Field Values

SCALE_EXTREME

public static final int SCALE_EXTREME
See Also:
Constant Field Values

SCALE_RANGE

public static final int SCALE_RANGE
See Also:
Constant Field Values

SCALE_MEAN

public static final int SCALE_MEAN
See Also:
Constant Field Values

SCALE_GEOMETRIC

public static final int SCALE_GEOMETRIC
See Also:
Constant Field Values

SCALE_CURTISREID

public static final int SCALE_CURTISREID
See Also:
Constant Field Values

SCALE_LINEAR

public static final int SCALE_LINEAR
See Also:
Constant Field Values

SCALE_QUADRATIC

public static final int SCALE_QUADRATIC
See Also:
Constant Field Values

SCALE_LOGARITHMIC

public static final int SCALE_LOGARITHMIC
See Also:
Constant Field Values

SCALE_USERWEIGHT

public static final int SCALE_USERWEIGHT
See Also:
Constant Field Values

SCALE_POWER2

public static final int SCALE_POWER2
See Also:
Constant Field Values

SCALE_EQUILIBRATE

public static final int SCALE_EQUILIBRATE
See Also:
Constant Field Values

SCALE_INTEGERS

public static final int SCALE_INTEGERS
See Also:
Constant Field Values

SCALE_DYNUPDATE

public static final int SCALE_DYNUPDATE
See Also:
Constant Field Values

SCALE_ROWSONLY

public static final int SCALE_ROWSONLY
See Also:
Constant Field Values

SCALE_COLSONLY

public static final int SCALE_COLSONLY
See Also:
Constant Field Values

PRICER_FIRSTINDEX

public static final int PRICER_FIRSTINDEX
See Also:
Constant Field Values

PRICER_DANTZIG

public static final int PRICER_DANTZIG
See Also:
Constant Field Values

PRICER_DEVEX

public static final int PRICER_DEVEX
See Also:
Constant Field Values

PRICER_STEEPESTEDGE

public static final int PRICER_STEEPESTEDGE
See Also:
Constant Field Values

PRICE_METHODDEFAULT

public static final int PRICE_METHODDEFAULT
See Also:
Constant Field Values

PRICE_PRIMALFALLBACK

public static final int PRICE_PRIMALFALLBACK
See Also:
Constant Field Values

PRICE_MULTIPLE

public static final int PRICE_MULTIPLE
See Also:
Constant Field Values

PRICE_PARTIAL

public static final int PRICE_PARTIAL
See Also:
Constant Field Values

PRICE_ADAPTIVE

public static final int PRICE_ADAPTIVE
See Also:
Constant Field Values

PRICE_HYBRID

public static final int PRICE_HYBRID
See Also:
Constant Field Values

PRICE_RANDOMIZE

public static final int PRICE_RANDOMIZE
See Also:
Constant Field Values

PRICE_AUTOPARTIAL

public static final int PRICE_AUTOPARTIAL
See Also:
Constant Field Values

PRICE_LOOPLEFT

public static final int PRICE_LOOPLEFT
See Also:
Constant Field Values

PRICE_LOOPALTERNATE

public static final int PRICE_LOOPALTERNATE
See Also:
Constant Field Values

PRICE_HARRISTWOPASS

public static final int PRICE_HARRISTWOPASS
See Also:
Constant Field Values

PRICE_TRUENORMINIT

public static final int PRICE_TRUENORMINIT
See Also:
Constant Field Values

NODE_FIRSTSELECT

public static final int NODE_FIRSTSELECT
See Also:
Constant Field Values

NODE_GAPSELECT

public static final int NODE_GAPSELECT
See Also:
Constant Field Values

NODE_RANGESELECT

public static final int NODE_RANGESELECT
See Also:
Constant Field Values

NODE_FRACTIONSELECT

public static final int NODE_FRACTIONSELECT
See Also:
Constant Field Values

NODE_PSEUDOCOSTSELECT

public static final int NODE_PSEUDOCOSTSELECT
See Also:
Constant Field Values

NODE_PSEUDONONINTSELECT

public static final int NODE_PSEUDONONINTSELECT
See Also:
Constant Field Values

NODE_PSEUDORATIOSELECT

public static final int NODE_PSEUDORATIOSELECT
See Also:
Constant Field Values

NODE_USERSELECT

public static final int NODE_USERSELECT
See Also:
Constant Field Values

NODE_WEIGHTREVERSEMODE

public static final int NODE_WEIGHTREVERSEMODE
See Also:
Constant Field Values

NODE_BRANCHREVERSEMODE

public static final int NODE_BRANCHREVERSEMODE
See Also:
Constant Field Values

NODE_GREEDYMODE

public static final int NODE_GREEDYMODE
See Also:
Constant Field Values

NODE_PSEUDOCOSTMODE

public static final int NODE_PSEUDOCOSTMODE
See Also:
Constant Field Values

NODE_DEPTHFIRSTMODE

public static final int NODE_DEPTHFIRSTMODE
See Also:
Constant Field Values

NODE_RANDOMIZEMODE

public static final int NODE_RANDOMIZEMODE
See Also:
Constant Field Values

NODE_DYNAMICMODE

public static final int NODE_DYNAMICMODE
See Also:
Constant Field Values

NODE_RESTARTMODE

public static final int NODE_RESTARTMODE
See Also:
Constant Field Values

NODE_BREADTHFIRSTMODE

public static final int NODE_BREADTHFIRSTMODE
See Also:
Constant Field Values

NODE_AUTOORDER

public static final int NODE_AUTOORDER
See Also:
Constant Field Values

NODE_RCOSTFIXING

public static final int NODE_RCOSTFIXING
See Also:
Constant Field Values

NODE_STRONGINIT

public static final int NODE_STRONGINIT
See Also:
Constant Field Values

BRANCH_CEILING

public static final int BRANCH_CEILING
See Also:
Constant Field Values

BRANCH_FLOOR

public static final int BRANCH_FLOOR
See Also:
Constant Field Values

BRANCH_AUTOMATIC

public static final int BRANCH_AUTOMATIC
See Also:
Constant Field Values

BRANCH_DEFAULT

public static final int BRANCH_DEFAULT
See Also:
Constant Field Values

UNKNOWNERROR

public static final int UNKNOWNERROR
See Also:
Constant Field Values

DATAIGNORED

public static final int DATAIGNORED
See Also:
Constant Field Values

NOBFP

public static final int NOBFP
See Also:
Constant Field Values

NOMEMORY

public static final int NOMEMORY
See Also:
Constant Field Values

NOTRUN

public static final int NOTRUN
See Also:
Constant Field Values

OPTIMAL

public static final int OPTIMAL
See Also:
Constant Field Values

SUBOPTIMAL

public static final int SUBOPTIMAL
See Also:
Constant Field Values

INFEASIBLE

public static final int INFEASIBLE
See Also:
Constant Field Values

UNBOUNDED

public static final int UNBOUNDED
See Also:
Constant Field Values

DEGENERATE

public static final int DEGENERATE
See Also:
Constant Field Values

NUMFAILURE

public static final int NUMFAILURE
See Also:
Constant Field Values

USERABORT

public static final int USERABORT
See Also:
Constant Field Values

TIMEOUT

public static final int TIMEOUT
See Also:
Constant Field Values

RUNNING

public static final int RUNNING
See Also:
Constant Field Values

PRESOLVED

public static final int PRESOLVED
See Also:
Constant Field Values

PROCFAIL

public static final int PROCFAIL
See Also:
Constant Field Values

PROCBREAK

public static final int PROCBREAK
See Also:
Constant Field Values

FEASFOUND

public static final int FEASFOUND
See Also:
Constant Field Values

NOFEASFOUND

public static final int NOFEASFOUND
See Also:
Constant Field Values
Method Detail

makeLp

public static LpSolve makeLp(int rows,
                             int columns)
                      throws LpSolveException
Creates a new problem. Upon successful completion, the lprec attribute in this class contains the value of the pointer to the lprec structure.

Parameters:
rows - Initial number of rows.
columns - Initial number of columns.
Throws:
LpSolveException - if lp_solve could not create the problem

readLp

public static LpSolve readLp(java.lang.String filename,
                             int verbose,
                             java.lang.String lpName)
                      throws LpSolveException
Read an lp model from file and create a new problem.

Throws:
LpSolveException

readMps

public static LpSolve readMps(java.lang.String filename,
                              int verbose)
                       throws LpSolveException
Read an mps model from file and create a new problem.

Throws:
LpSolveException

readFreeMps

public static LpSolve readFreeMps(java.lang.String filename,
                                  int verbose)
                           throws LpSolveException
Read a model in free MPS format from file and create a new problem.

Throws:
LpSolveException

readXLI

public static LpSolve readXLI(java.lang.String xliname,
                              java.lang.String modelname,
                              java.lang.String dataname,
                              java.lang.String options,
                              int verbose)
                       throws LpSolveException
Read a model via the External Language Interface and create a new problem.

Throws:
LpSolveException

lpSolveVersion

public static VersionInfo lpSolveVersion()
Returns the full version number of the underlying lp_solve library.

Returns:
VersionInfo object with full version info

finalize

protected void finalize()
                 throws java.lang.Throwable
Throws:
java.lang.Throwable

getLp

public long getLp()
Return the value of the lp attribute.

Returns:
the value of the lp attribute

copyLp

public LpSolve copyLp()
               throws LpSolveException
Copy an existing lprec structure to a new lprec structure. Creates an independent new problem.

Throws:
LpSolveException

resizeLp

public void resizeLp(int rows,
                     int columns)
                   throws LpSolveException
Allocate memory for the specified size.


setLpName

public void setLpName(java.lang.String name)
               throws LpSolveException
Set the name of the problem.

Throws:
LpSolveException

getLpName

public java.lang.String getLpName()
                           throws LpSolveException
Get the name of the problem.

Throws:
LpSolveException

addConstraint

public void addConstraint(double[] row,
                          int constrType,
                          double rh)
                   throws LpSolveException
Add a constraint to the problem.

Throws:
LpSolveException

strAddConstraint

public void strAddConstraint(java.lang.String row,
                             int constrType,
                             double rh)
                      throws LpSolveException
Add a constraint to the problem.

Throws:
LpSolveException

addConstraintex

public void addConstraintex(int count,
                            double[] row,
                            int[] colno,
                            int constrType,
                            double rh)
                     throws LpSolveException
Add a constraint to the problem.

Throws:
LpSolveException

delConstraint

public void delConstraint(int rownr)
                   throws LpSolveException
Remove a constraint from the problem.

Throws:
LpSolveException

isConstrType

public boolean isConstrType(int row,
                            int mask)
Returns if constraint type specified in mask is active.


addLagCon

public void addLagCon(double[] row,
                      int constrType,
                      double rh)
               throws LpSolveException
Add a Lagrangian constraint to the problem.

Throws:
LpSolveException

strAddLagCon

public void strAddLagCon(java.lang.String row,
                         int constrType,
                         double rh)
                  throws LpSolveException
Add a Lagrangian constraint to the problem.

Throws:
LpSolveException

addColumn

public void addColumn(double[] column)
               throws LpSolveException
Add a column to the problem.

Throws:
LpSolveException

addColumnex

public void addColumnex(int count,
                        double[] column,
                        int[] rowno)
                 throws LpSolveException
Add a column to the problem.

Throws:
LpSolveException

strAddColumn

public void strAddColumn(java.lang.String column)
                  throws LpSolveException
Add a column to the problem.

Throws:
LpSolveException

delColumn

public void delColumn(int columnnr)
               throws LpSolveException
Remove a column from the problem.

Throws:
LpSolveException

setRow

public void setRow(int rowno,
                   double[] row)
            throws LpSolveException
Set a constraint in the lp.

Throws:
LpSolveException

setRowex

public void setRowex(int rowno,
                     int count,
                     double[] row,
                     int[] colno)
              throws LpSolveException
Set a constraint in the lp.

Throws:
LpSolveException

setColumn

public void setColumn(int colno,
                      double[] column)
               throws LpSolveException
Set a column in the lp.

Throws:
LpSolveException

setColumnex

public void setColumnex(int colno,
                        int count,
                        double[] column,
                        int[] rowno)
                 throws LpSolveException
Set a column in the lp.

Throws:
LpSolveException

columnInLp

public int columnInLp(double[] column)
Check if a column is already present in the problem.


setRowName

public void setRowName(int rownr,
                       java.lang.String name)
                throws LpSolveException
Set the name of a constraint (row) in the problem.

Throws:
LpSolveException

getRowName

public java.lang.String getRowName(int rownr)
                            throws LpSolveException
Gets the name of a constraint (row) in the problem.

Throws:
LpSolveException

getOrigrowName

public java.lang.String getOrigrowName(int rownr)
                                throws LpSolveException
Gets the name of a constraint (row) in the problem.

Throws:
LpSolveException

setColName

public void setColName(int colnr,
                       java.lang.String name)
                throws LpSolveException
Set the name of a column in the problem.

Throws:
LpSolveException

getColName

public java.lang.String getColName(int colnr)
                            throws LpSolveException
Gets the name of a column in the problem.

Throws:
LpSolveException

getOrigcolName

public java.lang.String getOrigcolName(int colnr)
                                throws LpSolveException
Gets the name of a column in the problem.

Throws:
LpSolveException

setRhVec

public void setRhVec(double[] rh)
              throws LpSolveException
Set the right hand side (RHS) vector (column 0).

Throws:
LpSolveException

strSetRhVec

public void strSetRhVec(java.lang.String rh)
                 throws LpSolveException
Set the right hand side (RHS) vector (column 0).

Throws:
LpSolveException

setRh

public void setRh(int row,
                  double value)
           throws LpSolveException
Set the value of the right hand side (RHS) vector (column 0) for one row.

Throws:
LpSolveException

getRh

public double getRh(int row)
Get the value of the right hand side (RHS) vector (column 0) for one row. NOTE: Returns 0 even if the row index is out of bounds, in accordance to the behaviour of the lp_solve routine!


setConstrType

public void setConstrType(int rownr,
                          int constrType)
                   throws LpSolveException
Set the type of a constraint.

Throws:
LpSolveException

getConstrType

public short getConstrType(int rownr)
                    throws LpSolveException
Get the type of a constraint.

Throws:
LpSolveException

addSOS

public void addSOS(java.lang.String name,
                   int sostype,
                   int priority,
                   int count,
                   int[] sosvars,
                   double[] weights)
            throws LpSolveException
Add a SOS constraint.

Throws:
LpSolveException

isSOSVar

public boolean isSOSVar(int colnr)
                 throws LpSolveException
Returns if the variable is SOS or not.

Throws:
LpSolveException

setObjFn

public void setObjFn(double[] row)
              throws LpSolveException
Set the objective function (row 0) of the matrix.

Throws:
LpSolveException

strSetObjFn

public void strSetObjFn(java.lang.String row)
                 throws LpSolveException
Set the objective function (row 0) of the matrix.

Throws:
LpSolveException

setObjFnex

public void setObjFnex(int count,
                       double[] row,
                       int[] colno)
                throws LpSolveException
Set the objective function (row 0) of the matrix.

Throws:
LpSolveException

setObj

public void setObj(int column,
                   double value)
            throws LpSolveException
Set the objective function (row 0) of the matrix.

Throws:
LpSolveException

setMat

public void setMat(int row,
                   int column,
                   double value)
            throws LpSolveException
Set a single element in the matrix.

Throws:
LpSolveException

getMat

public double getMat(int row,
                     int column)
Get a single element from the matrix.


getRow

public void getRow(int rownr,
                   double[] row)
            throws LpSolveException
Get all row elements from the matrix. Passed in arrays must be allocated by the caller of the method.

Throws:
LpSolveException

getRowex

public int getRowex(int rownr,
                    double[] row,
                    int[] nzcols)
             throws LpSolveException
Get the non-zero row elements from the matrix. Passed in arrays must be allocated by the caller of the method.

Throws:
LpSolveException

getPtrRow

public double[] getPtrRow(int rownr)
                   throws LpSolveException
Get all row elements from the matrix. Returned array is allocated by the method. This is an additional method which is not implemented by lp_solve. Internally, get_row is used.

Throws:
LpSolveException

getColumn

public void getColumn(int colnr,
                      double[] column)
               throws LpSolveException
Get all column elements from the matrix. Passed in arrays must be allocated by the caller of the method.

Throws:
LpSolveException

getColumnex

public int getColumnex(int colnr,
                       double[] column,
                       int[] nzrows)
                throws LpSolveException
Get the non-zero column elements from the matrix. Passed in arrays must be allocated by the caller of the method.

Throws:
LpSolveException

getPtrColumn

public double[] getPtrColumn(int columnrnr)
                      throws LpSolveException
Get all column elements from the matrix. Returned array is allocated by the method. This is an additional method which is not implemented by lp_solve. Internally, get_column is used.

Throws:
LpSolveException

setMaxim

public void setMaxim()
Set objective function to maximize.


setMinim

public void setMinim()
Set objective function to minimize.


setSense

public void setSense(boolean maximize)
Set objective function sense.


isMaxim

public boolean isMaxim()
Returns objective function direction.


setLowbo

public void setLowbo(int colnr,
                     double value)
              throws LpSolveException
Set the lower bound of a variable.

Throws:
LpSolveException

getLowbo

public double getLowbo(int colnr)
                throws LpSolveException
Get the lower bound of a variable.

Throws:
LpSolveException

setUpbo

public void setUpbo(int colnr,
                    double value)
             throws LpSolveException
Set the upper bound of a variable.

Throws:
LpSolveException

getUpbo

public double getUpbo(int colnr)
               throws LpSolveException
Get the upper bound of a variable.

Throws:
LpSolveException

setUnbounded

public void setUnbounded(int colnr)
                  throws LpSolveException
Sets if the variable is free.

Throws:
LpSolveException

isUnbounded

public boolean isUnbounded(int colnr)
Returns if the variable is free.


isNegative

public boolean isNegative(int colnr)
Returns if the variable is negative.


setBounds

public void setBounds(int colnr,
                      double lower,
                      double upper)
               throws LpSolveException
Set the upper and lower bound of a variable.

Throws:
LpSolveException

setBoundsTighter

public void setBoundsTighter(boolean tighten)
Specifies if set bounds may only be tighter or also less restrictive.


getBoundsTighter

public boolean getBoundsTighter()
Returns if set bounds may only be tighter or also less restrictive.


setRhRange

public void setRhRange(int rownr,
                       double range)
                throws LpSolveException
Set the range on a constraint.

Throws:
LpSolveException

getRhRange

public double getRhRange(int rownr)
                  throws LpSolveException
Gets the range on a constraint.

Throws:
LpSolveException

setInt

public void setInt(int colnr,
                   boolean mustBeInteger)
            throws LpSolveException
Set the type of the variable. Integer or floating point.

Throws:
LpSolveException

isInt

public boolean isInt(int colnr)
Get the type of the variable. Integer or floating point.


setBinary

public void setBinary(int colnr,
                      boolean mustBeBin)
               throws LpSolveException
Set the type of the variable. Binary or floating point.

Throws:
LpSolveException

isBinary

public boolean isBinary(int colnr)
Gets the type of the variable. Binary integer or floating point.


setSemicont

public void setSemicont(int colnr,
                        boolean mustBeSc)
                 throws LpSolveException
Set the type of the variable. semi-continious or not.

Throws:
LpSolveException

isSemicont

public boolean isSemicont(int colnr)
Get the type of the variable. semi-continious or not.


setInfinite

public void setInfinite(double value)
Specifies the practical value for "infinite".


getInfinite

public double getInfinite()
Returns the value of "infinite".


isInfinite

public boolean isInfinite(double value)
Checks if the provided absolute of the value is larger or equal to "infinite".


setEpsint

public void setEpsint(double value)
Specifies the tolerance that is used to determine whether a floating-point number is in fact an integer.


getEpsint

public double getEpsint()
Returns the tolerance that is used to determine whether a floating-point number is in fact an integer


setEpsb

public void setEpsb(double value)
Specifies the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0


getEpsb

public double getEpsb()
Returns the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.


setEpsd

public void setEpsd(double value)
Specifies the value that is used as a tolerance for reduced costs to determine whether a value should be considered as 0.


getEpsd

public double getEpsd()
Returns the value that is used as a tolerance for the reduced costs to determine whether a value should be considered as 0.


setEpsel

public void setEpsel(double value)
Specifies the value that is used as a tolerance for rounding values to zero.


getEpsel

public double getEpsel()
Returns the value that is used as a tolerance for rounding values to zero.


setEpspivot

public void setEpspivot(double value)
Specifies the value that is used as a tolerance pivot element to determine whether a value should be considered as 0.


getEpspivot

public double getEpspivot()
Returns the value that is used as a tolerance pivot element to determine whether a value should be considered as 0.


setEpsperturb

public void setEpsperturb(double value)
Specifies the value that is used as perturbation scalar for degenerative problems.


getEpsperturb

public double getEpsperturb()
Returns the value that is used as perturbation scalar for degenerative problems.


setEpslevel

public void setEpslevel(int epslevel)
                 throws LpSolveException
This is a simplified way of specifying multiple eps thresholds that are "logically" consistent.

Throws:
LpSolveException

getStatus

public int getStatus()
Returns an extra status after a call to a function.


setMipGap

public void setMipGap(boolean absolute,
                      double value)
Specifies the MIP gap value.


getMipGap

public double getMipGap(boolean absolute)
Returns the MIP gap value.


setVerbose

public void setVerbose(int verbose)
Set the verbose level.


getVerbose

public int getVerbose()
Returns the verbose level.


setTimeout

public void setTimeout(long timeout)
Set a timeout.


getTimeout

public long getTimeout()
Gets the timout.


timeElapsed

public double timeElapsed()
Gets the time elapsed since start of solve.


setPrintSol

public void setPrintSol(int printSol)
Sets a flag if all intermediate valid solutions must be printed while solving.


getPrintSol

public int getPrintSol()
Returns a flag if all intermediate valid solutions must be printed while solving.


setDebug

public void setDebug(boolean debug)
Sets a flag if all intermediate results and the branch-and-bound decisions must be printed while solving.


isDebug

public boolean isDebug()
Returns a flag if all intermediate results and the branch-and-bound decisions must be printed while solving.


setTrace

public void setTrace(boolean trace)
Sets a flag if pivot selection must be printed while solving.


isTrace

public boolean isTrace()
Returns a flag if pivot selection must be printed while solving.


setLagTrace

public void setLagTrace(boolean lagTrace)
Sets a flag if Lagrangian progression must be printed while solving.


isLagTrace

public boolean isLagTrace()
Returns a flag if Lagrangian progression must be printed while solving.


setAddRowmode

public boolean setAddRowmode(boolean turnon)
Specifies which add routine performs best.


isAddRowmode

public boolean isAddRowmode()
Returns a flag which of the add routines perform best.


setAntiDegen

public void setAntiDegen(int antiDegen)
Specifies if special handling must be done to reduce degeneracy/cycling while solving.


isAntiDegen

public boolean isAntiDegen(int testmask)
Returns if the degeneracy rule specified in testmask is active.


getAntiDegen

public int getAntiDegen()
Returns the used degeneracy rule.


setPresolve

public void setPresolve(int doPresolve,
                        int maxloops)
Specifies if a presolve must be done before solving.


isPresolve

public boolean isPresolve(int testmask)
Returns if presolve level specified in testmask is active.


getPresolve

public int getPresolve()
Returns the current presolve setting.


getPresolveloops

public int getPresolveloops()
Returns the number of times presolve is done.


setMaxpivot

public void setMaxpivot(int maxNumInv)
Sets the maximum number of pivots between a reinversion of the matrix.


getMaxpivot

public int getMaxpivot()
Returns the maximum number of pivots between a reinversion of the matrix.


setBbRule

public void setBbRule(int bbRule)
Specifies the branch-and-bound rule.


getBbRule

public int getBbRule()
Returns the branch-and-bound rule.


setBbDepthlimit

public void setBbDepthlimit(int bbMaxlevel)
Sets the maximum branch-and-bound depth.


getBbDepthlimit

public int getBbDepthlimit()
Returns the maximum branch-and-bound depth.


getSolutioncount

public int getSolutioncount()
Returns the number of equal solutions.


setSolutionlimit

public void setSolutionlimit(int limit)
Sets the solution number that must be returned.


getSolutionlimit

public int getSolutionlimit()
Returns the solution number that must be returned.


setObjBound

public void setObjBound(double objBound)
Set initial "at least better than" guess for objective function.


getObjBound

public double getObjBound()
Returns initial "at least better than" guess for objective function.


setBbFloorfirst

public void setBbFloorfirst(int floorFirst)
Specifies which branch to take first in branch-and-bound algorithm.


getBbFloorfirst

public int getBbFloorfirst()
Returns which branch to take first in branch-and-bound algorithm.


setVarBranch

public void setVarBranch(int colnr,
                         int branchMode)
                  throws LpSolveException
Specifies, for the specified variable, which branch to take first in branch-and-bound algorithm.

Throws:
LpSolveException

getVarBranch

public int getVarBranch(int colnr)
                 throws LpSolveException
Returns, for the specified variable, which branch to take first in branch-and-bound algorithm.

Throws:
LpSolveException

setVarWeights

public void setVarWeights(double[] weights)
                   throws LpSolveException
Set the weights on variables.

Throws:
LpSolveException

getVarPriority

public int getVarPriority(int colnr)
                   throws LpSolveException
Returns, for the specified variable, the priority the variable has in the branch-and-bound algorithm.

Throws:
LpSolveException

setBreakAtFirst

public void setBreakAtFirst(boolean breakAtFirst)
Specifies if the branch-and-bound algorithm stops at first found solution.


isBreakAtFirst

public boolean isBreakAtFirst()
Returns if the branch-and-bound algorithm stops at first found solution.


setBreakAtValue

public void setBreakAtValue(double breakAtValue)
Specifies if the branch-and-bound algorithm stops when the object value is better than a given value.


getBreakAtValue

public double getBreakAtValue()
Returns the value at which the branch-and-bound algorithm stops when the object value is better than this value.


setScaling

public void setScaling(int scalemode)
Specifies which scaling algorithm must be used.


getScaling

public int getScaling()
Specifies which scaling algorithm is used.


isScalemode

public boolean isScalemode(int testmask)
Returns if scaling mode specified in testmask is active.


isScaletype

public boolean isScaletype(int scaletype)
Returns if scaling type specified in scaletype is active.


isIntegerscaling

public boolean isIntegerscaling()
Specifies which scaling algorithm is used.


setScalelimit

public void setScalelimit(double scalelimit)
Sets the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations.


getScalelimit

public double getScalelimit()
Returns the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations.


setImprove

public void setImprove(int improve)
Specifies the iterative improvement level.


getImprove

public int getImprove()
Returns the iterative improvement level.


setPivoting

public void setPivoting(int pivRule)
Specifies the pivot rule.


getPivoting

public int getPivoting()
Returns the pivot rule.


isPivMode

public boolean isPivMode(int testmask)
Returns if pivot strategy specified in testmask is active.


isPivRule

public boolean isPivRule(int rule)
Checks if the specified pivot rule is active.


setPreferdual

public void setPreferdual(boolean dodual)
Sets the desired combination of primal and dual simplex algorithms.


setSimplextype

public void setSimplextype(int simplextype)
Sets the desired combination of primal and dual simplex algorithms.


getSimplextype

public int getSimplextype()
Returns the desired combination of primal and dual simplex algorithms.


setNegrange

public void setNegrange(double negRange)
Set negative value below which variables are split into a negative and a positive part.


getNegrange

public double getNegrange()
Returns the negative value below which variables are split into a negative and a positive part.


getTotalIter

public long getTotalIter()
Returns the total number of iterations with Branch-and-bound of the last solution.


getMaxLevel

public int getMaxLevel()
Returns the deepest Branch-and-bound level of the last solution.


getTotalNodes

public long getTotalNodes()
Returns the total number of nodes processed in branch-and-bound.


getNrows

public int getNrows()
Returns the number of rows (constraints) in the problem.


getNorigRows

public int getNorigRows()
Returns the number of original rows (constraints) in the problem.


getLrows

public int getLrows()
Returns the number of Lagrangian rows in the lp.


getNcolumns

public int getNcolumns()
Returns the number of columns (variables) in the problem.


getNorigColumns

public int getNorigColumns()
Returns the number of original columns (variables) in the problem.


getNonzeros

public int getNonzeros()
Returns the number of non-zero elements in the matrix.


getOrigIndex

public int getOrigIndex(int index)
Returns the original row/column where a constraint/variable was before presolve.


getLpIndex

public int getLpIndex(int index)
Returns the index in the lp of the original row/column.


setBasis

public void setBasis(int[] bascolumn,
                     boolean nonbasic)
              throws LpSolveException
Sets an initial basis of the lp.

Throws:
LpSolveException

getBasis

public void getBasis(int[] bascolumn,
                     boolean nonbasic)
              throws LpSolveException
Returns the basis of the lp.

Throws:
LpSolveException

resetBasis

public void resetBasis()
Resets the basis to the initial basis.


defaultBasis

public void defaultBasis()
Sets the starting base to an all slack basis (the default simplex starting basis).


setBasiscrash

public void setBasiscrash(int mode)
Specifies which basis crash mode must be used.


getBasiscrash

public int getBasiscrash()
Returns which basis crash mode must be used.


guessBasis

public void guessBasis(double[] guessvector, int[] basisvector)
              throws LpSolveException
Guess a basis for the lp.

Throws:
LpSolveException

unscale

public void unscale()
Unscales the model.


setBFP

public void setBFP(java.lang.String filename)
            throws LpSolveException
Set basis factorization package.

Throws:
LpSolveException

isNativeBFP

public boolean isNativeBFP()
Returns if the native (build-in) basis factorization package (BFP) is used, or an external package.


hasBFP

public boolean hasBFP()
Returns if there is a basis factorization package (BFP) available.


solve

public int solve()
          throws LpSolveException
Solve the model.

Throws:
LpSolveException

getStatustext

public java.lang.String getStatustext(int statuscode)
Returns the description of a returncode of the solve function.


isFeasible

public boolean isFeasible(double[] values,
                          double threshold)
                   throws LpSolveException
Checks if provided solution is a feasible solution.

Throws:
LpSolveException

getObjective

public double getObjective()
                    throws LpSolveException
Returns the value of the objective function.

Throws:
LpSolveException

getWorkingObjective

public double getWorkingObjective()
                           throws LpSolveException
Returns the value of the objective function.

Throws:
LpSolveException

getVariables

public void getVariables(double[] var)
                  throws LpSolveException
Returns the values of the variables. Passed in arrays must be allocated by the caller of the method.

Throws:
LpSolveException

getPtrVariables

public double[] getPtrVariables()
                         throws LpSolveException
Returns the values of the variables. Returned array is allocated by the method.

Throws:
LpSolveException

getConstraints

public void getConstraints(double[] var)
                    throws LpSolveException
Returns the values of the constraints. Passed in arrays must be allocated by the caller of the method.

Throws:
LpSolveException

getPtrConstraints

public double[] getPtrConstraints()
                           throws LpSolveException
Returns the values of the constraints. Returned array is allocated by the method.

Throws:
LpSolveException

getPrimalSolution

public void getPrimalSolution(double[] pv)
                       throws LpSolveException
Returns the solution of the model. Passed in arrays must be allocated by the caller of the method.

Throws:
LpSolveException

getPtrPrimalSolution

public double[] getPtrPrimalSolution()
                              throws LpSolveException
Returns the solution of the model. Returned array is allocated by the method.

Throws:
LpSolveException

getVarPrimalresult

public double getVarPrimalresult(int index)
                          throws LpSolveException
Returns the solution of the model.

Throws:
LpSolveException

getSensitivityRhs

public void getSensitivityRhs(double[] duals,
                              double[] dualsfrom,
                              double[] dualstill)
                       throws LpSolveException
Returns the sensitivity of the constraints and the variables. Passed in arrays must be allocated by the caller of the method.

Throws:
LpSolveException

getPtrSensitivityRhs

public double[][] getPtrSensitivityRhs()
                                throws LpSolveException
Returns the sensitivity of the constraints and the variables. Returned arrays are allocated by the method. The returned array contains two elements of type double[]. element [0] is the duals array, element [1] is the dualsfrom array, element [2] is the dualstill array.

Throws:
LpSolveException

getDualSolution

public void getDualSolution(double[] duals)
                     throws LpSolveException
Returns the sensitivity of the constraints and the variables. Passed in arrays must be allocated by the caller of the method.

Throws:
LpSolveException

getPtrDualSolution

public double[] getPtrDualSolution()
                            throws LpSolveException
Returns the sensitivity of the constraints and the variables. Returned array is allocated by the method.

Throws:
LpSolveException

getVarDualresult

public double getVarDualresult(int index)
                        throws LpSolveException
Returns the sensitivity of the constraints and the variables.

Throws:
LpSolveException

getSensitivityObj

public void getSensitivityObj(double[] objfrom,
                              double[] objtill)
                       throws LpSolveException
Returns the sensitivity of the objective function. Passed in arrays must be allocated by the caller of the method.

Throws:
LpSolveException

getPtrSensitivityObj

public double[][] getPtrSensitivityObj()
                                throws LpSolveException
Returns the sensitivity of the objective function. Returned arrays are allocated by the method. The returned array contains two elements of type double[]. element [0] is the objfrom array, element [1] is the objtill array.

Throws:
LpSolveException

getSensitivityObjex

public void getSensitivityObjex(double[] objfrom,
                                double[] objtill,
                                double[] objfromvalue,
                                double[] objtillvalue)
                         throws LpSolveException
Returns the sensitivity of the objective function. Passed in arrays must be allocated by the caller of the method.

Throws:
LpSolveException

getPtrSensitivityObjex

public double[][] getPtrSensitivityObjex()
                                  throws LpSolveException
Returns the sensitivity of the objective function. Returned arrays are allocated by the method. The returned array contains four elements of type double[]. element [0] is the objfrom array, element [1] is the objtill array, element [2] is the objfromvalue array, element [3] is the objtillvalue array.

Throws:
LpSolveException

getLambda

public void getLambda(double[] lambda)
               throws LpSolveException
Returns the Lamdba vectors (Lagrangian optimization). Passed in array must be allocated by the caller of the method.

Throws:
LpSolveException

getPtrLambda

public double[] getPtrLambda()
                      throws LpSolveException
Returns the Lamdba vectors (Lagrangian optimization). Returned array is allocated by the method.

Throws:
LpSolveException

deleteLp

public void deleteLp()
Frees all resources allocated to this problem.


writeLp

public void writeLp(java.lang.String filename)
             throws LpSolveException
Write an lp model to a file.

Throws:
LpSolveException

writeMps

public void writeMps(java.lang.String filename)
              throws LpSolveException
Write an mps model to a file.

Throws:
LpSolveException

writeFreeMps

public void writeFreeMps(java.lang.String filename)
                  throws LpSolveException
Write a model in free MPS format to a file.

Throws:
LpSolveException

readBasis

public java.lang.String readBasis(java.lang.String filename)
                           throws LpSolveException
Read basis from a file and set as default basis. The info text is returned as method result.

Throws:
LpSolveException

writeBasis

public void writeBasis(java.lang.String filename)
                throws LpSolveException
Writes current basis to a file.

Throws:
LpSolveException

readParams

public void readParams(java.lang.String filename,
                       java.lang.String options)
                throws LpSolveException
Read settings from a parameter file.

Throws:
LpSolveException

writeParams

public void writeParams(java.lang.String filename,
                        java.lang.String options)
                 throws LpSolveException
Write settings to a parameter file.

Throws:
LpSolveException

resetParams

public void resetParams()
Resets parameters back to their default values.


printLp

public void printLp()
Prints the lp model. This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to setOutputfile.


printConstraints

public void printConstraints(int columns)
Prints the values of the constraints of the lp. This can only be done after a successful solve. This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to setOutputfile.


printDuals

public void printDuals()
Prints the values of the duals of the lp. This can only be done after a successful solve. This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to setOutputfile.


printScales

public void printScales()
Prints the scales of the lp. This can only be done after a successful solve. This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to setOutputfile.


printTableau

public void printTableau()
Prints the tableau. This can only be done after a successful solve. This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to setOutputfile.


printObjective

public void printObjective()
Prints the objective value of the lp. This can only be done after a successful solve. This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to setOutputfile.


printSolution

public void printSolution(int columns)
Prints the solution (variables) of the lp. This can only be done after a successful solve. This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to setOutputfile.


printStr

public void printStr(java.lang.String str)
Prints a string.


setOutputfile

public void setOutputfile(java.lang.String filename)
                   throws LpSolveException
Defines the output for the print_* functions.

Throws:
LpSolveException

printDebugdump

public void printDebugdump(java.lang.String filename)
                    throws LpSolveException
Do a generic readable data dump of key lp_solve model variables; principally for run difference and debugging purposes.

Throws:
LpSolveException

setXLI

public void setXLI(java.lang.String filename)
            throws LpSolveException
Set External Language Interfaces package.

Throws:
LpSolveException

writeXLI

public void writeXLI(java.lang.String filename,
                     java.lang.String options,
                     boolean results)
              throws LpSolveException
Write a model to a file via the External Language Interface.

Throws:
LpSolveException

hasXLI

public boolean hasXLI()
Returns if there is an external language interface (XLI) set.


isNativeXLI

public boolean isNativeXLI()
Returns if a build-in External Language Interfaces (XLI) is available or not.


getNameindex

public int getNameindex(java.lang.String name,
                        boolean isRow)
Gets the index of a given column or row name in the lp. A return value of -1 indicates that the name does not exist.


dualizeLp

public void dualizeLp()
               throws LpSolveException
Create the dual of the current model.

Throws:
LpSolveException

isUseNames

public boolean isUseNames(boolean isRow)
Returns if variable or constraint names are used.


setUseNames

public void setUseNames(boolean isRow,
                        boolean useNames)
Sets if variable or constraint names are used.


getConstrValue

public double getConstrValue(int rownr,
                             int count,
                             double[] primsolution,
                             int[] nzindex)
Gets the value of a constraint according to provided variable values.


setBasisvar

public int setBasisvar(int basisPos,
                       int enteringCol)
This is an internal function that has been published for special purposes. It should generally not be used.


putAbortfunc

public void putAbortfunc(AbortListener listener,
                         java.lang.Object userhandle)
                  throws LpSolveException
Register an AbortListener for callback.

Parameters:
listener - the listener that should be called by lp_solve
userhandle - an arbitrary object that is passed to the listener on call
Throws:
LpSolveException

putLogfunc

public void putLogfunc(LogListener listener,
                       java.lang.Object userhandle)
                throws LpSolveException
Register an LogListener for callback.

Parameters:
listener - the listener that should be called by lp_solve
userhandle - an arbitrary object that is passed to the listener on call
Throws:
LpSolveException

putMsgfunc

public void putMsgfunc(MsgListener listener,
                       java.lang.Object userhandle,
                       int mask)
                throws LpSolveException
Register an MsgListener for callback.

Parameters:
listener - the listener that should be called by lp_solve
userhandle - an arbitrary object that is passed to the listener on call
Throws:
LpSolveException

putBbBranchfunc

public void putBbBranchfunc(BbListener listener,
                            java.lang.Object userhandle)
                     throws LpSolveException
Register an BbBranchListener for callback.

Parameters:
listener - the listener that should be called by lp_solve
userhandle - an arbitrary object that is passed to the listener on call
Throws:
LpSolveException

putBbNodefunc

public void putBbNodefunc(BbListener listener,
                          java.lang.Object userhandle)
                   throws LpSolveException
Register an BbNodeListener for callback.

Parameters:
listener - the listener that should be called by lp_solve
userhandle - an arbitrary object that is passed to the listener on call
Throws:
LpSolveException


Copyright 2004 - Juergen Ebert doc/Java/docs/api/lpsolve/LpSolveException.html0000644000175000017500000002345510257560740020505 0ustar renerene LpSolveException (Using lp_solve in Java programs)

lpsolve
Class LpSolveException

java.lang.Object
  extended byjava.lang.Throwable
      extended byjava.lang.Exception
          extended bylpsolve.LpSolveException
All Implemented Interfaces:
java.io.Serializable

public class LpSolveException
extends java.lang.Exception

Exception thrown by the native methods in the C stub DLL.

Author:
Juergen Ebert
See Also:
Serialized Form

Field Summary
 
Fields inherited from class java.lang.Exception
 
Constructor Summary
LpSolveException()
           
LpSolveException(java.lang.String arg0)
           
 
Methods inherited from class java.lang.Throwable
fillInStackTrace, getCause, getLocalizedMessage, getMessage, getStackTrace, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

LpSolveException

public LpSolveException()

LpSolveException

public LpSolveException(java.lang.String arg0)
Parameters:
arg0 -


Copyright 2004 - Juergen Ebert doc/Java/docs/api/lpsolve/package-tree.html0000644000175000017500000001336410257560736017575 0ustar renerene lpsolve Class Hierarchy (Using lp_solve in Java programs)

Hierarchy For Package lpsolve

Class Hierarchy

Interface Hierarchy



Copyright 2004 - Juergen Ebert doc/Java/docs/api/lpsolve/MsgListener.html0000644000175000017500000002120510257560736017472 0ustar renerene MsgListener (Using lp_solve in Java programs)

lpsolve
Interface MsgListener


public interface MsgListener

Classes that implement this interface may be passed to the putMsgfunc method of the LpSolve class.

Author:
Juergen Ebert
See Also:
LpSolve.putMsgfunc(lpsolve.MsgListener, java.lang.Object, int), "lp_solve documentation for 'put_msgfunc'"

Method Summary
 void msgfunc(LpSolve problem, java.lang.Object userhandle, int msg)
          This routine is called when a situation specified in the mask parameter of putMsgfunc occurs.
 

Method Detail

msgfunc

public void msgfunc(LpSolve problem,
                    java.lang.Object userhandle,
                    int msg)
             throws LpSolveException
This routine is called when a situation specified in the mask parameter of putMsgfunc occurs. Note that this routine is called while solving the model. This can be usefull to follow the solving progress.

Parameters:
problem - the problem this Listener was defined for
userhandle - the userhandle object that was passed to putMsgfunc
msg - event code why this method was called
Throws:
LpSolveException


Copyright 2004 - Juergen Ebert doc/Java/docs/api/lpsolve/package-summary.html0000644000175000017500000001737110257560736020335 0ustar renerene lpsolve (Using lp_solve in Java programs)

Package lpsolve

This package contains the files for the Java wrapper for the lp_solve optimization library.

See:
          Description

Interface Summary
AbortListener Classes that implement this interface may be passed to the putAbortfunc method of the LpSolve class.
BbListener Classes that implement this interface may be passed to the putbbBranchfunc and putbbNodefunc method of the LpSolve class.
LogListener Classes that implement this interface may be passed to the putLogfunc method of the LpSolve class.
MsgListener Classes that implement this interface may be passed to the putMsgfunc method of the LpSolve class.
 

Class Summary
LpSolve Object wrapper for a problem structure of the lp_solve library.
VersionInfo Contains the full version info for a lp_solve library instance.
 

Exception Summary
LpSolveException Exception thrown by the native methods in the C stub DLL.
 

Package lpsolve Description

This package contains the files for the Java wrapper for the lp_solve optimization library. See the file README.html in the root direcory of the distribution archive for details.



Copyright 2004 - Juergen Ebert doc/Java/docs/api/lpsolve/VersionInfo.html0000644000175000017500000002527610257560736017513 0ustar renerene VersionInfo (Using lp_solve in Java programs)

lpsolve
Class VersionInfo

java.lang.Object
  extended bylpsolve.VersionInfo

public class VersionInfo
extends java.lang.Object

Contains the full version info for a lp_solve library instance.

Author:
Juergen Ebert

Constructor Summary
VersionInfo(int major, int minor, int release, int build)
          Creates a new instance of this class
 
Method Summary
 int getBuild()
           
 int getMajorversion()
           
 int getMinorversion()
           
 int getRelease()
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

VersionInfo

public VersionInfo(int major,
                   int minor,
                   int release,
                   int build)
Creates a new instance of this class

Method Detail

getBuild

public int getBuild()
Returns:
value of the build attribute

getMajorversion

public int getMajorversion()
Returns:
value of the majorversion attribute

getMinorversion

public int getMinorversion()
Returns:
value of the minorversion attribute

getRelease

public int getRelease()
Returns:
value of the release attribute


Copyright 2004 - Juergen Ebert doc/Java/docs/api/lpsolve/BbListener.html0000644000175000017500000002136510257560736017276 0ustar renerene BbListener (Using lp_solve in Java programs)

lpsolve
Interface BbListener


public interface BbListener

Classes that implement this interface may be passed to the putbbBranchfunc and putbbNodefunc method of the LpSolve class.

Author:
Juergen Ebert
See Also:
LpSolve.putBbBranchfunc(lpsolve.BbListener, java.lang.Object), LpSolve.putBbNodefunc(lpsolve.BbListener, java.lang.Object), "lp_solve documentation for 'put_bb_branchfunc'", "lp_solve documentation for 'put_bb_nodefunc'"

Method Summary
 int bbfunc(LpSolve problem, java.lang.Object userhandle, int message)
          TODO: add documentation when available
 

Method Detail

bbfunc

public int bbfunc(LpSolve problem,
                  java.lang.Object userhandle,
                  int message)
           throws LpSolveException
TODO: add documentation when available

Parameters:
problem - the problem this Listener was defined for
userhandle - the userhandle object that was passed to putLogfunc
Throws:
LpSolveException


Copyright 2004 - Juergen Ebert doc/Java/docs/api/index-all.html0000644000175000017500000027645711230412665015441 0ustar renerene Index (Using lp_solve in Java programs)
A B C D E F G H I L M N O P R S T U V W

A

ANTIDEGEN_BOUNDFLIP - Static variable in class lpsolve.LpSolve
 
ANTIDEGEN_COLUMNCHECK - Static variable in class lpsolve.LpSolve
 
ANTIDEGEN_DURINGBB - Static variable in class lpsolve.LpSolve
 
ANTIDEGEN_DYNAMIC - Static variable in class lpsolve.LpSolve
 
ANTIDEGEN_FIXEDVARS - Static variable in class lpsolve.LpSolve
 
ANTIDEGEN_INFEASIBLE - Static variable in class lpsolve.LpSolve
 
ANTIDEGEN_LOSTFEAS - Static variable in class lpsolve.LpSolve
 
ANTIDEGEN_NONE - Static variable in class lpsolve.LpSolve
 
ANTIDEGEN_NUMFAILURE - Static variable in class lpsolve.LpSolve
 
ANTIDEGEN_RHSPERTURB - Static variable in class lpsolve.LpSolve
 
ANTIDEGEN_STALLING - Static variable in class lpsolve.LpSolve
 
AUTOMATIC - Static variable in class lpsolve.LpSolve
 
AbortListener - interface lpsolve.AbortListener.
Classes that implement this interface may be passed to the putAbortfunc method of the LpSolve class.
abortfunc(LpSolve, Object) - Method in interface lpsolve.AbortListener
When set, the abort routine is called regularly during solve().
addColumn(double[]) - Method in class lpsolve.LpSolve
Add a column to the problem.
addColumnex(int, double[], int[]) - Method in class lpsolve.LpSolve
Add a column to the problem.
addConstraint(double[], int, double) - Method in class lpsolve.LpSolve
Add a constraint to the problem.
addConstraintex(int, double[], int[], int, double) - Method in class lpsolve.LpSolve
Add a constraint to the problem.
addLagCon(double[], int, double) - Method in class lpsolve.LpSolve
Add a Lagrangian constraint to the problem.
addSOS(String, int, int, int, int[], double[]) - Method in class lpsolve.LpSolve
Add a SOS constraint.

B

BRANCH_AUTOMATIC - Static variable in class lpsolve.LpSolve
 
BRANCH_CEILING - Static variable in class lpsolve.LpSolve
 
BRANCH_FLOOR - Static variable in class lpsolve.LpSolve
 
BRANCH_DEFAULT - Static variable in class lpsolve.LpSolve
 
BbListener - interface lpsolve.BbListener.
Classes that implement this interface may be passed to the putbbBranchfunc and putbbNodefunc method of the LpSolve class.
bbfunc(LpSolve, Object, int) - Method in interface lpsolve.BbListener
TODO: add documentation when available

C

CRASH_MOSTFEASIBLE - Static variable in class lpsolve.LpSolve
 
CRASH_NOTHING - Static variable in class lpsolve.LpSolve
 
CRITICAL - Static variable in class lpsolve.LpSolve
 
columnInLp(double[]) - Method in class lpsolve.LpSolve
Check if a column is already present in the problem.
copyLp() - Method in class lpsolve.LpSolve
Copy an existing lprec structure to a new lprec structure.

D

DATAIGNORED - Static variable in class lpsolve.LpSolve
 
DEGENERATE - Static variable in class lpsolve.LpSolve
 
DETAILED - Static variable in class lpsolve.LpSolve
 
DYNAMIC - Static variable in class lpsolve.LpSolve
 
defaultBasis() - Method in class lpsolve.LpSolve
Sets the starting base to an all slack basis (the default simplex starting basis).
delColumn(int) - Method in class lpsolve.LpSolve
Remove a column from the problem.
delConstraint(int) - Method in class lpsolve.LpSolve
Remove a constraint from the problem.
deleteLp() - Method in class lpsolve.LpSolve
Frees all resources allocated to this problem.
dualizeLp() - Method in class lpsolve.LpSolve
Create the dual of the current model.

E

EQ - Static variable in class lpsolve.LpSolve
 

F

FALSE - Static variable in class lpsolve.LpSolve
 
FEASFOUND - Static variable in class lpsolve.LpSolve
 
FR - Static variable in class lpsolve.LpSolve
 
FULL - Static variable in class lpsolve.LpSolve
 
PRESOLVED - Static variable in class lpsolve.LpSolve
 
finalize() - Method in class lpsolve.LpSolve
 

G

GE - Static variable in class lpsolve.LpSolve
 
getAntiDegen() - Method in class lpsolve.LpSolve
Returns the used degeneracy rule.
getBasis(int[], boolean) - Method in class lpsolve.LpSolve
Returns the basis of the lp.
getBasiscrash() - Method in class lpsolve.LpSolve
Returns which basis crash mode must be used.
getBbDepthlimit() - Method in class lpsolve.LpSolve
Returns the maximum branch-and-bound depth.
getBbFloorfirst() - Method in class lpsolve.LpSolve
Returns which branch to take first in branch-and-bound algorithm.
getBbRule() - Method in class lpsolve.LpSolve
Returns the branch-and-bound rule.
getBoundsTighter() - Method in class lpsolve.LpSolve
Returns if set bounds may only be tighter or also less restrictive.
getBreakAtValue() - Method in class lpsolve.LpSolve
Returns the value at which the branch-and-bound algorithm stops when the object value is better than this value.
getBuild() - Method in class lpsolve.VersionInfo
 
getColName(int) - Method in class lpsolve.LpSolve
Gets the name of a column in the problem.
getColumn(int, double[]) - Method in class lpsolve.LpSolve
Get all column elements from the matrix.
getColumnex(int, double[], int[]) - Method in class lpsolve.LpSolve
Get the non-zero column elements from the matrix.
getConstrType(int) - Method in class lpsolve.LpSolve
Get the type of a constraint.
getConstrValue(int, int, double[], int[]) - Method in class lpsolve.LpSolve
Gets the value of a constraint according to provided variable values.
getConstraints(double[]) - Method in class lpsolve.LpSolve
Returns the values of the constraints.
getDualSolution(double[]) - Method in class lpsolve.LpSolve
Returns the sensitivity of the constraints and the variables.
getEpsb() - Method in class lpsolve.LpSolve
Returns the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.
getEpsd() - Method in class lpsolve.LpSolve
Returns the value that is used as a tolerance for the reduced costs to determine whether a value should be considered as 0.
getEpsel() - Method in class lpsolve.LpSolve
Returns the value that is used as a tolerance for rounding values to zero.
getEpsint() - Method in class lpsolve.LpSolve
Returns the tolerance that is used to determine whether a floating-point number is in fact an integer
getEpsperturb() - Method in class lpsolve.LpSolve
Returns the value that is used as perturbation scalar for degenerative problems.
getEpspivot() - Method in class lpsolve.LpSolve
Returns the value that is used as a tolerance pivot element to determine whether a value should be considered as 0.
getImprove() - Method in class lpsolve.LpSolve
Returns the iterative improvement level.
getInfinite() - Method in class lpsolve.LpSolve
Returns the value of "infinite".
getLambda(double[]) - Method in class lpsolve.LpSolve
Returns the Lamdba vectors (Lagrangian optimization).
getLowbo(int) - Method in class lpsolve.LpSolve
Get the lower bound of a variable.
getLp() - Method in class lpsolve.LpSolve
Return the value of the lp attribute.
getLpIndex(int) - Method in class lpsolve.LpSolve
Returns the index in the lp of the original row/column.
getLpName() - Method in class lpsolve.LpSolve
Get the name of the problem.
getLrows() - Method in class lpsolve.LpSolve
Returns the number of Lagrangian rows in the lp.
getMajorversion() - Method in class lpsolve.VersionInfo
 
getMat(int, int) - Method in class lpsolve.LpSolve
Get a single element from the matrix.
getMaxLevel() - Method in class lpsolve.LpSolve
Returns the deepest Branch-and-bound level of the last solution.
getMaxpivot() - Method in class lpsolve.LpSolve
Returns the maximum number of pivots between a reinversion of the matrix.
getMinorversion() - Method in class lpsolve.VersionInfo
 
getMipGap(boolean) - Method in class lpsolve.LpSolve
Returns the MIP gap value.
getNameindex(String, boolean) - Method in class lpsolve.LpSolve
Gets the index of a given column or row name in the lp.
getNcolumns() - Method in class lpsolve.LpSolve
Returns the number of columns (variables) in the problem.
getNegrange() - Method in class lpsolve.LpSolve
Returns the negative value below which variables are split into a negative and a positive part.
getNonzeros() - Method in class lpsolve.LpSolve
Returns the number of non-zero elements in the matrix.
getNorigColumns() - Method in class lpsolve.LpSolve
Returns the number of original columns (variables) in the problem.
getNorigRows() - Method in class lpsolve.LpSolve
Returns the number of original rows (constraints) in the problem.
getNrows() - Method in class lpsolve.LpSolve
Returns the number of rows (constraints) in the problem.
getObjBound() - Method in class lpsolve.LpSolve
Returns initial "at least better than" guess for objective function.
getObjective() - Method in class lpsolve.LpSolve
Returns the value of the objective function.
getOrigIndex(int) - Method in class lpsolve.LpSolve
Returns the original row/column where a constraint/variable was before presolve.
getOrigcolName(int) - Method in class lpsolve.LpSolve
Gets the name of a column in the problem.
getOrigrowName(int) - Method in class lpsolve.LpSolve
Gets the name of a constraint (row) in the problem.
getPivoting() - Method in class lpsolve.LpSolve
Returns the pivot rule.
getPresolve() - Method in class lpsolve.LpSolve
Returns the current presolve setting.
getPresolveloops() - Method in class lpsolve.LpSolve
Returns the number of times presolve is done.
getPrimalSolution(double[]) - Method in class lpsolve.LpSolve
Returns the solution of the model.
getPrintSol() - Method in class lpsolve.LpSolve
Returns a flag if all intermediate valid solutions must be printed while solving.
getPtrColumn(int) - Method in class lpsolve.LpSolve
Get all column elements from the matrix.
getPtrConstraints() - Method in class lpsolve.LpSolve
Returns the values of the constraints.
getPtrDualSolution() - Method in class lpsolve.LpSolve
Returns the sensitivity of the constraints and the variables.
getPtrLambda() - Method in class lpsolve.LpSolve
Returns the Lamdba vectors (Lagrangian optimization).
getPtrPrimalSolution() - Method in class lpsolve.LpSolve
Returns the solution of the model.
getPtrRow(int) - Method in class lpsolve.LpSolve
Get all row elements from the matrix.
getPtrSensitivityObj() - Method in class lpsolve.LpSolve
Returns the sensitivity of the objective function.
getPtrSensitivityObjex() - Method in class lpsolve.LpSolve
Returns the sensitivity of the objective function.
getPtrSensitivityRhs() - Method in class lpsolve.LpSolve
Returns the sensitivity of the constraints and the variables.
getPtrVariables() - Method in class lpsolve.LpSolve
Returns the values of the variables.
getRelease() - Method in class lpsolve.VersionInfo
 
getRh(int) - Method in class lpsolve.LpSolve
Get the value of the right hand side (RHS) vector (column 0) for one row.
getRhRange(int) - Method in class lpsolve.LpSolve
Gets the range on a constraint.
getRow(int, double[]) - Method in class lpsolve.LpSolve
Get all row elements from the matrix.
getRowName(int) - Method in class lpsolve.LpSolve
Gets the name of a constraint (row) in the problem.
getRowex(int, double[], int[]) - Method in class lpsolve.LpSolve
Get the non-zero row elements from the matrix.
getScalelimit() - Method in class lpsolve.LpSolve
Returns the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations.
getScaling() - Method in class lpsolve.LpSolve
Specifies which scaling algorithm is used.
getSensitivityObj(double[], double[]) - Method in class lpsolve.LpSolve
Returns the sensitivity of the objective function.
getSensitivityObjex(double[], double[], double[], double[]) - Method in class lpsolve.LpSolve
Returns the sensitivity of the objective function.
getSensitivityRhs(double[], double[], double[]) - Method in class lpsolve.LpSolve
Returns the sensitivity of the constraints and the variables.
getSimplextype() - Method in class lpsolve.LpSolve
Returns the desired combination of primal and dual simplex algorithms.
getSolutioncount() - Method in class lpsolve.LpSolve
Returns the number of equal solutions.
getSolutionlimit() - Method in class lpsolve.LpSolve
Returns the solution number that must be returned.
getStatus() - Method in class lpsolve.LpSolve
Returns an extra status after a call to a function.
getStatustext(int) - Method in class lpsolve.LpSolve
Returns the description of a returncode of the solve function.
getTimeout() - Method in class lpsolve.LpSolve
Gets the timout.
getTotalIter() - Method in class lpsolve.LpSolve
Returns the total number of iterations with Branch-and-bound of the last solution.
getTotalNodes() - Method in class lpsolve.LpSolve
Returns the total number of nodes processed in branch-and-bound.
getUpbo(int) - Method in class lpsolve.LpSolve
Get the upper bound of a variable.
getVarBranch(int) - Method in class lpsolve.LpSolve
Returns, for the specified variable, which branch to take first in branch-and-bound algorithm.
getVarDualresult(int) - Method in class lpsolve.LpSolve
Returns the sensitivity of the constraints and the variables.
getVarPrimalresult(int) - Method in class lpsolve.LpSolve
Returns the solution of the model.
getVarPriority(int) - Method in class lpsolve.LpSolve
Returns, for the specified variable, the priority the variable has in the branch-and-bound algorithm.
getVariables(double[]) - Method in class lpsolve.LpSolve
Returns the values of the variables.
getVerbose() - Method in class lpsolve.LpSolve
Returns the verbose level.
getWorkingObjective() - Method in class lpsolve.LpSolve
Returns the value of the objective function.
guessBasis(double[], int[]) - Method in class lpsolve.LpSolve
Guess an initial basis of the lp.

H

hasBFP() - Method in class lpsolve.LpSolve
Returns if there is a basis factorization package (BFP) available.
hasXLI() - Method in class lpsolve.LpSolve
Returns if there is an external language interface (XLI) set.

I

IMPORTANT - Static variable in class lpsolve.LpSolve
 
IMPROVE_BBSIMPLEX - Static variable in class lpsolve.LpSolve
 
IMPROVE_DUALFEAS - Static variable in class lpsolve.LpSolve
 
IMPROVE_NONE - Static variable in class lpsolve.LpSolve
 
IMPROVE_SOLUTION - Static variable in class lpsolve.LpSolve
 
IMPROVE_THETAGAP - Static variable in class lpsolve.LpSolve
 
INFEASIBLE - Static variable in class lpsolve.LpSolve
 
isAddRowmode() - Method in class lpsolve.LpSolve
Returns a flag which of the add routines perform best.
isAntiDegen(int) - Method in class lpsolve.LpSolve
Returns if the degeneracy rule specified in testmask is active.
isBinary(int) - Method in class lpsolve.LpSolve
Gets the type of the variable.
isBreakAtFirst() - Method in class lpsolve.LpSolve
Returns if the branch-and-bound algorithm stops at first found solution.
isConstrType(int, int) - Method in class lpsolve.LpSolve
Returns if constraint type specified in mask is active.
isDebug() - Method in class lpsolve.LpSolve
Returns a flag if all intermediate results and the branch-and-bound decisions must be printed while solving.
isFeasible(double[], double) - Method in class lpsolve.LpSolve
Checks if provided solution is a feasible solution.
isInfinite(double) - Method in class lpsolve.LpSolve
Checks if the provided absolute of the value is larger or equal to "infinite".
isInt(int) - Method in class lpsolve.LpSolve
Get the type of the variable.
isIntegerscaling() - Method in class lpsolve.LpSolve
Specifies which scaling algorithm is used.
isLagTrace() - Method in class lpsolve.LpSolve
Returns a flag if Lagrangian progression must be printed while solving.
isMaxim() - Method in class lpsolve.LpSolve
Returns objective function direction.
isNativeBFP() - Method in class lpsolve.LpSolve
Returns if the native (build-in) basis factorization package (BFP) is used, or an external package.
isNativeXLI() - Method in class lpsolve.LpSolve
Returns if a build-in External Language Interfaces (XLI) is available or not.
isNegative(int) - Method in class lpsolve.LpSolve
Returns if the variable is negative.
isPivMode(int) - Method in class lpsolve.LpSolve
Returns if pivot strategy specified in testmask is active.
isPivRule(int) - Method in class lpsolve.LpSolve
Checks if the specified pivot rule is active.
isPresolve(int) - Method in class lpsolve.LpSolve
Returns if presolve level specified in testmask is active.
isSOSVar(int) - Method in class lpsolve.LpSolve
Returns if the variable is SOS or not.
isScalemode(int) - Method in class lpsolve.LpSolve
Returns if scaling mode specified in testmask is active.
isScaletype(int) - Method in class lpsolve.LpSolve
Returns if scaling type specified in scaletype is active.
isSemicont(int) - Method in class lpsolve.LpSolve
Get the type of the variable. semi-continious or not.
isTrace() - Method in class lpsolve.LpSolve
Returns a flag if pivot selection must be printed while solving.
isUnbounded(int) - Method in class lpsolve.LpSolve
Returns if the variable is free.
isUseNames(boolean) - Method in class lpsolve.LpSolve
Returns if variable or constraint names are used.

L

LE - Static variable in class lpsolve.LpSolve
 
LogListener - interface lpsolve.LogListener.
Classes that implement this interface may be passed to the putLogfunc method of the LpSolve class.
LpSolve - class lpsolve.LpSolve.
Object wrapper for a problem structure of the lp_solve library.
LpSolveException - exception lpsolve.LpSolveException.
Exception thrown by the native methods in the C stub DLL.
LpSolveException() - Constructor for class lpsolve.LpSolveException
 
LpSolveException(String) - Constructor for class lpsolve.LpSolveException
 
logfunc(LpSolve, Object, String) - Method in interface lpsolve.LogListener
When set, the log routine is called when lp_solve has someting to report (error conditions or so).
lpSolveVersion() - Static method in class lpsolve.LpSolve
Returns the full version number of the underlying lp_solve library.
lpsolve - package lpsolve
This package contains the files for the Java wrapper for the lp_solve optimization library.

M

MSG_INITPSEUDOCOST - Static variable in class lpsolve.LpSolve
 
MSG_INVERT - Static variable in class lpsolve.LpSolve
 
MSG_ITERATION - Static variable in class lpsolve.LpSolve
 
MSG_LPBETTER - Static variable in class lpsolve.LpSolve
 
MSG_LPEQUAL - Static variable in class lpsolve.LpSolve
 
MSG_LPFEASIBLE - Static variable in class lpsolve.LpSolve
 
MSG_LPOPTIMAL - Static variable in class lpsolve.LpSolve
 
MSG_MILPBETTER - Static variable in class lpsolve.LpSolve
 
MSG_MILPEQUAL - Static variable in class lpsolve.LpSolve
 
MSG_MILPFEASIBLE - Static variable in class lpsolve.LpSolve
 
MSG_MILPOPTIMAL - Static variable in class lpsolve.LpSolve
 
MSG_MILPSTRATEGY - Static variable in class lpsolve.LpSolve
 
MSG_NONE - Static variable in class lpsolve.LpSolve
 
MSG_PERFORMANCE - Static variable in class lpsolve.LpSolve
 
MSG_PRESOLVE - Static variable in class lpsolve.LpSolve
 
MsgListener - interface lpsolve.MsgListener.
Classes that implement this interface may be passed to the putMsgfunc method of the LpSolve class.
makeLp(int, int) - Static method in class lpsolve.LpSolve
Creates a new problem.
msgfunc(LpSolve, Object, int) - Method in interface lpsolve.MsgListener
This routine is called when a situation specified in the mask parameter of putMsgfunc occurs.

N

NEUTRAL - Static variable in class lpsolve.LpSolve
 
NOBFP - Static variable in class lpsolve.LpSolve
 
NODE_AUTOORDER - Static variable in class lpsolve.LpSolve
 
NODE_BRANCHREVERSEMODE - Static variable in class lpsolve.LpSolve
 
NODE_BREADTHFIRSTMODE - Static variable in class lpsolve.LpSolve
 
NODE_DEPTHFIRSTMODE - Static variable in class lpsolve.LpSolve
 
NODE_DYNAMICMODE - Static variable in class lpsolve.LpSolve
 
NODE_FIRSTSELECT - Static variable in class lpsolve.LpSolve
 
NODE_FRACTIONSELECT - Static variable in class lpsolve.LpSolve
 
NODE_GAPSELECT - Static variable in class lpsolve.LpSolve
 
NODE_GREEDYMODE - Static variable in class lpsolve.LpSolve
 
NODE_PSEUDOCOSTMODE - Static variable in class lpsolve.LpSolve
 
NODE_PSEUDOCOSTSELECT - Static variable in class lpsolve.LpSolve
 
NODE_PSEUDONONINTSELECT - Static variable in class lpsolve.LpSolve
 
NODE_PSEUDORATIOSELECT - Static variable in class lpsolve.LpSolve
 
NODE_RANDOMIZEMODE - Static variable in class lpsolve.LpSolve
 
NODE_RANGESELECT - Static variable in class lpsolve.LpSolve
 
NODE_RCOSTFIXING - Static variable in class lpsolve.LpSolve
 
NODE_RESTARTMODE - Static variable in class lpsolve.LpSolve
 
NODE_STRONGINIT - Static variable in class lpsolve.LpSolve
 
NODE_USERSELECT - Static variable in class lpsolve.LpSolve
 
NODE_WEIGHTREVERSEMODE - Static variable in class lpsolve.LpSolve
 
NOFEASFOUND - Static variable in class lpsolve.LpSolve
 
NOMEMORY - Static variable in class lpsolve.LpSolve
 
NORMAL - Static variable in class lpsolve.LpSolve
 
NOTRUN - Static variable in class lpsolve.LpSolve
 
NUMFAILURE - Static variable in class lpsolve.LpSolve
 

O

OF - Static variable in class lpsolve.LpSolve
 
OPTIMAL - Static variable in class lpsolve.LpSolve
 

P

PRESOLVE_BOUNDS - Static variable in class lpsolve.LpSolve
 
PRESOLVE_COLDOMINATE - Static variable in class lpsolve.LpSolve
 
PRESOLVE_COLFIXDUAL - Static variable in class lpsolve.LpSolve
 
PRESOLVE_COLS - Static variable in class lpsolve.LpSolve
 
PRESOLVE_DUALS - Static variable in class lpsolve.LpSolve
 
PRESOLVE_ELIMEQ2 - Static variable in class lpsolve.LpSolve
 
PRESOLVE_IMPLIEDFREE - Static variable in class lpsolve.LpSolve
 
PRESOLVE_IMPLIEDSLK - Static variable in class lpsolve.LpSolve
 
PRESOLVE_KNAPSACK - Static variable in class lpsolve.LpSolve
 
PRESOLVE_LINDEP - Static variable in class lpsolve.LpSolve
 
PRESOLVE_MERGEROWS - Static variable in class lpsolve.LpSolve
 
PRESOLVE_NONE - Static variable in class lpsolve.LpSolve
 
PRESOLVE_PROBEFIX - Static variable in class lpsolve.LpSolve
 
PRESOLVE_PROBEREDUCE - Static variable in class lpsolve.LpSolve
 
PRESOLVE_REDUCEGCD - Static variable in class lpsolve.LpSolve
 
PRESOLVE_REDUCEMIP - Static variable in class lpsolve.LpSolve
 
PRESOLVE_ROWDOMINATE - Static variable in class lpsolve.LpSolve
 
PRESOLVE_ROWS - Static variable in class lpsolve.LpSolve
 
PRESOLVE_SENSDUALS - Static variable in class lpsolve.LpSolve
 
PRESOLVE_SOS - Static variable in class lpsolve.LpSolve
 
PRICER_DANTZIG - Static variable in class lpsolve.LpSolve
 
PRICER_DEVEX - Static variable in class lpsolve.LpSolve
 
PRICER_FIRSTINDEX - Static variable in class lpsolve.LpSolve
 
PRICER_STEEPESTEDGE - Static variable in class lpsolve.LpSolve
 
PRICE_ADAPTIVE - Static variable in class lpsolve.LpSolve
 
PRICE_AUTOPARTIAL - Static variable in class lpsolve.LpSolve
 
PRICE_HARRISTWOPASS - Static variable in class lpsolve.LpSolve
 
PRICE_HYBRID - Static variable in class lpsolve.LpSolve
 
PRICE_LOOPALTERNATE - Static variable in class lpsolve.LpSolve
 
PRICE_LOOPLEFT - Static variable in class lpsolve.LpSolve
 
PRICE_METHODDEFAULT - Static variable in class lpsolve.LpSolve
 
PRICE_MULTIPLE - Static variable in class lpsolve.LpSolve
 
PRICE_PARTIAL - Static variable in class lpsolve.LpSolve
 
PRICE_PRIMALFALLBACK - Static variable in class lpsolve.LpSolve
 
PRICE_RANDOMIZE - Static variable in class lpsolve.LpSolve
 
PRICE_TRUENORMINIT - Static variable in class lpsolve.LpSolve
 
PROCBREAK - Static variable in class lpsolve.LpSolve
 
PROCFAIL - Static variable in class lpsolve.LpSolve
 
printConstraints(int) - Method in class lpsolve.LpSolve
Prints the values of the constraints of the lp.
printDebugdump(String) - Method in class lpsolve.LpSolve
Do a generic readable data dump of key lp_solve model variables; principally for run difference and debugging purposes.
printDuals() - Method in class lpsolve.LpSolve
Prints the values of the duals of the lp.
printLp() - Method in class lpsolve.LpSolve
Prints the lp model.
printObjective() - Method in class lpsolve.LpSolve
Prints the objective value of the lp.
printScales() - Method in class lpsolve.LpSolve
Prints the scales of the lp.
printSolution(int) - Method in class lpsolve.LpSolve
Prints the solution (variables) of the lp.
printStr(String) - Method in class lpsolve.LpSolve
Prints a string.
printTableau() - Method in class lpsolve.LpSolve
Prints the tableau.
putAbortfunc(AbortListener, Object) - Method in class lpsolve.LpSolve
Register an AbortListener for callback.
putBbBranchfunc(BbListener, Object) - Method in class lpsolve.LpSolve
Register an BbBranchListener for callback.
putBbNodefunc(BbListener, Object) - Method in class lpsolve.LpSolve
Register an BbNodeListener for callback.
putLogfunc(LogListener, Object) - Method in class lpsolve.LpSolve
Register an LogListener for callback.
putMsgfunc(MsgListener, Object, int) - Method in class lpsolve.LpSolve
Register an MsgListener for callback.

R

RUNNING - Static variable in class lpsolve.LpSolve
 
readBasis(String) - Method in class lpsolve.LpSolve
Read basis from a file and set as default basis.
readFreeMps(String, int) - Static method in class lpsolve.LpSolve
Read a model in free MPS format from file and create a new problem.
readLp(String, int, String) - Static method in class lpsolve.LpSolve
Read an lp model from file and create a new problem.
readMps(String, int) - Static method in class lpsolve.LpSolve
Read an mps model from file and create a new problem.
readParams(String, String) - Method in class lpsolve.LpSolve
Read settings from a parameter file.
readXLI(String, String, String, String, int) - Static method in class lpsolve.LpSolve
Read a model via the External Language Interface and create a new problem.
resetBasis() - Method in class lpsolve.LpSolve
Resets the basis to the initial basis.
resetParams() - Method in class lpsolve.LpSolve
Resets parameters back to their default values.
resizeLp(int, int) - Method in class lpsolve.LpSolve
Allocates memory for the specified size.

S

SCALE_COLSONLY - Static variable in class lpsolve.LpSolve
 
SCALE_CURTISREID - Static variable in class lpsolve.LpSolve
 
SCALE_DYNUPDATE - Static variable in class lpsolve.LpSolve
 
SCALE_EQUILIBRATE - Static variable in class lpsolve.LpSolve
 
SCALE_EXTREME - Static variable in class lpsolve.LpSolve
 
SCALE_GEOMETRIC - Static variable in class lpsolve.LpSolve
 
SCALE_INTEGERS - Static variable in class lpsolve.LpSolve
 
SCALE_LINEAR - Static variable in class lpsolve.LpSolve
 
SCALE_LOGARITHMIC - Static variable in class lpsolve.LpSolve
 
SCALE_MEAN - Static variable in class lpsolve.LpSolve
 
SCALE_NONE - Static variable in class lpsolve.LpSolve
 
SCALE_POWER2 - Static variable in class lpsolve.LpSolve
 
SCALE_QUADRATIC - Static variable in class lpsolve.LpSolve
 
SCALE_RANGE - Static variable in class lpsolve.LpSolve
 
SCALE_ROWSONLY - Static variable in class lpsolve.LpSolve
 
SCALE_USERWEIGHT - Static variable in class lpsolve.LpSolve
 
SEVERE - Static variable in class lpsolve.LpSolve
 
SIMPLEX_DEFAULT - Static variable in class lpsolve.LpSolve
 
SIMPLEX_DUAL_DUAL - Static variable in class lpsolve.LpSolve
 
SIMPLEX_DUAL_PRIMAL - Static variable in class lpsolve.LpSolve
 
SIMPLEX_PRIMAL_DUAL - Static variable in class lpsolve.LpSolve
 
SIMPLEX_PRIMAL_PRIMAL - Static variable in class lpsolve.LpSolve
 
SUBOPTIMAL - Static variable in class lpsolve.LpSolve
 
setAddRowmode(boolean) - Method in class lpsolve.LpSolve
Specifies which add routine performs best.
setAntiDegen(int) - Method in class lpsolve.LpSolve
Specifies if special handling must be done to reduce degeneracy/cycling while solving.
setBFP(String) - Method in class lpsolve.LpSolve
Set basis factorization package.
setBasis(int[], boolean) - Method in class lpsolve.LpSolve
Sets an initial basis of the lp.
setBasiscrash(int) - Method in class lpsolve.LpSolve
Specifies which basis crash mode must be used.
setBasisvar(int, int) - Method in class lpsolve.LpSolve
This is an internal function that has been published for special purposes. It should generally not be used.
setBbDepthlimit(int) - Method in class lpsolve.LpSolve
Sets the maximum branch-and-bound depth.
setBbFloorfirst(int) - Method in class lpsolve.LpSolve
Specifies which branch to take first in branch-and-bound algorithm.
setBbRule(int) - Method in class lpsolve.LpSolve
Specifies the branch-and-bound rule.
setBinary(int, boolean) - Method in class lpsolve.LpSolve
Set the type of the variable.
setBounds(int, double, double) - Method in class lpsolve.LpSolve
Set the upper and lower bound of a variable.
setBoundsTighter(boolean) - Method in class lpsolve.LpSolve
Specifies if set bounds may only be tighter or also less restrictive.
setBreakAtFirst(boolean) - Method in class lpsolve.LpSolve
Specifies if the branch-and-bound algorithm stops at first found solution.
setBreakAtValue(double) - Method in class lpsolve.LpSolve
Specifies if the branch-and-bound algorithm stops when the object value is better than a given value.
setColName(int, String) - Method in class lpsolve.LpSolve
Set the name of a column in the problem.
setColumn(int, double[]) - Method in class lpsolve.LpSolve
Set a column in the lp.
setColumnex(int, int, double[], int[]) - Method in class lpsolve.LpSolve
Set a column in the lp.
setConstrType(int, int) - Method in class lpsolve.LpSolve
Set the type of a constraint.
setDebug(boolean) - Method in class lpsolve.LpSolve
Sets a flag if all intermediate results and the branch-and-bound decisions must be printed while solving.
setEpsb(double) - Method in class lpsolve.LpSolve
Specifies the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0
setEpsd(double) - Method in class lpsolve.LpSolve
Specifies the value that is used as a tolerance for reduced costs to determine whether a value should be considered as 0.
setEpsel(double) - Method in class lpsolve.LpSolve
Specifies the value that is used as a tolerance for rounding values to zero.
setEpsint(double) - Method in class lpsolve.LpSolve
Specifies the tolerance that is used to determine whether a floating-point number is in fact an integer.
setEpslevel(int) - Method in class lpsolve.LpSolve
This is a simplified way of specifying multiple eps thresholds that are "logically" consistent.
setEpsperturb(double) - Method in class lpsolve.LpSolve
Specifies the value that is used as perturbation scalar for degenerative problems.
setEpspivot(double) - Method in class lpsolve.LpSolve
Specifies the value that is used as a tolerance pivot element to determine whether a value should be considered as 0.
setImprove(int) - Method in class lpsolve.LpSolve
Specifies the iterative improvement level.
setInfinite(double) - Method in class lpsolve.LpSolve
Specifies the practical value for "infinite".
setInt(int, boolean) - Method in class lpsolve.LpSolve
Set the type of the variable.
setLagTrace(boolean) - Method in class lpsolve.LpSolve
Sets a flag if Lagrangian progression must be printed while solving.
setLowbo(int, double) - Method in class lpsolve.LpSolve
Set the lower bound of a variable.
setLpName(String) - Method in class lpsolve.LpSolve
Set the name of the problem.
setMat(int, int, double) - Method in class lpsolve.LpSolve
Set a single element in the matrix.
setMaxim() - Method in class lpsolve.LpSolve
Set objective function to maximize.
setMaxpivot(int) - Method in class lpsolve.LpSolve
Sets the maximum number of pivots between a reinversion of the matrix.
setMinim() - Method in class lpsolve.LpSolve
Set objective function to minimize.
setMipGap(boolean, double) - Method in class lpsolve.LpSolve
Specifies the MIP gap value.
setNegrange(double) - Method in class lpsolve.LpSolve
Set negative value below which variables are split into a negative and a positive part.
setObj(int, double) - Method in class lpsolve.LpSolve
Set the objective function (row 0) of the matrix.
setObjBound(double) - Method in class lpsolve.LpSolve
Set initial "at least better than" guess for objective function.
setObjFn(double[]) - Method in class lpsolve.LpSolve
Set the objective function (row 0) of the matrix.
setObjFnex(int, double[], int[]) - Method in class lpsolve.LpSolve
Set the objective function (row 0) of the matrix.
setOutputfile(String) - Method in class lpsolve.LpSolve
Defines the output for the print_* functions.
setPivoting(int) - Method in class lpsolve.LpSolve
Specifies the pivot rule.
setPreferdual(boolean) - Method in class lpsolve.LpSolve
Sets the desired combination of primal and dual simplex algorithms.
setPresolve(int, int) - Method in class lpsolve.LpSolve
Specifies if a presolve must be done before solving.
setPrintSol(int) - Method in class lpsolve.LpSolve
Sets a flag if all intermediate valid solutions must be printed while solving.
setRh(int, double) - Method in class lpsolve.LpSolve
Set the value of the right hand side (RHS) vector (column 0) for one row.
setRhRange(int, double) - Method in class lpsolve.LpSolve
Set the range on a constraint.
setRhVec(double[]) - Method in class lpsolve.LpSolve
Set the right hand side (RHS) vector (column 0).
setRow(int, double[]) - Method in class lpsolve.LpSolve
Set a constraint in the lp.
setRowName(int, String) - Method in class lpsolve.LpSolve
Set the name of a constraint (row) in the problem.
setRowex(int, int, double[], int[]) - Method in class lpsolve.LpSolve
Set a constraint in the lp.
setScalelimit(double) - Method in class lpsolve.LpSolve
Sets the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations.
setScaling(int) - Method in class lpsolve.LpSolve
Specifies which scaling algorithm must be used.
setSemicont(int, boolean) - Method in class lpsolve.LpSolve
Set the type of the variable. semi-continious or not.
setSense(boolean) - Method in class lpsolve.LpSolve
Set objective function sense.
setSimplextype(int) - Method in class lpsolve.LpSolve
Sets the desired combination of primal and dual simplex algorithms.
setSolutionlimit(int) - Method in class lpsolve.LpSolve
Sets the solution number that must be returned.
setTimeout(long) - Method in class lpsolve.LpSolve
Set a timeout.
setTrace(boolean) - Method in class lpsolve.LpSolve
Sets a flag if pivot selection must be printed while solving.
setUnbounded(int) - Method in class lpsolve.LpSolve
Sets if the variable is free.
setUpbo(int, double) - Method in class lpsolve.LpSolve
Set the upper bound of a variable.
setUseNames(boolean, boolean) - Method in class lpsolve.LpSolve
Sets if variable or constraint names are used.
setVarBranch(int, int) - Method in class lpsolve.LpSolve
Specifies, for the specified variable, which branch to take first in branch-and-bound algorithm.
setVarWeights(double[]) - Method in class lpsolve.LpSolve
Set the weights on variables.
setVerbose(int) - Method in class lpsolve.LpSolve
Set the verbose level.
setXLI(String) - Method in class lpsolve.LpSolve
Set External Language Interfaces package.
solve() - Method in class lpsolve.LpSolve
Solve the model.
strAddColumn(String) - Method in class lpsolve.LpSolve
Add a column to the problem.
strAddConstraint(String, int, double) - Method in class lpsolve.LpSolve
Add a constraint to the problem.
strAddLagCon(String, int, double) - Method in class lpsolve.LpSolve
Add a Lagrangian constraint to the problem.
strSetObjFn(String) - Method in class lpsolve.LpSolve
Set the objective function (row 0) of the matrix.
strSetRhVec(String) - Method in class lpsolve.LpSolve
Set the right hand side (RHS) vector (column 0).

T

TIMEOUT - Static variable in class lpsolve.LpSolve
 
TRUE - Static variable in class lpsolve.LpSolve
 
timeElapsed() - Method in class lpsolve.LpSolve
Gets the time elapsed since start of solve.

U

UNBOUNDED - Static variable in class lpsolve.LpSolve
 
UNKNOWNERROR - Static variable in class lpsolve.LpSolve
 
USERABORT - Static variable in class lpsolve.LpSolve
 
unscale() - Method in class lpsolve.LpSolve
Unscales the model.

V

VersionInfo - class lpsolve.VersionInfo.
Contains the full version info for a lp_solve library instance.
VersionInfo(int, int, int, int) - Constructor for class lpsolve.VersionInfo
Creates a new instance of this class

W

writeBasis(String) - Method in class lpsolve.LpSolve
Writes current basis to a file.
writeFreeMps(String) - Method in class lpsolve.LpSolve
Write a model in free MPS format to a file.
writeLp(String) - Method in class lpsolve.LpSolve
Write an lp model to a file.
writeMps(String) - Method in class lpsolve.LpSolve
Write an mps model to a file.
writeParams(String, String) - Method in class lpsolve.LpSolve
Write settings to a parameter file.
writeXLI(String, String, boolean) - Method in class lpsolve.LpSolve
Write a model to a file via the External Language Interface.

A B C D E F G H I L M N O P R S T U V W

Copyright 2004 - Juergen Ebert doc/Java/docs/reference.html0000644000175000017500000006660311244305537014743 0ustar renerene lp_solve 5.5 Java Wrapper - Function Reference

Using lp_solve 5.5 in Java programs

C - Java function reference

This file contains a reference for all methods in the lp_solve library and the Java wrapper. The first column of the following table contains the C functions of the lp_solve library, the second column the corresponding methods of the Java wrapper.

C functionJava wrapper method (LpSolve class)
unsigned char add_column (lprec* lp, REAL* column)void addColumn(double[] column) throws LpSolveException
unsigned char add_columnex (lprec* lp, int count, REAL* column, int* rowno)void addColumnex(int count, double[] column, int[] rowno) throws LpSolveException
unsigned char add_constraint (lprec* lp, REAL *row, int constr_type, REAL rh)void addConstraint(double[] row, int constrType, double rh) throws LpSolveException
unsigned char add_constraintex (lprec *lp, int count, REAL *row, int *colno, int constr_type, REAL rh)void addConstraintex(int count, double[] row, int[] colno, int constrType, double rh) throws LpSolveException
unsigned char add_lag_con (lprec* lp, REAL *row, int con_type, REAL rhs)void addLagCon(double[] row, int constrType, double rh) throws LpSolveException
int add_SOS (lprec* lp, char *name, int sostype, int priority, int count, int *sosvars, REAL *weights)void addSOS(String name, int sostype, int priority, int count, int[] sosvars, double[] weights) throws LpSolveException
int column_in_lp (lprec* lp, REAL *column)int columnInLp(double[] column)
void default_basis (lprec* lp)void defaultBasis()
unsigned char del_column(lprec *lp, int column)void delColumn(int columnnr) throws LpSolveException
unsigned char del_constraint(lprec *lp, int del_row)void delConstraint(int rownr) throws LpSolveException
void delete_lp(lprec *lp)void deleteLp()
void free_lp(lprec **plp)<Not implemented, use deleteLp() instead>
int get_anti_degen(lprec *lp)int getAntiDegen()
void get_basis(lprec *lp, int *bascolumn, unsigned char nonbasic)void getBasis(int[] bascolumn, boolean nonbasic)
int get_basiscrash(lprec *lp)int getBasiscrash()
int get_bb_depthlimit(lprec *lp)int getBbDepthlimit()
int get_bb_floorfirst(lprec *lp)int getBbFloorfirst()
int get_bb_rule(lprec *lp)int getBbRule()
unsigned char get_bounds_tighter(lprec *lp)boolean getBoundsTighter()
REAL get_break_at_value(lprec *lp)double getBreakAtValue()
char *get_col_name(lprec *lp, int column)String getColName(int colnr) throws LpSolveException
unsigned char get_column(lprec *lp, int col_nr, REAL *column)void getColumn(int columnrnr, double[] column) throws LpSolveException
<Not implemented>double[] getPtrColumn(int columnrnr) throws LpSolveException
int get_constr_type(lprec *lp, int row)short getConstrType(int rownr) throws LpSolveException
unsigned char get_constraints(lprec *lp, REAL *constr)void getConstraints(double[] var) throws LpSolveException
unsigned char get_dual_solution(lprec *lp, REAL *duals)void getDualSolution(double[] duals) throws LpSolveException
REAL get_epsb(lprec *lp)double getEpsb()
REAL get_epsd(lprec *lp)double getEpsd()
REAL get_epsel(lprec *lp)double getEpsel()
REAL get_epsint(lprec *lp)double getEpsint()
REAL get_epsperturb(lprec *lp)double getEpsperturb()
REAL get_epspivot(lprec *lp)double getEpspivot()
int get_improve(lprec *lp)int getImprove()
REAL get_infinite(lprec *lp)double getInfinite()
unsigned char get_lambda(lprec *lp, REAL *lambda)void getLambda(double[] lambda) throws LpSolveException
REAL get_lowbo(lprec *lp, int column)double getLowbo(int colnr) throws LpSolveException
int get_lp_index(lprec *lp, int orig_index)int getLpIndex(int index)
char *get_lp_name(lprec *lp)String getLpName() throws LpSolveException
int get_Lrows(lprec *lp)int getLrows()
REAL get_mat(lprec *lp, int row, int column)double getMat(int row, int column)
int get_max_level(lprec *lp)int getMaxLevel()
int get_maxpivot(lprec *lp)int getMaxpivot()
REAL get_mip_gap(lprec *lp, unsigned char absolute)double getMipGap(boolean absolute)
int get_Ncolumns(lprec *lp)int getNcolumns()
REAL get_negrange(lprec *lp)double getNegrange()
int get_nonzeros(lprec *lp)int getNonzeros()
int get_Norig_columns(lprec *lp)int getNorigColumns()
int get_Norig_rows(lprec *lp)int getNorigRows()
int get_Nrows(lprec *lp)int getNrows()
REAL get_obj_bound(lprec *lp)double getObjBound()
REAL get_objective(lprec *lp)getObjective()
int get_orig_index(lprec *lp, int lp_index)int getOrigIndex(int index)
char *get_origcol_name(lprec *lp, int column)String getOrigcolName(int colnr) throws LpSolveException
char *get_origrow_name(lprec *lp, int row)String getOrigrowName(int rownr) throws LpSolveException
int get_pivoting(lprec *lp)int getPivoting()
int get_presolve(lprec *lp)int getPresolve()
unsigned char get_primal_solution(lprec *lp, REAL *pv)void getPrimalSolution(double[] pv) throws LpSolveException
int get_print_sol(lprec *lp)int getPrintSol()
unsigned char get_ptr_constraints(lprec *lp, REAL **ptr_constr)double[] getPtrConstraints() throws LpSolveException
unsigned char get_ptr_dual_solution(lprec *lp, REAL **ptr_duals)double[] getPtrDualSolution() throws LpSolveException
unsigned char get_ptr_lambda(lprec *lp, REAL **ptr_lambda)double[] getPtrLambda() throws LpSolveException
unsigned char get_ptr_primal_solution(lprec *lp, REAL **ptr_pv)double[] getPtrPrimalSolution() throws LpSolveException
unsigned char get_ptr_sensitivity_obj(lprec *lp, REAL **ptr_objfrom, REAL **ptr_objtill)double[][] getPtrSensitivityObj() throws LpSolveException
unsigned char get_ptr_sensitivity_objex(lprec *lp, REAL **ptr_objfrom, REAL **ptr_objtill, REAL *ptr_objfromvalue, REAL *ptr_objtillvalue)double[][] getPtrSensitivityObjex() throws LpSolveException
unsigned char get_ptr_sensitivity_rhs(lprec *lp, REAL **ptr_duals, REAL **ptr_dualsfrom, REAL **ptr_dualstill)double[][] getPtrSensitivityRhs() throws LpSolveException
unsigned char get_ptr_variables(lprec *lp, REAL **ptr_var)double[] getPtrVariables() throws LpSolveException
REAL get_rh(lprec *lp, int row)double getRh(int row)
REAL get_rh_range(lprec *lp, int row)double getRhRange(int rownr) throws LpSolveException
unsigned char get_row(lprec *lp, int row_nr, REAL *row)void getRow(int rownr, double[] row) throws LpSolveException
<Not implemented>double[] getPtrRow(int rownr) throws LpSolveException
char *get_row_name(lprec *lp, int row)String getRowName(int rownr) throws LpSolveException
REAL get_scalelimit(lprec *lp)double getScalelimit()
int get_scaling(lprec *lp)int getScaling()
unsigned char get_sensitivity_obj(lprec *lp, REAL *objfrom, REAL *objtill)void getSensitivityObj(double[] objfrom, double[] objtill) throws LpSolveException
unsigned char get_sensitivity_objex(lprec *lp, REAL *objfrom, REAL *objtill, REAL *objfromvalue, REAL *objtillvalue)void getSensitivityObjex(double[] objfrom, double[] objtill, double[] objfromvalue, double[] objtillvalue) throws LpSolveException
unsigned char get_sensitivity_rhs(lprec *lp, REAL *duals, REAL *dualsfrom, REAL *dualstill)void getSensitivityRhs(double[] duals, double[] dualsfrom, double[] dualstill) throws LpSolveException
int get_simplextype(lprec *lp)int getSimplextype()
int get_solutioncount(lprec *lp)int getSolutioncount()
int get_solutionlimit(lprec *lp)int getSolutionlimit()
int get_status(lprec *lp)int getStatus()
char *get_statustext(lprec *lp, int statuscode)String getStatustext(int statuscode)
long get_timeout(lprec *lp)long getTimeout()
int get_total_iter(lprec *lp)int getTotalIter()
int get_total_nodes(lprec *lp)int getTotalNodes()
REAL get_upbo(lprec *lp, int column)double getUpbo(int colnr) throws LpSolveException
int get_var_branch(lprec *lp, int column)int getVarBranch(int colnr) throws LpSolveException
REAL get_var_dualresult(lprec *lp, int index)double getVarDualresult(int index) throws LpSolveException
REAL get_var_primalresult(lprec *lp, int index)double getVarPrimalresult(int index) throws LpSolveException
int get_var_priority(lprec *lp, int column)int getVarPriority(int colnr) throws LpSolveException
unsigned char get_variables(lprec *lp, REAL *var)void getVariables(double[] var) throws LpSolveException
int get_verbose(lprec *lp)int getVerbose()
REAL get_working_objective(lprec *lp)double getWorkingObjective() throws LpSolveException
unsigned char guess_basis(lprec *lp, double *guessvector, int *basisvector)void guessBasis(double[] guessvector, int[] basisvector) throws LpSolveException
unsigned char has_BFP(lprec *lp)boolean hasBFP()
unsigned char has_XLI(lprec *lp)boolean hasXLI()
unsigned char is_add_rowmode(lprec *lp)boolean isAddRowmode()
unsigned char is_anti_degen(lprec *lp, int testmask)boolean isAntiDegen(int testmask)
unsigned char is_binary(lprec *lp, int column)boolean isBinary(int colnr)
unsigned char is_break_at_first(lprec *lp)boolean isBreakAtFirst()
unsigned char is_constr_type(lprec *lp, int row, int mask)boolean isConstrType(int row, int mask)
unsigned char is_debug(lprec *lp)boolean isDebug()
unsigned char is_feasible(lprec *lp, REAL *values, REAL threshold)boolean isFeasible(double[] values, double threshold) throws LpSolveException
unsigned char is_free(lprec *lp, int column)boolean isFree(int colnr)
unsigned char is_infinite(lprec *lp, REAL value)boolean isInfinite(double value)
unsigned char is_int(lprec *lp, int column)boolean isInt(int colnr)
unsigned char is_integerscaling(lprec *lp)boolean isIntegerscaling()
unsigned char is_lag_trace(lprec *lp)boolean isLagTrace()
unsigned char is_maxim(lprec *lp)boolean isMaxim()
unsigned char is_nativeBFP(lprec *lp)boolean isNativeBFP()
unsigned char is_nativeXLI(lprec *lp)boolean isNativeXLI()
unsigned char is_negative(lprec *lp, int column)boolean isNegative(int colnr)
unsigned char is_piv_mode(lprec *lp, int testmask)boolean isPivMode(int testmask)
unsigned char is_piv_rule(lprec *lp, int rule)boolean isPivRule(int rule)
unsigned char is_presolve(lprec *lp, int testmask)boolean isPresolve(int testmask)
unsigned char is_scalemode(lprec *lp, int testmask)boolean isScalemode(int testmask)
unsigned char is_scaletype(lprec *lp, int scaletype)boolean isScaletype(int scaletype)
unsigned char is_semicont(lprec *lp, int column)boolean isSemicont(int colnr)
unsigned char is_SOS_var(lprec *lp, int column)boolean isSOSVar(int colnr) throws LpSolveException
unsigned char is_trace(lprec *lp)boolean isTrace()
int lag_solve(lprec *lp, REAL start_bound, int num_iter, short verbose)<Function is currently not exported from lp_solve dll>
void lp_solve_version(int *majorversion, int *minorversion, int *release, int *build)static VersionInfo lpSolveVersion()
lprec *make_lp(int rows, int columns)static LpSolve makeLp(int rows, int columns) throws LpSolveException
void print_constraints(lprec *lp, int columns)void printConstraints(int columns)
unsigned char print_debugdump(lprec *lp, char *filename)void printDebugdump(String filename) throws LpSolveException
void print_duals(lprec *lp)void printDuals()
void print_lp(lprec *lp)void printLp()
void print_objective(lprec *lp)void printObjective()
void print_scales(lprec *lp)void printScales()
void print_solution(lprec *lp, int columns)void printSolution(int columns)
void print_str(lprec *lp, char *str)void printStr(String str)
void print_tableau(lprec *lp)void printTableau()
void put_abortfunc(lprec *lp, ctrlcfunc newctrlc, void *ctrlchandle)void putAbortfunc(AbortListener listener, Object userhandle) throws LpSolveException
void put_logfunc(lprec *lp, logfunc newlog, void *loghandle)void putLogfunc(LogListener listener, Object userhandle) throws LpSolveException
void put_msgfunc(lprec *lp, msgfunc newmsg, void *msghandle, int mask)void putMsgfunc(MsgListener listener, Object userhandle, int mask) throws LpSolveException
lprec *read_freeMPS(char *filename, int options)static LpSolve readFreeMps(String filename, int options) throws LpSolveException
lprec *read_freemps(FILE *stream, int options)<Not implemented, use readFreeMps instead>
lprec *read_lp(FILE *stream, int verbose, char *lp_name)<Not implemented, use readLp instead>
lprec *read_LP(char *filename, int verbose, char *lp_name)static LpSolve readLp(String filename, int verbose, String lpName) throws LpSolveException
lprec *read_lpt(FILE *stream, int verbose, char *lp_name)<Not implemented, use readLpt instead>
lprec *read_LPT(char *filename, int verbose, char *lp_name)static LpSolve readLpt(String filename, int verbose, String lpName) throws LpSolveException
lprec *read_mps(FILE *stream, int options)<Not implemented, use readMps instead>
lprec *read_MPS(char *filename, int options)static LpSolve readMps(String filename, int options) throws LpSolveException
lprec *read_XLI(char *xliname, char *modelname, char *dataname, char *options, int verbose)static LpSolve readXLI(String xliname, String modelname, String dataname, String options, int verbose) throws LpSolveException
void reset_basis(lprec *lp)void resetBasis()
unsigned char resize_lp(lprec *lp, int rows, int columns)void resizeLp(int rows, int columns) throws LpSolveException
unsigned char set_add_rowmode(lprec *lp, unsigned char turnon)boolean setAddRowmode(boolean turnon)
void set_anti_degen(lprec *lp, int anti_degen)void setAntiDegen(int antiDegen)
unsigned char set_basis(lprec *lp, int *bascolumn, unsigned char nonbasic)void setBasis(int[] bascolumn, boolean nonbasic) throws LpSolveException
void set_basiscrash(lprec *lp, int mode)void setBasiscrash(int mode)
void set_bb_depthlimit(lprec *lp, int bb_maxlevel)void setBbDepthlimit(int bbMaxlevel)
void set_bb_floorfirst(lprec *lp, int bb_floorfirst)void setBbFloorfirst(int floorFirst)
void set_bb_rule(lprec *lp, int bb_rule)void setBbRule(int bbRule)
unsigned char set_BFP(lprec *lp, char *filename)void setBFP(String filename) throws LpSolveException
unsigned char set_XLI(lprec *lp, char *filename)void setXLI(String filename) throws LpSolveException
unsigned char set_binary(lprec *lp, int column, unsigned char must_be_bin)void setBinary(int colnr, boolean mustBeBin) throws LpSolveException
unsigned char set_bounds(lprec *lp, int column, REAL lower, REAL upper)void setBounds(int colnr, double lower, double upper) throws LpSolveException
void set_bounds_tighter(lprec *lp, unsigned char tighten)void setBoundsTighter(boolean tighten)
void set_break_at_first(lprec *lp, unsigned char break_at_first)void setBreakAtFirst(boolean breakAtFirst)
void set_break_at_value(lprec *lp, REAL break_at_value)void setBreakAtValue(double breakAtValue)
unsigned char set_col_name(lprec *lp, int column, char *new_name)void setColName(int colnr, String name) throws LpSolveException
unsigned char set_column(lprec *lp, int col_no, REAL *column)void setColumn(int colno, double[] column) throws LpSolveException
unsigned char set_columnex(lprec *lp, int col_no, int count, REAL *column, int *rowno)void setColumnex(int colno, int count, double[] column, int[] rowno) throws LpSolveException
unsigned char set_constr_type(lprec *lp, int row, int con_type)void setConstrType(int rownr, int constrType) throws LpSolveException
void set_debug(lprec *lp, unsigned char debug)void setDebug(boolean debug)
void set_epsb(lprec *lp, REAL epsb)void setEpsb(double value)
void set_epsd(lprec *lp, REAL epsd)void setEpsd(double value)
void set_epsel(lprec *lp, REAL epsel)void setEpsel(double value)
void set_epsint(lprec *lp, REAL epsint)void setEpsint(double value)
void set_epsperturb(lprec *lp, REAL epsperturb)void setEpsperturb(double value)
void set_epspivot(lprec *lp, REAL epspivot)void setEpspivot(double value)
unsigned char set_free(lprec *lp, int column)void setFree(int colnr) throws LpSolveException
void set_improve(lprec *lp, int improve)void setImprove(int improve)
void set_infinite(lprec *lp, REAL infinite)void setInfinite(double value)
unsigned char set_int(lprec *lp, int column, unsigned char must_be_int)void setInt(int colnr, boolean mustBeInteger) throws LpSolveException
void set_lag_trace(lprec *lp, unsigned char lag_trace)void setLagTrace(boolean lagTrace)
unsigned char set_lowbo(lprec *lp, int column, REAL value)void setLowbo(int colnr, double value) throws LpSolveException
unsigned char set_lp_name(lprec *lp, char *lpname)void setLpName(String name) throws LpSolveException
unsigned char set_mat(lprec *lp, int row, int column, REAL value)void setMat(int row, int column, double value) throws LpSolveException
void set_maxim(lprec *lp)void setMaxim()
void set_maxpivot(lprec *lp, int max_num_inv)void setMaxpivot(int maxNumInv)
void set_minim(lprec *lp)void setMinim()
void set_mip_gap(lprec *lp, unsigned char absolute, REAL mip_gap)void setMipGap(boolean absolute, double value)
void set_negrange(lprec *lp, REAL negrange)void setNegrange(double negRange)
void set_obj_bound(lprec *lp, REAL obj_bound)void setObjBound(double objBound)
unsigned char set_obj_fn(lprec *lp, REAL *row)void setObjFn(double[] row) throws LpSolveException
unsigned char set_obj_fnex(lprec *lp, int count, REAL *row, int *colno)void setObjFnex(int count, double[] row, int[] colno) throws LpSolveException
unsigned char set_obj(lprec *lp, int column, REAL value)void setObj(int column, double value) throws LpSolveException
void set_outputstream(lprec *lp, FILE *stream)<Not implemented, use setOutputfile instead>
unsigned char set_outputfile(lprec *lp, char *filename)void setOutputfile(String filename) throws LpSolveException
void set_pivoting(lprec *lp, int pivoting)void setPivoting(int pivRule)
void set_preferdual(lprec *lp, unsigned char dodual)void setPreferdual(int dodual)
void set_presolve(lprec *lp, int do_presolve)void setPresolve(int doPresolve)
void set_print_sol(lprec *lp, int print_sol)void setPrintSol(int printSol)
unsigned char set_rh(lprec *lp, int row, REAL value)void setRh(int row, double value) throws LpSolveException
unsigned char set_rh_range(lprec *lp, int row, REAL deltavalue)void setRhRange(int rownr, double range) throws LpSolveException
void set_rh_vec(lprec *lp, REAL *rh)void setRhVec(double[] rh) throws LpSolveException
unsigned char set_row(lprec *lp, int row_no, REAL *row)void setRow(int rowno, double[] row) throws LpSolveException
unsigned char set_rowex(lprec *lp, int row_no, int count, REAL *row, int *colno)void setRowex(int rowno, int count, double[] row, int[] colno) throws LpSolveException
unsigned char set_row_name(lprec *lp, int row, char *new_name)void setRowName(int rownr, String name) throws LpSolveException
void set_scalelimit(lprec *lp, REAL scalelimit)void setScalelimit(double scalelimit)
void set_scaling(lprec *lp, int scalemode)void setScaling(int scalemode)
unsigned char set_semicont(lprec *lp, int column, unsigned char must_be_sc)void setSemicont(int colnr, boolean mustBeSc) throws LpSolveException
void set_sense(lprec *lp, unsigned char maximize)void setSense(boolean maximize)
void set_simplextype(lprec *lp, int simplextype)void setSimplextype(int simplextype)
void set_solutionlimit(lprec *lp, int limit)void setSolutionlimit(int limit)
void set_timeout(lprec *lp, long sectimeout)void setTimeout(long timeout)
void set_trace(lprec *lp, unsigned char trace)void setTrace(boolean trace)
unsigned char set_upbo(lprec *lp, int column, REAL value)void setUpbo(int colnr, double value) throws LpSolveException
unsigned char set_var_branch(lprec *lp, int column, int branch_mode)void setVarBranch(int colnr, int branchMode) throws LpSolveException
unsigned char set_var_weights(lprec *lp, REAL *weights)void setVarWeights(double[] weights) throws LpSolveException
void set_verbose(lprec *lp, int verbose)void setVerbose(int verbose)
int solve(lprec *lp)int solve() throws LpSolveException
unsigned char str_add_column (lprec* lp, char* col_string)void strAddColumn(String column) throws LpSolveException
unsigned char str_add_constraint (lprec* lp, char *row_string, int constr_type, REAL rh)void strAddConstraint(String row, int constrType, double rh) throws LpSolveException
unsigned char str_add_lag_con (lprec* lp, char *row_string, int con_type, REAL rhs)void strAddLagCon(String row, int constrType, double rh) throws LpSolveException
unsigned char str_set_obj_fn(lprec *lp, char *row_string)void strSetObjFn(String row) throws LpSolveException
unsigned char str_set_rh_vec(lprec *lp, char *rh_string)void strSetRhVec(String rh) throws LpSolveException
REAL time_elapsed(lprec *lp)double timeElapsed()
void unscale(lprec *lp)void unscale()
unsigned char write_freeMPS(lprec *lp, FILE *stream)<Not implemented, use writeFreeMps instead>
unsigned char write_freemps(lprec *lp, char *filename)void writeFreeMps(String filename) throws LpSolveException
unsigned char write_lp(lprec *lp, char *filename)void writeLp(String filename) throws LpSolveException
unsigned char write_LP(lprec *lp, FILE *stream)<Not implemented, use writeLp instead>
unsigned char write_mps(lprec *lp, char *filename)void writeMps(String filename) throws LpSolveException
unsigned char write_MPS(lprec *lp, FILE *stream)<Not implemented, use writeMps instead>
unsigned char write_XLI(lprec *lp, char *filename, char *options, unsigned char results)void writeXLI(String filename, String options, boolean results) throws LpSolveException
doc/Java/README.html0000644000175000017500000003727511137710245013012 0ustar renerene Using lp_solve 5.5 in Java programs

Using lp_solve 5.5 in Java programs

Contents

1. Introduction
2. Installation
3. Usage
4. Implementation notes
5. Building from source
6. Calling lp_solve from Python/Jython

1. Introduction

lp_solve is a free (see LGPL for the GNU lesser general public license) linear (integer) programming solver based on the revised simplex method and the Branch-and-bound method for the integers. lp_solve has its own community via the Yahoo group http://groups.yahoo.com/group/lp_solve. There you can find the latest sources, executables for the common platforms, examples, manuals and a message board where people can share their thoughts on lp_solve.

lp_solve is written in ANSI C and can be compiled on many different platforms like Linux and Windows. Basically, lp_solve is a library, a set of routines, that can be called easily from programming languages like C, C++, C# and VB. Unfortunately, there is no simple and straightforward way to use native C libraries like lp_solve in Java programs. This library (also called "Java wrapper") is designed to remedy this shortcoming. It consists of two main parts:

This document should help you getting started using the Java wrapper and lp_solve in your Java programs. Read it in addition to the documentation that comes with lp_solve. Always refer to the lp_solve docs as ultimate reference for using the routines of the optimization library. Bug reports, succes stories and requests for changes concerning the Java wrapper are welcome by email at juergen.ebert@web.de or in the lp_solve discussion group.

The current wrapper version was written to work with lp_solve 5.5.0.9 and was tested under Windows XP and Linux. As long as the API stays the same, other versions of lp_solve are likely to work as well. The wrapper requires a Java Runtime Environment 1.3 or later.

The latest version of the Java wrapper can be found in the files section of the lp_solve group. The wrapper is released under the same LGPL license conditions as lp_solve. A copy of the LGPL text is contained in the distribution archive.

2. Installation

3. Usage

To create a Java application that uses lp_solve routines, you must perform the following steps:

A simple example

The following program is a very simple example that shows how to program with lp_solve in Java.

import lpsolve.*;

public class Demo {

  public static void main(String[] args) {
    try {
      // Create a problem with 4 variables and 0 constraints
      LpSolve solver = LpSolve.makeLp(0, 4);

      // add constraints
      solver.strAddConstraint("3 2 2 1", LpSolve.LE, 4);
      solver.strAddConstraint("0 4 3 1", LpSolve.GE, 3);

      // set objective function
      solver.strSetObjFn("2 3 -2 3");

      // solve the problem
      solver.solve();

      // print solution
      System.out.println("Value of objective function: " + solver.getObjective());
      double[] var = solver.getPtrVariables();
      for (int i = 0; i < var.length; i++) {
        System.out.println("Value of var[" + i + "] = " + var[i]);
      }

      // delete the problem and free memory
      solver.deleteLp();
    }
    catch (LpSolveException e) {
       e.printStackTrace();
    }
  }

}

Using callbacks

The following code fragment shows you how to use callbacks in Java. The example defines an anonymous inner class that implements the AbortListener interface which is then passed to the putAbortfunc method.

    LpSolve solver = LpSolve.makeLp(0, 4);
    AbortListener abortfunc = new AbortListener() {
      public boolean abortfunc(LpSolve problem, Object handle) {
        System.out.println("Java abortfunc called, handle = " + handle);
        return false;
      }
    };
    solver.putAbortfunc(abortfunc, new Integer(123));

Running the demo application

Follow these steps to run the demo application, which is a port of the C demo program that comes with lp_solve to the Java language. You will need a Java Runtime Environment (JRE) on your machine in order to run the demo. You can download the latest JRE from http://java.sun.com

More example code

In the demo directory you will find the file LpSolveTest.java which contains more than 100 JUnit test cases (see http://www.junit.org for details about this highly useful software) to strengthen the faith in the Java wrapper implementation. The test cases may also seve as examples of basic lp_solve usage in Java. You will need the library junit.jar in your CLASSPATH to run the test cases. junit.jar is included in the lib directory of the Java wrapper. You can run the test cases directly by starting the batch script "run_unittests.bat" on Windows or "sh run_unittests" on Linux.

4. Implementation notes

5. Building from source

The Java wrapper archive contains precompiled binary libraries for Windows and Linux. If you just want to use the wrapper there should be no need to build the libs from the sources. But if you absolutely have to, follow the guidelines in this chapter.

On Windows OS

The following prerequisites must be met in order to build the wrapper C library from source on Windows operating systems: Change to the lib directory and edit the file build.bat. Change the path to the directory where you unpacked the lp_solve Windows archive. Run the script to build lpsolve55j.dll. The dll will be created in directory win32 or win64 depending on the OS.

On Linux

The following prerequisites must be met in order to build the wrapper C library from source on Linux operating systems: Change to the lib directory and edit the file build. Change the paths to the directory where you unpacked the lp_solve linux archive and where the JDK is installed. Run sh build to build liblpsolve55j.so. The dll will be created in directory ux32 or ux64 depending on the OS.

On Mac OS X

Change to the lib/mac directory and edit the file build_osx. Change the directory paths as indicated in the comments. Thanks to Sean P. Kane (spkane@genomatica.com) who provided this build script.

6. Calling lp_solve from Python/Jython

Jython (http://www.jython.org) is a 100% Java implementation of the popular scripting language Python. One of the most remarkable features of Jython is the seamless interaction between Python and Java. Java programmers can add the Jython libraries to their system to allow end users to write scripts that add functionality to the application. On the other hand, Python/Jython programs can interact with Java packages or with running Java applications.

lp_solve functions can be called via the Java wrapper from Python/Jython programs. See the file demo.py in the demo directory of the Java wrapper distribution for an example program. To run this program, you must install lp_solve, the Java wrapper, and Jython. Don't forget to include lpsolve55j.jar in the Java CLASSPATH when you run Jython.

doc/Zimpl.htm0000644000175000017500000001713311235624466012112 0ustar renerene Zimpl

Zimpl

Zimpl is a language to translate the mathematical model of a problem into a linear or (mixed-) integer mathematical program expressed in .lp or .mps file format which can be read and (hopefully) solved by a LP or MIP solver.

See http://www.zib.de/koch/zimpl/ for the home page of this tool and examples.

On the above page, a command line tool is provided to read a model written in the Zimpl language and it creates a CPLEX lp file. lp_solve is able to read this generated CPLEX lp file via the xli_CPLEX XLI driver, but that would require an extra step.
lp_solve can read/write and solve these Zimpl models directly via the xli_Zimpl XLI driver (see External Language Interfaces). It reads such a model in above format and can solve it then.
Also note that the XLI driver depends on an external dll: zlib1.dll. When it cannot be found on the system, an appropriate message will be given. This dll must be in a directory specified by the Path environment variable. A common place is c:\windows\system32. The dll is distributed with the package. The latest version can be found at http://www.zlib.net/

For example:

lp_solve -rxli xli_Zimpl chvatal_diet.zpl

This gives as result:

Value of objective function: 97

Actual values of the variables:
x$Oatmeal                       4
x$Chicken                       0
x$Eggs                          0
x$Milk                          5
x$Pie                           2
x$Pork                          0

Options

The XLI accepts several options:

  -b             Enable Bison (Lex parser) debugging output.
  -D name=value  Sets the parameter name to the specified value.
                 This is equivalent with having this line in the ZIMPL program: param name:=val.
  -f             enable flex debugging output.
  -n cm|cn|cf    name column make/name/full
  -O             Try to reduce the generated LP by doing some presolve analysis.
  -s seed        Positive seed number for the random number generator.
  -v[0-5]        Set the verbosity level. 0 is quiet, 1 is default, 2 is verbose, 3 and 4 are chatter, and 5 is debug.
  -V             show version info

These options are the same as the stand-alone zimpl program.

The lp_solve command line program can provide these parameters via the -rxliopt argument.

For example:

lp_solve -rxli xli_Zimpl chvatal_diet.zpl -rxliopt "-v0 -O"

Generating ZIMPL models

The XLI can also create a ZIMPL model, however it doesn't use the strength of the language. Constraints are written out line per line. But it can be a starter. For example:

lp_solve model.lp -wxli xli_Zimpl model.zpl

This gives as model.zpl:

# Variable definitions
var x >= 0;
var y >= 0;

# Objective function
maximize obj: +143*x +60*y;

# Constraints
subto R1: +120*x +210*y <= 15000;
subto R2: +110*x +30*y <= 4000;
subto R3: +x +y <= 75;

API

Use the lpsolve API call read_XLI to read a model and write_XLI to write a model. See also External Language Interfaces.

IDE

Also from within the IDE, this XLI can be used. However, some entries must be added in LpSolveIDE.ini (in the folder where the IDE is installed).

In the [XLI] section the following must be added:

lib5=xli_ZIMPL

And a new section for the ZIMPL XLI must also be added:

[xli_ZIMPL]
extension=.zpl
language=ZIMPL

Then make sure that the xli_ZIMPL.dll is available for the IDE. This must be done by placing this dll in the IDE folder or in the Windows system32 folder.

Example models

chvatal_diet.zpl
# $Id: chvatal_diet.zpl,v 1.2 2003/10/02 08:20:12 bzfkocht Exp $
#
# From V. Chvatal: Linear Programming
# Chapter 1, Page 3ff.
#
# A diet problem
#
set Food      := { "Oatmeal", "Chicken", "Eggs", "Milk", "Pie", "Pork" };
set Nutrients := { "Energy", "Protein", "Calcium" };
set Attr      := Nutrients + {"Servings", "Price"};

param needed[Nutrients] := <"Energy"> 2000, <"Protein"> 55, <"Calcium"> 800;

param data[Food * Attr] :=
           | "Servings", "Energy", "Protein", "Calcium", "Price" |
|"Oatmeal" |         4 ,     110 ,        4 ,        2 ,      3  |
|"Chicken" |         3 ,     205 ,       32 ,       12 ,     24  |
|"Eggs"    |         2 ,     160 ,       13 ,       54 ,     13  |
|"Milk"    |         8 ,     160 ,        8 ,      284 ,      9  |
|"Pie"     |         2 ,     420 ,        4 ,       22 ,     20  |
|"Pork"    |         2 ,     260 ,       14 ,       80 ,     19  |;
#                          (kcal)        (g)        (mg)  (cents)

var x[<f> in Food] integer >= 0 <= data[f, "Servings"];

minimize cost: sum <f> in Food : data[f, "Price"] * x[f];

subto need :
  forall <n> in Nutrients do
    sum <f> in Food : data[f, n] * x[f] >= needed[n];
model.lp
/* model.lp */

max: 143 x + 60 y;

120 x + 210 y <= 15000;
110 x + 30 y <= 4000;
x + y <= 75;
doc/get_solutionlimit.htm0000644000175000017500000000511310237176656014570 0ustar renerene get_solutionlimit

get_solutionlimit

Returns the solution number that must be returned.

int get_solutionlimit(lprec *lp);

Return Value

get_solutionlimit returns the solution number that must be returned. This value gives the number of the solution that must be returned.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

This is only valid if there are integer, semi-continious or SOS variables in the model so that the branch-and-bound algoritm is used. If there are more solutions with the same objective value, then this number specifies which solution must be returned. This can be used to retrieve all possible solutions. Start with 1 till get_solutioncount

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int solutionlimit;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  solutionlimit = get_solutionlimit(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_solutionlimit, get_solutioncount

doc/set_mip_gap.htm0000644000175000017500000000663210237176664013313 0ustar renerene set_mip_gap

set_mip_gap

Specifies the MIP gap value.

void set_mip_gap(lprec *lp, unsigned char absolute, REAL mip_gap);

Return Value

set_mip_gap has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

absolute

If TRUE then the absolute MIP gap is set, else the relative MIP gap

mip_gap

The MIP gap.

Remarks

The set_mip_gap function sets the MIP gap that specifies a tolerance for the branch and bound algorithm. This tolerance is the difference between the best-found solution yet and the current solution. If the difference is smaller than this tolerance then the solution (and all the sub-solutions) is rejected. This can result in faster solving times, but results in a solution which is not the perfect solution. So be careful with this tolerance.
The default mip_gap value is 1e-11

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_mip_gap(lp, TRUE, 1.0e-8); /* sets absolute mip_gap to 1e-8 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_mip_gap, get_epsd, set_epsd, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb

doc/is_integerscaling.htm0000644000175000017500000000503110237176660014501 0ustar renerene is_integerscaling

is_integerscaling

Returns if integer scaling is active.

unsigned char is_integerscaling(lprec *lp);

Return Value

is_integerscaling returns if integer scaling is active (SCALE_INTEGERS set in get_scalelimit)

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_integerscaling function returns if integer scaling is active (SCALE_INTEGERS set in get_scalelimit). By default integers are not scaled. set_scaling must be called to active this feature.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int integerscaling;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  integerscaling = is_integerscaling(lp); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_scaling, set_scaling, set_scalelimit, get_scalelimit

doc/set_epsd.htm0000644000175000017500000000675010237176662012631 0ustar renerene set_epsd

set_epsd

Specifies the value that is used as a tolerance for reduced costs to determine whether a value should be considered as 0.

void set_epsd(lprec *lp, REAL epsd);

Return Value

set_epsd has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epsd

The value that is used as a tolerance for reduced costs to determine whether a value should be considered as 0.

Remarks

The set_epsd function specifies the value that is used as a tolerance for reduced costs to determine whether a value should be considered as 0.
Floating-point calculations always result in loss of precision and rounding errors. Therefore a very small value (example 1e-99) could be the result of such errors and should be considered as 0 for the algorithm. epsd specifies the tolerance to determine if a reducedcost value should be considered as 0. If abs(value) is less than this epsd value, it is considered as 0.
The default epsd value is 1e-9

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epsd(lp, 1.0e-8); /* sets epsd to 1e-8 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_epsd, set_infinite, is_infinite, get_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap

doc/reset_params.htm0000644000175000017500000000404210252424564013472 0ustar renerene reset_params

reset_params

Resets parameters back to their default values.

void reset_params(lprec *lp);

Return Value

No return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

This routine resets parameters back to their default values.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  reset_params(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, read_params, write_params

doc/O-Matrix.htm0000644000175000017500000034265711244025364012463 0ustar renerene Using lpsolve from O-Matrix

Using lpsolve from O-Matrix

O-Matrix?

O-Matrix is an integrated environment for analysing and visualizing data, and building turnkey scientific and engineering computing solutions. The program includes hundreds of engineering and statistical functions for solving a broad range of technical computing problems. Easy-to-use and flexible plotting commands enable you to rapidly build design prototypes, and implement sophisticated systems.

The foundation of O-Matrix is a high-performance matrix language that is specifically designed for high-performance technical computing. The notation of this language will dramatically reduce your design and implementation efforts, and enable the construction of systems that execute far quicker than other interpreted environments. O-Matrix also provides a compatibility mode that enables you to run MATLAB m-files. This enables you to leverage existing m-files, and simplifies the transition to O-Matrix for users experienced with MATLAB.

The O-Matrix environment is interpreted which means your commands are immediately executed as you enter them. Textual output is displayed in the Command window, and plotting commands are displayed in one or more Graphic windows. The environment provides a debugger for debugging, analysing, and profiling complex algorithms.

We will not discuss the specifics of O-Matrix here but instead refer the reader to the O-Matrix website.

O-Matrix and lpsolve

lpsolve is callable from O-Matrix via a dynamic linked DLL function. As such, it looks like lpsolve is fully integrated with O-Matrix. Matrices can directly be transferred between O-Matrix and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for O-Matrix (especially for matrix support). So you have full control to the complete lpsolve functionality via the omlpsolve O-Matrix driver. If you find that this involves too much work to solve an lp model then you can also work via higher-level script files that can make things a lot easier. See further in this article.

Quickstart

Compile and build omlpsolve:
----------------------------

1. Under Windows, the Microsoft Visual C/C++ compiler must be installed
   and the environment variables must be active do that when a command prompt
   is opened, the cl and nmake commands can be executed.

2. Go to directory lp_solve_5.5\extra\O-Matrix\lpsolve

3. To compile and build omlpsolve, enter the following command:
      cvc

Load the omlpsolve driver in the O-Matrix memory space:
-------------------------------------------------------

1. Under Windows, make sure that the lpsolve55.dll file is somewhere in the path
   (archive lp_solve_5.5.0.15_dev.zip)

2. A precompiled library is provided for Windows (omlpsolve.dll).

3. Start O-Matrix

4. Enter the following command in O-Matrix:
      O> dll <path>\omlpsolve.dll, omlpsolve
   This can also be added in autoexec.oms to automatically load the omlpsolve driver.

Note that O-Matrix version 5.8 or above is strongly recommended. Lower versions (at least 5.7) should work with this driver, but these versions don't have the ability to print information on the command prompt. For example default while a solve is done, information is printed to the command window. This will only be visible from version 5.8 or above.

O-Matrix is ideally suited to handle linear programming problems. These are problems in which you have a quantity, depending linearly on several variables, that you want to maximize or minimize subject to several constraints that are expressed as linear inequalities in the same variables.If the number of variables and the number of constraints are small, then there are numerous mathematical techniques for solving a linear programming problem. Indeed these techniques are often taught in high school or university level courses in finite mathematics.But sometimes these numbers are high, or even if low, the constants in the linear inequalities or the object expression for the quantity to be optimized may be numerically complicated in which case a software package like O-Matrix is required to effect a solution.

Installation

To make this possible, a driver program is needed: omlpsolve (omlpsolve.dll under Windows). This driver must be loaded in O-Matrix and O-Matrix can call the omlpsolve solver.

This driver calls lpsolve via the lpsolve shared library (lpsolve55.dll under Windows). This has the advantage that the omlpsolve driver doesn't have to be recompiled when an update of lpsolve is provided. The shared library must be somewhere in the Windows path.

So note the difference between the O-Matrix lpsolve driver that is called omlpsolve and the lpsolve library that implements the API that is called lpsolve55.

There are also some O-Matrix script files (.oms) as a quick start.

The first thing that must be done, each time O-Matrix is restarted and you want to use lpsolve is load the omlpsolve driver into the O-Matrix workspace. This is done via the dll command. Suppose that omlpsolve.dll is installed in c:\omwin\dll, then the following command must be used to load the driver:

dll c:\omwin\dll\omlpsolve.dll, omlpsolve

That is basically all you need to do. From now on, you can use the library. This until a clear command is given or O-Matrix is restarted. Then this command must be given again to reload the library.

To make things easier, you can edit the file autoexec.oms with your favourite editor (or notepad) in the omwin folder and add above line at the end of this file (before the last end). That will automatically load the lpsolve driver in memory when O-Matrix is started and also when a clear command is executed. So it will appear as if the omlpsolve command is then always available.

To test if everything is installed correctly, enter omlpsolve in the O-Matrix command prompt. If it gives the following, then everything is ok:

omlpsolve O-Matrix Interface version 5.5.0.6
using lpsolve version 5.5.0.15

Usage: [ret1, ret2, ...] = omlpsolve("functionname", arg1, arg2, ...)

Possibly, this is followed with:

No printing capability to command window available.
You need to upgrade to version 5.8 for this feature.

Then you are working with an O-Matrix version lower than 5.8. The driver should work, but nothing is printed on the command window when lpsolve has something to report (for example while solving).

However, if you get a message box with the following:

The identifier omlpsolve is not defined.

Then either the dll command that was previous given was unsuccessful (or not given at all) or something was misspelled after the ,

If you get the following:

This application has failed to start because lpsolve55.dll was not found.
Re-installing the application may fix this problem.

Then O-Matrix can find the omlpsolve driver program, but the driver program cannot find the lpsolve library that contains the lpsolve implementation. This library is called lpsolve55.dll and should be on your system in a directory that in the PATH environment variable. This path can be shown via the command getenv("PATH")

The lpsolve55.dll files must be in one of these specified directories. It is common to place this in the WINDOWS\system32 folder.

All this is developed and tested with O-Matrix version 5.7. This is the minimum supported release. Older releases are unsupported.

Solve an lp model from O-Matrix via omlpsolve

In the following text, O> before the O-Matrix commands is the O-Matrix command line. Only the text after O> must be entered.

To call an lpsolve function, the following syntax must be used:

O> [ret1, ret2, ...] = omlpsolve("functionname", arg1, arg2, ...)

The return values are optional and depend on the function called. functionname must always be enclosed between double quotes to make it alphanumerical and it is case sensitive. The number and type of arguments depend on the function called. Some functions even have a variable number of arguments and a different behaviour occurs depending on the type of the argument. functionname can be (almost) any of the lpsolve API routines (see lp_solve API reference) plus some extra O-Matrix specific functions. Most of the lpsolve API routines use or return an lprec structure. To make things more robust in O-Matrix, this structure is replaced by a handle or the model name. The lprec structures are maintained internally by the lpsolve driver. The handle is an incrementing number starting from 0. Starting from driver version 5.5.0.2, it is also possible to use the model name instead of the handle. This can of course only be done if a name is given to the model. This is done via lpsolve routine set_lp_name or by specifying the model name in routine read_lp. See Using model name instead of handle.

Almost all callable functions can be found in the lp_solve API reference. Some are exactly as described in the reference guide, others have a slightly different syntax to make maximum use of the O-Matrix functionality. For example make_lp is used identical as described. But get_variables is slightly different. In the API reference, this function has two arguments. The first the lp handle and the second the resulting variables and this array must already be dimensioned. When lpsolve is used from O-Matrix, nothing must be dimensioned in advance. The omlpsolve driver takes care of dimensioning all return variables and they are always returned as return value of the call to omlpsolve. Never as argument to the routine. This can be a single value as for get_objective (although O-Matrix stores this in a 1x1 matrix) or a matrix or vector as in get_variables. In this case, get_variables returns a 4x1 matrix (vector) with the result of the 4 variables of the lp model.

An example

(Note that you can execute this example by entering command per command as shown below or by just entering example1. This will execute example1.oms.)

O> lp=omlpsolve("make_lp", 0, 4);
O> omlpsolve("set_verbose", lp, 3);
O> omlpsolve("set_obj_fn", lp, [1, 3, 6.24, 0.1]);
O> omlpsolve("add_constraint", lp, [0, 78.26, 0, 2.9], 2, 92.3);
O> omlpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], 1, 14.8);
O> omlpsolve("add_constraint", lp, [12.68, 0, 0.08, 0.9], 2, 4);
O> omlpsolve("set_lowbo", lp, 1, 28.6);
O> omlpsolve("set_lowbo", lp, 4, 18);
O> omlpsolve("set_upbo", lp, 4, 48.98);
O> omlpsolve("set_col_name", lp, 1, "COLONE");
O> omlpsolve("set_col_name", lp, 2, "COLTWO");
O> omlpsolve("set_col_name", lp, 3, "COLTHREE");
O> omlpsolve("set_col_name", lp, 4, "COLFOUR");
O> omlpsolve("set_row_name", lp, 1, "THISROW");
O> omlpsolve("set_row_name", lp, 2, "THATROW");
O> omlpsolve("set_row_name", lp, 3, "LASTROW");
O> omlpsolve("write_lp", lp, "a.lp");
O> omlpsolve("get_mat", lp, 1, 2)
   78.2600
O> omlpsolve("solve", lp)
     0
O> omlpsolve("get_objective", lp)
   31.7828
O> omlpsolve("get_variables", lp)
{
28.6
0
0
31.8276
}

O> omlpsolve("get_constraints", lp)
{
92.3
6.8640
391.293
}

Note that there are some commands that return an answer. To see the answer, the command was not terminated with a semicolon (;). If the semicolon is put at the end of a command, the answer is not shown. However it is also possible to write the answer in a variable. In that case the result is never shown. With or without a terminating semicolon. For example:

O> obj=omlpsolve("get_objective", lp)

Or:

O> obj=omlpsolve("get_objective", lp);

Both will only write the result in variable obj without showing anything on screen. get_variables and get_constraints return a vector with the result. This can also be put in a variable:

O> x=omlpsolve("get_variables", lp);
O> b=omlpsolve("get_constraints", lp);

It is always possible to show the contents of a variable by just giving it as command:

O> x
{
28.6
0
0
31.8276
}

Don't forget to free the handle and its associated memory when you are done:

O> omlpsolve("delete_lp", lp);

Using model name instead of handle

From driver version 5.5.0.2, it is possible to use the model name instead of the handle. From the moment the model has a name, you can use this name instead of the handle. This is best shown by an example. Above example would look like this:
O> lp=omlpsolve("make_lp", 0, 4);
O> omlpsolve("set_lp_name", lp, "mymodel");
O> omlpsolve("set_verbose", "mymodel", 3);
O> omlpsolve("set_obj_fn", "mymodel", [1, 3, 6.24, 0.1]);
O> omlpsolve("add_constraint", "mymodel", [0, 78.26, 0, 2.9], 2, 92.3);
O> omlpsolve("add_constraint", "mymodel", [0.24, 0, 11.31, 0], 1, 14.8);
O> omlpsolve("add_constraint", "mymodel", [12.68, 0, 0.08, 0.9], 2, 4);
O> omlpsolve("set_lowbo", "mymodel", 1, 28.6);
O> omlpsolve("set_lowbo", "mymodel", 4, 18);
O> omlpsolve("set_upbo", "mymodel", 4, 48.98);
O> omlpsolve("set_col_name", "mymodel", 1, "COLONE");
O> omlpsolve("set_col_name", "mymodel", 2, "COLTWO");
O> omlpsolve("set_col_name", "mymodel", 3, "COLTHREE");
O> omlpsolve("set_col_name", "mymodel", 4, "COLFOUR");
O> omlpsolve("set_row_name", "mymodel", 1, "THISROW");
O> omlpsolve("set_row_name", "mymodel", 2, "THATROW");
O> omlpsolve("set_row_name", "mymodel", 3, "LASTROW");
O> omlpsolve("write_lp", "mymodel", "a.lp");
O> omlpsolve("get_mat", "mymodel", 1, 2)
   78.2600
O> omlpsolve("solve", "mymodel")
     0
O> omlpsolve("get_objective", "mymodel")
   31.7828
O> omlpsolve("get_variables", "mymodel")
{
28.6
0
0
31.8276
}

O> omlpsolve("get_constraints", "mymodel")
{
92.3
6.8640
391.293
}

So everywhere a handle is needed, you can also use the model name. You can even mix the two methods. There is also a specific O-Matrix routine to get the handle from the model name: get_handle.
For example:

O> omlpsolve("get_handle", "mymodel")
0

Don't forget to free the handle and its associated memory when you are done:

O> omlpsolve("delete_lp", "mymodel")

In the next part of this documentation, the handle is used. But if you name the model, the name could thus also be used.

Matrices

In O-Matrix, all numerical data is stored in matrices; even a scalar variable. O-Matrix also supports complex numbers. omlpsolve can only work with real numbers. For example:
O> omlpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], 1, 14.8);

Most of the time, variables are used to provide the data:

O> omlpsolve("add_constraint", lp, a1, 1, 14.8);

Where a1 is a matrix variable.

Matrices with too few or too much elements gives an 'invalid vector.' error.

Most of the time, omlpsolve needs vectors (rows or columns). In all situations, it doesn't matter if the vectors are row or column vectors. The driver accepts them both. For example:

O> omlpsolve("add_constraint", lp, {0.24, 0, 11.31, 0}, 1, 14.8);

Which is a column vector, but it is also accepted.

An important final note. Several lp_solve API routines accept a vector where the first element (element 0) is not used. Other lp_solve API calls do use the first element. In the O-Matrix interface, there is never an unused element in the matrices. So if the lp_solve API specifies that the first element is not used, then this element is not in the O-Matrix matrix.

Maximum usage of matrices with omlpsolve

Because O-Matrix is all about matrices, all lpsolve API routines that need a column or row number to get/set information for that column/row are extended in the omlpsolve O-Matrix driver to also work with matrices. For example set_int in the API can only set the integer status for one column. If the status for several integer variables must be set, then set_int must be called multiple times. The omlpsolve O-Matrix driver however also allows specifying a vector to set the integer status of all variables at once. The API call is: return = omlpsolve("set_int", lp, column, must_be_int). The matrix version of this call is: return = omlpsolve("set_int", lp, [must_be_int]). The API call to return the integer status of a variable is: return = omlpsolve("is_int", lp, column). The matrix version of this call is: [is_int] = omlpsolve("is_int", lp)
Also note the get_mat and set_mat routines. In O-Matrix these are extended to return/set the complete constraint matrix. See following example.

Above example can thus also be done as follows:
(Note that you can execute this example by entering command per command as shown below or by just entering example2. This will execute example2.oms.)

O> lp=omlpsolve("make_lp", 0, 4);
O> omlpsolve("set_verbose", lp, 3);
O> omlpsolve("set_obj_fn", lp, [1, 3, 6.24, 0.1]);
O> omlpsolve("add_constraint", lp, [0, 78.26, 0, 2.9], 2, 92.3);
O> omlpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], 1, 14.8);
O> omlpsolve("add_constraint", lp, [12.68, 0, 0.08, 0.9], 2, 4);
O> omlpsolve("set_lowbo", lp, [28.6, 0, 0, 18]);
O> omlpsolve("set_upbo", lp, [INF, INF, INF, 48.98]);
O> omlpsolve("set_col_name", lp, {"COLONE", "COLTWO", "COLTHREE", "COLFOUR"});
O> omlpsolve("set_row_name", lp, {"THISROW", "THATROW", "LASTROW"});
O> omlpsolve("write_lp", lp, "a.lp");
O> omlpsolve("get_mat", lp)
{
[ 0 , 78.26 , 0 , 2.9 ]
[ 0.24 , 0 , 11.31 , 0 ]
[ 12.68 , 0 , 0.08 , 0.9 ]
}

O> omlpsolve("solve", lp)
0
O> omlpsolve("get_objective", lp)
31.7828
O> omlpsolve("get_variables", lp)
{
28.6
0
0
31.8276
}

O> omlpsolve("get_constraints", lp)
{
92.3
6.8640
391.293
}

Note the usage of INF in set_upbo. This stands for "infinity". Meaning an infinite upper bound. It is also possible to use -INF to express minus infinity. This can for example be used to create a free variable.

To show the full power of the matrices, let's now do some matrix calculations to check the solution. It works further on above example:

O> A=omlpsolve("get_mat", lp);
O> X=omlpsolve("get_variables", lp);
O> B = A * X
O> B
{
92.3
6.864
391.293
}

So what we have done here is calculate the values of the constraints (RHS) by multiplying the constraint matrix with the solution vector. Now take a look at the values of the constraints that lpsolve has found:

O> omlpsolve("get_constraints", lp)
{
92.3
6.864
391.293
}

Exactly the same as the calculated B vector, as expected.

Also the value of the objective can be calculated in a same way:

O> C=omlpsolve("get_obj_fn", lp);
O> X=omlpsolve("get_variables", lp);
O> obj = C * X
O> obj
31.7828

So what we have done here is calculate the value of the objective by multiplying the objective vector with the solution vector. Now take a look at the value of the objective that lpsolve has found:

O> omlpsolve("get_objective", lp)
31.7828

Again exactly the same as the calculated obj value, as expected.

Using string constants

From driver version 5.5.0.15 on, it is possible to use string constants everywhere an lp_solve constant is needed or returned. This is best shown by an example. In the above code we had:
O> lp=omlpsolve("make_lp", 0, 4);
O> omlpsolve("set_verbose", lp, 3);
O> omlpsolve("add_constraint", lp, [0, 78.26, 0, 2.9], 2, 92.3);
O> omlpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], 1, 14.8);
O> omlpsolve("add_constraint", lp, [12.68, 0, 0.08, 0.9], 2, 4);

Note the 3rd parameter on set_verbose and the 4th on add_constraint. These are lp_solve constants. One could define all the possible constants in O-Matrix and then use them in the calls, but that has several disadvantages. First there stays the possibility to provide a constant that is not intended for that particular call. Another issue is that calls that return a constant are still returning it numerical.

Both issues can now be handled by string constants. The above code can be done as following with string constants:

O> lp=omlpsolve("make_lp", 0, 4);
O> omlpsolve("set_verbose", lp, "IMPORTANT");
O> omlpsolve("add_constraint", lp, [0, 78.26, 0, 2.9], "GE", 92.3);
O> omlpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], "LE", 14.8);
O> omlpsolve("add_constraint", lp, [12.68, 0, 0.08, 0.9], "GE", 4);

This is not only more readable, there is much lesser chance that mistakes are being made. The calling routine knows which constants are possible and only allows these. So unknown constants or constants that are intended for other calls are not accepted. For example:

O> omlpsolve("set_verbose", lp, "blabla");
BLABLA: Unknown.

O> omlpsolve("set_verbose", lp, "GE");
GE: Not allowed here.

Note the difference between the two error messages. The first says that the constant is not known, the second that the constant cannot be used at that place.

Constants are case insensitive. Internally they are always translated to upper case. Also when returned they will always be in upper case.

The constant names are the ones as specified in the documentation of each API routine. There are only 3 exceptions, extensions actually. "LE", "GE" and "EQ" in add_constraint and is_constr_type can also be "<", "<=", ">", ">=", "=". When returned however, "GE", "LE", "EQ" will be used.

Also in the matrix version of calls, string constants are possible. For example:

O> omlpsolve("set_constr_type", lp, {"LE", "EQ", "GE"});

Some constants can be a combination of multiple constants. For example set_scaling:

O> omlpsolve("set_scaling", lp, 3+128);

With the string version of constants this can be done as following:

O> omlpsolve("set_scaling", lp, "SCALE_MEAN|SCALE_INTEGERS");

| is the OR operator used to combine multiple constants. There may optinally be spaces before and after the |.

Not all OR combinations are legal. For example in set_scaling, a choice must be made between SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC or SCALE_CURTISREID. They may not be combined with each other. This is also tested:

O> omlpsolve("set_scaling", lp, "SCALE_MEAN|SCALE_RANGE");
SCALE_RANGE cannot be combined with SCALE_MEAN

Everywhere constants must be provided, numeric or string values may be provided. The routine automatically interpretes them.

Returning constants is a different story. The user must let lp_solve know how to return it. Numerical or as string. The default is numerical:

O> omlpsolve("get_scaling", lp)
131

To let lp_solve return a constant as string, a call to a new function must be made: return_constants

O> omlpsolve("return_constants", 1);

From now on, all returned constants are returned as string:

O> omlpsolve("get_scaling", lp)
SCALE_MEAN|SCALE_INTEGERS

Also when an array of constants is returned, they are returned as string when return_constants is set:

O> omlpsolve("get_constr_type", lp)

LE
EQ
GE

This for all routines until return_constants is again called with 0:

O> omlpsolve("return_constants", 0);

The (new) current setting of return_constants is always returned by the call. Even when set:

O> omlpsolve("return_constants", 1)
1

To get the value without setting it, don"t provide the second argument:

O> omlpsolve("return_constants")
1

In the next part of this documentation, return_constants is the default, 0, so all constants are returned numerical and provided constants are also numerical. This to keep the documentation as compatible as possible with older versions. But don"t let you hold that back to use string constants in your code.

oms scripts

O-Matrix can execute a sequence of statements stored in files. Such files are called oms files because they must have the file type of ".oms" as the last part of their filename (extension).

oms scripts can be compared with batch files or scripts. You can put O-Matrix commands in them and execute them at any time. The oms script is executed like any other command, by entering its name (without the .oms extension).

The omlpsolve O-Matrix distribution contains some example oms scripts to demonstrate this.

You can also edit these files with your favourite text editor (or notepad).

example1.oms

Contains the commands as shown in the first example of this article. To execute and also see which commands are executed in the debug window, use following commands:

O> stop
O> trace on example1.oms
O> quit
O> example1

Note however that execution is much slower when trace is on. It is only used here to see the statements executed.

example2.oms

Contains the commands as shown in the second example of this article. To execute and also see which commands are executed in the debug window, use following commands:

O> stop
O> trace on example2.oms
O> quit
O> example2

Note however that execution is much slower when trace is on. It is only used here to see the statements executed.

example3.oms

Contains the commands of a practical example. See further in this article.

example4.oms

Contains the commands of a practical example. See further in this article.

example5.oms

Contains the commands of a practical example. See further in this article.

example6.oms

Contains the commands of a practical example. See further in this article.

lp_solve.oms

This script uses the API to create a higher-level function called lp_solve. This function accepts as arguments some matrices and options to create and solve an lp model. See the beginning of the file to see its usage:

 LP_SOLVE  Solves mixed integer linear programming problems.

   SYNOPSIS: [obj,x,duals] = lp_solve(f,a,b,e,vlb,vub,xint,scalemode,keep)

      solves the MILP problem

              max v = f'*x
                a*x <> b
                  vlb <= x <= vub
                  x(int) are integer

   ARGUMENTS: The first four arguments are required:

            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) = -1  ==> Less Than
                      e(i) =  0  ==> Equals
                      e(i) =  1  ==> Greater Than
          vlb: n vector of lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
         keep: Flag for keeping the lp problem after it's been solved.
               If omitted, the lp will be deleted when solved.

   OUTPUT: A nonempty output is returned if a solution is found:

          obj: Optimal value of the objective function.
            x: Optimal value of the decision variables.
        duals: solution of the dual problem.

Example of usage. To create and solve following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

O> include lp_solve.oms
O> [obj, x]=lp_solve([-1, 2], {[2, 1], [-4, 4]}, [5, 5], [-1, -1], [], [], [1, 2])
O> obj
3
O> x
{
1
2
}

lp_maker.oms

This script is analog to the lp_solve script and also uses the API to create a higher-level function called lp_maker. This function accepts as arguments some matrices and options to create an lp model. Note that this scripts only creates a model and returns a handle. See the beginning of the file to see its usage:

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Example of usage. To create following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

O> include lp_maker.oms
O> lp=lp_maker([-1, 2], {[2, 1], [-4, 4]}, [5, 5], [-1, -1], [], [], [1, 2])
O> lp
0

To solve the model and get the solution:

O> omlpsolve("solve", lp)
0
O> omlpsolve("get_objective", lp)
3
O> omlpsolve("get_variables", lp)
{
1
2
}

Don't forget to free the handle and its associated memory when you are done:

O> omlpsolve("delete_lp", lp);

lpdemo.oms

Contains several examples to build and solve lp models. To execute and also see which commands are executed in the debug window, use following commands:

O> stop
O> trace on lpdemo.oms
O> quit
O> lpdemo

Note however that execution is much slower when trace is on. It is only used here to see the statements executed.

ex.oms

Contains several examples to build and solve lp models. Also solves the lp_examples from the lp_solve distribution. To execute and also see which commands are executed in the debug window, use following commands:

O> stop
O> trace on ex.oms
O> quit
O> ex

Note however that execution is much slower when trace is on. It is only used here to see the statements executed.

A practical example

We shall illustrate the method of linear programming by means of a simple example, giving a combination graphical/numerical solution, and then solve both a slightly as well as a substantially more complicated problem.

Suppose a farmer has 75 acres on which to plant two crops: wheat and barley. To produce these crops, it costs the farmer (for seed, fertilizer, etc.) $120 per acre for the wheat and $210 per acre for the barley.The farmer has $15000 available for expenses. But after the harvest, the farmer must store the crops while awaiting favourable market conditions. The farmer has storage space for 4000 bushels.Each acre yields an average of 110 bushels of wheat or 30 bushels of barley. If the net profit per bushel of wheat (after all expenses have been subtracted) is $1.30 and for barley is $2.00, how should the farmer plant the 75 acres to maximize profit?

We begin by formulating the problem mathematically. First we express the objective, that is the profit, and the constraints algebraically, then we graph them, and lastly we arrive at the solution by graphical inspection and a minor arithmetic calculation.

Let x denote the number of acres allotted to wheat and y the number of acres allotted to barley. Then the expression to be maximized, that is the profit, is clearly

P = (110)(1.30)x + (30)(2.00)y = 143x + 60y.

There are three constraint inequalities, specified by the limits on expenses, storage and acreage. They are respectively:

120x + 210y <= 15000
110x + 30y <= 4000
x + y <= 75

Strictly speaking there are two more constraint inequalities forced by the fact that the farmer cannot plant a negative number of acres, namely:

x >= 0,y >= 0.

Next we graph the regions specified by the constraints. The last two say that we only need to consider the first quadrant in the x-y plane. Here's a graph delineating the triangular region in the first quadrant determined by the first inequality.

O> clear
O> X = 0.1:0.05:125;
O> Y1 = (15000. - 120*X)/210;
O> bar(X, Y1)

Source

Now let's put in the other two constraint inequalities.

O> clear
O> X = 0.1:0.05:38;
O> mlmode
O> Y1 = (15000. - 120*X)/210;
O> Y2 = max((4000 - 110.*X)./30, 0);
O> Y3 = max(75 - X, 0.);
O> Ytop = min(min(Y1, Y2), Y3);
O> omatrix
O> bar(X, Ytop)
O> gtitle("Solution space")

Source

The black area is the solution space that holds valid solutions. This means that any point in this area fulfils the constraints.

Now let's superimpose on top of this picture a contour plot of the objective function P.

O> mlmode meshgrid.m
O> [U, V] = meshgrid(0:1:40, 0:1:80);
O> Ur = U.row(1)
O> Vc = V.col(1)
O> Z = 143.*U + 60.*V
O> levels = (0:1:11)*1000.
O> contour(Z', levels, Ur', Vc');
O> gtitle("Solution space and objective")

Source

The lines give a picture of the objective function. All solutions that intersect with the black area are valid solutions, meaning that this result also fulfils the set constraints. The more the lines go to the right, the higher the objective value is. The optimal solution or best objective is a line that is still in the black area, but with an as large as possible value.

It seems apparent that the maximum value of P will occur on the level curve (that is, level line) that passes through the vertex of the polygon that lies near (22,53).
It is the intersection of x + y = 75 and 110*x + 30*y = 4000
This is a corner point of the diagram. This is not a coincidence. The simplex algorithm, which is used by lp_solve, starts from a theorem that the optimal solution is such a corner point.
In fact we can compute the result:

O> x = {[1, 1], [110, 30]} \ {75, 4000}
O> print "x =", x
x = {
21.875
53.125
}

The acreage that results in the maximum profit is 21.875 for wheat and 53.125 for barley. In that case the profit is:

O> P = [143, 60] * x
O> print "Profit, P =", P
Profit, P = 6315.63

That is, $6315.63.

Note that these command are in script example3.oms

Now, lp_solve comes into the picture to solve this linear programming problem more generally. After that we will use it to solve two more complicated problems involving more variables and constraints.

For this example, we use the higher-level script lp_maker to build the model and then some lp_solve API calls to retrieve the solution. Here is again the usage of lp_maker:

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Now let's formulate this model with lp_solve:

O> f = [143, 60];
O> A = {[120, 210], [110, 30], [1, 1]};
O> b = {15000, 4000, 75};
O> lp = lp_maker(f, A, b, [-1, -1, -1], [], [], [], 1, 0);
O> solvestat = omlpsolve("solve", lp)
O> omlpsolve("get_objective", lp)
6315.63
O> omlpsolve("get_variables", lp)
{
21.875
53.125
}
O> omlpsolve("delete_lp", lp);

Note that these command are in script example4.oms

With the higher-level script lp_maker, we provide all data to lp_solve. lp_solve returns a handle (lp) to the created model. Then the API call 'solve' is used to calculate the optimal solution of the model. The value of the objective function is retrieved via the API call 'get_objective' and the values of the variables are retrieved via the API call 'get_variables'. At last, the model is removed from memory via a call to 'delete_lp'. Don't forget this to free all memory allocated by lp_solve.

The solution is the same answer we obtained before. Note that the non-negativity constraints are accounted implicitly because variables are by default non-negative in lp_solve.

Well, we could have done this problem by hand (as shown in the introduction) because it is very small and it can be graphically presented.
Now suppose that the farmer is dealing with a third crop, say corn, and that the corresponding data is:

cost per acre$150.75
yield per acre125 bushels
profit per bushel$1.56

With three variables it is already a lot more difficult to show this model graphically. Adding more variables makes it even impossible because we can't imagine anymore how to represent this. We only have a practical understanding of 3 dimentions, but beyound that it is all very theorethical.

If we denote the number of acres allotted to corn by z, then the objective function becomes:

P = (110)(1.30)x + (30)(2.00)y+ (125)(1.56) = 143x + 60y + 195z

And the constraint inequalities are:

120x + 210y + 150.75z <= 15000
110x + 30y + 125z <= 4000
x + y + z <= 75
x >= 0,y >= 0, z >= 0

The problem is solved with lp_solve as follows:

O> f = [143, 60, 195];
O> A = {[120, 210, 150.75], [110, 30, 125], [1, 1, 1]};
O> b = {15000, 4000, 75};
O> lp = lp_maker(f, A, b, [-1, -1, -1], [], [], [], 1, 0);
O> solvestat = omlpsolve("solve", lp)
O> omlpsolve("get_objective", lp)
6986.84
O> omlpsolve("get_variables", lp)
{
0
56.5789
18.4211
}
O> omlpsolve("delete_lp", lp);

Note that these command are in script example5.oms

So the farmer should ditch the wheat and plant 56.5789 acres of barley and 18.4211 acres of corn.

There is no practical limit on the number of variables and constraints that O-Matrix can handle. Certainly none that the relatively unsophisticated user will encounter.Indeed, in many true applications of the technique of linear programming, one needs to deal with many variables and constraints.The solution of such a problem by hand is not feasible, and software like O-Matrix is crucial to success.For example, in the farming problem with which we have been working, one could have more crops than two or three. Think agribusiness instead of family farmer.And one could have constraints that arise from other things beside expenses, storage and acreage limitations. For example:

Below is a sequence of commands that solves exactly such a problem. You should be able to recognize the objective expression and the constraints from the data that is entered. But as an aid, you might answer the following questions:

O> f = [110*1.3, 30*2.0, 125*1.56, 75*1.8, 95*.95, 100*2.25, 50*1.35];
O> A = {[120,210,150.75,115,186,140,85],[110,30,125,75,95,100,50],[1,1,1,1,1,1,1],
                  [1,-1,0,0,0,0,0],[0,0,1,0,-2,0,0],[0,0,0,-1,0,-1,1]};
O> b = {55000, 40000, 400, 0, 0, 0};
O> lp = lp_maker(f, A, b, [-1,-1,-1,-1,-1,-1],[10,10,10,10,20,20,20],[100,INF,50,INF,INF,250,INF],[],1,0);
O> solvestat = omlpsolve("solve", lp)
O> omlpsolve("get_objective", lp)
75398
O> omlpsolve("get_variables", lp)
{
10
10
40
45.6522
20
250
20
}
O> omlpsolve("delete_lp", lp);

Note that these command are in script example6.oms

Note that we have used in this formulation the vlb and vub arguments of lp_maker. This to set lower and upper bounds on variables. This could have been done via extra constraints, but it is more performant to set bounds on variables. Also note that Inf is used for variables that have no upper limit. This stands for Infinity.

Note that despite the complexity of the problem, lp_solve solves it almost instantaneously. It seems the farmer should bet the farm on crop number 6.We strongly suggest you alter the expense and/or the storage limit in the problem and see what effect that has on the answer.

Another, more theoretical, example

Suppose we want to solve the following linear program using O-Matrix:

max 4x1 + 2x2 + x3
s. t. 2x1 + x2 <= 1
x1 + 2x3 <= 2
x1 + x2 + x3 = 1
x1 >= 0
x1 <= 1
x2 >= 0
x2 <= 1
x3 >= 0
x3 <= 2

Convert the LP into O-Matrix format we get:

f = [4, 2, 1]
A = {[2, 1, 0], [1, 0, 2], [1, 1, 1]}
b = {1, 2, 1}

Note that constraints on single variables are not put in the constraint matrix. lp_solve can set bounds on individual variables and this is more performant than creating additional constraints. These bounds are:

l = [ 0, 0, 0]
u = [ 1, 1, 2]

Now lets enter this in O-Matrix:

O> f = [4, 2, 1];
O> A = {[2, 1, 0], [1, 0, 2], [1, 1, 1]};
O> b = {1, 2, 1};
O> l = [ 0, 0, 0];
O> u = [ 1, 1, 2];

Now solve the linear program using O-Matrix: Type the commands

O> lp = lp_maker(f, A, b, [-1, -1, -1], l, u, [], 1, 0);
O> solvestat = omlpsolve("solve", lp)
O> omlpsolve("get_objective", lp)
2.5
O> omlpsolve("get_variables", lp)
{
0.5
0
0.5
}
O> omlpsolve("delete_lp", lp)

What to do when some of the variables are missing ?
For example, suppose there are no lower bounds on the variables. In this case define l to be the empty set using the O-Matrix command:

O> l = [];

This has the same effect as before, because lp_solve has as default lower bound for variables 0.

But what if you want that variables may also become negative?
Then you can use -INF as lower bounds:

O> l = [-INF, -INF, -INF];

Solve this and you get a different result:

O> lp = lp_maker(f, A, b, [-1, -1, -1], l, u, [], 1, 0);
O> solvestat = omlpsolve("solve", lp)
O> omlpsolve("get_objective", lp)
2.66667
O> omlpsolve("get_variables", lp)
{
0.666667
-0.333333
0.666667
}
O> omlpsolve("delete_lp", lp)

Overview of API routines

Note that everwhere where lp is used as argument that this can be a handle (lp_handle) or the models name.

Extra O-Matrix routines

These routines are not part of the lpsolve API, but are added for backwards compatibility. Most of them exist in the lpsolve API with another name.

Compile the omlpsolve driver

Windows

Under Windows, the omlpsolve O-Matrix driver is a dll: omlpsolve.dll
This dll is an interface to the lpsolve55.dll lpsolve dll that contains the implementation of lp_solve. lpsolve55.dll is distributed with the lp_solve package (archive lp_solve_5.5.0.15_dev.zip). The omlpsolve O-Matrix driver dll (omlpsolve.dll) is just a wrapper between O-Matrix and lp_solve to translate the input/output to/from O-Matrix and the lp_solve library.

The omlpsolve O-Matrix driver is written in C. To compile this code, Microsoft compiler is needed. Other compilers might also work, but this is untested. To make the compilation process easier, a batch file can be used: cvc.bat
It may be necessary to edit this file first to change the path where lp_solve and the O-Matrix dll sources are installed. Change at the beginning lpsolvepath and dllsrcpath. dllsrcpath must point to the folder where dll.h is located.
To make for release, just enter cvc and everything is build.
This compiles three source files: lpsolve.c, omatrix.c and hash.c
Then these are linked with the library lpsolve55.lib to generate the omlpsolve.dll file.
The optional arguments to cvc are used for development. Source files can be provided and then only these are compiled. For example hash.c should only be compiled once while developing. So specifying lpsolve.c as first argument will only compile this file and then link everything. This makes the build process a bit faster. Also the option -DDEMO can be added to add the demo command to test some functionality of lpsolve. This is also only for debugging. Also the option -DDEBUG can be added. This to print some debug information while executing omlpsolve. Should only be used for debugging purposes.

Note that the omlpsolve.dll file can be locked by O-Matrix. Then the build process will fail because the dll can not be overwritten. This can be solved by giving the clear command in O-Matrix. This will free the dll.

Unix/Linux

At this moment, there is no O-Matrix version for this platform.

See also Using lpsolve from MATLAB, Using lpsolve from Sysquake, Using lpsolve from Scilab, Using lpsolve from Octave, Using lpsolve from FreeMat, Using lpsolve from Euler, Using lpsolve from Python, Using lpsolve from Sage, Using lpsolve from PHP, Using lpsolve from R

doc/quickstart.htm0000644000175000017500000002323011236130514013167 0ustar renerene Quick Start

Quick Start

lp_solve (or lpsolve) has allot of features in-house. For a beginner, it can be difficult to determine where to start. The distribution contains many files and to start with, you need only a couple of them. As you learn the package you may need extras. This text explains how to start with lp_solve.

Skip the blabla, just give me a very quick start.

How to call lp_solve

Basically, lp_solve is a library, a set of routines, called the API that can be called from almost any programming language to solve MILP problems. There are several ways to pass the data to the library:

  • Via the API
  • Via input files
  • Via an IDE

Via the API

The API is a set of routines that can be called from a programming language to build the model in memory, solve it and return the results. There are many API routines to perform many possible tasks and set several options. See lp_solve API reference for an overview.

Via input files

Standard, lp_solve supports several input files types. The common known MPS format (see mps-format) is supported by most solvers, but it is not very readable for humans. Another format is the lp format (see lp-format) that is more readable. lp_solve has the unique ability to use user-written routines to input the model (see External Language Interface). See read_mps, read_freemps, read_MPS, read_freeMPS and read_lp, read_LP for the API calls to read the model from file.

There is also a driver program called lp_solve that uses the API to provide a command line application to solve models. See lp_solve for its usage. With this program you don't have to know anything of API or computer programming languages. You can just provide your model via file to the program and it will solve the model and give you the result.

Via an IDE

Thanks to Henri Gourvest, there is now also an IDE program called LPSolve IDE that uses the API to provide a Windows application to solve models. See LPSolve IDE for its usage. With this program you don't have to know anything of API or computer programming languages. You can just provide your model to the program and it will solve the model and give you the result.

As already stated, lp_solve can be called from many programming language. Among them are C, C++, Pascal, Delphi, Java, VB, C#, VB.NET, Excel. But let this list not be a limitation. Any programming language capable of calling external libraries (DLLs under Windows, Shared libraries (.so) under Unix/Linux) can call lp_solve.

Some key features of lp_solve

  • Mixed Integer Linear Programming (MILP) solver
  • Basically no limit on model size
  • It is free and with sources
  • Supports Integer variables, Semi-continuous variables and Special Ordered Sets
  • Can read model from MPS, LP or user written format
  • Models can be build in-memory without the use of files
  • Has a powerful API interface
  • Easy callable from other programming languages
  • Advanced pricing using Devex and Steepest Edge for both primal and dual simplexes
  • Provides different scaling methods to make the model more numerical stable
  • Has presolve capabilities to tighten constraints/make the model smaller and faster to solve
  • Has a base crashing routine to determine a starting point
  • Allows restart after making changes to the model. Solve continues from the last found solution
  • Possible to select desired combinations of primal and dual phases 1 and 2
  • Possible to set several solver parameters like tolerances
  • Alternative (and faster) inverse/re-factorisation libraries are provided for. See Basis Factorization Packages
  • Alternative model readers and writers possible via the XLI implementation. See External Language Interfaces
  • Has the possibility to convert one model format to another format
  • Provides post-optimal sensitivity analysis. See Sensitivity
  • ...

Quick quick start

Formulating a problem

If you don't know much about linear programming, first take a look at Formulation of an lp problem in lpsolve. Start with reading the first part where a practical example is presented until the point where the formulation is given in mathematical format, then return to here. This practical example is used in the next presentations.

Another very usefull and free paper about linear programming fundamentals and advanced features plus several problems being discussed and modeled is Applications of optimization with Xpress-MP. It describes linear programming and modeling with the commercial solver Xpress-MP, but is as usefull for other solvers like lp_solve. In case that this link would not work anymore, try this via google search.

Solve a problem via the IDE

The easiest way to start with lp_solve is via the IDE. This only works under Windows. See LPSolve IDE.

Solve a problem via the lp_solve command line program

Another way to solve a model is via the lp_solve command line program. This works on any platform, but is completely command-line driven. Well known by Unix/Linux shell programmers and DOS box users. See lp_solve command.

solve a problem via the API

Programmers want to call lp_solve in a totally different way. They want to call lp_solve as a library directly from their programming language. This is what is called the API (Application Programming Interface). See Calling the lpsolve API from your application and Construct the model from a Programming Language. An overview of the complete API can be found on: lp_solve API reference.

Compile the source code yourself

The distribution contains precompiled libraries/binaries for Windows and Linux. However lp_solve can be compiled on other platforms also. You may also to make modifications to it and then you have to recompile also, even on the precompiled platforms. See Calling the lpsolve API from your application. In this article it is both explained how to link your code to the library and how to compile the lp_solve code.

Basis Factorization Packages

Alternative inverse/re-factorization libraries can be used by lp_solve. This is a feature for the more experienced users of lp_solve. See Basis Factorization Packages for more information. The sources of these packages are in the lp_solve_5.5.0.15_bfp_*_source.tar.gz archives. The binaries are in the lp_solve_5.5.0.15_exe* archive.

External Language Interfaces

Alternative model readers and writers possible via the XLI implementation. Models expressed in format files other than lp or MPS format can also be read or written by lp_solve via this unique feature. See External Language Interfaces for more information. The sources of these packages are in the lp_solve_5.5.0.15_xli_*_source.tar.gz archives. The binaries are in the lp_solve_5.5.0.15_exe* archive.

Calling lp_solve from higher level Mathematical languages.

lp_solve can be called from AMPL, MATLAB, O-Matrix, Sysquake, Scilab, Octave, FreeMat, Euler, Python, Sage, PHP, R.

You now have a pretty good idea what lp_solve is about.

doc/LPBasics.htm0000644000175000017500000002135511050351355012445 0ustar renerene Linear programming basics

Linear programming basics

A short explanation is given what Linear programming is and some basic knowledge you need to know.

A linear programming problem is mathematically formulated as follows:

  • A linear function to be maximized or minimized
e.g.
maximize c1 x1 + c2 x2
  • Problem constraints of the following form
e.g.
a11 x1 + a12 x2 <= b1
a21 x1 + a22 x2 <= b2
a31 x1 + a32 x2 <= b3
  • Default lower bounds of zero on all variables.

The problem is usually expressed in matrix form, and then becomes:

     maximize     CT x
     subject to   A x <= B
                  x >= 0

So a linear programming model consists of one objective which is a linear equation that must be maximized or minimized. Then there are a number of linear inequalities or constraints.

cT, A and B are constant matrixes. x are the variables (unknowns). All of them are real, continue values.

Note the default lower bounds of zero on all variables x. People tend to forget this build-in default. If no negative (or negative infinite) lower bound is explicitely set on variables, they can and will take only positive (zero included) values.

The inequalities can be <=, >= or =
Because all numbers are real values, <= is the same as < and >= is the same as >

Also note that both objective function and constraints must be linear equations. This means that no variables can be multiplied with each other.

This formulation is called the Standard form. It is the usual and most intuitive form of describing a linear programming problem.

Example:

     minimize     3 x1 - x2
     subject to    -x1 + 6 x2 - x3   + x4 >= -3
                         7 x2      + 2 x4  =  5
                    x1 +   x2 + x3         =  1
                                x3 +   x4 <=  2

Sometimes, these problems are formulated in the canonical form. All inequalities are converted to equalities by adding an extra variable where needed:

     maximize     CT x
     subject to   A x = B
                  x >= 0

Above example can then be written as:

     minimize     3 x1 - x2
     subject to    -x1 + 6 x2 - x3   + x4 - s = -3
                         7 x2      + 2 x4     =  5
                    x1 +   x2 + x3            =  1
                                x3 +   x4 + t =  2

So everywhere an equality was specified, an extra variable is introduced and subtracted (if it was >) or added (if it was <) to the constraint. These variables also only take positive (or zero) values only. These extra variables are called slack or surplus variables.

lp_solve add's these variables automatically to its internal structure. The formulator doesn't have to do it and it is even better not to. There will be fewer variables in the model and thus quicker to solve.

See Formulation of an lp problem in lpsolve for a practical example.

The right hand side (RHS), the B-vector, must be a constant matrix. Some people see this as a problem, but it isn't The RHS can always be brought to the left by a simple operation:

     A x <= B
Is equal to:
     A x - B <= 0
So if B is not constant, just do that.

Basic mathematics also states that if a constraint is multiplied by a negative constant, that the inequality changes from direction. For example:

     5 x1 - 2 x2 >= 3
If multiplied by -1, it becomes:
    -5 x1 + 2 x2 <= -3

If the objective is multiplied by -1, then maximization becomes minimization and the other way around. For example:

    minimize     3 x1 - x2
Can also be written as:
    maximize     -3 x1 + x2

The result will be the same, but changed from sign.

Bounds

Minima and maxima on single variables are special cases of restrictions. They are called bounds. The optimization algorithm can handle these bounds more effeciently than other restrictions. They consume less memory and the algorithm is faster with them. As already specified, there is by default an implicit lower bound of zero on each variable. Only when explicitly another lower bound is set, the default of 0 is overruled. This other bound can be negative also. There is no default upper bound on variables. Almost all solvers support bounds on variables. So does lp_solve.

Ranges

Frequently, it happens that on the same equation a less than and a greater than restriction must be set. Instead of adding two extra restrictions to the model, it is more performant and less memory consument to only add one restiction with either the less than or greater than restriction and put the other inequality on that same constraint by means of a range. Not all solvers support this feature but lp_solve does.

Integer and binary variables

By default, all variables are real. Sometimes it is required that one or more variables must be integer. It is not possible to just solve the model as is and then round to the nearest solution. At best, this result will maybe furfill all constraints, but you cannot be sure of. As you cannot be sure of the fact that this is the most optimal solution. Problems with integer variables are called integer or descrete programming problems. If all variables are integer it is called a pure integer programming problem, else it is a mixed integer programming problem. A special case of integer variables are binary variables. These are variables that can only take 0 or 1 as value. They are used quite frequently to program discontinue conditions. lp_solve can handle integer and binary variables. Binary variables are defined as integer variables with a maximum (upper bound) of 1 on them. See integer variables for a description on them.

Semi-continuous variables

Semi-continuous variables are variables that must take a value between their minimum and maximum or zero. So these variables are treated the same as regular variables, except that a value of zero is also accepted, even if there is a minimum bigger than zero is set on the variable. See semi-continuous variables for a description on them.

Special ordered sets (SOS)

A specially ordered set of degree N is a collection of variables where at most N variables may be non-zero. The non-zero variables must be contiguous (neighbours) sorted by the ascending value of their respective unique weights. In lp_solve, specially ordered sets may be of any cardinal type 1, 2, and higher, and may be overlapping. The number of variables in the set must be equal to, or exceed the cardinal SOS order. See Special ordered sets (SOS) for a description on them.

lp_solve uses the simplex algorithm to solve these problems. To solve the integer restrictions, the branch and bound (B&B) method is used.

Other resources

Another very usefull and free paper about linear programming fundamentals and advanced features plus several problems being discussed and modeled is Applications of optimization with Xpress-MP. It describes linear programming and modeling with the commercial solver Xpress-MP, but is as usefull for other solvers like lp_solve. In case that this link would not work anymore, try this via google search.

doc/get_anti_degen.htm0000644000175000017500000001027110246351116013735 0ustar renerene get_anti_degen

get_anti_degen

Returns the used degeneracy rule.

int get_anti_degen(lprec *lp);

Return Value

get_anti_degen returns the used degeneracy rule. Can be a combination of any of the following values:

ANTIDEGEN_NONE (0) No anti-degeneracy handling
ANTIDEGEN_FIXEDVARS (1) Check if there are equality slacks in the basis and try to drive them out in order to reduce chance of degeneracy in Phase 1
ANTIDEGEN_COLUMNCHECK (2)  
ANTIDEGEN_STALLING (4)  
ANTIDEGEN_NUMFAILURE (8)  
ANTIDEGEN_LOSTFEAS (16)  
ANTIDEGEN_INFEASIBLE (32)  
ANTIDEGEN_DYNAMIC (64)  
ANTIDEGEN_DURINGBB (128)  
ANTIDEGEN_RHSPERTURB (256) Perturbation of the working RHS at refactorization
ANTIDEGEN_BOUNDFLIP (512) Limit bound flips that can sometimes contribute to degeneracy in some models

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_anti_degen function returns the used degeneracy rule.
The default is ANTIDEGEN_INFEASIBLE + ANTIDEGEN_STALLING + ANTIDEGEN_FIXEDVARS (37)

Example

#include
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int anti_degen;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }
  anti_degen= get_anti_degen(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_anti_degen, is_anti_degen

doc/read_lp.htm0000644000175000017500000000726710661665156012437 0ustar renerene read_lp, read_LP

read_lp, read_LP

Create an lprec structure and read an lp model from file.

lprec *read_lp(FILE *stream, int verbose, char *lp_name);

lprec *read_LP(char *filename, int verbose, char *lp_name);

Return Value

Returns a pointer to a new lprec structure. This must be provided to almost all lp_solve functions.
A NULL return value indicates an error. Specifically file could not be opened or file has wrong structure or not enough memory available to setup an lprec structure.

Parameters

stream

Pointer to FILE structure.

filename

Filename to read the lp model from.

verbose

The verbose level. Can be one of the following values:
CRITICAL (1), SEVERE (2), IMPORTANT (3), NORMAL (4), DETAILED (5), FULL (6)

See also set_verbose and get_verbose.

lp_name

Initial name of the model. See also set_lp_name and get_lp_name. May be NULL if the model has no name.

Remarks

The read_lp and read_LP functions construct a new lprec structure and read the model from filename. read_lp needs a file pointer to an already opened file. read_LP accepts the name of the file. The latter function will generally be more convenient.

The model in the file must be in lp-format.

It is advised not to read/write the lprec structure. Instead, use the function interface to communicate with the lp_solve library. This because the structure can change over time. The function interface will be more stable.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"
int main(void)
{
  lprec *lp;

  /* Read LP model */
  lp = read_LP("model.lp", NORMAL, "test model");
  if(lp == NULL) {
    fprintf(stderr, "Unable to read model\n");
    return(1);
  }

  /* Model read */

  /*
  .
  .
  .
  */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, copy_lp, write_lp, write_LP, write_lpex, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_mps, write_freemps, write_MPS, write_freeMPS, MPS_writefileex

doc/contents.htm0000644000175000017500000005677411246262546012671 0ustar renerene Contents

lp_solve 5.5.0.15 index

doc/SpecialOrderedSetsOfTypeOne_files/0000755000175000017500000000000010762557070016777 5ustar renerenedoc/SpecialOrderedSetsOfTypeOne_files/img00343.gif0000644000175000017500000000251007755240740020633 0ustar renereneGIF89a!,H*\ȰÇ#JHŋ3jȱǏ CH%Or%Ca$́7]$h3Ο iT¢4TRHusiГR(שS)DzL-qϕn^{]8e[nʜ{X۠~k2۔q^t)v;PC˶&ᛑ=/-pUhsV8؝kCE<熜cf=-hʦ>8/v-KO.Oڹp弧*=;u1^=U6^ݶx}z|rjKJ{zCYfDSj ]UYy *߁6]e6GsVaΖb{Sh gӅp8 ݸy#`+X})Yv=ډ=_F2tw5HcZu7Qa'MB Qy_ic|n$ejZY+di&ԖyhkIg<&&`#b(ik#F7i&ނz'3bGp5brJ_JYk&*;doc/SpecialOrderedSetsOfTypeOne_files/img00345.gif0000644000175000017500000000232407755240740020640 0ustar renereneGIF89a !, H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ%I\ʜISc̐7gEwݸ3hњHqTaΡN/%jƪR+HW;Nc=4Tb5{\۾]v-՞nmTZcҥpWi&cQrK8!'W*8(ˁ1mh.i?~f칶+6ǐ#6Zpq̚CT6h V]i#-y\~Wxɦ;ܰaZd2^~EZcI~I[X֟ICvW^jEW xuxe9[QMWRq^6‡~Q.8id>HcO@'\N'sJD\J%dm_&c?hlp^;doc/SpecialOrderedSetsOfTypeOne_files/img00342.gif0000644000175000017500000000177307755240740020644 0ustar renereneGIF89aL!,LH*\ȰÇ#JH"A`xp@ =$FGfTBSt)ʙe2 QM k $PAKҼqc҆Ivt:'˥LY!ҝXحg[ZMRק-JPũ: ϲa-y֫@RJĺP6K(Ф*\5 n ӮX 1ܿz춪No*<t䚟.3"%YntjcCSM|{ukp޹iߕm\9ڔcNi3D`6#bG;.>zX6m:;= 4) { gbNav4 = (navigator.appName == "Netscape"); gbIE4 = (navigator.appName.indexOf("Microsoft") != -1); if (gbIE4) { if (gAgent.indexOf("msie 5.0") != -1) { gbIE5 = true; } if (gAgent.indexOf("msie 5.5") != -1) { // curently IE 5.5 has some buggy stuff. we need do some remedy to our code. gbIE55 = true; } } } function HHActivateComponents() { if (HH_ActiveX && (HH_ChmFilename != "") && ((self == top) || (self == top.frames[0]))) { var objBody = document.all.tags("BODY")[0]; if( typeof(objBody) == "object" ) { objBody.insertAdjacentHTML("beforeEnd", ''); if (HHComponentActivator.object) { HHComponentActivator.Activate(HH_ChmFilename, HH_WindowName, HH_GlossaryFont, HH_Glossary, HH_Avenue); } } } } var gAmc = new Array(); var BSSCSequenceIndex = 0; function animationContext(el, progressAnimation, finishAnimiation, animationDuration, animationPeriod) { this.el = el; this.progressAnimation = progressAnimation; this.finishAnimiation = finishAnimiation; this.animationDuration = parseFloat(animationDuration); this.animationPeriod = animationPeriod; this.animationStartTime = (new Date()).getTime(); this.continueAnimation = true; } function progressFade(ndx) { if( typeof( gAmc[ndx].el.filters.alpha ) != "object" ) return; percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0){ percent = 1.0; gAmc[ndx].continueAnimation = false; } gAmc[ndx].el.filters.alpha.opacity = gAmc[ndx].initialOpacity*(1.0-percent) + gAmc[ndx].finalOpacity*percent; } function finishFade(ndx) { if( typeof( gAmc[ndx].el.filters.alpha ) == "object" ) gAmc[ndx].el.filters.alpha.opacity = parseInt(gAmc[ndx].finalOpacity); } function progressTranslation(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } gAmc[ndx].el.style.pixelLeft = gAmc[ndx].startX*(1.0-percent) + gAmc[ndx].finalX*percent; gAmc[ndx].el.style.pixelTop = gAmc[ndx].startY*(1.0-percent) + gAmc[ndx].finalY*percent; } function progressSpiral(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } rf = 1.0 - percent t = percent * 2.0*Math.PI rx = Math.max(Math.abs(gAmc[ndx].el.initLeft), 200) ry = Math.max(Math.abs(gAmc[ndx].el.initTop), 200) gAmc[ndx].el.style.pixelLeft = Math.ceil(-rf*Math.cos(t)*rx) gAmc[ndx].el.style.pixelTop = Math.ceil(-rf*Math.sin(t)*ry) gAmc[ndx].el.style.visibility="visible" } function progressElasticFromRight(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } rf=Math.exp(-percent*7) t = percent * 1.5*Math.PI rx =Math.abs(gAmc[ndx].el.initLeft) gAmc[ndx].el.style.pixelLeft = rf*Math.cos(t)*rx gAmc[ndx].el.style.pixelTop = 0 gAmc[ndx].el.style.visibility="visible" } function progressElasticFromBottom(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } rf=Math.exp(-percent*7) t = percent * 1.5*Math.PI rx =Math.abs(gAmc[ndx].el.initTop) gAmc[ndx].el.style.pixelLeft = 0 gAmc[ndx].el.style.pixelTop = rf*Math.cos(t)*rx gAmc[ndx].el.style.visibility="visible" } function progressZoomIn(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1; gAmc[ndx].continueAnimation = false; } for (var index=0; index= 1.0) { finishZoom(ndx); } } function progressZoomOut(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } for (var index=0; index= 1.0) { finishZoom(ndx); } } function finishTranslation(ndx) { gAmc[ndx].el.style.pixelLeft = parseInt(gAmc[ndx].finalX); gAmc[ndx].el.style.pixelTop = parseInt(gAmc[ndx].finalY); } function finishZoom(ndx) { for (i=0; i BSSCSequenceIndex && (!bFound || objectOrder < minBSSCSequenceIndexFound)) { minBSSCSequenceIndexFound = objectOrder; bFound = true; } } } if (bFound) { BSSCSequenceIndex = minBSSCSequenceIndexFound; bStarted = startAnimationSet(BSSCSequenceIndex); } } function getOffsetFromTopOfBrowser(el) { if (null == el.offsetParent) return el.offsetTop; else return el.offsetTop + getOffsetFromTopOfBrowser(el.offsetParent); } function startAnimationSet(ndx) { var m = 0; bStarted = false; // Find document elements with "BSSCAnimationType" attribute divElements = document.all.tags("DIV"); for (var index = 0; index < divElements.length; index++) { el = divElements[index]; animationType = el.getAttribute("BSSCAnimationType", false); if(null != animationType) { framePeriod = el.getAttribute("BSSCFramePeriod", false); frameCount = el.getAttribute("BSSCFrameCount", false); sequenceIndex = el.getAttribute("BSSCObjectOrder", false); // Stop any currently running RevealTrans filters if ("RevealTrans" == animationType && parseInt(sequenceIndex) == ndx-1 && gbWindows) el.filters.RevealTrans.stop(); // Filter on ndx if (0 == ndx && null == sequenceIndex || ndx == parseInt(sequenceIndex)) { if ("FlyInFromRight" == animationType) { animationDuration = el.getAttribute("BSSCDuration", false); if (null == animationDuration) animationDuration = 1000; // default to 1s gAmc[m] = new animationContext(el, progressTranslation, finishTranslation, animationDuration, 10); gAmc[m].startX = document.body.clientWidth + document.body.scrollLeft; gAmc[m].startY = 0; gAmc[m].finalX = 0; gAmc[m].finalY = 0; animationPump(m++); bStarted = true; } if ("FlyOutToRight" == animationType) { animationDuration = el.getAttribute("BSSCDuration", false); if (null == animationDuration) animationDuration = 1000; // default to 1s gAmc[m] = new animationContext(el, progressTranslation, finishTranslation, animationDuration, 10); gAmc[m].startX = 0; gAmc[m].startY = 0; gAmc[m].finalX = document.body.clientWidth + document.body.scrollWidth; gAmc[m].finalY = 0; animationPump(m++); bStarted = true; } if ("FlyInFromLeft" == animationType) { animationDuration = el.getAttribute("BSSCDuration", false); if (null == animationDuration) animationDuration = 1000; // default to 1s for (childIndex=0; childIndex 0) && (document.images[0].src.indexOf('bsscnav1.gif') != -1)) { document.links[0].href = "javascript:void(null);"; } } } return; } ////////////////////////////////////////////////////////////////////////////////////////////// // // Begin DHTML Popup Functions // ////////////////////////////////////////////////////////////////////////////////////////////// //variables used to isolate the browser type var gBsDoc = null; var gBsSty = null; var gBsHtm = null; var gBsStyVisShow = null; var gBsStyVisHide = null; var gBsClientWidth = 640; var gBsClientHeight = 480; var gBsBrowser = null; // here is the varible for judge popup windows size. these parameter is for IE5.0, it may need adjust for others. var gBRateH_W = 0.618; // 1.618 Golden cut. var gBMaxXOfParent = 0.8; var gBMaxYOfParent = 0.8; var gBscrollHeight = 16; var gBscrollWidth = 16; var gBpermitXDelta = 3; var gBpermitYDelta = 3; //the browser information itself function _BSPSBrowserItself() { var agent = navigator.userAgent.toLowerCase(); this.major = parseInt(navigator.appVersion); this.minor = parseFloat(navigator.appVersion); this.ns = ((agent.indexOf('mozilla') != -1) && ((agent.indexOf('spoofer') == -1) && (agent.indexOf('compatible') == -1))); this.ns2 = ((this.ns) && (this.major == 2)); this.ns3 = ((this.ns) && (this.major == 3)); this.ns4 = ((this.ns) && (this.major >= 4)); this.ie = (agent.indexOf("msie") != -1); this.ie3 = ((this.ie) && (this.major == 2)); this.ie4 = ((this.ie) && (this.major >= 4)); this.op3 = (agent.indexOf("opera") != -1); if (this.ns4) { gBsDoc = "document"; gBsSty = ""; gBsHtm = ".document"; gBsStyVisShow = "show"; gBsStyVisHide = "hide"; } else if (this.ie4) { gBsDoc = "document.all"; gBsSty = ".style"; gBsHtm = ""; gBsStyVisShow = "visible"; gBsStyVisHide = "hidden"; } } //Here is the browser type function _BSPSGetBrowserInfo() { gBsBrowser = new _BSPSBrowserItself(); } //Get client size info function _BSPSGetClientSize() { if (gBsBrowser.ns4) { gBsClientWidth = innerWidth; gBsClientHeight = innerHeight; } else if (gBsBrowser.ie4) { gBsClientWidth = document.body.clientWidth; gBsClientHeight = document.body.clientHeight; } } var gstrPopupID = 'BSSCPopup'; var gstrPopupShadowID = 'BSSCPopupShadow'; var gstrPopupTopicID = 'BSSCPopupTopic'; var gstrPopupIFrameID = 'BSSCPopupIFrame'; var gstrPopupIFrameName = 'BSSCPopupIFrameName'; var gstrPopupSecondWindowName = 'BSSCPopup'; var gPopupDiv = null; var gPopupDivStyle = null; var gPopupShadow = null; var gPopupTopic = null; var gPopupIFrame = null; var gPopupIFrameStyle = null; var gPopupWindow = null; var gnPopupClickX = 0; var gnPopupClickY = 0; var gnPopupScreenClickX = 0; var gnPopupScreenClickY = 0; var gbPopupTimeoutExpired = false; var gbScriptName = "EHELP_DHTM"; var gbPathofJS = ""; if (gbIE4) { var aScripts = document.scripts; var aScript = null; var i = 0; for (i = 0; i < aScripts.length ; i ++ ) { if (aScripts[i].name == gbScriptName) { aScript = aScripts[i]; break; } } if (aScript != null) { var nPathPos = 0; var strCurrentSrc = ""; strCurrentSrc = aScript.src; var nPathPos1 = strCurrentSrc.lastIndexOf("\\"); var nPathPos2 = strCurrentSrc.lastIndexOf("/"); if (nPathPos1 > nPathPos2) nPathPos = nPathPos1 + 1; else nPathPos = nPathPos2 + 1; gbPathofJS = strCurrentSrc.substring(0, nPathPos); } } // Replace point - Used by SingleSource // var gbBlankPageForIFrame = gbPathofJS + "_blank.htm"; var gbBlankPageForIFrame = "about:blank"; if (BSSCPopup_IsPopup()) { document.write(""); } function DHTMLPopupSupport() { if ((gbIE4) && (!gbMac)) { return true; } return false; } function BSSCPopup_IsPopup() { if (DHTMLPopupSupport() && (this.name == gstrPopupIFrameName)) { return true; } else if ((gbNav4 || gbIE4) && (this.name == gstrPopupID)) { return true; } else { return false; } } function _BSSCCreatePopupDiv() { if (gPopupDiv == null) { if (DHTMLPopupSupport()) { document.write(""); var tempColl = document.all.tags("DIV"); for (var iDiv = 0; iDiv < tempColl.length; iDiv++) { if (tempColl(iDiv).id == gstrPopupID) { gPopupDiv = tempColl(iDiv); } if (tempColl(iDiv).id == gstrPopupShadowID) { gPopupShadow = tempColl(iDiv); } if (tempColl(iDiv).id == gstrPopupTopicID) { gPopupTopic = tempColl(iDiv); } } gPopupIFrame = eval("gPopupDiv.document.frames['" + gstrPopupIFrameName + "']"); gPopupDivStyle = eval("gPopupDiv" + gBsSty); gPopupIFrameStyle = eval(gBsDoc + "['" + gstrPopupIFrameName + "']" + gBsSty); } } } function BSSCPopup_Timeout() { if ((gPopupIFrame.document.readyState == "complete") && (gPopupIFrame.document.body != null) && (gPopupIFrame.location.href.indexOf(gbBlankPageForIFrame) == -1)) { BSSCPopup_TimeoutReal(); } else { setTimeout("BSSCPopup_Timeout()", 100); } } function BSSCPopup_TimeoutReal() { window.gbPopupTimeoutExpired = true; if (gPopupIFrame.document) { BSSCPopup_ChangeTargettoParent(gPopupIFrame.document); gPopupIFrame.document.body.onclick = BSSCPopupClicked; } document.onmousedown = BSSCPopupParentClicked; } function BSSCPopup_ChangeTargettoParent(tagsObject) { var collA = tagsObject.all.tags("A"); var j = 0; if (collA != null) { for (j = 0; j < collA.length; j ++ ) { collA[j].target = "_parent"; } } } function BSPSPopupTopicWinHelp(strURL) { _BSSCPopup(strURL); return; } function _BSSCPopup(strURL) { if (DHTMLPopupSupport()) { // If we are already in a popup, replace the contents if (BSSCPopup_IsPopup()) { location.href = strURL; parent.window.gbPopupTimeoutExpired = false; if (gbMac) { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 400); } else { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 100); } } else { // Load the requested URL into the IFRAME gPopupIFrame.location.href = strURL; window.gbPopupTimeoutExpired = false; if (gbMac) { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 400); } else { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 100); } } } else { _BSSCPopup2(strURL); } return; } function _BSSCPopup2(strURL) { if (window.name == gstrPopupSecondWindowName) { window.location = strURL; } else { BSSCHidePopupWindow(); var nX = 0; var nY = 0; var nHeight = 300; var nWidth = 400; _BSPSGetClientSize(); if (gBsBrowser.ns4) { nX = window.screenX + (window.outerWidth - window.innerWidth) + window.gnPopupClickX; nY = window.screenY + (window.outerHeight - window.innerHeight) + window.gnPopupClickY; if (nY + nHeight + 40 > screen.availHeight) { nY = screen.availHeight - nHeight - 40; } if (nX + nWidth + 40 > screen.availWidth) { nX = screen.availWidth - nWidth - 40; } } else { nX = window.gnPopupScreenClickX; nY = window.gnPopupScreenClickY; } // Launch a separate window var strParam = "titlebar=no,toolbar=no,status=no,location=no,menubar=no,resizable=yes,scrollbars=yes"; if (gBsBrowser.ns) { strParam += ",OuterHeight=" + nHeight + ",OuterWidth=" + nWidth; strParam += ",screenX=" + nX + ",screenY=" + nY; strParam += ",dependent=yes"; } else { strParam += ",height=" + nHeight + ",width=" + nWidth; strParam += ",left=" + nX + ",top=" + nY; } window.gPopupWindow = window.open(strURL, gstrPopupSecondWindowName, strParam); if (gBsBrowser.ns4) { window.gPopupWindow.captureEvents(Event.CLICK | Event.BLUE); window.gPopupWindow.onclick = NonIEPopup_HandleClick; window.gPopupWindow.onblur = NonIEPopup_HandleBlur; } else if (gBsBrowser.ie4) { window.gPopupWindow.focus(); } } return; } function NonIEPopup_HandleBlur(e) { window.gPopupWindow.focus(); } function NonIEPopup_HandleClick(e) { // Because navigator will give the event to the handler before the hyperlink, let's // first route the event to see if we are clicking on a Popup menu in a popup. document.routeEvent(e); // If a popup menu is active then don't do anything with the click if (window.gPopupWindow.gbInPopupMenu) { window.gPopupWindow.captureEvents(Event.CLICK); window.gPopupWindow.onclick = NonIEPopup_HandleClick; return false; } // Close the popup window if (e.target.href != null) { window.location.href = e.target.href; if (e.target.href.indexOf("BSSCPopup") == -1) { this.close(); } } else { this.close(); } return false; } function BSSCPopup_AfterLoad(strURL) { if (typeof(window.gPopupIFrame.document) == "unknown") { _BSSCPopup2(strURL); return; } if ((window.gPopupIFrame.document.readyState == "complete") && (window.gPopupIFrame.document.body != null) && (window.gPopupIFrame.location.href.indexOf(gbBlankPageForIFrame) == -1)) { BSSCPopup_ResizeAfterLoad(strURL); } else { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 200); } } function BSSCPopup_ResizeAfterLoad(strURL) { window.gPopupDivStyle.visibility = gBsStyVisHide; // Determine the width and height for the window //var size = new BSSCSize(0, 0); //BSSCGetContentSize(window.gPopupIFrame, size); //var nWidth = size.x; //var nHeight = size.y; _BSPSGetClientSize(); var size = new BSSCSize(0, 0); BSSCGetContentSize(window.gPopupIFrame, size); // Determine the width and height for the window var nWidth = size.x; var nHeight = size.y; window.gPopupDivStyle.width = nWidth; window.gPopupDivStyle.height = nHeight; // Determine the position of the window var nClickX = window.gnPopupClickX; var nClickY = window.gnPopupClickY; var nTop = 0; var nLeft = 0; if (nClickY + nHeight + 20 < gBsClientHeight + document.body.scrollTop) { nTop = nClickY + 10; } else { nTop = (document.body.scrollTop + gBsClientHeight) - nHeight - 20; } if (nClickX + nWidth < gBsClientWidth + document.body.scrollLeft) { nLeft = nClickX; } else { nLeft = (document.body.scrollLeft + gBsClientWidth) - nWidth - 8; } if (nTop < document.body.scrollTop ) nTop = document.body.scrollTop + 1; if (nLeft< document.body.scrollLeft) nLeft = document.body.scrollLeft + 1; window.gPopupDivStyle.left = nLeft; window.gPopupDivStyle.top = nTop; // Set the location of the background blocks window.gPopupShadow.style.left = 6; window.gPopupShadow.style.top = 6; if (gbIE55) { window.gPopupShadow.style.left = 4; window.gPopupShadow.style.top = 4; } window.gPopupShadow.style.width = nWidth; window.gPopupShadow.style.height = nHeight; window.gPopupTopic.style.width = nWidth; window.gPopupTopic.style.height = nHeight; if (gbIE55) { window.gPopupShadow.style.width = nWidth + 2; window.gPopupShadow.style.height = nHeight + 2; window.gPopupTopic.style.width = nWidth + 2; window.gPopupTopic.style.height = nHeight + 2; } if (gbMac) { // Total hack on the iMac to get the IFrame to position properly window.gPopupIFrameStyle.pixelLeft = 100; window.gPopupIFrameStyle.pixelLeft = 0; // Explicitly call BSSCOnLoad because the Mac doesn't seem to do it window.gPopupIFrame.window.BSSCOnLoad(); } //var nOriWidth = window.gPopupIFrameStyle.width window.gPopupIFrameStyle.width = nWidth; window.gPopupIFrameStyle.height = nHeight; if (gbIE55) { window.gPopupIFrameStyle.top = 0; window.gPopupIFrameStyle.left = 0; } gPopupIFrame.location.href = strURL; // reload again, this will fix the bookmark misunderstand in IE5. window.gPopupDivStyle.visibility = gBsStyVisShow; setTimeout("BSSCPopup_Timeout();", 100); return false; } function BSSCSize(x, y) { this.x = x; this.y = y; } function BSSCGetContentSize(thisWindow, size) { if (!((gBsBrowser.ie4) || (gBsBrowser.ns4))) return; if (gbMac) { size.x = 300; size.y = 300; return; } // Resize the width until it is wide enough to handle the content // The trick is to start wide and determine when the scrollHeight changes // because then we know a scrollbar is necessary. We can then go back // to the next widest size (for no scrollbar) var ClientRate = gBsClientHeight / gBsClientWidth; var GoldenSize = new BSSCSize(0,0); GoldenSize.x = gBsClientWidth * gBMaxXOfParent; GoldenSize.y = gBsClientHeight *gBMaxYOfParent ; if (ClientRate > gBRateH_W) { GoldenSize.y = GoldenSize.x * gBRateH_W; } else { GoldenSize.x = GoldenSize.y / gBRateH_W; } // Try to using parent specified max x. var x = 0; var maxgoldx = GoldenSize.x; var maxx = gBsClientWidth * gBMaxXOfParent; // This double resize causes the document to re-render (and we need it to) thisWindow.moveTo(10000,10000); // this is used to fix the flash on IE4. thisWindow.resizeTo(1, 1); thisWindow.resizeTo(1, 1); thisWindow.resizeTo(maxgoldx, thisWindow.document.body.scrollHeight + gBscrollHeight); thisWindow.resizeTo(maxgoldx, thisWindow.document.body.scrollHeight + gBscrollHeight); var miny = thisWindow.document.body.scrollHeight + gBscrollHeight; if (miny > GoldenSize.y) // the popup does not fix in the parent wanted golden area. so try to expand itself as large as it can { thisWindow.resizeTo(maxx , thisWindow.document.body.scrollHeight + gBscrollHeight); thisWindow.resizeTo(maxx , thisWindow.document.body.scrollHeight + gBscrollHeight); miny = thisWindow.document.body.scrollHeight + gBscrollHeight; maxy = gBsClientHeight * gBMaxYOfParent; if (miny > maxy) { // the popup must have a scroll, OK let it be. miny = maxy; size.x = maxx; size.y = maxy; } else { // popup still can fit in the parent area by someway. now we choose the same h/w rate as parent. size.y = miny; // downsize from maxx , now I try to using binary divide. x = maxx; deltax = -maxx/2; //j = 0; while (true) { x = x + deltax; thisWindow.resizeTo(x, miny); thisWindow.resizeTo(x, miny); diffy = thisWindow.document.body.scrollHeight + gBscrollHeight - x * ClientRate; if (diffy > gBpermitYDelta ) // it is higher than wanted, so x need to be wide a little bitter deltax = Math.abs(deltax) /2; else if (diffy < -gBpermitYDelta) // it is shorter than wanted, so x need to be narrow a little bitter deltax = -Math.abs(deltax) /2; else // the y is close enough to wanted. break; if (Math.abs(deltax) < gBpermitXDelta) // the next change is too slight and it can be ignore. break; //j ++; } size.x = thisWindow.document.body.scrollWidth; //+ gBscrollWidth; size.y = thisWindow.document.body.scrollHeight;// + gBscrollHeight; thisWindow.document.body.scroll = 'no'; // At this time we do not want to show scroll any more. so it will looks better a little. // Handle absurd cases just in case IE flakes // if (size.y < 100) { // size.y = 100; // } } } else { // downsize from maxgoldx , now I try to using binary divide. x = maxgoldx; deltax = -maxgoldx/2; //i = 0; while (true) { x = x + deltax; thisWindow.resizeTo(x, miny); thisWindow.resizeTo(x, miny); diffy = thisWindow.document.body.scrollHeight + gBscrollHeight - x * gBRateH_W; if (diffy > gBpermitYDelta ) // it is higher than wanted, so x need to be wide a little bitter deltax = Math.abs(deltax) /2; else if (diffy < -gBpermitYDelta) // it is shorter than wanted, so x need to be narrow a little bitter deltax = -Math.abs(deltax) /2; else // the y is close enough to wanted. break; if (Math.abs(deltax) < gBpermitXDelta) // the next change is too slight and it can be ignore. break; //i ++; } size.x = thisWindow.document.body.scrollWidth ;//+ gBscrollWidth; size.y = thisWindow.document.body.scrollHeight ;//+ gBscrollHeight; thisWindow.document.body.scroll = 'no'; // At this time we do not want to show scroll any more. so it will looks better a little. } if ((gbIE4) && (!gbIE5)) { size.x = size.x + 16; //reserve a width for scrollbar (IE 4.0 only) } thisWindow.resizeTo(size.x, size.y); thisWindow.resizeTo(size.x, size.y); return; } function BSSCPopupParentClicked() { BSSCPopupClicked(); return; } function BSSCPopupClicked() { if (!window.gbPopupTimeoutExpired) { return false; } if (gPopupIFrame.window.gbInPopupMenu) { return false; } // Give the user a message about javascript calls through objects. if ((gPopupIFrame.window.event != null) && (gPopupIFrame.window.event.srcElement != null) && (gPopupIFrame.window.event.srcElement.tagName == "A") && (gPopupIFrame.window.event.srcElement.href.indexOf("javascript:") == 0) && (gPopupIFrame.window.event.srcElement.href.indexOf(".") != -1)) { gPopupIFrame.window.event.cancelBubble = true; alert('Hyperlinks to objects do not work in popups.'); return false; } if (gPopupIFrame.document) { gPopupIFrame.document.body.onclick = null; } document.onclick = null; document.onmousedown = null; // Simply hide the popup gPopupDivStyle.visibility = gBsStyVisHide; gPopupIFrame.location.href = gbBlankPageForIFrame; return true; } //trace the mouse over's position for hotspot function BSPSPopupOnMouseOver(event) { if (gBsBrowser.ie4) { window.gnPopupClickX = event.clientX + document.body.scrollLeft; window.gnPopupClickY = event.clientY + document.body.scrollTop; window.gnPopupScreenClickX = event.screenX; window.gnPopupScreenClickY = event.screenY; } else if (gBsBrowser.ns4) { window.gnPopupClickX = event.pageX; window.gnPopupClickY = event.pageY; } } function BSSCHidePopupWindow() { if (window.gPopupWindow != null) { if (gBsBrowser.ns4) { if ((typeof window.gPopupWindow != "undefined") && (!window.gPopupWindow.closed)) { window.gPopupWindow.close(); window.gPopupWindow = null; } } } return; } var gbPopupMenuTimeoutExpired = false; var gbInPopupMenu = false; var gbPopupMenuTopicList = null; ////////////////////////////////////////////////////////////////////////////////////////// // // Popup Menu code // ////////////////////////////////////////////////////////////////////////////////////////// function _WritePopupMenuLayer() { if (gbNav4) { //Do not try to write ininle styles for NS! NS can not handle it and will not stop downloading the html page... document.write("
"); } else { document.write(""); if (gbIE4) { document.write(""); } } } //Define variable arguments as: strTitle, strUrl function PopupMenuTopicEntry() { this.strTitle = PopupMenuTopicEntry.arguments[0]; this.strURL = PopupMenuTopicEntry.arguments[1]; } // If the topic list is set, it is an array of TopicEntry objects (defined in WebHelp3.js) function PopupMenu_SetTopicList(aPopupTopicArray) { gbPopupMenuTopicList = aPopupTopicArray; } //Seek for the bsscright frame function _SeekFrameByName( cRoot, strName ) { if( cRoot == null ) return null; if( cRoot.frames == null ) return null; if( cRoot.frames[strName] != null ) return cRoot.frames[strName]; for (var i=0; i"); wndPopupLinks.document.write(""); var strParaLine = ""; for (var i = 0; i < (argLen - 2) / 2; i++) { strParaLine = ""; strParaLine += ""); wndPopupLinks.document.close(); window.gbInPopupMenu = true; if (!gbIE) { wndPopupLinks.focus(); } return false; } // Make sure we have reasonable arguments var argLen = fn_arguments.length; if (argLen < 3) { return false; } // Check to see if we only have one target var strTarget = ""; if (((argLen < 5) && ((isNaN(fn_arguments[2])) || (gbPopupMenuTopicList == null))) || ((argLen < 4) && ((!isNaN(fn_arguments[2])) && (gbPopupMenuTopicList != null)))) { // Get the place that we will be putting the topic into var targetDoc = null; if (fn_arguments[1] == '') { targetDoc = window.document; } else { targetDoc = _GetFrameByName( parent, fn_arguments[1] ); if (targetDoc == null) { targetDoc = window.document; } //if (gbIE4) { // targetDoc = eval("top.document.frames['" + fn_arguments[1] + "']"); // } else if (gbNav4) { // targetDoc = eval("window.top." + fn_arguments[1] + ".document"); //} strTarget = "TARGET='" + fn_arguments[1] + "'"; } if (isNaN(fn_arguments[2]) || (gbPopupMenuTopicList == null)) { targetDoc.location.href = fn_arguments[3]; } else { targetDoc.location.href = gbPopupMenuTopicList[fn_arguments[2]].strURL; } return false; } var strMenu = ""; if (gbNav4) { strMenu = ''; } else { strMenu = '
'; } else { strMenu += '' + gbPopupMenuTopicList[fn_arguments[i]].strTitle + ''; } strMenu += ''; if (isNaN(fn_arguments[i]) || (gbPopupMenuTopicList == null)) { i += 2; } else { i += 1; } } strMenu += "
"; if (gbMac) { // totally hack. because ie5 in mac need something. is one of them. mac is mad. strMenu +="
"; } var layerPopup = null; var stylePopup = null; var nEventX = 0; var nEventY = 0; var nWindowWidth = 0; if (gbIE4) { layerPopup = document.all["PopupMenu"]; layerPopup.innerHTML = strMenu; stylePopup = layerPopup.style; _BSPSGetClientSize(); // Get the position of the item causing the event (relative to its parent) //if (gbMac) { if (true) { nEventX = window.event.clientX; nEventY = window.event.clientY; } else { //??? YJ: Can not remember why we calculate envent position by following code... //but it is wrong in a case like: CENTER->P->TABLE: //the offset positions of TABLE, P and CENTER are same (same offsetTop,offsetLeft) //so we get triple times of offset of x and y as we expect... nEventX = window.event.srcElement.offsetLeft - document.body.scrollLeft; nEventY = window.event.srcElement.offsetTop - document.body.scrollTop; // Get the location of the parent var nParentLocX = 0; var nParentLocY = 0; var ParentItem = window.event.srcElement.offsetParent; while (ParentItem != null) { if (ParentItem.offsetLeft) { nParentLocX += ParentItem.offsetLeft; nParentLocY += ParentItem.offsetTop; } ParentItem = ParentItem.parentElement; } // Adjust the location of the item using the location of the parent(s) nEventX += nParentLocX; nEventY += nParentLocY; } if (nEventY + layerPopup.scrollHeight + 10 < gBsClientHeight) { nEventY += document.body.scrollTop + 10; } else { nEventY = (document.body.scrollTop + gBsClientHeight) - layerPopup.scrollHeight - 20; } stylePopup.top = nEventY; if (nEventX + layerPopup.scrollWidth + 20 > gBsClientWidth) { if (gBsClientWidth - layerPopup.scrollWidth < 5) { stylePopup.left = 5; } else { stylePopup.left = gBsClientWidth - layerPopup.scrollWidth - 5; } } else { stylePopup.left = nEventX + document.body.scrollLeft + 20; } stylePopup.visibility = "visible"; document.onclick = PopupMenu_HandleClick; } else if (gbNav4) { layerPopup = document.layers.PopupMenu; layerPopup.visibility = "hide"; stylePopup = layerPopup.document; stylePopup.write(strMenu); stylePopup.close(); var e = fn_arguments[0]; nEventX = e.pageX; nEventY = e.pageY; _BSPSGetClientSize(); if (nEventY + layerPopup.clip.height + 20 < window.pageYOffset + gBsClientHeight) { nEventY += 20; } else { nEventY = gBsClientHeight + window.pageYOffset- layerPopup.clip.height - 20; } layerPopup.top = nEventY; if (nEventX + layerPopup.clip.width + 20 > gBsClientWidth + window.pageXOffset) { if (gBsClientWidth + window.pageXOffset - layerPopup.clip.width < 20) { nEventX = 5; } else { nEventX = gBsClientWidth + window.pageXOffset - layerPopup.clip.width - 20; } } else { nEventX += 20; } layerPopup.left = nEventX; layerPopup.visibility = "show"; // window.captureEvents(Event.CLICK | Event.MOUSEDOWN); window.captureEvents(Event.MOUSEDOWN); // window.onclick = PopupMenu_HandleClick; window.onmousedown = PopupMenu_HandleClick; } window.gbInPopupMenu = true; window.gbPopupMenuTimeoutExpired = false; setTimeout("PopupMenu_Timeout();", 100); return false; } function PopupMenu_Timeout() { window.gbPopupMenuTimeoutExpired = true; } function PopupMenu_Over(e) { if (gbIE4) { e.srcElement.className = "PopupOver"; } else if (gbNav4) { // this.bgColor = "red"; // e.target.document.className = "PopupOver"; } return; } function PopupMenu_Out(e) { if (gbIE4) { e.srcElement.className = "PopupNotOver"; } else if (gbNav4) { this.bgColor = "#f0f0f0"; } return; } function PopupMenu_HandleClick(e) { if (!window.gbPopupMenuTimeoutExpired) { return; } window.gbInPopupMenu = false; if (gbNav4) { // window.releaseEvents(Event.CLICK); window.releaseEvents(Event.MOUSEDOWN); } var layerPopup = null; var stylePopup = null; if (gbIE4) { layerPopup = document.all["PopupMenu"]; stylePopup = layerPopup.style; stylePopup.visibility = "hidden"; } else if (gbNav4) { layerPopup = document.layers.PopupMenu; layerPopup.visibility = "hide"; } return; } // This function should be deleted when all old projects are cleaned up function BSPSWritePopupFrameForIE4() { return false; } ///////////////////////////////////////////////////////////////////// function BSSCPopup_ClickMac() { if ((!DHTMLPopupSupport()) && (gbIE4)) { var bClickOnAnchor = false; var el; if ((window.event != null) && (window.event.srcElement != null)) { el = window.event.srcElement; while (el != null) { if ((el.tagName == "A") || (el.tagName == "AREA")) { bClickOnAnchor = true; break; } if (el.tagName == "BODY") { break; } el = el.parentElement; } } if (BSSCPopup_IsPopup()) { if (!bClickOnAnchor) { parent.window.gPopupWindow = null; self.close(); } } else { bClosePopupWindow = true; if ((bClickOnAnchor) && (el.href) && (el.href.indexOf("javascript:BSSCPopup") != -1)) { bClosePopupWindow = false; } if (bClosePopupWindow) { if (window.gPopupWindow != null) { var strParam = "titlebar=no,toolbar=no,status=no,location=no,menubar=no,resizable=yes,scrollbars=yes,height=300,width=400"; window.gPopupWindow = window.open("", gstrPopupSecondWindowName,strParam); window.gPopupWindow.close(); window.gPopupWindow = null; } } } } } ////////////////////////////////////////////////////////////////////// _BSPSGetBrowserInfo(); function _BSSCOnLoad() { if (!gbIE4 && !gbNav4) return; // Make everything visible in navigator if (gbNav4) { // Make some special effects items visible for (var iLayer = 0; iLayer < document.layers.length; iLayer++) { document.layers[iLayer].visibility = gBsStyVisShow; document.layers[iLayer].left = 0; } } // Remove the NavBar if necessary RemoveNavBar(); // Don't continue without IE4 if (gbIE4) { HHActivateComponents(); doStaticEffects(); startAnimationSet(0); } } function _BSSCOnUnload() { } function _BSSCOnClick() { if (!gbIE4) return; BSSCPopup_ClickMac(); startNextAnimationSet(); } function _BSSCOnError(message) { if(-1 != message.indexOf("denied") || -1 != message.indexOf("Object required")) return true; } function ResizeBasedonRate(thisWindow, size, rate, maxx, maxy) { x = maxx; y = maxy; deltax = -maxx/2; while (true) { x = x + deltax; thisWindow.resizeTo(x, y); thisWindow.resizeTo(x, y); diffy = thisWindow.document.body.scrollHeight + gBscrollHeight - x * rate; if (diffy > gBpermitYDelta ) // it is higher than wanted, so x need to be wide a little bitter deltax = Math.abs(deltax) /2; else if (diffy < -permitYDelta) // it is shorter than wanted, so x need to be narrow a little bitter deltax = -Math.abs(deltax) /2; else // the y is close enough to wanted. break; if (Math.abs(deltax) < gBpermitXDelta) // the next change is too slight and it can be ignore. break; //j ++; } size.x = thisWindow.document.body.scrollWidth; //+ gBscrollWidth; size.y = thisWindow.document.body.scrollHeight;// + gBscrollHeight; thisWindow.document.body.scroll = 'no'; // At this time we do not want to show scroll any more. so it will looks better a little. } //////////BSSCDHTML Section Embedded Code////////// var s_strAgent = navigator.userAgent.toLowerCase(); var s_nVer = parseInt(navigator.appVersion); var s_bIE = (s_strAgent.indexOf('msie') != -1); var s_bNS = (s_strAgent.indexOf('mozilla') != -1) && ((s_strAgent.indexOf('spoofer') == -1) && (s_strAgent.indexOf('compatible') == -1)); var s_bOpera = (s_strAgent.indexOf('opera') != -1); var s_bIE3Before = ((s_bIE) && (s_nVer <= 2)); var s_bNS3Before = ((s_bNS) && (s_nVer <= 3)); var s_bNS2 = ((s_bNS) && (s_nVer <= 2)); var s_bNS3 = ((s_bNS) && (s_nVer == 3)); var s_bIE300301 = ((s_bIE) && (s_nVer == 2) && ((s_strAgent.indexOf("3.00") != -1)||(s_strAgent.indexOf("3.0a") != -1)||(s_strAgent.indexOf("3.0b")!=-1)||(s_strAgent.indexOf("3.01")!=-1))); var s_bIE302 = ((s_bIE) && (s_nVer == 2) && (s_strAgent.indexOf("3.02") != -1)); function HasExtJs() { if (s_bIE3Before) { return false;} if (s_bNS3Before) { return false;} if (typeof (_BSSCOnLoad) == "undefined"){ return false; } return true; } function BSSCOnLoad() { if (HasExtJs()) { _BSSCOnLoad(); } } function BSSCOnUnload() { if (HasExtJs()) { _BSSCOnUnload(); } } function BSSCOnClick() { if (HasExtJs()) { _BSSCOnClick(); } } function BSSCOnError(message) { if (HasExtJs()) { return _BSSCOnError(message); } } function WritePopupMenuLayer() { if (HasExtJs()) {_WritePopupMenuLayer();} } function BSSCCreatePopupDiv() { if (HasExtJs()) {_BSSCCreatePopupDiv(); } } function BSSCPopup(strURL) { if (HasExtJs()) { _BSSCPopup(strURL); }else{ //Create a temporary window first to ensure the real popup comes up on top var wndTemp = null; if (!s_bNS3) { wndTemp = window.open("", "temp", "titlebar=no,toolbar=no,status=no,location=no,menubar=no,resizable=yes,scrollbars=yes,height=3,width=4"); } // Create the real popup window var wndPopup = window.open(strURL, "BSSCPopup", "titlebar=no,toolbar=no,status=no,location=no,menubar=no,resizable=yes,scrollbars=yes,height=300,width=400"); // Close the temporary if (!s_bNS3) { wndTemp.close(); } else { wndPopup.focus(); } } } var gbWndTemp = null, gbWndPopupLinks = null; var gbstrParaTotal = ""; function PopupMenu_Invoke() { if (HasExtJs()) { return _PopupMenu_Invoke(PopupMenu_Invoke.arguments); } if (s_bNS3Before || s_bIE3Before ) { var argLen = PopupMenu_Invoke.arguments.length; if (argLen < 5) { window.document.location.href = PopupMenu_Invoke.arguments[3]; return false; } gbWndTemp = null; gbWndPopupLinks = null; gbstrParatotal = ""; for (var i = 0; i < (argLen - 2) / 2; i++) { var strParaLine = ""; if (s_bNS2 || s_bOpera){ strParaLine += "
" strParaLine += PopupMenu_Invoke.arguments[2 * i + 2]; strParaLine += ""; } else { strParaLine += ""); if (s_bNS2 || s_bOpera) { gbWndPopupLinks.document.write(""); } else { //YJ: IE301,302 and NS3.x works fine gbWndPopupLinks.document.write("<"); gbWndPopupLinks.document.write("script>"); gbWndPopupLinks.document.write("function gotoUrl(aUrl) {opener.window.location=aUrl; close();}"); gbWndPopupLinks.document.write("<"); gbWndPopupLinks.document.write("/script>"); } gbWndPopupLinks.document.write(""); gbWndPopupLinks.document.write(gbstrParaTotal); gbWndPopupLinks.document.write(""); gbWndPopupLinks.document.close(); // Close the temporary if (!s_bNS3 && gbWndTemp != null) { gbWndTemp.close(); }else { gbWndPopupLinks.focus(); } return true; } return false; } onload = BSSCOnLoad; document.onclick = BSSCOnClick; onunload = BSSCOnUnload; onerror = BSSCOnError;doc/SpecialOrderedSetsOfTypeOne_files/img00341.gif0000644000175000017500000001054607755240740020641 0ustar renereneGIF89a$a!,$aH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ NȱX<FNt׫k={^:x{Gݮ_>ߪUtU`֜\`׃B[sEavhӂuGyhOg^+x:X-3"Z$8cqrYوW%9XB@-I\ _cA~&O9!D`nVaBgT$w`xĨGh>J*NꕧI9^t%)seZu kZJKre뭩߮&lVڱH,iV 質E[VkBm~ .R*gSע{;MFo<,L>0gV9m'鿛64pSO\תw+UqD'+282V0S%3D7s*ܐ1@/TtPG+ II3f2zGԩ4XǪ76MjUW|iPWسR-lwo͍v/{-L~y6axxi?56wf'9<+wݙ#|k䥆m]_:[[;\{&qquC3lj-1^9w=s_.Y}췴=n4b_eHlsJ?̭+!Bخ|c(X~ _=aSUJcgPH;$!ch;aB k ]%!:P"bœ/Fl^6*DM\Xaу;SC_11]gZ6F jP# сЋH"1#z|سљ0%z$XI8G@t, J7f{ HL%%HBFd'S.eW22*cB&ba?`vG e1K1v&&&l7wIL33 4mN6LEg#x'+{Ѓpd+$Ie(YQQ3e)O~t ('QOW&4)I;^4Pt~jJu5)RR.R+Ԛ>!*;aRm)KS̬E?հb5GMU:dXz֮'^(֛o^XֵnlQ%XRvjO\wZVpVAm)UMkg U*S]mi1 Y^6ebukVkC۵_D.SR;Y]q+v.GKvu^swY\})Dž=w.zŻ_VmƗK/{`Z2v,\Vظܝջa*ãm0,`p=Xv0{5ܶXoO\fzEI$?GC Y4&-0qQ:fEQTܪ'ز@;\3y"YrH|ѢY|RD/n&k y RY:w6B;֤, :3XnDK47=eE:"Lu@]jMIDTZ3@ΗN.mO3mئَ`md{0JovHԣX5bvb$ ԳT4nY#&4]ikn}]%kQa{5Jky^mLKw nkdT[$nzjS}r}7UQ>n5]sG~-wYG׻bJY*M? jD^v>Y#eA};#{I~zg{]ڲO \CDŽ_^j7Z$tlz[{v{*~&|J{_ܿ$<=(1!&e3\lZ.`gf4c 6|z*րL}h(](WGb%Ex%,xy1Yƀ!8gn'e#8P%5)Z;^7`3HC$XL hSxӦ˕Pу16LRdex"nHDX((Ņugzah}wkhmh7NW?؂|ȈqH臖[2&8cXww(hX+h芙X3^8T8ȋ؉X؁ȆhX88XJHވhȌ͸MȉH稂8툎Cȏ8g݈Xr8thX`)) iՑԐ>W$Y Ix!9 yxԸ`>Ƀ-EƘxGm5Oٔ7TVIxX)i_iKy:NIɐoxe=) ȖULj)s m/ٖ1蒇1&مq|Z)(62i@V%YGz)d٘6i~Iٗ]IsuIFtyx7{\ _wd9yg) 9 vٜyY9CIdɗEKɓyHٚIp)ɝƙi+g`iיfڞzy:鉛j %'|ٟٙIjzy ٩թ .zc3Zj|fȤF~O)Qj~+Jj1JHzZaj{2e$T:KZ]}Cy:Zzڨ3:Z<.ؒB:2F&iH" dzsz媾"Czj:Sg:ob{jJFeW?Ǭz- 9ȡc7ںS8WsUʭL0 ncus:$ƭ gE97ǃ«7&گ1fgwi:eڰ yl |CvV;2kO dwX'|f !Q e# 8$$婲B;D[F{HJL۴NPR;T[V{XZ\۵^`K;doc/set_epsint.htm0000644000175000017500000000775510237176662013206 0ustar renerene set_epsint

set_epsint

Specifies the tolerance that is used to determine whether a floating-point number is in fact an integer.

void set_epsint(lprec *lp, REAL epsint);

Return Value

set_epsint has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epsint

The tolerance that is used to determine whether a floating-point number is in fact an integer.

Remarks

The set_epsint function specifies the tolerance that is used to determine whether a floating-point number is in fact an integer. This is only used when there is at least one integer variable and the branch and bound algorithm is used to make variables integer.
Integer variables are internally in the algorithm also stored as floating point. Therefore a tolerance is needed to determine if a value is to be considered as integer or not. If the absolute value of the variable minus the closed integer value is less than epsint, it is considered as integer. For example if a variable has the value 0.9999999 and epsint is 0.000001 then it is considered integer because abs(0.9999999 - 1) = 0.0000001 and this is less than 0.000001
The default value for epsint is 1e-7
So by changing epsint you determine how close a value must approximate the nearest integer. Changing this tolerance value to for example 0.001 will generally result in faster solving times, but your solution is less integer.
So it is a compromise.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epsint(lp, 1.0e-3); /* sets epsint to 0.001 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_epsint, set_infinite, is_infinite, get_infinite, set_epsb, get_epsb, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap

doc/set_basis.htm0000644000175000017500000001065410472142522012762 0ustar renerene set_basis

set_basis

Sets an initial basis of the lp.

unsigned char set_basis(lprec *lp, int *bascolumn, unsigned char nonbasic);

Return Value

set_basis returns TRUE if provided basis was set. FALSE if not. If FALSE then provided data was invalid.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

bascolumn

An array with 1+get_Nrows or 1+get_Nrows+get_Ncolumns elements that specifies the basis.

nonbasic

If FALSE, then bascolumn must have 1+get_Nrows elements and only contains the basic variables. If TRUE, then bascolumn must have 1+get_Nrows+get_Ncolumns elements and will also contain the non-basic variables.

Remarks

The set_basis function sets an initial basis of the lp.
The array receives the basic variables and if nonbasic is TRUE, then also the non-basic variables. If an element is less then zero then it means on lower bound, else on upper bound.
Element 0 of the array is unused.
The default initial basis is bascolumn[x] = -x.
Each element represents a basis variable. If the absolute value is between 1 and get_Nrows, it represents a slack variable and if it is between get_Nrows+1 and get_Nrows+get_Ncolumns then it represents a regular variable. If the value is negative, then the variable is on its lower bound. If positive it is on its upper bound.
Setting an initial basis can speed up the solver considerably. It is the starting point from where the algorithm continues to find an optimal solution.
When a restart is done, lp_solve continues at the last basis, except if set_basis, default_basis or read_basis is called.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int bascolumn[1+2]; /* must be 1 more then number of rows ! */

  /* Create a new LP model */
  lp = make_lp(2, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  bascolumn[0] = 0;
  bascolumn[1] = -1;
  bascolumn[2] = -2;
  set_basis(lp, bascolumn, FALSE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_basis, default_basis, read_basis, write_basis, guess_basis, get_basiscrash, set_basiscrash

doc/default_basis.htm0000644000175000017500000000462510472143134013614 0ustar renerene default_basis

default_basis

Sets the starting base to an all slack basis (the default simplex starting basis).

void default_basis(lprec *lp);

Return Value

None

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The default_basis function sets the starting base to an all slack basis (the default simplex starting basis).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  default_basis(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_basiscrash, set_basiscrash, get_basis, set_basis, read_basis, write_basis, guess_basis

doc/is_binary.htm0000644000175000017500000000562110237176656013001 0ustar renerene is_binary

is_binary

Gets the type of the variable. Binary integer or floating point.

unsigned char is_binary(lprec *lp, int column);

Return Value

is_binary returns TRUE (1) if the variable is set as binary, FALSE (0) otherwise.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be checked. It must be between 1 and the number of columns in the lp.

Remarks

The is_binary function returns if a variable must be binary or not. Default a variable is not binary. A binary variable is an integer variable with lower bound 0 and upper bound 1. From the moment there is at least one integer variable in the model, the Branch and Bound algorithm is used to make these variables integer. Note that solving times can be considerably larger when there are integer variables. See integer variables for a description about integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int binary;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  binary = is_binary(lp, 1); /* will return 0 since the variable is not set as binary at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_binary, is_int, set_int

doc/Presolve.htm0000644000175000017500000003057311236130503012602 0ustar renerene Presolve

Presolve

Presolve is a preprocess of the lp-model. It looks for ways to simplify it. For example it can delete unused variables and restrictions. Substitute fixed variable values by a constant and so on. The result is a new model that is less complex than the original model and likely solves faster.
The result of presolve can be that there are less variables and/or constraints in the presolved model.

Presolve is not active by default. It must specifically being enabled via the API call set_presolve.

Different presolve options are possible.
The more are chosen, the more presolve can be done and the model could me made simpler thus solved faster, but also presolve takes more time. Presolve will most of the time result in a netto time that is faster than without, but can also result in a slower time. So it is up to the user to decide when and which presolve to use on specific models. There is no general presolve option applicable for all models.

A simple example:

max: x1 + x2 + x3;

r1: x2 = 2;
r2: x1 + x2 <= 6;
r3: x1 - 2 x3 >= 2;
r4: x2 + 3 x3 <= 5;

Row r1 is a constraint on one variable. Presolve can detect this and convert it to a bound on that variable. For this, presolve of rows must be activated:

lp_solve model.lp -wlp con -S1 -wafter -presolverow
/* Objective function */
max: +x1 +x2 +x3;

/* Constraints */
r2: +x1 +x2 <= 6;
r3: +x1 -2 x3 >= 2;
r4: +x2 +3 x3 <= 5;

/* Variable bounds */
x2 = 2;

And even this model can be presolved further.
When presolve of columns is active, variables can be eliminated from the model.

lp_solve model.lp -wlp con -S1 -wafter -presolverow -presolvecol
/* Objective function */
max: +x1 +x3 +2;

/* Constraints */
r3: +x1 -2 x3 >= 2;

/* Variable bounds */
x1 <= 4;
x3 <= 1;

Note the -wafter option. If this option is not specified, the original model is printed. The reason for this is the moment that write_lp is called. The effect of presolve happens when a solve is done. If write_lp is called before solve then the original model is given. If called after solve then the presolved model is.

As previously stated, presolve can result in removal of variables and/or constraints. For some models, presolve can even find the solution of the model.

For constraints that are removed, all information of them are lost. Presolve has removed them from the matrix and cannot retrieve any information of them anymore. The number of rows is decreased by the number of constraints deleted. get_Nrows does not return the original number of rows, but the number of rows in the new model.

Variables that are removed from the matrix result in less columns in the model. get_Ncolumns does not return the original number of columns, but the number of columns in the new model.

However the information of the removed variables is not lost. Only variables that result in a fixed value are removed by presolve and their value is remembered at that time.

Example in C:

#include <stdio.h>

#include "lp_lib.h"

int main(void)
{
# if defined ERROR
#  undef ERROR
# endif
# define ERROR() { fprintf(stderr, "Error\n"); exit(1); }
  lprec *lp;

  if ((lp=make_lp(0, 3)) == NULL)
    ERROR();
  set_col_name(lp, 1, "x1");
  set_col_name(lp, 2, "x2");
  set_col_name(lp, 3, "x3");
  set_maxim(lp);
  if (!str_add_constraint(lp, "0 1 0", EQ, 2))
    ERROR();
  set_row_name(lp, 1, "R1");
  if (!str_add_constraint(lp, "1 1 0", LE, 6))
    ERROR();
  set_row_name(lp, 2, "R2");
  if (!str_add_constraint(lp, "1 0 -2", GE, 2))
    ERROR();
  set_row_name(lp, 3, "R3");
  if (!str_add_constraint(lp, "0 1 3", LE, 5))
    ERROR();
  set_row_name(lp, 4, "R4");
  if (!str_set_obj_fn(lp, "1 1 1"))
    ERROR();

  write_LP(lp, stdout);
  set_presolve(lp, PRESOLVE_ROWS + PRESOLVE_COLS, 0);
  solve(lp);
  print_objective(lp);
  print_solution(lp, 1);
  print_constraints(lp, 1);

  print_duals(lp);

  write_LP(lp, stdout);

  delete_lp(lp);

}

This gives:

/* Objective function */
max: +x1 +x2 +x3;

/* Constraints */
R1: +x2 = 2;
R2: +x1 +x2 <= 6;
R3: +x1 -2 x3 >= 2;
R4: +x2 +3 x3 <= 5;

Model name:  '' - run #1
Objective:   Maximize(R0)

SUBMITTED
Model size:        4 constraints,       3 variables,            7 non-zeros.
Sets:                                   0 GUB,                  0 SOS.

Presolve O:1 -> Reduced rows:    3, cols:    1 --- changed bnds:    4, Ab:    0.

PRESOLVE             Elimination loops performed.......... O3:M3:I5
                   1 empty or fixed variables............. REMOVED.
                   3 empty or redundant constraints....... REMOVED.
                   4 bounds............................... TIGHTENED.
                     [           +2 < Z < +7           ]

REDUCED
Model size:        1 constraints,       2 variables,            2 non-zeros.
Sets:                                   0 GUB,                  0 SOS.
Row-types:         0 LE,                1 GE,                   0 EQ.

Using DUAL simplex for phase 1 and PRIMAL simplex for phase 2.
The primal and dual simplex pricing strategy set to 'Devex'.


Optimal solution                   7 after          0 iter.

Excellent numeric accuracy ||*|| = 0

 MEMO: lp_solve version 5.5.0.15 for 32 bit OS, with 64 bit REAL variables.
      In the total iteration count 0, 0 (100.0%) were bound flips.
      There were 0 refactorizations, 0 triggered by time and 0 by density.
       ... on average 0.0 major pivots per refactorization.
      The largest [etaPFI v1.4] fact(B) had 0 NZ entries, 0.0x largest basis.
      The constraint matrix inf-norm is 2, with a dynamic range of 2.
      Time to load data was 0.235 seconds, presolve used 0.140 seconds,
       ... 0.047 seconds in simplex solver, in total 0.422 seconds.

Value of objective function: 7

Actual values of the variables:
x1                              4
x2                              2
x3                              1

Actual values of the constraints:
R3                              2

Objective function limits:
                                 From            Till       FromValue
x1                                  0          1e+030         -1e+030
x3                                  0          1e+030         -1e+030

Dual values with from - till limits:
                           Dual value            From            Till
R3                                  0         -1e+030          1e+030
x1                                  1               4          1e+030
x3                                  1         -1e+030               1
/* Objective function */
max: +x1 +x3 +2;

/* Constraints */
R3: +x1 -2 x3 >= 2;

/* Variable bounds */
x1 <= 4;
x3 <= 1;

The result only shows values of contraint R3, the one that is kept. The information of the removed constraints is no longer there.
The variable result however is not lost. x2 is removed by presolve, but its value is still known. On the other hand, note also that the variable does not appear in the sensitivity result.

Almost all API calls return information of the presolved model. get_Nrows and get_Ncolumns return the number of rows and columns of the presolved model. To know the original values, get_Norig_rows and get_Norig_columns must be used:

printf("get_Nrows: %d\n", get_Nrows(lp));
printf("get_Norig_rows: %d\n", get_Norig_rows(lp));
printf("get_Ncolumns: %d\n", get_Ncolumns(lp));
printf("get_Norig_columns: %d\n", get_Norig_columns(lp));

get_Nrows: 1
get_Norig_rows: 4
get_Ncolumns: 2
get_Norig_columns: 3

To retrieve the variable data of all variables, including the presolved variables, API call get_var_primalresult must be used. This is the only call available to get all information.
The following code prints the values of all variables:

int column, Nrows, Ncolumns;

Ncolumns = get_Norig_columns(lp);
Nrows = get_Norig_rows(lp);
for (column = 1; column <= Ncolumns; column++) {
  printf("x%d: %f\n", column, get_var_primalresult(lp, Nrows + column));
}

With result:

x1: 4.000000
x2: 2.000000
x3: 1.000000

get_var_primalresult also returns information about rows.
The following code prints the results of all rows:

int row, Nrows;

Nrows = get_Norig_rows(lp);

for (row = 1; row <= Nrows; row++) {
  printf("R%d: %f\n", row, get_var_primalresult(lp, row));
}

With result:

R1: 0.000000
R2: 0.000000
R3: 2.000000
R4: 0.000000

You could think here that a result for all original rows are returned, but this is not the case. Only the result of constraints that were kept in the model are given. The other rows will return 0!

There is also a possibility to know which rows and columns are removed from the model. get_orig_index can be used for that.
The following code demonstrates it:

int row, Nrows;
int column, Ncolumns;

Ncolumns = get_Ncolumns(lp);
Nrows = get_Nrows(lp);

for (row = 1; row <= Nrows; row++)
  printf("row %d was row R%d\n", row, get_orig_index(lp, row));

for (column = 1; column <= Ncolumns; column++)
  printf("column %d was column x%d\n", column, get_orig_index(lp, Nrows + column));

With result:

row 1 was row R3
column 1 was column x1
column 2 was column x3

So from this it can be determined that only row R3 and columns x1 and x3 are kept in the model. The others are removed by presolve.

Again note that all other API calls return information about the presolved model. So for example get_ptr_primal_solution must be used like this:

int row, Nrows;
int column, Ncolumns;
double *pv;

get_ptr_primal_solution(lp, &pv);

Ncolumns = get_Ncolumns(lp);
Nrows = get_Nrows(lp);

for (row = 1; row <= Nrows; row++)
  printf("row %d: %f\n", row, pv[row]);

for (column = 1; column <= Ncolumns; column++)
  printf("column %d: %f\n", column, pv[Nrows + column]);

With result:

row 1: 2.000000
column 1: 4.000000
column 2: 1.000000

Row and column names of the original model can be obtained via get_origrow_name and get_origcol_name:

int row, Nrows;
int column, Ncolumns;

Ncolumns = get_Norig_columns(lp);
Nrows = get_Norig_rows(lp);

for (row = 1; row <= Nrows; row++)
 printf("row %d: %s\n", row, get_origrow_name(lp, row));

for (column = 1; column <= Ncolumns; column++)
 printf("column %d: %s\n", column, get_origcol_name(lp, column));

With result:

row 1: R1
row 2: R2
row 3: R3
row 4: R4
column 1: x1
column 2: x2
column 3: x3

Row and column names of the presolved model can be obtained via get_row_name and get_col_name:

int row, Nrows;
int column, Ncolumns;

Ncolumns = get_Ncolumns(lp);
Nrows = get_Nrows(lp);

for (row = 1; row <= Nrows; row++)
 printf("row %d: %s\n", row, get_row_name(lp, row));

for (column = 1; column <= Ncolumns; column++)
 printf("column %d: %s\n", column, get_col_name(lp, column));

With result:

row 1: R3
column 1: x1
column 2: x3
doc/Win32/0000755000175000017500000000000011141423065011166 5ustar renerenedoc/Win32/HTML Help/0000755000175000017500000000000011141423065012603 5ustar renerenedoc/get_Ncolumns.htm0000644000175000017500000000531010237176654013450 0ustar renerene get_Ncolumns

get_Ncolumns

Returns the number of columns (variables) in the lp.

int get_Ncolumns(lprec *lp);

Return Value

get_Ncolumns returns the number of columns (variables) in the lp.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_Ncolumns function returns the number of columns (variables) in the lp.
Note that the number of columns can change when a presolve is done or when negative variables are split in a positive and a negative part.
Therefore it is advisable to use this function to determine how many columns there are in the lp instead of relying on an own count.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int Ncolumns;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  Ncolumns = get_Ncolumns(lp); /* Will return 1 */

  set_presolve(lp, PRESOLVE_COLS);
  solve(lp);

  Ncolumns = get_Ncolumns(lp); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_Norig_columns, get_Nrows, get_Norig_rows, get_orig_index, get_lp_index, get_Lrows

doc/reset_basis.htm0000644000175000017500000000434110237177564013322 0ustar renerene reset_basis

reset_basis

Causes reinversion at next opportunity

void reset_basis(lprec *lp);

Return Value

reset_basis has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

This routine is ment for internal use and development. It causes a reinversion of the matrix at a next opportunity. The routine should only be used by people deeply understanding the code.
In the past, this routine was documented as the routine to set an initial base. This is incorrect. default_basis must be used for this purpose. It is very unlikely that you must call this routine.

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_basis, set_basis, default_basis, get_basiscrash set_basiscrash

doc/unscale.htm0000644000175000017500000000451710237176666012460 0ustar renerene unscale

unscale

Unscales the model.

void unscale(lprec *lp);

Return Value

unscale has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The unscale function unscales the model. Scaling can influence numerical stability considerably. It is advisable to always use some sort of scaling.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  unscale(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_scaling, get_scaling, is_integerscaling, set_scalelimit, get_scalelimit, is_scalemode, is_scaletype

doc/get_presolveloops.htm0000644000175000017500000000471110237207712014560 0ustar renerene get_presolveloops

get_presolveloops

Returns the number of times presolve is done.

int get_presolveloops(lprec *lp);

Return Value

get_presolveloops returns the number of times presolve is done.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_presolveloops function returns the number of times presolve is done. After a presolve is done, another presolve can again result in elimination of extra rows and/or columns. This number specifies the maximum number of times this process is repeated. By default this is until presolve has nothing to do anymore.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int presolveloops;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  presolveloops = get_presolveloops(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_presolve, get_presolve, get_presolveloops

doc/set_rh.htm0000644000175000017500000000625710242131752012274 0ustar renerene set_rh

set_rh

Set the value of the right hand side (RHS) vector (column 0) for one row.

unsigned char set_rh(lprec *lp, int row, REAL value);

Return Value

set_rh returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the RHS value must be set. Must be between 0 and number of rows in the lp.

value

The value of the RHS.

Remarks

The set_rh function sets the value of the RHS vector (column 0) for the specified row.
Note that row can also be 0 with this function. In that case an initial value for the objective value is set. Functions set_rh_vec, str_set_rh_vec ignore row 0 (for historical reasons) in the specified RHS vector, but it is possible to first call one of these functions and then set the value of the objective with set_rh.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(2, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_rh(lp, 1, 1.0); /* sets the value 1.0 for RHS row 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_rh_vec, str_set_rh_vec, get_rh, add_constraint, add_constraintex, str_add_constraint, get_row, get_rowex, get_mat

doc/dimacs_asn.gif0000644000175000017500000001114710425477150013070 0ustar renereneGIF87a`*U****U***UU*UUUUU*U*U*UԪ****U**********U*******U*U**UU*U*U*U****U*******U*******U**Ԫ*UU*UUUUUU*U**U*UU*U*U*UUUU*UUUUUUUUUUU*UUUUUUU*UUUUUUU*UUUUԪU*U****U***UU*UUUUU*U*U*UԪԪ*UԪ****U***ԪUU*UUUUUԪ*UԪ*UԪ*UԪ*U****U***UU*UUUUU*UԪԪ*ԪUԪԪԪ*UԪ &&&333???LLLYYYfffrrr𠠤,` H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۩}KnBshWl_y _`&6xc3l__fW2ØiυSw U.Bէ ^tlڣst}pۛcWm ?Yݡ77 :VבK7n0;a..g/W2qY3nvuQ}p1[j ^h!G)ȝRE~a`|E(jtvXt)(4h8<@)DiH|I6Y9)PV9U~XvYז`z)``9RPlSQJĦo֩I|]z}f Z"VYhYFx_V>R袜bjW4kz)٪hm9٬&lKBdԬA z:~6E,tފ,e^{U/nk)?.Ƥ=ۮZ*zV{Y*/⺚, Ǚ0'ZflźNiǨ|\lFz<+粕{2Lˀ\Qn!lE5m,wFP1nnoJB[I/8wyw;x_#ٵZ:2iUXJcmP6oíj yvWmm݃Nw(EE^~RgL1:.:NG-lBYNS':cEH(㎔*"prÙ'7/rя|snG%+v{yϗb?TzN7<ѯ~[II2@&e\x@0\JH Z0& TBX z.^[vZI*usvAI׹ݭnvzν yEZh .|J`\^+ӔlK*;}!\Z<8șnͬ$ ȍvscPzսq%hCBw/+M3wʁIzfӼE;fMzՂ/M}Jz HͰHيJ!2u|XUv[c; }{jsL\bWTuG|efc/W"~]lX&_{N0_T.VnR pw/?%Dr6ȇ{5HbJh|䱵$?Q|/:ŸW.`r|2Rrozʃ6/u~ja.Ҥ톽hArkm׉T!ۙfU^|;1ҥ|lw\Nr~qZÉ_x|ݎh]61Wf]ӓ܌%PϞ i]|(7Dׇ( _n[!Mk >-'~3ch-eiCJf?uU]{˹m ^sѶЅ?)غ+˲:M7/*zˊpJ=軼z4'I[*U4$מ h} [(6k鉇͛ 8ᛗ5K# ۾e;KI; $0<\| ';doc/get_break_at_value.htm0000644000175000017500000000553110237176652014621 0ustar renerene get_break_at_value

get_break_at_value

Returns the value at which the branch-and-bound algorithm stops when the object value is better than this value.

REAL get_break_at_value(lprec *lp);

Return Value

get_break_at_value returns the value to break on.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_break_at_value function returns the value at which the branch-and-bound algorithm stops when the object value is better than this value. Stopping at a given object value can be useful if you are only interested for a solution that has an object value which is at least a given value, but not necessarily (and most probably) the most optimal solution.
The default value is (-) infinity.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL break_at_value;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  break_at_value = get_break_at_value(lp); /* Will return -1e30 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_break_at_value, set_break_at_first, is_break_at_first, set_obj_bound, get_obj_bound, set_mip_gap, get_mip_gap

doc/dimacs_mcf.gif0000644000175000017500000001520010407617574013054 0ustar renereneGIF87aFj679:<C:<7.8 !&(-.# rHP$T/% <8L4LGO`xp4'4PT#0|0+!(?|(+ 3*\OverwGrOiXte xi+s!ting f$lSe '/fils/ho%md e/ow7enj$dima cs_m. c.g7f+'pf?$ PT(7+p= a+h!7p0 ah $\uf s7p{X,Fj+(@*\ȰÇ#JHŋ3jȱǏ C9Q  ˗0cʜI͛8s4H@%2pAԃG*]ʴӧPJJիXjʵׯ`ÊKٳhr DȝKݻx˷߿ LÈ+^̸ǐ# ۸3k̹ϠCM]ʖ^ͺװc˞˴sͻȓ+_wjУKN:c瘭kνwؿOyϫ_Ͼ˟O8>( ` & ^.`Vhr^ΖaUvs$F,(b](#sZ"|+6\B{cLFd!)PV)ۓVFKfjX~ٖIEhrfuir H杍cn&֣{j*֧@(a.Zؙ:*)&7d.饜h}miifꨱv ksͪ)+:ŠIl"K> h^.-Բim16-^d"*[).>+[工,r[L ()0Gl҆;mũN|r/3.̩|x C)zu)'ۦnj˜cs<2|i.J]MГBz 2tSKTwh50ge\wג~-e}])bh$vmalv[w.d6)`R6KN]7gɹYyߣXzϱ;ykt{(%:e-6V"/|c7||C)=b1N. =fC8G/6fO)[Þ@/ %!= K3' h,]o4A`B$\M K8Fh* L Qf*"3@T 1u80J91bЮXD *6S܏us3J'թ^JnT9d.YvxNQ::G27dHd|$_"6g"vjhL$rOܑ^:T"FҀuGXzs;2el\>G7C})u X$faY] ,f#Lid!I~!͔&- e3&mi&,x BNxslg0/S=AI)1^EVIjch%-tكLӡ5DEJ5 5i]9̏)ӿH+]D O}#."u%rӆfD!M1%RQd22iR9Ѡn,܅nǒje&?qukU*GCȽK;Zվ54D'WΩVVJR5]XЬTUD ͐~$0I;XԚh5DQal;?["qEGlSzٻ bd^2Ne!r[i jhUKDm;D%1소*%y$RwF;Lڗ0z,cle0xE灅tq:뢸:7d쩵ÿ 8|2b% ۨi<~,%4D6|OR9TS/ * 8c&3ʒܵVEevJ5R&3R&%4ʠc,*%b vs3[GNP:GQpX}=X/Σ5liW&u3e-3]e*;qG~m.5Vmiku}OI-W)yx߬OyyA#zwuJ~`}ܳ]'ybwuĀ31e;M၏y1t~ }p-fY;4hi"44^ZXxrzG]7Y_Ce'c|,2фuNs&VWis.jT7[LOT0L:i".|fh2dXxIW&}s-T}VX~Z\TRo"+i~Vc"tňeDCxs~Ԇ (|b._KDwd(fG~W`x؋X>"^b5o08XX2Sh*}Ŋ!ȈDH]1F0x$YasÉӍw؅1珟DWWȎqcͧiAtW]Œh=ȏ]&@$_9" 1GY uNS G7wR=ÒQ"cxɈ~:Տ63Fk5؂4PY~aEW)J_nWȄ1"ǖ|./RǕW,u)b c}I7nVchG7e/N7T4 mgdn92pܴ<1vk旙w^#yCeٚp9T7gwg0ɛ}|E{sЙGnWkY@%FqEi+י\9sg^3dy7)jI w Yi3]gk),I :9-iݦ%֠QndkeWH)Bi+F5ǝoFXǟr6l#wi]2JB?l=I<'S, :>7᡹ QTSg]K)?TCjn⤑c#7ʥuDƦpNVy%J#Yhtr^ :9ZlަrUgꩇUsPiZ䧳Ƶ^z##?&SBuq$R7r:j1ĬFfHzQ"LsT8+ֵ^[dKdb vfx*ZشLU+KF.n[_xK=&:WFõp[ NAc) "bgkEb)gE˹kVK]Reqk ܕUY &n wN@!a-/n6Ӂ IiPb76ԣYD ÇED;P#cꤽE9Q&7,L񍎤<m4,c'}+/R=p]~mn!&y[v4' VǨ݈-nt6y=MZ.K]u=&'?;r &.޺+}k N5'۩}gD ˿m<_HL{dRi.uC$G>ɤ?EY_+RV|jheN"/5,"%^qWLUTU4 tU]$0WAH ծmJԬӣIśW^e(IP*`2X.UR!S=]rhVGe7g m}0gMeH5s.\𽷉#lu:]u,^'|vݑ{[<\65ݯ^|ͯN_w>@A0B cpB /0C 7.81DG$ KD1EWd[1FgEo1GqG2ȵzH#D "dI'cBxJ+18K/,45dM7߄3N9|N;3O=O?4PA%PCE4:9"@RK`K7SO?5TQG%TSOE5UUWeUW_5VYgV[= ( :VcE6YeeYg6e;doc/get_constr_value.htm0000644000175000017500000000757410242170054014354 0ustar renerene get_constr_value

get_constr_value

Gets the value of a constraint according to provided variable values.

REAL get_constr_value(lprec *lp, int row, int count, REAL *primsolution, int *nzindex);

Return Value

get_constr_value returns the value of the constraint as calculated with the provided variable values.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the constraint value must be calculated. Must be between 1 and number of rows in the lp.

count

The number of items in primsolution and nzindex.

primsolution

The values of the variables.

nzindex

The variable indexes.

Remarks

The get_constr_value function returns the value of a constraint according to provided variable values.
If primsolution is NULL, then the solution of the last solve is taken. count and nzindex are then ignored.
If primsolution is not NULL, and nzindex is NULL, then the variable values are taken from primsolution and element i must specify the value for variable i. Element 0 is not used and thus data starts from element 1. The variable must then contain 1+get_Ncolumns elements. count is ignored in that case.
If primsolution is not NULL, and nzindex is not NULL, then the variable values are taken from primsolution. nzindex contains the indexes of the variables and count specifies how many elements there are in primsolution and nzindex. So the data is then provided in a sparse vector. Elements start from index 0 in that case.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int constr;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  printf("%f\n", get_constr_value(lp, 0, 0, NULL, NULL));

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_constraints, get_ptr_constraints, get_variables, get_ptr_variables, get_primal_solution, get_ptr_primal_solution, get_var_primalresult

doc/get_objective.htm0000644000175000017500000000556310237215260013621 0ustar renerene get_objective

get_objective

Returns the value of the objective function.

REAL get_objective(lprec *lp);

Return Value

get_objective returns the value of the objective.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_objective function returns the value of the objective of the last solve.
This value is only valid after a successful solve or lag_solve.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL obj;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  obj = get_objective(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_variables, get_ptr_variables, get_working_objective, get_constraints, get_ptr_constraints, get_constr_value, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex

doc/set_obj_bound.htm0000644000175000017500000000554210237176664013637 0ustar renerene set_obj_bound

set_obj_bound

Set initial "at least better than" guess for objective function.

void set_obj_bound(lprec *lp, REAL obj_bound);

Return Value

set_obj_bound has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

obj_bound

The initial "at least better than" guess for objective function.

Remarks

The set_obj_bound function specifies the initial "at least better than" guess for objective function. This is only used in the branch-and-bound algorithm when integer variables exist in the model. All solutions with a worse objective value than this value are immediately rejected. This can result in faster solving times, but it can be difficult to predict what value to take for this bound. Also there is the chance that the found solution is not the most optimal one.
The default is infinite.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_obj_bound(lp, 1000);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_obj_bound, , set_break_at_value, get_break_at_value set_mip_gap, get_mip_gap

doc/Euler.htm0000644000175000017500000034076211244025272012070 0ustar renerene Using lpsolve from Euler

Using lpsolve from Euler

Euler?

The Euler Mathematical Toolbox is a powerful, versatile, and open source software for numerical and symbolic computations written and maintained by R. Grothmann from the University of Eichsttt. Euler is similar to MATLAB, but uses an own style and an own syntax. Euler supports symbolic mathematics using the open algebra system Maxima.

The most recent version of Euler runs in Windows (98/XP/Vista), or under Linux in Wine. The native Linux version is currently outdated.

We will not discuss the specifics of Euler here but instead refer the reader to the Euler website.

Euler and lpsolve

lpsolve is callable from Euler via a dynamic linked DLL function. As such, it looks like lpsolve is fully integrated with Euler. Matrices can directly be transferred between Euler and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for Euler (especially for matrix support). So you have full control to the complete lpsolve functionality via the eulpsolve Euler driver. If you find that this involves too much work to solve an lp model then you can also work via higher-level Euler files that can make things a lot easier. See further in this article.

Quickstart

Compile and build eulpsolve:
----------------------------

1. Under Windows, the Microsoft Visual C/C++ compiler must be installed
   and the environment variables must be active do that when a command prompt
   is opened, the cl and nmake commands can be executed.

2. Go to directory lp_solve_5.5\extra\Euler

3. Edit cvc.bat and change the path of the Eulerpath environment variable to your path.

4. To compile and build eulpsolve, enter the following command:
      cvc

Load the eulpsolve driver in the Euler memory space:
-------------------------------------------------------

1. Under Windows, make sure that the lpsolve55.dll file is somewhere in the path
   (archive lp_solve_5.5.0.15_dev.zip)

2. A precompiled library is provided for Windows (eulpsolve.dll).

3. Start Euler

4. Enter the following command in Euler:
      >dll("<path>/eulpsolve.dll", "eulpsolve", -1)

      Or if this fails (because you use version an Euler version 7.0 or older):

      >dll("<path>/eulpsolve.dll", "eulpsolve", 0)
      >dll("<path>/eulpsolve.dll", "eulpsolve", 1);
      >dll("<path>/eulpsolve.dll", "eulpsolve", 2);
      >dll("<path>/eulpsolve.dll", "eulpsolve", 3);
      >dll("<path>/eulpsolve.dll", "eulpsolve", 4);
      >dll("<path>/eulpsolve.dll", "eulpsolve", 5);
      >dll("<path>/eulpsolve.dll", "eulpsolve", 6);
      >dll("<path>/eulpsolve.dll", "eulpsolve", 7);
   For <path> use the path where the eulpsolve.dll is located.
   These commands can be put in a file, for example loadlpsolve.en, with a regular editor like notepad.
   They can then be opened as a notebook in Euler and executed.

Euler is ideally suited to handle linear programming problems. These are problems in which you have a quantity, depending linearly on several variables, that you want to maximize or minimize subject to several constraints that are expressed as linear inequalities in the same variables.If the number of variables and the number of constraints are small, then there are numerous mathematical techniques for solving a linear programming problem. Indeed these techniques are often taught in high school or university level courses in finite mathematics.But sometimes these numbers are high, or even if low, the constants in the linear inequalities or the object expression for the quantity to be optimized may be numerically complicated in which case a software package like Euler is required to effect a solution.

Installation

To make this possible, a driver program is needed: eulpsolve (eulpsolve.dll under Windows). This driver must be loaded in Euler and Euler can call the eulpsolve solver.

This driver calls lpsolve via the lpsolve shared library (lpsolve55.dll under Windows). This has the advantage that the eulpsolve driver doesn't have to be recompiled when an update of lpsolve is provided. The shared library must be somewhere in the Windows path.

So note the difference between the Euler lpsolve driver that is called eulpsolve and the lpsolve library that implements the API that is called lpsolve55.

There are also some Euler notebooks (.en) as a quick start.

The first thing that must be done, each time Euler is restarted and you want to use lpsolve is load the eulpsolve driver into the Euler workspace. This is done via the dll command. Suppose that eulpsolve.dll is installed in c:\Program Files\Euler\dll, then the following command must be used to load the driver:

>dll("c:/Program Files/Euler/dll/eulpsolve.dll", "eulpsolve", -1)

Note that this command is only accepted from Euler version 7.1 or newer. On older Euler versions, -1 is not accepted on the third argument. There is however a work-around for this. You can then use the following commands (all together):

>dll("c:/Program Files/Euler/dll/eulpsolve.dll", "eulpsolve", 0)
>dll("c:/Program Files/Euler/dll/eulpsolve.dll", "eulpsolve", 1);
>dll("c:/Program Files/Euler/dll/eulpsolve.dll", "eulpsolve", 2);
>dll("c:/Program Files/Euler/dll/eulpsolve.dll", "eulpsolve", 3);
>dll("c:/Program Files/Euler/dll/eulpsolve.dll", "eulpsolve", 4);
>dll("c:/Program Files/Euler/dll/eulpsolve.dll", "eulpsolve", 5);
>dll("c:/Program Files/Euler/dll/eulpsolve.dll", "eulpsolve", 6);
>dll("c:/Program Files/Euler/dll/eulpsolve.dll", "eulpsolve", 7);

These commands can be put in a file, for example loadlpsolve.en or loadlpsolve.e, with a regular editor like notepad. The .en file can then be opened as a notebook in Euler and executed. The .e file can be loaded and executed via the load statement.

That is basically all you need to do. From now on, you can use the library. This until Euler is restarted. Then this command must be given again to reload the library.

To test if everything is installed correctly, enter eulpsolve(); in the Euler command prompt. If it gives the following, then everything is ok:

>eulpsolve();
eulpsolve Euler Interface version 5.5.0.7
using lpsolve version 5.5.0.15

Usage: [ret1, ret2, ...] = eulpsolve("functionname", arg1, arg2, ...)

However, if you get a message box with the following:

eulpsolve no function or variable, or wrong argument number!

Then either the dll command that was previous given was unsuccessful (or not given at all) or something was misspelled after the ,

Check the dll command again. If it gives a message box with the following message:

---------------------------
euler.exe - Unable To Locate Component
---------------------------
This application has failed to start because lpsolve55.dll was not found. Re-installing the application may fix this problem.
---------------------------
OK
---------------------------

And then in Euler:

 Could not open the DLL library!
 Could not find the function!
 error in :
 dll("<path>/eulpsolve.dll", "eulpsolve", 0)

Then Euler can find the eulpsolve driver program, but the driver program cannot find the lpsolve library that contains the lpsolve implementation. This library is called lpsolve55.dll and should be on your system in a directory that in the PATH environment variable. This path can be shown via the command line command PATH.

The lpsolve55.dll files must be in one of these specified directories. It is common to place this in the WINDOWS\system32 folder.

If the message in Euler is shown without a message box of a missing lpsolve55.dll file then eulpsolve.dll cannot be found.

All this is developed and tested with Euler versions 7.0 and 7.1 beta. This is the minimum supported release. Older releases are unsupported. Only from version 7.1 on, it is possible to print something in the Euler window from the external library. So on older versions, when something must be printed, it will be shown in a messagebox. If you are working with a lower version than 7.1 it is best that the verbose level of the set_verbose API call is less than or equal to 3. Otherwise too much messageboxes will be given and it is unpractical to work with this. If you need this verbose level, then use at least version 7.1

Solve an lp model from Euler via eulpsolve

In the following text, > before the Euler commands is the Euler command line. Only the text after > must be entered.

To call an lpsolve function, the following syntax must be used:

>{ret1, ret2, ...} = eulpsolve("functionname", arg1, arg2, ...)

The return values are optional and depend on the function called. functionname must always be enclosed between double quotes to make it alphanumerical and it is case sensitive. The number and type of arguments depend on the function called. Some functions even have a variable number of arguments and a different behaviour occurs depending on the type of the argument. functionname can be (almost) any of the lpsolve API routines (see lp_solve API reference) plus some extra Euler specific functions. Most of the lpsolve API routines use or return an lprec structure. To make things more robust in Euler, this structure is replaced by a handle or the model name. The lprec structures are maintained internally by the lpsolve driver. The handle is an incrementing number starting from 0. Starting from driver version 5.5.0.2, it is also possible to use the model name instead of the handle. This can of course only be done if a name is given to the model. This is done via lpsolve routine set_lp_name or by specifying the model name in routine read_lp. See Using model name instead of handle.

Almost all callable functions can be found in the lp_solve API reference. Some are exactly as described in the reference guide, others have a slightly different syntax to make maximum use of the Euler functionality. For example make_lp is used identical as described. But get_variables is slightly different. In the API reference, this function has two arguments. The first the lp handle and the second the resulting variables and this array must already be dimensioned. When lpsolve is used from Euler, nothing must be dimensioned in advance. The eulpsolve driver takes care of dimensioning all return variables and they are always returned as return value of the call to eulpsolve. Never as argument to the routine. This can be a single value as for get_objective (although Euler stores this in a 1x1 matrix) or a matrix or vector as in get_variables. In this case, get_variables returns a 4x1 matrix (vector) with the result of the 4 variables of the lp model.

An example

(Note that you can execute this example by entering command per command as shown below or by opening and executing notebook example1.en)

>lp=eulpsolve("make_lp", 0, 4);
>eulpsolve("set_verbose", lp, 3);
>eulpsolve("set_obj_fn", lp, [1, 3, 6.24, 0.1]);
>eulpsolve("add_constraint", lp, [0, 78.26, 0, 2.9], 2, 92.3);
>eulpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], 1, 14.8);
>eulpsolve("add_constraint", lp, [12.68, 0, 0.08, 0.9], 2, 4);
>eulpsolve("set_lowbo", lp, 1, 28.6);
>eulpsolve("set_lowbo", lp, 4, 18);
>eulpsolve("set_upbo", lp, 4, 48.98);
>eulpsolve("set_col_name", lp, 1, "COLONE");
>eulpsolve("set_col_name", lp, 2, "COLTWO");
>eulpsolve("set_col_name", lp, 3, "COLTHREE");
>eulpsolve("set_col_name", lp, 4, "COLFOUR");
>eulpsolve("set_row_name", lp, 1, "THISROW");
>eulpsolve("set_row_name", lp, 2, "THATROW");
>eulpsolve("set_row_name", lp, 3, "LASTROW");
>eulpsolve("write_lp", lp, "a.lp");
>eulpsolve("get_mat", lp, 1, 2)

                 78.26

>eulpsolve("solve", lp)

                     0

>eulpsolve("get_objective", lp)

        31.78275862069

>eulpsolve("get_variables", lp)

                  28.6
                     0
                     0
         31.8275862069

>eulpsolve("get_constraints", lp)

                  92.3
                 6.864
        391.2928275862

Note that there are some commands that return an answer. To see the answer, the command was not terminated with a semicolon (;). If the semicolon is put at the end of a command, the answer is not shown. However it is also possible to write the answer in a variable. For example:

>obj=eulpsolve("get_objective", lp)

        31.78275862069

Or:

>obj=eulpsolve("get_objective", lp);

Both will write the result in variable obj. Without the semicolon, the result is also shown on screen. get_variables and get_constraints return a vector with the result. This can also be put in a variable:

>x=eulpsolve("get_variables", lp);
>b=eulpsolve("get_constraints", lp);

It is always possible to show the contents of a variable by just giving it as command:

>x

                  28.6
                     0
                     0
         31.8275862069

Don't forget to free the handle and its associated memory when you are done:

>eulpsolve("delete_lp", lp);

Note that for larger and/or complex models, solving time can be long. If this must be interrupt then the ESC key can be pressed. Euler shows this also in the status bar. lp_solve checks regularly if this key is pressed and if so, solve is interrupted. If verbose level is set then this is also shown on screen. Anyway, the return status will indicate that solve was aborted.

Using model name instead of handle

From driver version 5.5.0.2, it is possible to use the model name instead of the handle. From the moment the model has a name, you can use this name instead of the handle. This is best shown by an example. Above example would look like this:
>lp=eulpsolve("make_lp", 0, 4);
>eulpsolve("set_lp_name", lp, "mymodel");
>eulpsolve("set_verbose", "mymodel", 3);
>eulpsolve("set_obj_fn", "mymodel", [1, 3, 6.24, 0.1]);
>eulpsolve("add_constraint", "mymodel", [0, 78.26, 0, 2.9], 2, 92.3);
>eulpsolve("add_constraint", "mymodel", [0.24, 0, 11.31, 0], 1, 14.8);
>eulpsolve("add_constraint", "mymodel", [12.68, 0, 0.08, 0.9], 2, 4);
>eulpsolve("set_lowbo", "mymodel", 1, 28.6);
>eulpsolve("set_lowbo", "mymodel", 4, 18);
>eulpsolve("set_upbo", "mymodel", 4, 48.98);
>eulpsolve("set_col_name", "mymodel", 1, "COLONE");
>eulpsolve("set_col_name", "mymodel", 2, "COLTWO");
>eulpsolve("set_col_name", "mymodel", 3, "COLTHREE");
>eulpsolve("set_col_name", "mymodel", 4, "COLFOUR");
>eulpsolve("set_row_name", "mymodel", 1, "THISROW");
>eulpsolve("set_row_name", "mymodel", 2, "THATROW");
>eulpsolve("set_row_name", "mymodel", 3, "LASTROW");
>eulpsolve("write_lp", "mymodel", "a.lp");
>eulpsolve("get_mat", "mymodel", 1, 2)

                 78.26

>eulpsolve("solve", "mymodel")

                     0

>eulpsolve("get_objective", "mymodel")

        31.78275862069

>eulpsolve("get_variables", "mymodel")

                  28.6
                     0
                     0
         31.8275862069

>eulpsolve("get_constraints", "mymodel")

                  92.3
                 6.864
        391.2928275862

So everywhere a handle is needed, you can also use the model name. You can even mix the two methods. There is also a specific Euler routine to get the handle from the model name: get_handle.
For example:

>eulpsolve("get_handle", "mymodel")

                     0

Don't forget to free the handle and its associated memory when you are done:

>eulpsolve("delete_lp", "mymodel");

In the next part of this documentation, the handle is used. But if you name the model, the name could thus also be used.

Matrices

In Euler, all numerical data is stored in matrices; even a scalar variable. Euler also supports complex numbers. eulpsolve can only work with real numbers. For example:
>eulpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], 1, 14.8);

Most of the time, variables are used to provide the data:

>eulpsolve("add_constraint", lp, a1, 1, 14.8);

Where a1 is a matrix variable.

Matrices with too few or too much elements gives an 'invalid vector.' error.

Most of the time, eulpsolve needs vectors (rows or columns). In all situations, it doesn't matter if the vectors are row or column vectors. The driver accepts them both. For example:

>eulpsolve("add_constraint", lp, [0.24; 0; 11.31; 0], 1, 14.8);

Which is a column vector, but it is also accepted.

An important final note. Several lp_solve API routines accept a vector where the first element (element 0) is not used. Other lp_solve API calls do use the first element. In the Euler interface, there is never an unused element in the matrices. So if the lp_solve API specifies that the first element is not used, then this element is not in the Euler matrix.

Maximum usage of matrices with eulpsolve

Because Euler is all about matrices, all lpsolve API routines that need a column or row number to get/set information for that column/row are extended in the eulpsolve Euler driver to also work with matrices. For example set_int in the API can only set the integer status for one column. If the status for several integer variables must be set, then set_int must be called multiple times. The eulpsolve Euler driver however also allows specifying a vector to set the integer status of all variables at once. The API call is: return = eulpsolve("set_int", lp, column, must_be_int). The matrix version of this call is: return = eulpsolve("set_int", lp, [must_be_int]). The API call to return the integer status of a variable is: return = eulpsolve("is_int", lp, column). The matrix version of this call is: [is_int] = eulpsolve("is_int", lp)
Also note the get_mat and set_mat routines. In Euler these are extended to return/set the complete constraint matrix. See following example.

Above example can thus also be done as follows:
(Note that you can execute this example by entering command per command as shown below or by opening and executing notebook example2.en)

>lp=eulpsolve("make_lp", 0, 4);
>eulpsolve("set_verbose", lp, 3);
>eulpsolve("set_obj_fn", lp, [1, 3, 6.24, 0.1]);
>eulpsolve("add_constraint", lp, [0, 78.26, 0, 2.9], 2, 92.3);
>eulpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], 1, 14.8);
>eulpsolve("add_constraint", lp, [12.68, 0, 0.08, 0.9], 2, 4);
>eulpsolve("set_lowbo", lp, [28.6, 0, 0, 18]);
>eulpsolve("set_upbo", lp, [1.0e30, 1.0e30, 1.0e30, 48.98]);
>eulpsolve("set_col_name", lp, 1, "COLONE");
>eulpsolve("set_col_name", lp, 2, "COLTWO");
>eulpsolve("set_col_name", lp, 3, "COLTHREE");
>eulpsolve("set_col_name", lp, 4, "COLFOUR");
>eulpsolve("set_row_name", lp, 1, "THISROW");
>eulpsolve("set_row_name", lp, 2, "THATROW");
>eulpsolve("set_row_name", lp, 3, "LASTROW");
>eulpsolve("write_lp", lp, "a.lp");
>eulpsolve("get_mat", lp)

                     0               78.26                   0                 2.9
                  0.24                   0               11.31                   0
                 12.68                   0                0.08                 0.9

>eulpsolve("solve", lp)

                     0

>eulpsolve("get_objective", lp)

        31.78275862069

>eulpsolve("get_variables", lp)

                  28.6
                     0
                     0
         31.8275862069

>eulpsolve("get_constraints", lp)

                  92.3
                 6.864
        391.2928275862

Note the usage of 1.0e30 in set_upbo. This stands for "infinity". Meaning an infinite upper bound. It is also possible to use -1.0e30 to express minus infinity. This can for example be used to create a free variable.

To show the full power of the matrices, let's now do some matrix calculations to check the solution. It works further on above example:

>A=eulpsolve("get_mat", lp);
>X=eulpsolve("get_variables", lp);
>B = A . X

                  92.3
                 6.864
        391.2928275862

So what we have done here is calculate the values of the constraints (RHS) by multiplying the constraint matrix with the solution vector. Now take a look at the values of the constraints that lpsolve has found:

>eulpsolve("get_constraints", lp)

                  92.3
                 6.864
        391.2928275862

Exactly the same as the calculated B vector, as expected.

Also the value of the objective can be calculated in a same way:

>C=eulpsolve("get_obj_fn", lp);
>X=eulpsolve("get_variables", lp);
>obj = C . X

        31.78275862069

So what we have done here is calculate the value of the objective by multiplying the objective vector with the solution vector. Now take a look at the value of the objective that lpsolve has found:

>eulpsolve("get_objective", lp)

        31.78275862069

Again exactly the same as the calculated obj value, as expected.

Using string constants

From driver version 5.5.0.15 on, it is possible to use string constants everywhere an lp_solve constant is needed or returned. This is best shown by an example. In the above code we had:
>lp=eulpsolve("make_lp", 0, 4);
>eulpsolve("set_verbose", lp, 3);
>eulpsolve("add_constraint", lp, [0, 78.26, 0, 2.9], 2, 92.3);
>eulpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], 1, 14.8);
>eulpsolve("add_constraint", lp, [12.68, 0, 0.08, 0.9], 2, 4);

Note the 3rd parameter on set_verbose and the 4th on add_constraint. These are lp_solve constants. One could define all the possible constants in Euler and then use them in the calls, but that has several disadvantages. First there stays the possibility to provide a constant that is not intended for that particular call. Another issue is that calls that return a constant are still returning it numerical.

Both issues can now be handled by string constants. The above code can be done as following with string constants:

>lp=eulpsolve("make_lp", 0, 4);
>eulpsolve("set_verbose", lp, "IMPORTANT");
>eulpsolve("add_constraint", lp, [0, 78.26, 0, 2.9], "GE", 92.3);
>eulpsolve("add_constraint", lp, [0.24, 0, 11.31, 0], "LE", 14.8);
>eulpsolve("add_constraint", lp, [12.68, 0, 0.08, 0.9], "GE", 4);

This is not only more readable, there is much lesser chance that mistakes are being made. The calling routine knows which constants are possible and only allows these. So unknown constants or constants that are intended for other calls are not accepted. For example:

>eulpsolve("set_verbose", lp, "blabla");

  eulpsolve returned an error:
  BLABLA: Unknown.

>eulpsolve("set_verbose", lp, "GE");

  eulpsolve returned an error:
  GE: Not allowed here.

Note the difference between the two error messages. The first says that the constant is not known, the second that the constant cannot be used at that place.

Constants are case insensitive. Internally they are always translated to upper case. Also when returned they will always be in upper case.

The constant names are the ones as specified in the documentation of each API routine. There are only 3 exceptions, extensions actually. "LE", "GE" and "EQ" in add_constraint and is_constr_type can also be "<", "<=", ">", ">=", "=". When returned however, "GE", "LE", "EQ" will be used.

Some constants can be a combination of multiple constants. For example set_scaling:

>eulpsolve("set_scaling", lp, 3+128);

With the string version of constants this can be done as following:

>eulpsolve("set_scaling", lp, "SCALE_MEAN|SCALE_INTEGERS");

| is the OR operator used to combine multiple constants. There may optinally be spaces before and after the |.

Not all OR combinations are legal. For example in set_scaling, a choice must be made between SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC or SCALE_CURTISREID. They may not be combined with each other. This is also tested:

>eulpsolve("set_scaling", lp, "SCALE_MEAN|SCALE_RANGE");

  eulpsolve returned an error:
  SCALE_RANGE cannot be combined with SCALE_MEAN

Everywhere constants must be provided, numeric or string values may be provided. The routine automatically interpretes them.

Returning constants is a different story. The user must let lp_solve know how to return it. Numerical or as string. The default is numerical:

>eulpsolve("get_scaling", lp)
                  131

To let lp_solve return a constant as string, a call to a new function must be made: return_constants

>eulpsolve("return_constants", 1);

From now on, all returned constants are returned as string:

>eulpsolve("get_scaling", lp)
  SCALE_MEAN|SCALE_INTEGERS

This for all routines until return_constants is again called with 0:

>eulpsolve("return_constants", 0);

The (new) current setting of return_constants is always returned by the call. Even when set:

>eulpsolve("return_constants", 1)
                    1

To get the value without setting it, don't provide the second argument:

>eulpsolve("return_constants")
                    1

In the next part of this documentation, return_constants is the default, 0, so all constants are returned numerical and provided constants are also numerical. This to keep the documentation as compatible as possible with older versions. But don't let you hold that back to use string constants in your code.

Notebooks and Euler files

Euler can execute a sequence of statements stored in files. There are two types. Notebooks and Euler files.

Notebooks contains a number of Euler statements that are stored in a file. They should have the extension *.en and are first loaded in the text window of Euler and then executed. There are some notebook examples with the distribution of lpsolve.

Euler files. If you want to develop longer and more complicated programs, it becomes useful to put all function definitions and all commands into external Euler files. These files should have the extension *.e, and can be loaded into Euler with the load command. Files in the current directory will be found using the name alone. The current directory is the directory, where the current notebook is loaded from or saved to. Otherwise, use the full path the file, or include the directory of the file into the Euler path. Euler files often contain support functions (subroutines) that can be used in your code.

You can also edit these files with your favourite text editor (or notepad).

loadlpsolve.en

Loads the eulpsolve driver in Euler. Also loads Euler files lpsolve.e and lpmaker.e. See further for their usage.

To execute and also see which commands are executed in the debug window, use following commands:

File, Open notebook...
Open loadlpsolve.en
File, Run all Commands in this Notebook

example1.en

Contains the commands as shown in the first example of this article.

example2.en

Contains the commands as shown in the second example of this article.

example3.en

Contains the commands of a practical example. See further in this article.

example4.en

Contains the commands of a practical example. See further in this article.

example5.en

Contains the commands of a practical example. See further in this article.

example6.en

Contains the commands of a practical example. See further in this article.

lpsolve.e

This Euler file uses the API to create a higher-level function called lpsolve. This function accepts as arguments some matrices and options to create and solve an lp model. See the beginning of the file or enter help lpsolve to see its usage:

>load "lpsolve"
>help lpsolve
 LPSOLVE  Solves mixed integer linear programming problems.

   SYNOPSIS: {obj,x,duals} = lpsolve(f,a,b,e,vlb,vub,xint,scalemode,keep)

      solves the MILP problem

              max v = f'.x
                a.x <> b
                  vlb <= x <= vub
                  x(int) are integer

   ARGUMENTS: The first four arguments are required:

            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) = -1  ==> Less Than
                      e(i) =  0  ==> Equals
                      e(i) =  1  ==> Greater Than
          vlb: n vector of lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
         keep: Flag for keeping the lp problem after it's been solved.
               If omitted, the lp will be deleted when solved.

   OUTPUT: A nonempty output is returned if a solution is found:

          obj: Optimal value of the objective function.
            x: Optimal value of the decision variables.
        duals: solution of the dual problem.

Example of usage. To create and solve following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

>load "lpsolve"
>{obj, x}=lpsolve([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2]);
>obj

                     3

>x

                     1
                     2

lpmaker.e

This Euler file is analog to the lpsolve Euler file and also uses the API to create a higher-level function called lpmaker. This function accepts as arguments some matrices and options to create an lp model. Note that this Euler file only creates a model and returns a handle. See the beginning of the file or enter help lpmaker to see its usage:

>load "lpmaker"
>help lpmaker
 LPMAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lpmaker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'.x
          a.x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Example of usage. To create following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

>load "lpmaker"
>lp=lpmaker([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])

                     0

To solve the model and get the solution:

>eulpsolve("solve", lp)

                     0

>eulpsolve("get_objective", lp)

                     3

>eulpsolve("get_variables", lp)

                     1
                     2

Don't forget to free the handle and its associated memory when you are done:

>eulpsolve("delete_lp", lp);

lpdemo.en

Contains several examples to build and solve lp models.

ex.en

Contains several examples to build and solve lp models. Also solves the lp_examples from the lp_solve distribution.

A practical example

We shall illustrate the method of linear programming by means of a simple example, giving a combination graphical/numerical solution, and then solve both a slightly as well as a substantially more complicated problem.

Suppose a farmer has 75 acres on which to plant two crops: wheat and barley. To produce these crops, it costs the farmer (for seed, fertilizer, etc.) $120 per acre for the wheat and $210 per acre for the barley.The farmer has $15000 available for expenses. But after the harvest, the farmer must store the crops while awaiting favourable market conditions. The farmer has storage space for 4000 bushels.Each acre yields an average of 110 bushels of wheat or 30 bushels of barley. If the net profit per bushel of wheat (after all expenses have been subtracted) is $1.30 and for barley is $2.00, how should the farmer plant the 75 acres to maximize profit?

We begin by formulating the problem mathematically. First we express the objective, that is the profit, and the constraints algebraically, then we graph them, and lastly we arrive at the solution by graphical inspection and a minor arithmetic calculation.

Let x denote the number of acres allotted to wheat and y the number of acres allotted to barley. Then the expression to be maximized, that is the profit, is clearly

P = (110)(1.30)x + (30)(2.00)y = 143x + 60y.

There are three constraint inequalities, specified by the limits on expenses, storage and acreage. They are respectively:

120x + 210y <= 15000
110x + 30y <= 4000
x + y <= 75

Strictly speaking there are two more constraint inequalities forced by the fact that the farmer cannot plant a negative number of acres, namely:

x >= 0,y >= 0.

Next we graph the regions specified by the constraints. The last two say that we only need to consider the first quadrant in the x-y plane. Here's a graph delineating the triangular region in the first quadrant determined by the first inequality.

>X = 0.1:0.05:125;
>Y1 = (15000. - 120*X)/210;
>plot2d(X,Y1,bar=1);
>insimg;

Source

Now let's put in the other two constraint inequalities.

>X = 0.1:0.05:38;
>Y1 = (15000. - 120*X)/210;
>Y2 = max((4000 - 110.*X)./30, 0);
>Y3 = max(75 - X, 0.);
>Ytop = min(min(Y1, Y2), Y3);
>plot2d(X,Ytop,bar=1);
>insimg;

Source

The black area is the solution space that holds valid solutions. This means that any point in this area fulfils the constraints.

Now let's superimpose on top of this picture a contour plot of the objective function P.

>X = 0.1:0.05:38;
>Y1 = (15000. - 120*X)/210;
>Y2 = max((4000 - 110.*X)./30, 0);
>Y3 = max(75 - X, 0.);
>Ytop = min(min(Y1, Y2), Y3);
>plot2d(X,Ytop,bar=1);
>n=(1000:1000:9000)';
>plot2d("(n-143*x)/60", add=1, color=2);
>insimg;

Source

The red lines give a picture of the objective function. All solutions that intersect with the black area are valid solutions, meaning that this result also fulfils the set constraints. The more the lines go to the right, the higher the objective value is. The optimal solution or best objective is a line that is still in the black area, but with an as large as possible value.

It seems apparent that the maximum value of P will occur on the level curve (that is, level line) that passes through the vertex of the polygon that lies near (22,53).
It is the intersection of x + y = 75 and 110*x + 30*y = 4000
This is a corner point of the diagram. This is not a coincidence. The simplex algorithm, which is used by lp_solve, starts from a theorem that the optimal solution is such a corner point.
In fact we can compute the result:

>x = [1 1; 110 30] \ [75; 4000]

                21.875
                53.125

The acreage that results in the maximum profit is 21.875 for wheat and 53.125 for barley. In that case the profit is:

>P = [143 60] . x

              6315.625

That is, $6315.625.

Note that these command are in notebook example3.en

Now, lp_solve comes into the picture to solve this linear programming problem more generally. After that we will use it to solve two more complicated problems involving more variables and constraints.

For this example, we use the higher-level Euler file lpmaker to build the model and then some lp_solve API calls to retrieve the solution. Here is again the usage of lpmaker:

 LPMAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lpmaker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'.x
          a.x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Now let's formulate this model with lp_solve:

>f = [143, 60];
>A = [120, 210; 110, 30; 1, 1];
>b = [15000; 4000; 75];
>lp = lpmaker(f, A, b, [-1, -1, -1], [], [], [], 1, 0);
>solvestat = eulpsolve("solve", lp);
>eulpsolve("get_objective", lp)

              6315.625

>eulpsolve("get_variables", lp)

                21.875
                53.125

>eulpsolve("delete_lp", lp);

Note that these command are in notebook example4.en

With the higher-level Euler file lpmaker, we provide all data to lp_solve. lp_solve returns a handle (lp) to the created model. Then the API call 'solve' is used to calculate the optimal solution of the model. The value of the objective function is retrieved via the API call 'get_objective' and the values of the variables are retrieved via the API call 'get_variables'. At last, the model is removed from memory via a call to 'delete_lp'. Don't forget this to free all memory allocated by lp_solve.

The solution is the same answer we obtained before. Note that the non-negativity constraints are accounted implicitly because variables are by default non-negative in lp_solve.

Well, we could have done this problem by hand (as shown in the introduction) because it is very small and it can be graphically presented.
Now suppose that the farmer is dealing with a third crop, say corn, and that the corresponding data is:

cost per acre$150.75
yield per acre125 bushels
profit per bushel$1.56

With three variables it is already a lot more difficult to show this model graphically. Adding more variables makes it even impossible because we can't imagine anymore how to represent this. We only have a practical understanding of 3 dimentions, but beyound that it is all very theorethical.

If we denote the number of acres allotted to corn by z, then the objective function becomes:

P = (110)(1.30)x + (30)(2.00)y+ (125)(1.56) = 143x + 60y + 195z

And the constraint inequalities are:

120x + 210y + 150.75z <= 15000
110x + 30y + 125z <= 4000
x + y + z <= 75
x >= 0,y >= 0, z >= 0

The problem is solved with lp_solve as follows:

>f = [143, 60, 195];
>A = [120, 210, 150.75; 110, 30, 125; 1, 1, 1];
>b = [15000; 4000; 75];
>lp = lpmaker(f, A, b, [-1, -1, -1], [], [], [], 1, 0);
>solvestat = eulpsolve("solve", lp);
>eulpsolve("get_objective", lp)

        6986.842105263

>eulpsolve("get_variables", lp)

                     0
        56.57894736842
        18.42105263158

>eulpsolve("delete_lp", lp);

Note that these command are in notebook example5.en

So the farmer should ditch the wheat and plant 56.5789 acres of barley and 18.4211 acres of corn.

There is no practical limit on the number of variables and constraints that Euler can handle. Certainly none that the relatively unsophisticated user will encounter.Indeed, in many true applications of the technique of linear programming, one needs to deal with many variables and constraints.The solution of such a problem by hand is not feasible, and software like Euler is crucial to success.For example, in the farming problem with which we have been working, one could have more crops than two or three. Think agribusiness instead of family farmer.And one could have constraints that arise from other things beside expenses, storage and acreage limitations. For example:

  • Availability of seed.This might lead to constraint inequalities like xj < k.
  • Personal preferences. Thus the farmer's spouse might have a preference for one variety over another and insist on a corresponding planting, or something similar with a collection of crops; thus constraint inequalities like xi < xj or x1 + x2 > x3.
  • Government subsidies. It may take a moment's reflection on the reader's part, but this could lead to inequalities like xj > k.

Below is a sequence of commands that solves exactly such a problem. You should be able to recognize the objective expression and the constraints from the data that is entered. But as an aid, you might answer the following questions:

  • How many crops are under consideration?
  • What are the corresponding expenses? How much is available for expenses?
  • What are the yields in each case? What is the storage capacity?
  • How many acres are available?
  • What crops are constrained by seed limitations? To what extent?
  • What about preferences?
  • What are the minimum acreages for each crop?
>f = [110*1.3, 30*2.0, 125*1.56, 75*1.8, 95*.95, 100*2.25, 50*1.35];
>A = [120,210,150.75,115,186,140,85; 110,30,125,75,95,100,50; 1,1,1,1,1,1,1; 1,-1,0,0,0,0,0; 0,0,1,0,-2,0,0; 0,0,0,-1,0,-1,1];
>b = [55000; 40000; 400; 0; 0; 0];
>lp = lpmaker(f, A, b, [-1,-1,-1,-1,-1,-1],[10,10,10,10,20,20,20],[100,1.0e30,50,1.0e30,1.0e30,250,1.0e30],[],1,0);
>solvestat = eulpsolve("solve", lp);
>eulpsolve("get_objective", lp)

        75398.04347826

>eulpsolve("get_variables", lp)

                    10
                    10
                    40
        45.65217391304
                    20
                   250
                    20

>eulpsolve("delete_lp", lp);

Note that these command are in notebook example6.en

Note that we have used in this formulation the vlb and vub arguments of lpmaker. This to set lower and upper bounds on variables. This could have been done via extra constraints, but it is more performant to set bounds on variables. Also note that Inf is used for variables that have no upper limit. This stands for Infinity.

Note that despite the complexity of the problem, lp_solve solves it almost instantaneously. It seems the farmer should bet the farm on crop number 6.We strongly suggest you alter the expense and/or the storage limit in the problem and see what effect that has on the answer.

Another, more theoretical, example

Suppose we want to solve the following linear program using Euler:

max 4x1 + 2x2 + x3
s. t. 2x1 + x2 <= 1
x1 + 2x3 <= 2
x1 + x2 + x3 = 1
x1 >= 0
x1 <= 1
x2 >= 0
x2 <= 1
x3 >= 0
x3 <= 2

Convert the LP into Euler format we get:

f = [4, 2, 1]
A = [2, 1, 0; 1, 0, 2; 1, 1, 1]
b = [1; 2; 1]

Note that constraints on single variables are not put in the constraint matrix. lp_solve can set bounds on individual variables and this is more performant than creating additional constraints. These bounds are:

l = [ 0, 0, 0]
u = [ 1, 1, 2]

Now lets enter this in Euler:

>f = [4, 2, 1];
>A = [2, 1, 0; 1, 0, 2; 1, 1, 1];
>b = [1; 2; 1];
>l = [ 0, 0, 0];
>u = [ 1, 1, 2];

Now solve the linear program using Euler: Type the commands

>lp = lpmaker(f, A, b, [-1, -1, -1], l, u, [], 1, 0);
>solvestat = eulpsolve("solve", lp);
>eulpsolve("get_objective", lp)

                   2.5

>eulpsolve("get_variables", lp)

                   0.5
                     0
                   0.5

>eulpsolve("delete_lp", lp);

What to do when some of the variables are missing ?
For example, suppose there are no lower bounds on the variables. In this case define l to be the empty set using the Euler command:

>l = [];

This has the same effect as before, because lp_solve has as default lower bound for variables 0.

But what if you want that variables may also become negative?
Then you can use -1.0e30 as lower bounds:

>l = [-1.0e30, -1.0e30, -1.0e30];

Solve this and you get a different result:

>lp = lpmaker(f, A, b, [-1, -1, -1], l, u, [], 1, 0);
>solvestat = eulpsolve("solve", lp);
>eulpsolve("get_objective", lp)

        2.666666666667

>eulpsolve("get_variables", lp)

       0.6666666666667
      -0.3333333333333
       0.6666666666667

>eulpsolve("delete_lp", lp);

Overview of API routines

Note that everwhere where lp is used as argument that this can be a handle (lp_handle) or the models name.

  • add_column, add_columnex
    • return = eulpsolve("add_column", lp, [column])
    • return = eulpsolve("add_columnex", lp, [column])
    • Both have the same interface from add_column but act as add_columnex
  • add_constraint, add_constraintex
    • return = eulpsolve("add_constraint", lp, [row], constr_type, rh)
    • return = eulpsolve("add_constraintex", lp, [row], constr_type, rh)
    • Both have the same interface from add_constraint but act as add_constraintex
  • add_SOS
    • return = eulpsolve("add_SOS", lp, name, sostype, priority, [sosvars], [weights])
    • The count argument in the API documentation is not needed in Euler since the number of elements is derived from the size of the sosvars and weights matrices. These must have the same size.
  • column_in_lp
    • return = eulpsolve("column_in_lp", lp, [column])
    • No special considerations.
  • copy_lp
    • lp_handle = eulpsolve("copy_lp", lp)
    • No special considerations.
  • default_basis
    • eulpsolve("default_basis", lp)
    • No special considerations.
  • del_column
    • return = eulpsolve("del_column", lp, column)
    • No special considerations.
  • del_constraint
    • return = eulpsolve("del_constraint", lp, del_row)
    • No special considerations.
  • delete_lp
    • eulpsolve("delete_lp", lp)
    • No special considerations.
  • free_lp
    • eulpsolve("free_lp", lp)
    • lp is not changed as in the lpsolve API since it is a read_only input parameter. So it acts the same as delete_lp.
  • get_anti_degen
    • return = eulpsolve("get_anti_degen", lp)
    • No special considerations.
  • get_basis
    • [bascolumn] = eulpsolve("get_basis", lp {, nonbasic})
    • The bascolumn argument in the API documentation is here the return value. The nonbasic argument is optional in Euler. If not provided, then 0 is used.
  • get_basiscrash
    • return = eulpsolve("get_basiscrash", lp)
    • No special considerations.
  • get_bb_depthlimit
    • return = eulpsolve("get_bb_depthlimit", lp)
    • No special considerations.
  • get_bb_floorfirst
    • return = eulpsolve("get_bb_floorfirst", lp)
    • No special considerations.
  • get_bb_rule
    • return = eulpsolve("get_bb_rule", lp)
    • No special considerations.
  • get_bounds_tighter
    • return = eulpsolve("get_bounds_tighter", lp)
    • No special considerations.
  • get_break_at_value
    • return = eulpsolve("get_break_at_value", lp)
    • No special considerations.
  • get_col_name
    • name = eulpsolve("get_col_name", lp, column)
    • column must be provided and is as such not optional. As such no array of names can be returned. This because Euler has no possibility to return string matrices.
  • get_column get_columnex
    • [column, return] = eulpsolve("get_column", lp, col_nr)
    • [column, return] = eulpsolve("get_columnex", lp, col_nr)
    • The column argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_constr_type
    • return = eulpsolve("get_constr_type", lp, row)
    • [constr_type] = eulpsolve("get_constr_type", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • get_constr_value
    • return = eulpsolve("get_constr_value", lp, row {, primsolution})
    • The primsolution argument is optional. If not provided, then the solution of last solve is used.
  • get_constraints
    • [constr, return] = eulpsolve("get_constraints", lp)
    • The constr argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_dual_solution
    • [duals, return] = eulpsolve("get_dual_solution", lp)
    • The duals argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In Euler, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_epsb
    • return = eulpsolve("get_epsb", lp)
    • No special considerations.
  • get_epsd
    • return = eulpsolve("get_epsd", lp)
    • No special considerations.
  • get_epsel
    • return = eulpsolve("get_epsel", lp)
    • No special considerations.
  • get_epsint
    • return = eulpsolve("get_epsint", lp)
    • No special considerations.
  • get_epsperturb
    • return = eulpsolve("get_epsperturb", lp)
    • No special considerations.
  • get_epspivot
    • return = eulpsolve("get_epspivot", lp)
    • No special considerations.
  • get_improve
    • return = eulpsolve("get_improve", lp)
    • No special considerations.
  • get_infinite
    • return = eulpsolve("get_infinite", lp)
    • No special considerations.
  • get_lowbo
    • return = eulpsolve("get_lowbo", lp, column)
    • [return] = eulpsolve("get_lowbo", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • get_lp_index
    • return = eulpsolve("get_lp_index", lp, orig_index)
    • No special considerations.
  • get_lp_name
    • name = eulpsolve("get_lp_name", lp)
    • No special considerations.
  • get_mat
    • value = eulpsolve("get_mat", lp, row, col)
    • [matrix, return] = eulpsolve("get_mat", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix in the first return value. The return code of the call is the second return value.
  • get_max_level
    • return = eulpsolve("get_max_level", lp)
    • No special considerations.
  • get_maxpivot
    • return = eulpsolve("get_maxpivot", lp)
    • No special considerations.
  • get_mip_gap
    • return = eulpsolve("get_mip_gap", lp, absolute)
    • No special considerations.
  • get_nameindex
    • return = eulpsolve("get_nameindex", lp, name, isrow)
    • No special considerations.
  • get_Ncolumns
    • return = eulpsolve("get_Ncolumns", lp)
    • No special considerations.
  • get_negrange
    • return = eulpsolve("get_negrange", lp)
    • No special considerations.
  • get_nonzeros
    • return = eulpsolve("get_nonzeros", lp)
    • No special considerations.
  • get_Norig_columns
    • return = eulpsolve("get_Norig_columns", lp)
    • No special considerations.
  • get_Norig_rows
    • return = eulpsolve("get_Norig_rows", lp)
    • No special considerations.
  • get_Nrows
    • return = eulpsolve("get_Nrows", lp)
    • No special considerations.
  • get_obj_bound
    • return = eulpsolve("get_obj_bound", lp)
    • No special considerations.
  • get_objective
    • return = eulpsolve("get_objective", lp)
    • No special considerations.
  • get_orig_index
    • return = eulpsolve("get_orig_index", lp, lp_index)
    • No special considerations.
  • get_origcol_name
    • name = eulpsolve("get_origcol_name", lp, column)
    • [names] = eulpsolve("get_origcol_name", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • get_origrow_name
    • name = eulpsolve("get_origrow_name", lp, row)
    • As such no array of names can be returned. This because Euler has no possibility to return string matrices.
  • get_pivoting
    • return = eulpsolve("get_pivoting", lp)
    • No special considerations.
  • get_presolve
    • return = eulpsolve("get_presolve", lp)
    • No special considerations.
  • get_presolveloops
    • return = eulpsolve("get_presolveloops", lp)
    • No special considerations.
  • get_primal_solution
    • [pv, return] = eulpsolve("get_primal_solution", lp)
    • The pv argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_print_sol
    • return = eulpsolve("get_print_sol", lp)
    • No special considerations.
  • get_ptr_constraints
    • Not implemented.
  • get_ptr_dualsolution
    • Not implemented.
  • get_ptr_primal_solution
    • Not implemented.
  • get_ptr_sensitivity_obj, get_ptr_sensitivity_objex
    • Not implemented.
  • get_ptr_sensitivity_rhs
    • Not implemented.
  • get_ptr_variables
    • Not implemented.
  • get_rh
    • return = eulpsolve("get_rh", lp, row)
    • [rh] = eulpsolve("get_rh", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • get_rh_range
    • return = eulpsolve("get_rh_range", lp, row)
    • [rh_ranges] = eulpsolve("get_rh_range", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • get_row get_rowex
    • [row, return] = eulpsolve("get_row", lp, row_nr)
    • [row, return] = eulpsolve("get_rowex", lp, row_nr)
    • The row argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In Euler, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_row_name
    • name = eulpsolve("get_row_name", lp, row)
    • [names] = eulpsolve("get_row_name", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • get_scalelimit
    • return = eulpsolve("get_scalelimit", lp)
    • No special considerations.
  • get_scaling
    • return = eulpsolve("get_scaling", lp)
    • No special considerations.
  • get_sensitivity_obj, get_sensitivity_objex
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = eulpsolve("get_sensitivity_obj", lp)
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = eulpsolve("get_sensitivity_objex", lp)
    • The objfrom, objtill, objfromvalue, objtillvalue arguments in the API documentation are here the return values. Note that Euler allows the return of fewer variables. For example if only objfrom and objtill are needed then the call can be [objfrom, objtill] = eulpsolve("get_sensitivity_obj", lp). The unrequested values are even not calculated.
    • Since the API routine doesn't calculate the objtillvalue value at this time, Euler always returns a zero vector for this.
    • The return code of the call is the last value.
    • get_sensitivity_obj and get_sensitivity_objex are both implemented, but have the same functionality.
  • get_sensitivity_rhs, get_sensitivity_rhsex
    • [duals, dualsfrom, dualstill, return] = eulpsolve("get_sensitivity_rhs", lp)
    • [duals, dualsfrom, dualstill, return] = eulpsolve("get_sensitivity_rhsex", lp)
    • The duals, dualsfrom, dualstill arguments in the API documentation are here the return values. Note that Euler allows the return of fewer variables. For example if only duals is needed then the call can be [duals] = eulpsolve("get_sensitivity_rhs", lp). The unrequested values are even not calculated.
    • The return code of the call is the last value.
    • get_sensitivity_rhs and get_sensitivity_rhsex are both implemented, but have the same functionality.
  • get_simplextype
    • return = eulpsolve("get_simplextype", lp)
    • No special considerations.
  • get_solutioncount
    • return = eulpsolve("get_solutioncount", lp)
    • No special considerations.
  • get_solutionlimit
    • return = eulpsolve("get_solutionlimit", lp)
    • No special considerations.
  • get_status
    • return = eulpsolve("get_status", lp)
    • No special considerations.
  • get_statustext
    • return = eulpsolve("get_statustext", lp, statuscode)
    • No special considerations.
  • get_timeout
    • return = eulpsolve("get_timeout", lp)
    • No special considerations.
  • get_total_iter
    • return = eulpsolve("get_total_iter", lp)
    • No special considerations.
  • get_total_nodes
    • return = eulpsolve("get_total_nodes", lp)
    • No special considerations.
  • get_upbo
    • return = eulpsolve("get_upbo", lp, column)
    • [upbo] = eulpsolve("get_upbo", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • get_var_branch
    • return = eulpsolve("get_var_branch", lp, column)
    • [var_branch] = eulpsolve("get_var_branch", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • get_var_dualresult
    • return = eulpsolve("get_var_dualresult", lp, index)
    • No special considerations.
  • get_var_primalresult
    • return = eulpsolve("get_var_primalresult", lp, index)
    • No special considerations.
  • get_var_priority
    • return = eulpsolve("get_var_priority", lp, column)
    • [var_priority] = eulpsolve("get_var_priority", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • get_variables
    • [var, return] = eulpsolve("get_variables", lp)
    • The var argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_verbose
    • return = eulpsolve("get_verbose", lp)
    • No special considerations.
  • get_working_objective
    • return = eulpsolve("get_working_objective", lp)
    • No special considerations.
  • guess_basis
    • [basisvector, return] = eulpsolve("guess_basis", lp, [guessvector])
    • In the API, element 0 of guessvector is not used and values start from element 1. In Euler, there is no unused element in the matrix.
    • In the API, element 0 of basisvector is not used and values start from element 1. In Euler, there is no unused element in the matrix.
  • has_BFP
    • return = eulpsolve("has_BFP", lp)
    • No special considerations.
  • has_XLI
    • return = eulpsolve("has_XLI", lp)
    • No special considerations.
  • is_add_rowmode
    • return = eulpsolve("is_add_rowmode", lp)
    • No special considerations.
  • is_anti_degen
    • return = eulpsolve("is_anti_degen", lp, testmask)
    • No special considerations.
  • is_binary
    • return = eulpsolve("is_binary", lp, column)
    • [binary] = eulpsolve("is_binary", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • is_break_at_first
    • return = eulpsolve("is_break_at_first", lp)
    • No special considerations.
  • is_constr_type
    • return = eulpsolve("is_constr_type", lp, row, mask)
    • No special considerations.
  • is_debug
    • return = eulpsolve("is_debug", lp)
    • No special considerations.
  • is_feasible
    • return = eulpsolve("is_feasible", lp, [values] {, threshold})
    • The threshold argument is optional. When not provided, the value of get_epsint will be taken.
  • is_free is_unbounded
    • return = eulpsolve("is_free", lp, column)
    • return = eulpsolve("is_unbounded", lp, column)
    • [free] = eulpsolve("is_free", lp)
    • [free] = eulpsolve("is_unbounded", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • is_infinite
    • return = eulpsolve("is_infinite", lp, value)
    • No special considerations.
  • is_int
    • return = eulpsolve("is_int", lp, column)
    • [int] = eulpsolve("is_int", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • is_integerscaling
    • return = eulpsolve("is_integerscaling", lp)
    • No special considerations.
  • is_maxim
    • return = eulpsolve("is_maxim", lp)
    • No special considerations.
  • is_nativeBFP
    • return = eulpsolve("is_nativeBFP", lp)
    • No special considerations.
  • is_nativeXLI
    • return = eulpsolve("is_nativeXLI", lp)
    • No special considerations.
  • is_negative
    • return = eulpsolve("is_negative", lp, column)
    • [negative] = eulpsolve("is_negative", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • is_piv_mode
    • return = eulpsolve("is_piv_mode", lp, testmask)
    • No special considerations.
  • is_piv_rule
    • return = eulpsolve("is_piv_rule", lp, rule)
    • No special considerations.
  • is_presolve
    • return = eulpsolve("is_presolve", lp, testmask)
    • No special considerations.
  • is_scalemode
    • return = eulpsolve("is_scalemode", lp, testmask)
    • No special considerations.
  • is_scaletype
    • return = eulpsolve("is_scaletype", lp, scaletype)
    • No special considerations.
  • is_semicont
    • return = eulpsolve("is_semicont", lp, column)
    • [semicont] = eulpsolve("is_semicont", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • is_SOS_var
    • return = eulpsolve("is_SOS_var", lp, column)
    • [SOS_var] = eulpsolve("is_SOS_var", lp)
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Euler matrix.
  • is_trace
    • return = eulpsolve("is_trace", lp)
    • No special considerations.
  • is_use_names
    • return = eulpsolve("is_use_names", lp, isrow)
    • No special considerations.
  • lp_solve_version
    • versionstring = eulpsolve("lp_solve_version")
    • The eulpsolve API routine returns the version information in 4 provided argument variables while the Euler version returns the information as a string in the format major.minor.release.build
  • make_lp
    • lp_handle = eulpsolve("make_lp", rows, columns)
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
  • print_constraints
    • eulpsolve("print_constraints", lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Euler (Windows) this means that the output is not shown.
    • The same information can also be obtained via eulpsolve("get_constraints", lp). This shows the result on screen.
  • print_debugdump
    • return = eulpsolve("print_debugdump", lp, filename)
    • No special considerations.
  • print_duals
    • eulpsolve("print_duals", lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Euler (Windows) this means that the output is not shown.
    • The same information can be obtained via eulpsolve("get_dual_solution", lp). This shows the result on screen.
  • print_lp
    • eulpsolve("print_lp", lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Euler (Windows) this means that the output is not shown.
  • print_objective
    • eulpsolve("print_objective", lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Euler (Windows) this means that the output is not shown.
    • The same information can be obtained via eulpsolve("get_objective", lp). This shows the result on screen.
  • print_scales
    • eulpsolve("print_scales", lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Euler (Windows) this means that the output is not shown.
  • print_solution
    • eulpsolve("print_solution", lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Euler (Windows) this means that the output is not shown.
    • The same information can also be obtained via eulpsolve("get_variables", lp). This shows the result on screen.
  • print_str
    • eulpsolve("print_str", lp, str)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Euler (Windows) this means that the output is not shown.
  • print_tableau
    • eulpsolve("print_tableau", lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Euler (Windows) this means that the output is not shown.
  • put_abortfunc
    • Not implemented.
  • put_logfunc
    • Not implemented.
    • However, the eulpsolve driver sets a log function to redirect the output of lpsolve from stdout (which is not visible in Windows Euler) to the command window of Euler. As such, all reported output can be seen in Euler. How much output is seen is controlled by the verbose level that can be defined by set_verbose or can be specified in the read_ routines. Note that at least Euler version 5.8 is needed to see this information on the command window. Older versions will not print information on the command window.
  • put_msgfunc
    • Not implemented.
  • read_basis
    • [ret, info] = eulpsolve("read_basis", lp, filename)
    • No special considerations.
  • read_freemps, read_freeMPS
    • lp_handle = eulpsolve("read_freemps", filename {, options})
    • lp_handle = eulpsolve("read_freeMPS", filename {, options})
    • In the lpsolve API, read_freemps needs a FILE handle. In Euler it needs the filename and thus acts the same as read_freeMPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_lp, read_LP
    • lp_handle = eulpsolve("read_lp", filename {, verbose {, lp_name}})
    • lp = eulpsolve("read_LP", filename {, verbose {, lp_name}})
    • In the lpsolve API, read_lp needs a FILE handle. In Euler it needs the filename and thus acts the same as read_LP.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not provided then NORMAL is used.
    • lp_name is optional. If not provided then no name is given to the model ("").
  • read_mps, read_MPS
    • lp_handle = eulpsolve("read_mps", filename {, options})
    • lp_handle = eulpsolve("read_MPS", filename {, options})
    • In the lpsolve API, read_mps needs a FILE handle. In Euler it needs the filename and thus acts the same as read_MPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_params
    • return = eulpsolve("read_params", lp, filename {, options })
    • options is optional.
  • read_XLI
    • lp_handle = eulpsolve("read_XLI", xliname, modelname {, dataname {, options {, verbose}}}
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • dataname is optional. When not provided, "" (NULL) is taken. "" is taken as NULL.
    • options is optional. When not provided, "" is taken.
    • verbose is optional. If not specified, then NORMAL is used.
  • reset_basis
  • set_basisvar
    • eulpsolve("set_basisvar", lp, basisPos, enteringCol)
    • No special considerations.
  • set_add_rowmode
    • return = eulpsolve("set_add_rowmode", lp, turnon)
    • No special considerations.
  • set_anti_degen
    • eulpsolve("set_anti_degen", lp, anti_degen)
    • No special considerations.
  • set_basis
    • return = eulpsolve("set_basis", lp, [bascolumn], nonbasic)
    • In the API, element 0 of bascolumn is not used and values start from element 1. In Euler, there is no unused element in the matrix.
  • set_basiscrash
    • eulpsolve("set_basiscrash", lp, mode)
    • No special considerations.
  • set_bb_depthlimit
    • eulpsolve("set_bb_depthlimit", lp, bb_maxlevel)
    • No special considerations.
  • set_bb_floorfirst
    • eulpsolve("set_bb_floorfirst", lp, bb_floorfirst)
    • No special considerations.
  • set_bb_rule
    • eulpsolve("set_bb_rule", lp, bb_rule)
    • No special considerations.
  • set_BFP
    • return = eulpsolve("set_BFP", lp, filename)
    • No special considerations.
  • set_binary
    • return = eulpsolve("set_binary", lp, column, must_be_bin)
    • return = eulpsolve("set_binary", lp, [must_be_bin])
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds
    • return = eulpsolve("set_bounds", lp, column, lower, upper)
    • return = eulpsolve("set_bounds", lp, [lower], [upper])
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds_tighter
    • eulpsolve("set_bounds_tighter", lp, tighten)
    • No special considerations.
  • set_break_at_first
    • eulpsolve("set_break_at_first", lp, break_at_first)
    • No special considerations.
  • set_break_at_value
    • eulpsolve("set_break_at_value", lp, break_at_value)
    • No special considerations.
  • set_col_name
    • return = eulpsolve("set_col_name", lp, column, name)
    • No special considerations.
  • set_column, set_columnex
    • return = eulpsolve("set_column", lp, col_no, [column])
    • return = eulpsolve("set_columnex", lp, col_no, [column])
    • Both have the same interface from set_column but act as set_columnex
  • set_constr_type
    • return = eulpsolve("set_constr_type", lp, row, con_type)
    • return = eulpsolve("set_constr_type", lp, [con_type])
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_debug
    • eulpsolve("set_debug", lp, debug)
    • No special considerations.
  • set_epsb
    • eulpsolve("set_epsb", lp, epsb)
    • No special considerations.
  • set_epsd
    • eulpsolve("set_epsd", lp, epsd)
    • No special considerations.
  • set_epsel
    • eulpsolve("set_epsel", lp, epsel)
    • No special considerations.
  • set_epsint
    • eulpsolve("set_epsint", lp, epsint)
    • No special considerations.
  • set_epslevel
    • eulpsolve("set_epslevel", lp, epslevel)
    • No special considerations.
  • set_epsperturb
    • eulpsolve("set_epsperturb", lp, epsperturb)
    • No special considerations.
  • set_epspivot
    • eulpsolve("set_epspivot", lp, epspivot)
    • No special considerations.
  • set_free set_unbounded
    • return = eulpsolve("set_free", lp, column)
    • return = eulpsolve("set_unbounded", lp, column)
    • No special considerations.
  • set_improve
    • eulpsolve("set_improve", lp, improve)
    • No special considerations.
  • set_infinite
    • eulpsolve("set_infinite", lp, infinite)
    • No special considerations.
  • set_int
    • return = eulpsolve("set_int", lp, column, must_be_int)
    • return = eulpsolve("set_int", lp, [must_be_int])
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lowbo
    • return = eulpsolve("set_lowbo", lp, column, value)
    • return = eulpsolve("set_lowbo", lp, [values])
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lp_name
    • return = eulpsolve("set_lp_name", lp, name)
    • In Euler, when you name a model, this name can be used everywhere where lp is specified. This to access the model via the name instead of via a handle.
  • set_mat
    • return = eulpsolve("set_mat", lp, row, column, value)
    • return = eulpsolve("set_mat", lp, [matrix])
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows to set the whole matrix (all rows/columns) at once. This is the most performant way to provide the constraint matrix. The matrix must be two-dimentional.
  • set_maxim
    • eulpsolve("set_maxim", lp)
    • No special considerations.
  • set_maxpivot
    • eulpsolve("set_maxpivot", max_num_inv)
    • No special considerations.
  • set_minim
    • eulpsolve("set_minim", lp)
    • No special considerations.
  • set_mip_gap
    • eulpsolve("set_mip_gap", lp, absolute, mip_gap)
    • No special considerations.
  • set_negrange
    • eulpsolve("set_negrange", negrange)
    • No special considerations.
  • set_obj
    • return = eulpsolve("set_obj", lp, column, value)
    • return = eulpsolve("set_obj", lp, [values])
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables. It is then the same as set_obj_fn
  • set_obj_bound
    • eulpsolve("set_obj_bound", lp, obj_bound)
    • No special considerations.
  • set_obj_fn, set_obj_fnex
    • return = eulpsolve("set_obj_fn", lp, [row])
    • return = eulpsolve("set_obj_fnex", lp, [row])
    • Both have the same interface from set_obj_fn but act as set_obj_fnex
    • In the API, element 0 is not used and values start from element 1. In Euler, there is no unused element in the matrix.
  • set_outputfile
    • return = eulpsolve("set_outputfile", lp, filename)
    • In the API description it says that setting filename to NULL results in writing output back to stdout. In Euler under Windows, output to stdout it not shown. However it results in closing the file. Use "" to have the effect of NULL.
  • set_outputstream
    • Not implemented.
  • set_pivoting
    • eulpsolve("set_pivoting", lp, pivoting)
    • No special considerations.
  • set_preferdual
    • eulpsolve("set_preferdual", lp, dodual)
    • No special considerations.
  • set_presolve
    • eulpsolve("set_presolve", lp, do_presolve {, maxloops})
    • The maxloops argument is optional in Euler. If not provided, then infinite is used.
  • set_print_sol
    • eulpsolve("set_print_sol", lp, print_sol)
    • No special considerations.
  • set_rh
    • return = eulpsolve("set_rh", lp, row, value)
    • return = eulpsolve("set_rh", lp, [values])
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows. Note that in this case, the value of row 0 is not specified in the matrix.
  • set_rh_range
    • return = eulpsolve("set_rh_range", lp, row, deltavalue)
    • return = eulpsolve("set_rh_range", lp, [deltavalues])
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_rh_vec
    • eulpsolve("set_rh_vec", lp, [rh])
    • In the API, element 0 is not used and values start from element 1. In Euler, there is no unused element in the matrix.
  • set_row, set_rowex
    • return = eulpsolve("set_row", lp, row_no, [row])
    • return = eulpsolve("set_rowex", lp, row_no, [row])
    • Both have the same interface from set_row but act as set_rowex
    • In the API, element 0 is not used and values start from element 1. In Euler, there is no unused element in the matrix.
  • set_row_name
    • return = eulpsolve("set_row_name", lp, row, name)
    • No special considerations.
  • set_scalelimit
    • eulpsolve("set_scalelimit", lp, scalelimit)
    • No special considerations.
  • set_scaling
    • eulpsolve("set_scaling", lp, scalemode)
    • No special considerations.
  • set_semicont
    • return = eulpsolve("set_semicont", lp, column, must_be_sc)
    • return = eulpsolve("set_semicont", lp, [must_be_sc])
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_sense
    • eulpsolve("set_sense", lp, maximize)
    • No special considerations.
  • set_simplextype
    • eulpsolve("set_simplextype", lp, simplextype)
    • No special considerations.
  • set_solutionlimit
    • eulpsolve("set_solutionlimit", lp, simplextype)
    • No special considerations.
  • set_timeout
    • eulpsolve("set_timeout", lp, sectimeout)
    • No special considerations.
  • set_trace
    • eulpsolve("set_trace", lp, trace)
    • No special considerations.
  • set_upbo
    • return = eulpsolve("set_upbo", lp, column, value)
    • return = eulpsolve("set_upbo", lp, [values])
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_use_names
    • eulpsolve("set_use_names", lp, isrow, use_names)
    • No special considerations.
  • set_var_branch
    • return = eulpsolve("set_var_branch", lp, column, branch_mode)
    • return = eulpsolve("set_var_branch", lp, [branch_mode])
    • In Euler, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_weights
    • return = eulpsolve("set_var_weights", lp, [weights])
    • No special considerations.
  • set_verbose
    • eulpsolve("set_verbose", lp, verbose)
    • No special considerations.
  • set_XLI
    • return = eulpsolve("set_XLI", lp, filename)
    • No special considerations.
  • solve
    • result = eulpsolve("solve", lp)
    • No special considerations.
  • str_add_column
    • Not implemented.
  • str_add_constraint
    • Not implemented.
  • str_set_obj_fn
    • Not implemented.
  • str_set_rh_vec
    • Not implemented.
  • time_elapsed
    • return = eulpsolve("time_elapsed", lp)
    • No special considerations.
  • unscale
    • eulpsolve("unscale", lp)
    • No special considerations.
  • write_basis
    • eulpsolve("write_basis", lp, filename)
    • No special considerations.
  • write_freemps, write_freeMPS
    • return = eulpsolve("write_freemps", lp, filename)
    • return = eulpsolve("write_freeMPS", lp, filename)
    • In the lpsolve API, write_freeMPS needs a FILE handle. In Euler it needs the filename and thus acts the same as write_freemps.
  • write_lp, write_LP
    • return = eulpsolve("write_lp", lp, filename)
    • return = eulpsolve("write_LP", lp, filename)
    • In the lpsolve API, write_LP needs a FILE handle. In Euler it needs the filename and thus acts the same as write_lp.
  • write_mps, write_MPS
    • return = eulpsolve("write_mps", lp, filename)
    • return = eulpsolve("write_MPS", lp, filename)
    • In the lpsolve API, write_MPS needs a FILE handle. In Euler it needs the filename and thus acts the same as write_mps.
    • No special considerations.
  • write_XLI
    • return = eulpsolve("write_XLI", lp, filename {, options {, results}})
    • No special considerations.

Extra Euler routines

These routines are not part of the lpsolve API, but are added for backwards compatibility. Most of them exist in the lpsolve API with another name.

  • [names] = eulpsolve("get_col_names", lp)
    • The same as get_col_name. Implemented for backwards compatibility.
  • [constr_type] = eulpsolve("get_constr_types", lp)
    • The same as get_constr_type. Implemented for backwards compatibility.
  • [int] = eulpsolve("get_int", lp)
    • The same as is_int. Implemented for backwards compatibility.
  • return = eulpsolve("get_no_cols", lp)
    • The same as get_Ncolumns. Implemented for backwards compatibility.
  • return = eulpsolve("get_no_rows", lp)
    • The same as get_Nrows. Implemented for backwards compatibility.
  • name = eulpsolve("get_objective_name", lp)
    • The same as get_row_name with row=0. Implemented for backwards compatibility.
  • [row_vec, return] = eulpsolve("get_obj_fn", lp)
    [row_vec, return] = eulpsolve("get_obj_fun", lp)
    • The same as get_row with row 0. Implemented for backwards compatibility.
  • name = eulpsolve("get_problem_name", lp)
    • The same as get_lp_name. Implemented for backwards compatibility.
  • [costs] = eulpsolve("get_reduced_costs", lp)
    • The same as get_dual_solution. Implemented for backwards compatibility.
  • [names] = eulpsolve("get_row_names", lp)
    • The same as get_row_name. Implemented for backwards compatibility.
  • [obj, x, duals, return] = eulpsolve("get_solution", lp)
    • Returns the value of the objective function, the values of the variables and the duals. Implemented for backwards compatibility.
    • The return code of the call is the last value.
  • value = eulpsolve("mat_elm", lp)
    • The same as get_mat. Implemented for backwards compatibility.
  • [handle_vec] = eulpsolve("print_handle")
    • Returns a vector with open handles. Can be handy to see which handles aren't closed yet with delete_lp or free_lp.
  • lp_handle = eulpsolve("read_lp_file", filename {, verbose {, lp_name}})
    • The same as read_LP. Implemented for backwards compatibility.
  • lp_handle = eulpsolve("get_handle", lp_name)
    • Get the handle for this model from the models name. If an unknown model name is given (or already deleted), -1 is returned.
  • return_constants = eulpsolve("return_constants"[, return_constants])
    • Returns the setting of return_constants and optionally sets its value.

Compile the eulpsolve driver

Under Windows, the eulpsolve Euler driver is a dll: eulpsolve.dll
Under Unix/Linux, the eulpsolve Euler driver is a shared library.: eulpsolve.so
This driver is an interface to the lpsolve library lpsolve55.dll/liblpsolve55.so that contains the implementation of lp_solve. lpsolve55.dll/liblpsolve55.so is distributed with the lp_solve package (archive lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). The eulpsolve Euler driver is just a wrapper between Euler and lp_solve to translate the input/output to/from Euler and the lp_solve library.

Compilation

The eulpsolve Euler driver is written in C. To compile this code, under Windows the Microsoft visual C compiler is needed and under Unix/Linux the standard cc compiler.
The needed commands are in a batch file/script.
Under Windows it is called cvc.bat, under Unix/Linux ccc.
In a command prompt/shell, go to the lpsolve Euler directory and enter cvc.bat/sh ccc and the compilation is done. The result is eulpsolve.dll/eulpsolve.so.

See also Using lpsolve from MATLAB, Using lpsolve from O-Matrix, Using lpsolve from Sysquake, Using lpsolve from Scilab, Using lpsolve from Octave, Using lpsolve from FreeMat, Using lpsolve from Python, Using lpsolve from Sage, Using lpsolve from PHP, Using lpsolve from R

doc/Euler2.jpg0000644000175000017500000015746411164443742012156 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?M1|̿ I_| k%|AmG 5FOxٵGU5gV߇4 gя/0<ɼFUI`JS oi?O SFG5M;B&rĻM)2CuZ8K\ %O0G`/8T(ᡖԌUxDa8߃ƏEWυ18c 8l[S1Ϊa!O **c3}Rg|.#FtυDhn~;x_gvOO6/ßGjV8mou7:{[oM%}?bOj{:%s}>umsI=?uueEs)na i~G\\!ObwF{W Gq^7x:!"| B";Ũ>*x ,=uY|z5)СXl濷9PC,?vxkg"4o7^g^:?h/=MW}ώ>>ڎ/zƁaZ|^ -mA|YA/RId>~_k\hW-|е}?Sc|>+o7tzi⎡oۋRé/|*>(xa˸36[Z8~e9Ź[,0UyfSy^d7[-_b|=7 8.Bx?vxkg"4o7^c_?WW 4q?>i>IӴ[V?"lOa׼\5 =u?Mm7/i|g ~쳦k*829 }K SG ;S/Rbs:UUhx<̩bc) (K b)`"}vxkg"4o7G. ,]FH:|?xfÏ7<1@VIӛEF:e5 Ŵ^kZMlnO_5O a]?5KO< WWuixLҵ &Pҵ;5(mk:9{;cx[0 ~M>|FLʆ&XZL&'FJ*pV3RQZ^m~UybhXxjRuIaքjP]QTVR*rʤM. ,]F% ѿ}/&&JUg>_O% ѿ(hϯ4Sn?_Naeg⦏'7uе6O [K]Os?Z &Nӯ<+~+m?>gH__ !Ꮙ~i4/3|@,Z["Uc.xDN9.`lnVWy.ṣWuSV9|9WT+is<."' NQNXі L,q.[Nyl*bW_O1':~F3 8N"TQ^U#/ .Y>ƨ% ??z.||X>6|kg/w/cOOҿg7t5}ju_ ?U[Ǻ΃e?^7zEϋiq|ǟ #$ױA&MGOOGOnx㏀<)f=?6Ӈng U|&mR͡Cejefv %',,,ʕ**5*CZq .\jWsUZX ฃ/1uㅄ'o,XΒt`, R+S_^>]}Q KP?V)kW>2[#"P) O W>|COC<+/0SCh~xŚM+?4-7 }gTMggj:ge\K(V .ў'4:caCQͰetqPJ&-ЫN_+<:"~m 8O%Lo`1V7UxT'$>9% ??|7Dg'SMic6{H8j<)ïf7\Ţok%6<;4:[Yȓ2j&~O_=_š|. o^"]B>+sj: kWtm?Jiڗ %]]iA=,o ׫J '^"YZ3+ҧ CJ8.|HEzkßf:(Tө^J>BiRcS%^jTjgCj^>]}WxT7Ŀ獴?mx?>|%ON4Oz~hi:eH~ק^^[\+|⟉:WOi'\?s~ۧ)ngxK/4#Oյ KOj:u^[[G,ɓ}GSE~b]ߵ>jYؿki,?g\ٟ=~YϴT9=nǶCj^>]}Wa{_?]8ߋb uo{|;5[Þ&7_[>gUҼI/^?x?5o  -[Z|o}]7÷lo RN/n a -xb̷::uQeTp0f] NuJaO͸ 2\D8b(M<7?SJ(bՕ8eCmIʊjn]_/ .Y>ƨ% ??rHڿJ&m 5/>M -j{k@Eց&<7)Դ2( jGSJ0} 2?~+|h~?,i>/u? ]}Q K>ğ>!w i=oZ\~*PW4V#SNuWMWG};M-Ě||a+/_[/oݧuٯ|s"W0m?}sjKrQ|r6oU bMV.G[30r~a^ _2JF# F7SU'>ae!B'1UNiWW)WaaySu*R^u(b!K?xow!O5Qc¥F9hN;g|Wux#~|D'~&i-8_ h_4%uּzm%tBmKAz֓tf57Κ,԰@澏 C*Ў'& ??w{Ÿ!.hC&7Wd OOgOy#]gm#)H'& ??w{Ÿ!.hC&7Wd OOgOy#]gm#)H'w> AG> |np\>TX1*K_ur`c{o  g~|ZymK}$-$AA/?S_qNMƸNἫ~.lV77XY9 P9M:TO(u9U\yY8k;Fsf\Eͱ8 42ʆLԖ#9cTR I974Z5^TnfU\2~Ъ#'^],]\mDp-i)_VɣWDQzYxf<qڈe܄T_rq_jχB@{?&F, ?ZRD$;dZ";?4l_2q%eYv fa L#,;V*s|<lOX_dOG fXf|QBtcjVO %^S5b,E:\V\<\~_W[:a]yY?h# r@k6o-_|?"%Rng sW;IQa_ F|K/7|Hρ46Ҿ x[}vėbŢ?nOI;_G~8|Qh ǖ9&t}H$nma>|5.~]:kgkj6i5=~e~:fw)_3z \MR:9t?|SK*xZ?b1(ѤZ47 ³X8cszir~ޥ5NRN3_ws|5O^7՗=x).m3&yK,Hcyz0fnO|hVl~rpd4qAb09;C)d|6o)|f?%4ydOq+ -ϞF%攴1rMz燿-S6p^. ۬5)ȏpX#mm nkH̸aH!1m CͫKU)fxXҡJd#R5*5F.u)N:pq18뉜_MPhRfYJRU0RHaj8œT.2?X]Qm,Sq{;Amk3;W`ؿ[uo$ޏCGSvVZU.Cs ƗZ~"K5Y%uw@.!inh6|^PĿP!v.0q 8ʗaWaZ|3΍|,:RRvH[UŜ#qUՖ+2:0xjì=,N:l-zs7g{ +2~!J彅o?E{" +(<Ul?%^~kO~=55⟄-|"R5-߄}RIIimuUa5ؽ~~_g\x3Q^4m|xJų T~+>!?._uALR$zmts1c~ڢqx'1‘_I ,p|G$>ψ8_2"+Qs^!q\sØ7z00vTb#^,W_=Y.q;$,Q[ IڕGFSZ5F\kJt'F9K/ /  I~34uz:nr%NJDҬw9⿃/x& s'[Zſ犾)|@lX1ׂ(ǚq/Ih[F͎kշ ܷypO3wŬ*G+#Q~>~Y뜝'O~8+/ c^8=PkĸOXis9s\6$˱y.gq6]93^TaR8ѧF0~w8(q.'ɨS|GVʥ,6*iRapYnQ FF,3JuSW_b_ #㿊nG PW?o|]jcνo%qiVLeĽ{ᯊtOKԣ<9/ß(?/|]H ̾?œ@ਟ~~h?I ڗ[O,Ƨ (7yq7Þh2?zѠl[8=rg933|GUOqF9BVJUo_^EbrX=zgّql*3[-`t<^A5S<+FJ8M9ƼPfqJtA}ON +w.YWz_ƟZ|"|>Xx|y퉯|N+Qշ_𽎃%B*~_Z?[O|:|S+7NxbF{x]u xTgFѼ%hx"?9 F/ٳ+7 ?f{ w8ʳ3fMCjg%>\kepbTh1Z28J:|0YSU8̱x1)O+36IΰL=9*u㣌NSྐྵOgW?ltwm={U>/.4w ,w4_?pfk[dm|v爣K-{.n/1>'|:*2>OW5o ׊4_⯇jzީwZ-챯[rZGq_+7 ?f{Þh2?p]/o } x3K8"p$cÞ1k ўj5Q 3/CuuO|^>Zf{[wᾹմ,,׆/o9&dR fA~s_?g=D4 q_ >9p \6_wb0ie|\Sx8L|\\jbj:_u|3?*|7P;*n?{nUj~+׬UEV%j$|H5ozTZVk_QKQ_|aIdߴ'_o M# 㯊_xF 1g|;Ru/~#xk{_Vo4~͟=Ye6߯8>]晦o9xln/2q] 9^t+ej,0m X?Ӳ Ap #Ϊ,g_c"~Mzkx=<ƴ' fA ٗ|3N=#JGoxwŖ٧t_< 6/xcB4?U^%E~Mg!g?ho_ZWuHW5O?-245i:{-\:umGWӢos_?g=?_Vo4~͟1[>p.ue9SF}⦡b]U0ԧP`_Rjʔy'ǹ~/-Y8|f;+WYVI.)aFq+ks(# ѝJUXiJi3Wh7ŻagOƛ/ gGSӾ]/O = |r?Ms 7g+4?ZT 1 0Xx/7B{|hk~?;=+,e~-|P𝏂<'_]YYub ;ZD0Iwk:md?4%3k )D>4M$㿉_ON~| /)RоsUơY,dx?9 F/ٛ_+'~fo{**_q9 Y\/Yq֎)?u:iVU%:|L~FXuIp]o.ESco8V#$iTsnϣ (93N2}|\Fs~׿O~#Ծ5k?o?Zg#}S''ASY4QxQE dž.Dz_} _ڣb,:k_}s7UiIcO?fW/Sw&4v*K.-x~ԢѴo?οVO3h:Y?3ݯ| DX |O~Y[mῄ)a?Z?|!t杯k~ Mx_ :x?m--beF|dgyĚ/z/lɼOi 9?o~0xk]s_??7=?οVO3k ^O1? O aq|OJ֧U CXj1ElzqƖ+岩q=HcxlG^֯xftg,] Sּa{-kmJ{/[dž5x$k_ǖ:o/^ZS|[qv h1>|C'>|2 kxN־*|B)M}kX7SO֧m7GKos_??7=?οVO3k; ѮMq7xiaxj ֏D-cFW_0R&[u14poQp3z3ub)CXa)ժ,LixBU| )K?l/?gZ} Ǎ|{u7 GGSm;Ǿ8wP^~*c^=<%vߴOt|b?e?MDž>" =ګAA ZZW'ƫG_@_Gľ3cukÝଟguџf_--Υ)~9XLYZ$p WW|+/2LcSq`qCjxa<akqSs*G;'QSU&7j': /1f?!ĿK)sv/3aS|sn|MkkKMEu^'eπ63"NJ>~?n_#cT?J5ZOÏ xW~8|F ^^SҾ ѼoeΣGp>Re|Z~R<_ړ7aǬiw.'+Hq{j7tZNgtl. #[DL%t =3O6M{ xm >0q/oq,m,{S\W_ҷx,V."`3 e'*_QiV3U׭Q9aBnThl?u3|%c"ߋZ5ZM[R~*Tzԭ~/k_i>6ex}>|]{A񗋵O~xco?zNĞuџfG9 F/ٛ}(qv3l-lT8+w\uŹ_S*ͰL.#uNX&^63QmSXW˸/eY1xl]:ogRN6ҡV,-_(? {sotG/?dO ,->{=^lLJ ;ḵYp% jXK)d+iRa`ai.Ǎ8_.87.%be,\A&9*T̪c+siND8}|^3eOG#S9?~Ý?ggbs?W?0G<rK_4}?IN|?+Z57O_o+O4أi;?f{}xKkS? %OWd#S9?M<+5vѝ?߳G=?V3hGL77?~3 _4}?IN|?+Z57O_o+O4أi;?f{}xKkS? %OWd#S9?M<+5vѝ?߳G=?V3hGL77?~3 _4}?IN|?+ihG2?^4jWIB0%_?\No uOğ?e햏x/Iu2h~= .uYk6ҋ}>L].>d źW1 Yjڧ{Wѵ}#\үw^*Kcxw5_xGKMWEhn\[_&dJ]G31KR(!"8j"*q~kVMg `)b~8 r3.#hV|SOxY GVrbaYa(O7 0߇lE<2,&q|Gq1 JqɌ+zmwR5eF 5hrzo>xS׍,?f~>?b x;~*{/j-߈~muoEO閆O i쬭>،ת|6־2i/-8FCsQ뵸^^s/KnH ~pAv[x?`)Ư#Budğ Ie*QHoKxxψ^fy/e5kW3ցV>9|fͤ^|?' iמq rvv'/? e φ_|c㟍ca=5>χi=Cm%3O𵭅j^uZmfѩcUD,~ UGx _9מMPbW"Ge/ܠ|o(R3\A<2ɣx#?^ejxʞ}. Y7EO _K *c,˖ю9^xss\ҩG3<>.l%Tg,XS59ºQ.xҊ^p<]q?e%Ā0~FrGCr}jź?/F^ G:ޫyk*gZA2!Q"yMͷ϶ʹN?->_xT|=\A;7ٷL𞟢xCH4>ͤI𿄴Fݝ}?$'w7s8##=1uF{e،P^ \7J+pOcZ'[mZzJ)T҇< ĹKxOq>Sf?5IԴ*6.,E?{:9g/5υcU6rjP>=#͵Ǘwo ?fh o#G{㜿ŏp|_1 FBPTQ%\:Ο述WK{3|vQvai~җaݳ 42YO/ke}q<Yx|Ma&żck*tͩ?׼G{gq7MU_Mjf?~ӕxW!7?X]w5wKp2~ྞe |]~QE(W|\KHO|?MqM2>4Լ boMi>6?ޝkco>y[A+7>+CFXDQZRjxz0֩:ӧӧ&ܖ\n/F3KT+jʦ&<5 ta֯Vuk֧JNrrkh$~(5?L|FLͿÞ;`>wOڧ12I?j#_$o?p6y?ϳ@#? :h$~(5?L|FLg>so00X03>~5?L|FLOڧ12ͿÞ`>wOڧ12I?j#_$o?p6y?ϳ@#.G61Z?6gx_?5OkA 'SDk~ĘЙS R.P4RT*-OݜemjE>$jʝQSMgWFԍԄ{Yn-7 $Oc7Be~?FgI _8?<wٗ`?;g}E| 'SDk~ĘЙG$Oc7Be8?<wه|#Q $Oc7Be~?FgI lmfFxG4W~?FgI IT&>#&Q9swy}?u@_?IT&>#&Q 'SDk~ĘЙG|a?a`?;g}E| 'SDk~ĘЙ\#Ӟ1|]|SvTX:SOo ~~!Ʃ _k}o{<nk8Nq{)ʜfeVm7͢j2o2V]TR#q.*Q+dYVoMFM}CE| 'SDk~ĘЙG$Oc7BeW|a?fFxG4W~?FgI IT&>#&Q9swy}?u@_?IT&>#&Q 'SDk~ĘЙG|a?a`?;g}E| 'SDk~ĘЙG$Oc7Be8?<wه|#Q $Oc7Be~?FgI lmfFxG4W~?FgI ?9m:S-?I׈<%_jix񏊴oz/kg[ϯk?|-xFMLJԥF*zaIe$ݒoFx-Njsӥ ԩ/g_,!)J\SodOڧ12I?j#_$oʯͿÞX03>~5?L|FLOڧ12ͿÞ`>wOڧ12I?j#_$o?p6y?ϳ@#? :h$~(5?L|FLg>so00X03> ٭|>߄;/XOic]7__c?>Xmy)\_{O ץ{>z8+B,(VUҟ%Hq(˖q{J*I <oPر46_}!ioڃůٯO^5Kad7yG8[. (OԂ~%L'1_@~ɟp>$V+ο \xA G@EQEQEQEQEQE O-CgAl_  wW# A5Y}iŨ~:m_;aynw& 3/W& 3bN,*nePQEvQ@Q@Q@Q@y[ O4پ 폵f|E> ߋH5@?Kyۿ_ڿۿi7ۿ;,ψg;w ?7c#,'?EWYQEQEQEQE/>6og?>*x2?kםH5ߵb GCe|9~ڿgOX}: OA>(h³w&?`332v?_bQEuEPEPEPEP߲gfkUφa?~ ٰ|=չAW=&ɫ~o\n;O[Ua?gŸMo?Kӓߵ_`ANk N~-ͿӵyU8?)|WO_7yG8[. (OԂ~%L'1YZu7ÒSu_:U[֍]"gXu>.D/ZmoI=WDž>67d ຟT_ao? ~]xb~+~̟vFvokGxcvo`%LJ͜V,=y[FWGn5} \ӽR( ( ( ( (<iŨ~:m_;aynw& 3/W2>#۾M??7+gw/3__.???f|E IŀO ̿c (Т((((?Kyۿ_ڿۿi7ۿ;,ψg;w  o?>3w۾x2KWwC>fw'>׿C_'~. 9'Lo5?eR2(;((((e|9~ڿgOX}: OA>(h³wWL4پ[??W^w ?~'V~.fqf_.+LT=(((((LV߾  ?w+/=?hk?տf7_|7_'Wr0j3Ve&;4IAb;_ו!i jfʯ)Kp2{ ɻ?iqQE~| ^;?|=__~D>:.<}~Z|.e|Y|>мu;BV|g7޹omm7co.|1w_kW<7=ֹyR<17:}aq\Xivj3u׏46[,,u«iTq:%f칪SJwdk' *u0TƄNʵ  I{e7B-*S`QElyǿ jf[8_O ?0g_J  {[_z>y~| 6&G?th^8 {hm n?$???I?w ?´gEcWB/F-}8T7/<]e{ZWVaXЯ~OmJ^Nksr\ܱ~U}N7G;sZ?m_[''"o῱ O7 k?_&FG]~8'|B5_y?^w;QY}C@XO&fe/%W/>rv??|Z?`g _ٿd/'* 9};Rھ-|TNx3߲ag?w?D_cS4~ߴ '&2|EI #?S? #k؟k+;_I O'5jH??z| м??Wh?gMg &gHo;^>,'Q3-~ (%wy×n/)M?aW(hH> '%?/?؟?AK?H?~?G%?Bg XeAE}oH?I? ` _J}?_}Ծ ?_4/c3b+7_]ះ/j_SCWů fy?|AO/bg®gQG0?j?fe/%W |??7p^x,7|TG½:o KiG.x(o5Agyڗk⦟lwvٞO,_ef ?؟"x2>#۾M??7+gw/3__.???f|E `0>XOQO,,}OO_ C8w>rv??|Z?`g _ٿd/'* 9};Rھ-|TNx3߲ag?w?D}MG;2+_q 9};Rھ-|TNx3߲ag?w?DKφ~w|AO_?*i_'kEP п?_?gyڗk⦟lwvٞO,_ef ?؟"^|3ۼK hjcSO?;_~;o'/?~_OU  (MG̷$y?_}Ծ ?_4/c3b+7_]ះ/j_SCWů fy?|AO/bg®gQG0?j?fe/%W>rv??|Z?`g _ٿd/'* 9};Rھ-|TNx3߲ag?w?D}>,'Q3-~ (%y×n/)M?aEuC@XO&ٙo ?IC/φ~w|AO_?*i_'krv??|Z?`g _ٿd/'*}C@XO&f[BP~K<ះ/j_SCWů fy?|AO/bg®gy×n/)M?aEP п?_?gyڗk⦟lwvٞO,_ef ?؟#>st??wO Ro}w4+J|A/'> ¾gξ?yi}?~?Sa_'?feAnO?]ɏ`~bb,,r%?wgyڗk⦟lwvٞO,_ef ?؟"^|3ۼK hjcSO?;_~;o'/?~_OU  +5@_J}ǟ|3ۼK hjcSO?;_~;o'/?~_OU />rv??|Z?`g _ٿd/'*}C@XO&f[BP~K<ះ/j_SCWů fy?|AO/bg®gy×n/)M?aEP п?_?gyڗk⦟lwvٞO,_ef ?؟"^|3ۼK hjcSO?;_~;o'/?~_OU  (MG̷$|&ɫ~o\n/;O[ߴ sgfkUφb~ n'WNFF}ܰOpioڃůٯO^5?MjfH?i J_lg d<wӋ+DH+տ_:U~,,u((((()A?߱CQ>/#>_k"~.IK@+o6^ ƍ v;Úg#6"wz(e񗅵]BJ~7^> ~,|S O>M#?~wP ZG4go=CLln`_'n_ ~_ 7şh?hݎs){o6':|;EuS/%gJh-VoY֚-5knFhMJzϙW%ʧRJ*QI7'vN?(g/k|g~Οu/c=3?x6'7xW,]xk^o?OCP((((?Kyۿ_ڿۿi7ۿ;,ψg;w  o?>3w۾x2KWwC>fw'>׿C_'~. 9'Lo5?eR2(;((((e|9~ڿgOX}: OA>(h³wWL4پ[??W^w ?~'V~.fqf_.+LT=(((((LV߾  ?wO6?h*d5oٟ {_{w꿠'UaɽC?K?ӟ&ߵgv*Cӯ&ߵ__ij)|V}|/? ǃnq\@QE) _zg_ڪ^<5??~xWZcw`xo|o[S|w<+egƺŧ?k?^sx Cu#!og^?egⅾmrwF_xgi<>բ,j: :NxiIn-bj*t׍βH(FT84ӔeM)7 <$x^YUGC/t0Φ#(gP * F%R*3:JέOo+p(((((({ 8QbC1x7x=W? ?jQbmbT/7'y㯃^|U/|?/eᢀ?k??>g|AVo4f:OSxW_o~z^uN}M^[ 'v r Em[>$~7wcŞ|?MAm ~¿ |]ߏ?{fh |Ɣ|> xO/m~1κV㏃)`uoQa\X}ytlҼ]j~&vg3KafΟOeƿV_ < 7_!ˬk,kg>@? _>ZA/l&[|9®")(5kѳmk:4E=ڒVmYbP㈓qRNjt(TӼ\Qi(?%}W?;'~2G__O-mcgLt^xvn~A>}RV?ocn#/'&ºf1С>l̿@~#wO_#z´a/weig?| 3y?}KP'=KZigwOeZ> ;B2O?ϳ=-¿wnw^ijnh}Úlnڿ>"hykw$y?}KP'=KZigwOeZ> Ͼs+ ?  J HxkKn ?"Ju/5_-_~;վ3 6װ/0caCK oa22>~#wO_#z´a/weig?| 3y?}KP'=KZigwOeZ> f;(ϼw3/d3(?%}W?;'~2G__O-mcgLt^xvn~A>}RV?ocn#/'&º>G1A`С>l̿@~#wO_#z´a/weig?| 3y?}KP'=KZigwOeZ> ;B2O?ϳ=O_:?|_ O?},|D|?/?WEGm'/CھG/i >>_">ho?g+f <> +ǩ|+O?NLW G?]3ۼujcԾ'd&Xۿ+K?_𮏮L_c?(ϼw3/d3+&^}Úln-h|Te~ ï;O?ٿ_jۿk+?3ۼujcԾ'd&Xۿ+K?_ǏGxr9gë8'7½_.Ņ w&xMҴK7]['|391?QLOc̳ ܱ_,̿>~#wO_#z´a/weig?| 3y?}KP'=KZigwOeZ> f;(ϼw3/d3(?%}W?;'~2G__O-mcgLt^xvn~A>}RV?ocn#/'&º>G1A`С>l̿@~#wO_#z´a/weig?| 3y?}KP'=KZigwOeZ> ;B2O?ϳ=O_:?|_ O?},|D|?/?WEGm'/CھG/i >>_">ho?g+f <> +ǩ|+O?NLW G?]3ۼujcԾ'd&Xۿ+K?_𮏮L_c?(ϼw3/d3Ͽd5oٟ {k?տf7_|7_'S̓ r0j3Vca!`~_Mjf?ӵx6?ZNW_8cX~=?4l(Q?R @oE??οU_/ ?j0J( ( ( ( ( ( ( ( ( ٣czOƿsGtA 75#wGD|kf_@k k_T)KWڵ;+DN};=wo ߋH5@?Kyۿ_ڿۿi7ۿ;,ψg;w ?7c#,'?EWYQEQEQEQE/>6og?>*x2?kםH5ߵb GCe|9~ڿgOX}: OA>(h³w&?`332v?_bQEuEPEPEPEP߲gfkUφb~ ~n#;&ɫ~o\n/;O[ߴ Ua?gxMw8;ioڃůٯO^5_Mjf?ӵx85Ra1? ǃnq\@QE( _zg_ڪ@oE??οU%Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@O 9< M|@ᗃ<;o.|Ho9'<9/_?x/*N_~o# O׈,xA֣Q<m;]?~*xFյ= 4}KF5bl;:o(h³wWL4پ[??W^w ?~'V~.fqf_.+LT=(((((LV߾  _w_5hd5oٟ {_{{꿠'UaɽC?Kӯ&ߵ__ikN~-~kp+})|V].GcMQcN/ˈ(#;_cp>3koWi?~+i>']~5j`ᾟ°i.~&xi5ƕOa @Z>"/?$x#S_SW!Q/{״ O;Wլ>ߤ]Sm|"9aO߱}W|Aelj~*3_?v lfo$Aoeet^)ԒoOs]O5oo.|1w_kW<7=ֹyR<17:}aq\Xivj3u׏46[Ň9ն"Ue6MX~Y(<29+TniCj<+OϓsaqUl!l}gghΗykz0E*PLws O^hm/"IAk>2%4F? xM4O KFluA;ǶuO>// &j~7?fώj+}2Q/GZ|HEq5kψNjuB_|.a\g~ZW??;'~__w*mlh|LRXM8&>[1CuYo&^h~3A۾ :{7W}67ww>_M?ZVE &O?|Lgϓo/?qfXLb[>'SޗxOů:| 3C} /K?®/Xwg%WxocCg,^ _ӷuYo&/<;y? k>Ǧ+N3?.W ?bY@͡,̷՟xOů:| 3C} /K?®/Xwg%WxocCg,S5>_~ɟj߳?W>+fV_&3ٿ|s<ko~5mQ,?#/7agou$kk;_׍!ioڃůٯO^5_M~+>Oc7yG8[. (Ԃ/=[QegU_ _zg_ڪ?(((((((((((((( k61]}oYy^#8xmW.umg3 ~ޟ/>gYh c1🉴ye  %+ ~8xB, w;;Q'=o=|\tOk_ A$|ìBx0㟇?( ( a7ۿAKgjc<awOoW$? ށ^2>fw~? l_3C⧃,>NyiP_' ?YLOřȻ`X1P (Т((((3M[g~5u1x?k?տf7_|7_'Wr0j3Ve&; -N~-~k; :mPص5Ư)Kp2{ ɻ?iqQE~~S 헠hrS៊fodm?~6x_|;x o+7/ w|w^G3?5όB_4U?e!`gkMP/{R: OQ!e{?@oE??οUqPin}H{5Iӏ45*§j%*tg 1sbJfM˸~9eh0K ]oeK&1XK̰.jW¥V:WQE|QEQEQEQEQEQEQEQEQEQEQEQEQEQEWN/sOUּAςAZJ.<9|l5u xAfOs#V>x/l5?`yo⦡cw?~w+efwC؟~]|h#NW⫏%?#\xQOeNO_?orO6 ð<#\ oo8}eAx7矯ωwA_? ~*jg?'k<sºWo< G%X~ ?53 ]x+7ۿ@Lw?7̿/y3Ö?n߈//MCa.W^ _??h3Ͼ,|X?6_by|TG*\X]\xgg?iV[o&O?~3 yϰsM % ;ui7+ Cw؟|QgL|1Q?1?[|,ʞekb__|O~Լyo⦡cw?~w+efwC؟~\^|Lۼ7 gjcKSP?;_~˟?;׈?~_OZ? . +A8O"o̿/y3Ö?n߈//MCa.W^ _??h3yo⦡cw?~w+efwC؟~]QɎ'Vy_~>&xrv|%y?`e _ٿk/'-<9c;MھT<Nx2OuߵnhxC?K91*2ZX~ ?53 ]x+7ۿg,~i_?W_ \iAbhg wQG&;pE[_}yK_?yo⦡cw?~w+efwC؟~\^|Lۼ7 gjcKSP?;_~˟?;׈?~_OZ? . (Nx{+fV_@?9O5r>2{?~_Mjf?ӵx6?ZNW_8cX~=?4l(Q?R @oE??οU_/ ?j0J( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (: ^W|u_x~6_4ox;>ux~*mx{sg> е{;=SFt]GKmmn`)W_S ; |?4OC⶗|$ 5SxW|eom} b'|sNTW??xWǾώ o>4xzΝ? ¾#ӭx>!o4{yghΗyujuյ+tWL4پ[??W^w ?~'V~. a7ۿAKgjc<awOoW$? ܘob,E銇QEvQ@Q@Q@Q@?~ɟj߳?W>+fV_&3ٿ|s<ko~5WQ,?/7agou$kk;_׍!ioڃůٯO^5NJ_3?cMQcN/ˈ( VY|YUW%?+9ZH.~?|7X?Xlkw3Fs&V|Ka};]wzM2_nqh~)K~>'Ƴ^# OIi:΍i\XjNaqo}j67 ʹ*;g h2|NVM)Ponh:1X{LN.zzaeB&4B1WP3ZTHIQZEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPU)P &Yxo]3Fo> xž ] 9#k &HjSx_?m_  2|+>&/34 Aqcymsg}oyktGþ,t[¾2𮭬Sz6gTg  YA~? tD-_*|G⟄Lwfw~? l_3C⧃,>NyiP_' ?YLOřȻ`X1P (Т((((3M[g~5u1x?k?տf7_|7_'Wr0j3Ve&; -N~-~k; :mPص5Ư)Kp2{ ɻ?iqQE~|'oG⧍_!\_i6b~6C{š$~s_??ǯ_M|OOӿ]|t3H?௏xu^1o?ß0xs{2>fw~? l_3C⧃,>NyiP_' ?YG1?3̲cܱ_3̿/ xOů:| 3C} /K?®/Xwg%WxocCg,_@G_擷>2/ϻ<#wk_#zo·a;3 eihy 3)yO_=7[fhwO wxOů:| 3C} /K?®/Xwg%WxocCg,_@Q|_?w/k<;y? k>Ǧ+N3?.W ?b ۼ_tjc~g'dy_x+KC]_}>G_ϡ?1s̿?g~ZW??;'~__w*mlh|L^x3w?n~-|A}MVٟ?og}a]/;w?>& (~;C>2/ϻ>~?տf7_|7_'W͇3M[g~5u1x>˟r0j3V|e&; -N~-~k; :mPص5Ư)Kp2{ ɻ?iqQE~/ ?jkտ_:T`QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE} ~?wgA/_tgF| ;ՍωR͵ WgXhƝxz~ xW~,пG~_?cC0erx{ڇ?j;/|3şW ~\9s5?|P~[ +fV_&3ٿ|s<ko~5WQ,?/7agou$kk;_׍!ioڃůٯO^5NJ_3?cMQcN/ˈ( VY|YUW쇉?oۯs/Fᯀ?fq_u?YړV+G/wҵi? '|O|b/+[vO'#\%>/xI/_SX ]\wFxVѭ RI.!ӠloWjMSOS &NsOfSmIGnͲ\6/kJq8RzbU)R*U*}Q]̅Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@5T*xⷈ?~?A?RJ׵I5Om| :7*x!5<=/ _|GwӬmwY_S G Gy?4OxN|$ 5leo~nkO xWUti >K j(P/ |ܶ璽k ؜69ӥnn^yG7̯=ωwA_? ~*jg?'k<sºWo< G%X~ ?53 ]x+7ۿ쾿'?`,_yW|Lۼ7 gjcKSP?;_~˟?;׈?~_OZ? ./>&xrv|%y?`e _ٿk/'-_n hat?g@g,~i_?W_ \iAbhg qy3Ö?n߈//MCa.W^ _??h3pSG<+0~~&5h?< ^,Lх[o<{BoLj< |Rx>~-|e{AϟA'¿Co3@76wFwH|; Nռ+/ υuM.(#U/w3}o8Wtjw ;O(((3M[g~5u1x?}ehk?տf7_|7_'Wr0j3Ve&; -N~-~k; :mPص5Ư)Kp2{ ɻ?iqQE~/ ?jkտ_:T`QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE~U=; ay1?iwOҬ[Ҿk'oEMWnk 'v|]b~EQEQE&3ٿ|s<ko~5ɟj߳?W>Z]¿qjsWee&; -N~-~k; :mPص5ƴpRa1? ǃnq\@QE(S{~Q Ww?/ _ >ņi >Ojލ]w^_L.o"C5?Io٧tkW{!u=cC״=_i5 'Yѵm>k SI,.-F{;9ṶXeGoMzF'/9ρw|ab~<7']Iծ]C]Z|Cf#ִ/ xS“ &GT $/?MK?h/8ʷ-l:GMNj|άq!ƵF(Vrsr>2p 5ަ31x8ҎQ׭8ʦ6nSQ]Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@}?ן`ڃq xY^,`/u;]O<x'~#sjz;[!o xG?/~ 5o_~?ϟcB׵> w"z9 a[Ѵxg~ZW??;'~__w*mlh|LRXM8&>[1CuYo+fV_@?9O5r>2{?~<6?Z?O~ӢCӟ&ߵo?^UNJ_3?cMQcN/ˈ( VY|YUW_(gY(((((((((((((((((((((q?^*~.?<1Ou#N_hw 9\pxwKG|A|=x+X4?_5E"Z  ~~? tK_*9gl_Lw xsMguoiG4~Zfaz}SEQE&3ٿ|s<le Q_&3ٿ|s<ko~5WQ,?/7agou$kl|AN_wu$kk;_׍_ӃR ad<wӋ+DH+տ_:U~,,u((((((((((((((((((((((??*>*R|f'G?N_<+y⫯ڟe?ik9_O?x^*ώ ox/ xzΣxO^mx>!l}gghΗykz0E* OO*;g|@Ӿ<+'𯄼'Jм#m^*Ux֧m]xúw5 ; QE|&ɫ~o\n/;O[ߴ sgfkUφb~ n5WQ,?/7agou$kk;_׍!ioڃůٯO^5NJ_3?cMQcN/ˈ(#'n }?<q/ÿh~:6]_f|j%?3fqKj rO[`H>2 `O'l$xAC`I 6#<<%,+i<)McZ? n|)6y.G֓7x;iIZ<8 D|>+=aK&_~(_ H4Z|LO}~1^>$ӵ¾G.*k(:~JTiQ:0-YU(5'N.gaid35CX8 O1fJZt"ҝWQ(+(Oz+(z+(){j]e SzD?=%i[_~K~ ~x/6KG?6&(P^jjIJJV*ĕ5J7i rj/26mV5Y<i|KE^4ڄz\ }7R9J#7 NQRpvjQnVVif2pVbס M )PFYSz2NJT(ӄMs?({ KHoK:x~aAj 0#m|+[Ũkrx{Ǿ*~ x^׌|YX= eI,?2?g_xؿ_#u_@7~ڶ~_jz~k_w[G4mGJմGᏅ4OL,O;Y9uc8x??><߲[oL$'Q䒔`))I-m-zx_<7Rp$G NIh%&ou$kk;_׍!ioڃůٯO^5_8cX~:|wӋ+DH(((((((((((((((((((((((((+<kn5|wO6?h*پ3?1_\)%%gH-o&'! ?qχuc:[:l?~7v82T_Gَ~t¾јIZ(}ƞza?K3lUB\?0?fF֗# sFa%uEџ=ah8>o^6_[g;oV|9fWG~δWß3#wE/?͞wn_p|5mdlT;a??dh~ј:E5f:i{%5Yl;'Rl?0?fw?a??dh>lKn?8?,.'-+/# sFa'sGF6N֊(_Fk4K_"\Mm_u_?0?fw?a??dh3__LlOwa90͓u# sFa'sE/7O/O9ǯz4/|AOx'@; ӆqqM߳ٔW>ybs+Wg3 :4.0fu*qNSM&N f get_lp_name

get_lp_name

Gets the name of the lp.

char *get_lp_name(lprec *lp);

Return Value

get_lp_name returns the name of the lp.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_lp_name returns the name of the lp.
Giving the lp a name is optional. The default name is "Unnamed".

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  char *name;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  name = get_lp_name(lp); /* will be "Unnamed" since no name was set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_lp_name

doc/set_bb_floorfirst.htm0000644000175000017500000000654110311063514014510 0ustar renerene set_bb_floorfirst

set_bb_floorfirst

Specifies which branch to take first in branch-and-bound algorithm.

void set_bb_floorfirst(lprec *lp, int bb_floorfirst);

Return Value

set_bb_floorfirst has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

bb_floorfirst

Specifies which branch to take first in branch-and-bound algorithm. Can by any of the following values:

BRANCH_CEILING (0) Take ceiling branch first
BRANCH_FLOOR (1) Take floor branch first
BRANCH_AUTOMATIC (2) Algorithm decides which branch being taken first

Remarks

The set_bb_floorfirst function specifies which branch to take first in branch-and-bound algorithm. This can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
The default is BRANCH_AUTOMATIC (2).
Note that this setting can be overruled by a user routine to choose the branch. See put_bb_branchfunc.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_bb_floorfirst(lp, BRANCH_AUTOMATIC);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_bb_floorfirst, set_var_branch, get_var_branch, set_var_weights, get_var_priority, put_bb_branchfunc

doc/lp_solve_5.5.0.14.chw0000644000175000017500000010066411204607666013604 0ustar renereneITSF`59] |{ "|{ "`8?aT .!"T Uncompressed MSCompressed{7FC28940-9D31-11D0LZXC Cd;)X44 )/'absolute valuesadd_column add_columnexadd_constraint'add_constraintex4add_lag_con Aadd_SOS NBasis Factorization Packages[Calling the lpsolve API from your applicationhChanges from version 4 to version 5.1uChanges from version 5.1 to version 5.5column_in_lp copy_lp CPLEX lp filesdefault_basis del_columndel_constraintdelete_lpDIMACS maximum flow problemsDIMACS minimum assignment problemsDIMACS minimum cost flow problemsDownloaddualize_lpExternal Language Interfaces+Formulation of an lp model in lpsolve8free variablesEfree_lpRFrequently Asked Questions_get_anti_degenlget_basisy%get_basiscrashget_bb_depthlimitget_bb_floorfirstget_bb_ruleget_bounds_tighterget_break_at_valueget_col_nameget_columnget_columnexget_constr_typeget_constr_valueget_constraintsget_dual_solution "get_epsb!/get_epsd"<get_epsel#Iget_epsint$Vget_epsperturb%cget_epspivot&pget_improve'}get_infinite(get_lambda)get_lowbo*get_lp_index+get_lp_name,get_Lrows-get_mat.get_max_level/get_maxpivot0get_mip_gap1get_nameindex2 get_Ncolumns3get_negrange4&get_nonzeros53get_Norig_columns6@get_Norig_rows7Mget_Nrows8Z!get_obj_bound9gget_objective:tget_orig_index;get_origcol_nameget_origrow_name<get_pivoting=get_presolve>get_presolveloops?get_primal_solution@get_print_solAget_ptr_constraintsget_ptr_dual_solution get_ptr_lambda)get_ptr_primal_solution@get_ptr_sensitivity_objBget_ptr_sensitivity_objexB*get_ptr_sensitivity_rhs 7get_ptr_variablesCDget_rhDQget_rh_rangeE^get_rowFkget_row_name<xget_rowexFget_scalelimitGget_scalingHget_sensitivity_objBget_sensitivity_objexBget_sensitivity_rhs get_simplextypeIget_solutioncountJget_solutionlimitKget_statusLget_statustextM8Z$get_timeoutNget_total_iterO!get_total_nodesP.get_upboQ;get_var_branchRHget_var_dualresult Uget_var_primalresult@bget_var_prioritySoget_variablesC|get_verboseTget_working_objectiveUGNU LESSER GENERAL PUBLIC LICENSEGNU MathProgguess_basisVhas_BFPWhas_XLIXInfeasible modelsinteger variablesIntroductionis_add_rowmodeY is_anti_degenZis_binary[%is_break_at_first\2is_constr_type]?is_debug^Lis_feasible_Yis_infiniteafis_intbsis_integerscalingcis_lag_tracedis_maximeis_nativeBFPfis_nativeXLIgis_negativehis_obj_in_basisiis_piv_modej#is_piv_rulekis_presolvelis_scalemodemis_scaletypenis_semicontois_SOS_varp)is_traceq6is_unbounded`Cis_use_namesrPlag_solves]LINDO lp filesjLinear programming basicswLinear Programming FAQlp file formatlp_solve API referencelp_solve commandlp_solve Yahoo grouplp_solve_versiontlpsolve distributed filesLPSolve IDEmake_lpumps bas file formatmps file formatMPS_writefileexvPresolve print_constraintsw-print_debugdumpx:print_dualsyGprint_lpzTprint_objective{aprint_scales|nprint_solution}{print_str~print_tableauput_abortfuncj*%put_bb_branchfuncput_bb_nodefuncput_logfuncput_msgfuncQuick startratio'sread_basisread_freemps read_freeMPS read_lp$ read_LP1 read_mps> read_MPSK read_paramsX read_XLIe reset_basisr reset_params resize_lp scaling semi-continuous variables sensitivity set_add_rowmode set_anti_degen set_basis set_basiscrash set_basisvar set_bb_depthlimit set_bb_floorfirst set_bb_rule set_BFP( set_binary5 set_boundsB set_bounds_tighterO set_break_at_first\ set_break_at_valuei set_col_namev set_column j 'set_columnex set_constr_type set_debug set_epsb set_epsd set_epsel set_epsint set_epslevel set_epsperturb set_epspivot set_improve set_infinite set_int, set_lag_trace9 set_lowboF set_lp_nameS set_mat` set_maximm set_maxpivotz set_minim set_mip_gap set_negrange set_obj set_obj_bound set_obj_fn set_obj_fnex set_obj_in_basis set_outputfile set_outputstream set_pivoting set_preferdual set_presolve# set_print_sol0 set_rh= set_rh_rangeJ set_rh_vecW set_rowd set_row_nameq set_rowex~ j"!set_scalelimit set_scaling set_semicont set_sense set_simplextype set_solutionlimit set_timeout set_trace set_unbounded set_upbo set_use_names set_var_branch set_var_weights' set_verbose4 set_XLIA solveN special ordered sets[ str_add_columnh str_add_constraintu str_add_lag_con  str_set_obj_fn str_set_rh_vec time_elapsed unscale Usefull links Using lpsolve from AMPL Using lpsolve from Euler Using lpsolve from FreeMat Using lpsolve from Java Using lpsolve from MATLABUsing lpsolve from OctaveUsing lpsolve from O-MatrixUsing lpsolve from PHP+~ jUsing lpsolve from Python8Using lpsolve from REUsing lpsolve from SageRUsing lpsolve from Scilab_Using lpsolve from Sysquakelwrite_basisywrite_freempsvwrite_freeMPSvwrite_lpwrite_LPwrite_lpexwrite_mpsvwrite_MPSvwrite_paramswrite_XLIXpress lp filesZimplonstraintu str_add_lag_con  str_set_obj_fn str_set_rh_vec time_elapsed unscale Usefull links Using lpsolve from AMPL Using lpsolve from Euler Using lpsolve from FreeMat Using lpsolve from Java Using lpsolve from MATLABUsing lpsolve from OctaveUsing lpsolve from O-MatrixUsing lpsolve from PHP+~ j>get_basiscrashget_obj_bound9get_timeoutNis_piv_rulekput_bb_branchfuncset_columnexset_scalelimitUsing lpsolve from Python $bFVOf/'ITSPT  j].!"TPMGL^/ /$HHTitleMap! /$OBJINST 4/$WWAssociativeLinks//$WWAssociativeLinks/PROPERTY:/$WWKeywordLinks//$WWKeywordLinks/BTREEL/$WWKeywordLinks/DATA /$WWKeywordLinks/MAP>J/$WWKeywordLinks/PROPERTYk ::DataSpace/NameList4<(::DataSpace/Storage/MSCompressed/Content,::DataSpace/Storage/MSCompressed/ControlData)::DataSpace/Storage/MSCompressed/SpanInfo/::DataSpace/Storage/MSCompressed/Transform/Listp&_::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/i::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/ResetTablealp_solve_5.5.0.14@F@F doc/set_int.htm0000644000175000017500000000600510237176662012461 0ustar renerene set_int

set_int

Set the type of the variable. Integer or floating point.

unsigned char set_int(lprec *lp, int column, unsigned char must_be_int);

Return Value

set_int returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be set. It must be between 1 and the number of columns in the lp.

must_be_int

TRUE (1) if the variable must be integer, FALSE (0) if not.

Remarks

The set_int function defines if a variable must be integer or not. Default a variable is not integer. The argument must_be_int defines what the status of the variable becomes. From the moment there is at least one integer variable in the model, the Branch and Bound algorithm is used to make these variables integer. Note that solving times can be considerably larger when there are integer variables. See integer variables for a description about integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_int(lp, 1, TRUE); /* sets variable 1 to integer */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_int, is_binary, set_binary

doc/index.html0000644000175000017500000000121610740225426012266 0ustar renerene lp_solve reference guide <body> You browser does not support frames.<br> Click <a href="menu.htm">here</a> to load menu </body> doc/read_params.htm0000644000175000017500000001065710252424336013271 0ustar renerene read_params

read_params

Read settings from a parameter file.

unsigned char read_params(lprec *lp, char *filename, char *options);

Return Value

Returns TRUE (1) if parameters could be read, else FALSE (0).

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

filename

Filename to read the parameters from.

options

Optional options. Can be:
-h header: Read parameters at specified header. By default this is Default

Remarks

lp_solve parameters (options) are read from a parameter file. This file has an ini-format as used by Windows applications. All parameters are read from a header. This is by default [Default]. The header can be specified in the options parameter. Other headers are ignored.

Example parameter file:

[Default]
; lp_solve version 5.5 settings

anti_degen=ANTIDEGEN_FIXEDVARS + ANTIDEGEN_STALLING + ANTIDEGEN_INFEASIBLE
basiscrash=CRASH_NONE
improve=IMPROVE_DUALFEAS + IMPROVE_THETAGAP
maxpivot=250
negrange=-1e+006
pivoting=PRICER_DEVEX + PRICE_ADAPTIVE
presolve=PRESOLVE_NONE
presolveloops=2147483647
scalelimit=5
scaling=SCALE_GEOMETRIC + SCALE_EQUILIBRATE + SCALE_INTEGERS
simplextype=SIMPLEX_DUAL_PRIMAL
bb_depthlimit=-50
bb_floorfirst=BRANCH_AUTOMATIC
bb_rule=NODE_PSEUDONONINTSELECT + NODE_GREEDYMODE + NODE_DYNAMICMODE + NODE_RCOSTFIXING
;break_at_first=0
;break_at_value=-1e+030
mip_gap_abs=1e-011
mip_gap_rel=1e-011
epsint=1e-007
epsb=1e-010
epsd=1e-009
epsel=1e-012
epsperturb=1e-005
epspivot=2e-007
infinite=1e+030
;debug=0
;obj_bound=1e+030
;print_sol=0
;timeout=0
;trace=0
;verbose=NORMAL

Note that there are some options commented out (;). This is done because these options can not be used in general for all models or because they are debug/trace/print options. These options can be made active and will be read by read_params but note again that they are possible dangerous to be used in general (except for the debug/trace/print options). Note that there are two kind of entries:

  • Numerical values
  • Options

Numercial values can be integer values like maxpivot or floating point values like epsel

Options are a combination of constants as defined in the manual. Multiple options are added with +. For example option anti_degen.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  read_params(lp, "a.ini", "-h MyParams"); /* Will read parameters from file a.ini under section MyParams */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_params, reset_params

doc/is_use_names.htm0000644000175000017500000000556010242162074013457 0ustar renerene is_use_names

is_use_names

Returns if variable or constraint names are used.

unsigned char is_use_names(lprec *lp, unsigned char isrow);

Return Value

is_use_names returns a boolean value indicating if variable or constraint names are used.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

isrow

Set to FALSE (0) if column information is needed and TRUE (1) if row information is needed.

Remarks

When a model is read from file or created via the API, variables and constraints can be named. These names are used to report information or to save the model in a given format. However, sometimes it is required to ignore these names and to use the internal names of lp_solve. This is for example the case when the names do not comply to the syntax rules of the format that will be used to write the model to.
Names are used by default.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  ret = is_use_names(lp); /* will return TRUE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_use_names, set_col_name, get_col_name, set_row_name, get_row_name

doc/set_epspivot.htm0000644000175000017500000000720410237176662013542 0ustar renerene set_epspivot

set_epspivot

Specifies the value that is used as a tolerance pivot element to determine whether a value should be considered as 0.

void set_epspivot(lprec *lp, REAL epspivot);

Return Value

set_epspivot has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epspivot

The value that is used as a tolerance for the pivot element to determine whether a value should be considered as 0.

Remarks

The set_epspivot function specifies the value that is used as a tolerance for the pivot element to determine whether a value should be considered as 0.
Floating-point calculations always result in loss of precision and rounding errors. Therefore a very small value (example 1e-99) could be the result of such errors and should be considered as 0 for the algorithm. epspivot specifies the tolerance to determine if a pivot element should be considered as 0. If abs(value) is less than this epspivot value it is considered as 0 and at first instance rejected as pivot element. Only when no larger other pivot element can be found and the value is different from 0 it will be used as pivot element.
The default epspivot value is 2e-7

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epspivot(lp, 1.0e-5); /* sets epspivot to 1e-5 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_epspivot, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsel, get_epsel, get_epsperturb, set_epsperturb, set_mip_gap, get_mip_gap

doc/read_basis.htm0000644000175000017500000000750410472143214013101 0ustar renerene read_basis

read_basis

Read basis from a file and set as default basis.

unsigned char read_basis(lprec *lp, char *filename, char *info);

Return Value

Returns TRUE if basis could be read from filename and FALSE if not.
A FALSE return value indicates an error. Specifically file could not be opened or file has wrong structure or wrong number/names rows/variables or invalid basis.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

filename

Filename to read the basis from.

info

When not NULL, returns the information of the INFO card in filename. When NULL, the information is ignored. Note that when not NULL, that you must make sure that this variable is long enough, else a memory overrun could occur.

Remarks

The read_basis function reads a basis from filename and sets it as initial basis of the lp.
Setting an initial basis can speed up the solver considerably. It is the starting point from where the algorithm continues to find an optimal solution.
When a restart is done, lp_solve continues at the last basis, except if set_basis, default_basis, guess_basis or read_basis is called.

The basis in the file must be in MPS bas file format.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;

  /* Read LP model */
  lp = read_LP("model.lp", NORMAL, "test model");
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  ret = read_basis(lp, "model.bas", NULL);

  ret = solve(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_basis, set_basis, default_basis, write_basis, guess_basis, get_basiscrash, set_basiscrash

doc/get_bb_floorfirst.htm0000644000175000017500000000604010244172542014475 0ustar renerene get_bb_floorfirst

get_bb_floorfirst

Returns which branch to take first in branch-and-bound algorithm.

int get_bb_floorfirst(lprec *lp);

Return Value

get_bb_floorfirst returns which branch to take first in branch-and-bound algorithm. Can by any of the following values:

BRANCH_CEILING (0) Take ceiling branch first
BRANCH_FLOOR (1) Take floor branch first
BRANCH_AUTOMATIC (2) Algorithm decides which branch being taken first

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_bb_floorfirst function returns which branch to take first in branch-and-bound algorithm. This can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
The default is BRANCH_AUTOMATIC (2).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int floor_first;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  floor_first = get_bb_floorfirst(lp); /* Will return 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_bb_floorfirst, set_var_branch, get_var_branch, set_var_weights, get_var_priority

doc/get_constraints.htm0000644000175000017500000001140410237215134014205 0ustar renerene get_constraints, get_ptr_constraints

get_constraints, get_ptr_constraints

Returns the values of the constraints.

unsigned char get_constraints(lprec *lp, REAL *constr);

unsigned char get_ptr_constraints(lprec *lp, REAL **ptr_constr);

Return Value

get_constraints, get_ptr_constraints returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

constr

An array that will contain the values of the constraints.

ptr_constr

The address of a pointer that will point to an array that will contain the values of the constraints.

Remarks

The get_constraints, get_ptr_constraints functions retrieve the values of the constraints.
These values are only valid after a successful solve or lag_solve. Function get_constraints needs an array that is already dimensioned with get_Nrows elements. get_ptr_constraints returns a pointer to an array already dimensioned by lp_solve. Element 0 will contain the value of the first row, element 1 of the second row, ...
Note that when set_presolve was called with parameter PRESOLVE_LINDEP that this can result in deletion of rows (the linear dependent ones). get_constraints, get_ptr_constraints will then return only the values of the rows that are kept and the values of the deleted rows are not known anymore.

Note that get_ptr_constraints returns a pointer to memory allocated and maintained by lp_solve. Be careful what you do with it. Don't modify its contents or free the memory. Unexpected behaviour would occur. Also note that this memory pointer is only guaranteed to remain constant until a next lp_solve API call is done. You should call this function again to make sure you have again the correct pointer. Otherwise, this pointer could point to invalid memory. This should not be a problem since this call is very efficient.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL constr[2], *ptr_constr;

  /* Create a new LP model */
  lp = make_lp(2, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  get_constraints(lp, constr);
  get_ptr_constraints(lp, &ptr_constr);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_constr_value, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex,

doc/Octave3.jpg0000644000175000017500000020521510252703674012310 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?e|H>9߉'ԮX wv9k| 5֛~ sii_P񆯥I^z'qvM{lmgrvm$S=wZ%)E.O&&^G 4YWiGYkZகm+UM6;uAj?gu-ş-f *j3rxfO C2]66ގjd׈}">o|)9?f9&V2B5s^ pFY`ib]zt0?J>zWT(TYY/X*8>icU5̱ Jz\W V>Th eT`r8j,hɪ]jmkytxlk7mlbi YԭƄ>s"0NN:,=93'8 ~7f| м+?_~-QhK$5{ƙqu[\i+"txDWk >|:>÷VsJ߃ |Q^k|J')Bg>'i> {.xzU5kV_?~)d<tCi%ѣ>Ǒxூuox|oj>&=>:41j>umCs|>?iw>E]~ְb_ V^X.:ߋ<3_/SVy-5ըY>W_̝|ׇigbpX,2aWe7M,Gd9*aC+ԡ> YTxT<o7[(n*+ҩK19[Ʀ'4O Y-?2 eȵ ~'<];~Lj;C/E/~4iUEn%߉o-u,{cjT׾GR I%?h߆?ů-|%Oo|&4_ῆ ~){xg6Vz֟5q9MV,G ckq9+ 8L3F+ѭ(d1 Rb*X\%U ҬzX 80Wx3O F_5e0ҫ4nuWRxԧN5>tAk/E'[/St"oI ~ǚOP]w%qko|qwz{K~:/|MmYѯ;KzGCOx?oux[^wo~"Z| }N=ߋ<]]Aw^833} 14x_/ʳl+r<*̫frq*3ա qNJ|O`NIQqnY;eaeTEVsmSgoDAk/E'[}-9| j0~k+@_Ϋq|p~+K5W2$2jx_4+ޥ 8J8աĩQ+6VqN6JZ ʥ9xwPS~/Y׫9ejKxRz8h |Qg@QWTeF}~lwVmͶyz>0a,<{w|5,Q/4M> kWoVK}#=gMѴtE83 SMC3gqhUT x3V!s#|GZYQVS/'HE搋2E~K UW\YAk/E'[n-k윻_>;o1/<Ϥ"ehAk/E?renӯO>؞[LG'[ioZ<'.F_?:<o1/<Ϥ"ehAk/E?renӯO>؞[LK0n^8KG5o ֟_5gҏ,t~`?ۅ}C?q?Y_}) Gr5" Gr5"~Y(GG>_Bp>,y/>AhAk,t~yg/F _PPOb~.i<7߶_o$lUb2?b q?'_+Xao/4/j!o;/J8$]>!{[Ƀ;4ĞqsyqN#$reNMX?d4̝SiW~7%>g1~К/x|Q>u_Xɮ?i[ '[+-o5OO_v3m0ş~N/>7uMWċ}#-gRSřoN$`m5?m|\}QYk9pn9fIϰuzE ٴa0ɆXJRɍP3sxx*yC,~|Au3\-<^7ONׯJ7i5 gOKov~$>>2W~/5kX4#G|Ckƿoikzv.qk c4 $w?/k^0*7n Q_Z-(~vƭOc:5'5*MTKkl=J+;,UӘ7߲/:~OUKYPL9h:J$MfWwXxקu '{o#]^)𿅾"xYKx+A,N{x#:Z&癴Pd k)gۓž?o@!Oكտ^xsZ|Ly4?Z埊>.xN:7>"l5 Y~(6u o/ V~+}>+:fSxG>VK{ji|1EΌ֦YoV Q_4|cO~7nG9%pKN 4x#Ǿ4s `p=|v /it*)O , .1Up P?<+x7 2|3ʤSu9SL69UN$gB9|/?߄ ?|"-Qx;~^*֡W~2闺?'*-C{'쫥|Q>6-~g֧sšqofo bm{iv:։oOiO[+῏~!>~ӺfBMk~sF'fIO,/K۞\~S\>*kV'a]{^x׊>/jc>W?gȃ|RF]cjW}&~ 9{OYǀkx}'B]7<:^x%c'{ߏ|CCr^-?=O?f/gk>=i֋v|5y^W i~b,؋74[ư[[""c5TEUPcipU>30~cG6 ?[f>b)n~>7O_߅?-6Oj*K[Qg}z'Ğ4/~Cg=[ǫ ^xι࿂o&>j:ï/4 !T? sַ67b+yo,q6oʍ#+~0|Ɯ#Þ6e9m^509>ef3沞+/3\TG,Ɩ6'9G[N]GìL^9'-9LJC,/o xz~OUa^cS >OMeJ+ #Z_9]Pk Ο5eOxQ| \ /|Eu⿈z~<uO~^@C~~_c{ڃOZgѾKhK-?@'h_V>1CP3gkio^3{Dko oO\Ҿo7jo'y{|ݽF?~Ɵ_|l_#> xߓfδ%2W*%.LFMa*Ay1q8zq9<7a)8)>g/M.)g/4*vh"*cӓx*l w `e,>+xeXz=_(m??G?05;?[[|(4?kk~gTԵ|;l o9[׈bx|( |uk/2i-Bx7ou{%~64MuyLA_SoKL2jeٿo~_>?7h|!T? (q,8s 󌱰2`2N*x*Y-4L>._1V|f>J8. W#o# C,ʲL>*8K_w8[w?+{KHf$\T?꟧ݿW 1ES5Åck 8*?o>_w8[w?+{KHf$\T?꟧ݿW 1ES5Åck 8*?o>_w8[w?+{KHf$\T?꟧ݿW 1ES5Åck 8*?o>_w8[w?+{KHf$\T?꟧ݿW 1ES5Åck 8*?o>_w8[w?+{KHf$\T?꟧ݿW 1ES5Åck 8*?o>_w8[w?+{KHf$\T?꟧ݿW 1ES5Åck 8*?o>_w8[w?+{KHf$\T?꟧ݿW 1ES5Åck 8*?o>_w8[w?+{KHf! sX!918oM~7# }E9=G?^rTF¯8.$n~8[I,ru0ڭ]tk!W"S ;E_187F;\)ӦaP^eĿD7P_~0??oM~:Q*QG?^rGMѧ ty?_pK(y/|?oM7O_&wO( ߎ_(u?ࣿUc/~9&Gk:t< /8%<_7O_&F/_wc/q:Q*Q}i:f_O?__/F/G# S ;E_18?O( ߎ_(4N3/v'KIce/{/# C{Ewc/q}pNAz;}%$2=~:jr!Ij9YS荤b1%{hF![O?^)~_S%=^3< 2;omxwf|c1l&+V%˜jeNqT8cB>.[Ugό0Ҏå\qqugsQBD$Ѥqev` (jT~ɇct$<3X o QuXό<+h'ƻNuմcK+>(^??D+C`h*-t|q ȶQ[Ǿl^Z=*IcjS{^9xFØL~CsBX,\٬ [(Yu N42aK/~l.;ȣ[N33Rquܓ*L,0xq.&;l~_zVMb%%K>"x~8YazOgh5i}G&?~/&kƞ&о|g_7v}gZu/{/-<3ᯈlt?Lc'JݠS8Ur0n$?p{tzqTVWDZiRxG!ݮϥ?/|uCwWz^4oX^^i׍5|nO 2 0yC&23q|XÔ Uٖ*4،ҕ,DzaZ0g#9R+X&3d u1X\%VJX^G/Vb"麔ÏxO `/ƳCoĒx]F_ۃ[.58.}p2Ӛ{9-db/*} |#m'R:4?C*G⻟wRMCjY5˛;85߈7_E+oï '4?NxVTִςGm7ڮP׾!x|&\_ cǮIc˫Yz wt~ȿ9 [ ˃pH##oE\?>"x#H?㬾q>;q،>efJ\&+*uk CFVPT[w =&}To<_p^0*yel-bl.k[I,&f\8f/AT^gm}KxoQ<k jέeiWw5aw-YO$/ x^8ϊ.? (OŠ(((((((((((((((((((((((((((((k ) h\2햽h|h(sG=q}_g|;A7&~;83³WSG7?X?M_vs?,C׿i+ʾ})/|B/ 2uWA/ⷎ|-\NJ<ú~6_tZG|"|S)?k?e _3P|K ? M|Fíx?NDXÏW2|?o6SŗQ^MVY{W`_>~Ŀ_.@1B):< UWwO|y?g+ٷSE||64+?( ;6}ƾ@?okƯ O> t?et £¾#Ӽ< xUm?-㛏xf?7Zvx+Ŗ5_xh^0 X _b?ao~˿0|o7 [#KiOS_?o?'KuOh [G_|3_xi#:>9xs:玥c:x/?hO~ǟ߱CL]o1|ekF?ƟÿN9k9A/~hqhnu\E| '۷oŸ ÿ?W;[bxWt7HfWu9So|c<|O?ֿ |S`u<}"e1C៌t~))ƃ/W?࠿5?f;IФ/'fA+=<{E(_K?/ٯK-AZ=1?ï]ٓ|@e3D>)|0k&ψv3KΗB=cenO xOvKRտ^; w O/ ~__)[h*e#e/\!oxKgK ߳Ŀ-|IwU(e|4O~|f# 7H_ x_[F_+W yľhONO{^-> ͯj_7pxw៍>9Jx#w~(|`O73/^'ψ~Ook qj?i]K¿V F)('7kkmjwiO9ߌmdmϊO/ۆg<Ij?><|A}Wÿ G:~ʺ¯ؿ ~|o2(O:qV'৚mK]b_x[7ſ;%χ?-^8?|B=_~*x/Y_ ৎ5]:NռU|FYUno?~?x;K,E)GMZG ^W?]xwwe^_>Z eOh?Co'Y# ??οUM ž&~ӟ>l/ƾ,j_{l<.o;π?e _O-~>9b3s៍_mğ;u|+ᗁ$G 5WW~ JQƟ:|ֺvQ_iφ[{⶟~NJ<3kÛ;FӼI?4/~P~>)x7> x{|A;9,|] ogco ~hŷM7^|7ϟ| ~!|J_ |? ?G/+ ]7|dƻNl|A'_mUO?^/xxg7ý{_SW};{~3|#I}uJ4h)n៉"~ ='xGe٧_E|?_|YGoׇ4ox]χ~"` oZ)/ty|GsI|EAmL袊((((((((+?౟O/^z!,guOx# U :mPص5ƿ4Ab?/~Ӣ)Kp2w1&(eEWQEQEQEQEQEQEQEQEQEQEQEQEQE wφ>_2? ~xgOX'i-CW#OWS/OP{}((((5gCWO//#M-uSo!x/¾; ;UoOOkz߁ik.<'l( ( ( ( ( ( ( ( ( ( ( ( !,guמc ?dQ?_?ſ'_WOǼRNwG6?[!k7 9mPط6CN_8?)|WN?4l+bߵAk'x{?Go+WO'Ú/wxn[WcN?oAҼ)=[9#?sCOOكw||աx׊fϊ߱ρ|;=gHH[qQQWɼ~9_ k3> ռAk=/?%/_u/_iڮc?>:ִ"Fj5䚍Ɲj=y,>q|9F~_>Wo~ |)~4<+W㷍>⦡ 9Sj8{^>iӤwl8$u{Yd~ο,%&G>,%&G{Yd~ο({Yd~ο,%&GS¿:4#B=|k֝gٯO3}ڦ?o|+Xo+yXp/%$QbYK?`L5}E|bYK?`L5/%$WP/%$QbYK?`L5}^?৅~?x/E/uiFzgq᛭:Q__߆gtM+Y6W/ŖYèxVY]W4?_K/Ig:ƣ~*|+Szׁ|CxfXҵ"zFyq]j[1M}j6-0ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u_@ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u_O_<+59P?|v˭:Z~/E/_hV^xHЬ5/CѴFKt:ⳇ({Yd~ο,%&G>,%&G{Yd~ο({Yd~ο,%&G xWk?s. [?~4)SŗZu/ +^_j&H摡Yk7Z^i3XZugP/%$QbYK?`L5}E|bYK?`L5/%$WP/%$QbYK?`L5}??৅~/Z/jZFyqk:Q_߉gi+FO>6/vͨVF5]{W5`?_K/Ig:ƣ~ xW_?h_x{PJ|`~5YӮ4'Z/8lt:x'K]b^_Za/4F ~Sl0&Wg )#?h]~9Hl:3W_kxd _0 _H?ӟ&ߵo?^U<|6?Z?_~Ӧҗ adcMQcN/ˈ( ?l8$u?l8$u>((((((((((((((((((((((㿃7)χZ# _ u C3GO?XO/- E G/.k'χu #fd|k~)_ EOॿΟ[Wo ;?ٻR|-$>&Яc6h?:OGg5C^&i^ Vj|9( hjzq{{ nE[_Sw"֚ǁiߌAo?|c< c[i_6PӼ'¤q.[+m' j>'As@iz>)_~|VZG?5NG/R ;]v__]D/'H5g{ߟiا_~)xg_cÙWvſ; OoSS_4m oٵ jzg? 6'<S2woQS(O#Gge9uxs> h? 5ҵ?i?_; P?lV^1^ğ >-8Tu+O;~Ğ  Ť|Vs}⏟mo?|?ق|>]o|*/ guSZ}/w_; Λ/Ex* FѬj7w|M&ߎ?c|:v~mgoقNm>io|U]o~w>ucu=OMmmessgqΞunY>kV%UaK-9 PPRxVSԅWQՌ-HF5^R*t(VNY_帵^QC(1yxeNYⱙAVyUu,.yp OǼSsWSz?MjfHiN~-~͟?ikߧJ_|g 'nq\@?/ï۫??`#ů~ bYڟQYf+u?ٗI?^?g3 .ό<;+xo/؇º[̿q~ ~/Sxkej|@|5.#A>~Ϟ"s8|17!4?~h|h_/#?sCOOكw||աx׊fϊ߱ρ|;=gHH[qQQWɼ~95wŸI kZM(5@ԯ4}w@ttkE魵 +Vҵ k{7Rnfx7>>s:|o*Si:xWKo|MC?sqg7|6Ӽ'I^?O<Iɟ~;kxR'GxQ[(M&iib>?FSB~QF#RjU>Z_-"οTMRjxdO~mncXӵOuMCIO2?. hb4/&O ;Jx,c Pp.6T9(Ԍ(>*~ĞK[L'nYr>sp*Ί~US)ʭL.# Ju} +1Q*+jS嵟M +յ]KTԴ{͝΅h)yx Jtv zi~)u(5X.t[~``gkՇuwRg_>#*O־\s{Ox]i;S[N/jz~sEGbO^M'iQM+JX:mn.((.axWV߆u_ƮaTN SV5 5jVzT{(Kߴ" }>Iֵ7fZwWIյ(,5$ ]ҵm:M4F+6' OPa'*X5ZuUn.TҔ)'&3g:1eCe#KgY~/+05eNKJJuc a'N&EVQEQEQEQT+5];PRMԵQ $K cGմԎFk]KKlgX[&F'N&SIFu#NRJnJqUT:0Jtթ*4QEpVʔ%+)ԍ҄[QvX54Wt\YfeC4f*є*b7 RTqXoΰkz_q f]`ʆ7/BZ=%mbp8^b~' QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE=|XY_ ~­W+_ / 2+ wO;j?@ u߰xC}k7)GOZ+ __3_tgW c?$___;>_U0,Vyk?o4IAbvCӯ&ߵ__ikJ_l_ 'Ɯ_Q_GA_'&}kXѯ閿:OL>_)ǟCEa?Rgx8QEGQ@Q@~F}G|[-fV_H쨯54 jZLV7Z7s}U<=sS$Ƣ<:2J晆W^\rf# : ƣR K4Ri?xgωm<~<(gqeCC +AM~ 9E`[AX˟{<h[;e3:;[o5ǡ7>4~꺶6:ޕx[G5ٴ+/.4YZhoE~xǹ[ }l}Pq09i<꒕H6&ի*^To?dw+YŞfKwb,Xqj)`\"i`nǣ|' ;_ŕ >GOu-+OKxŚ5?V%_%>"O$vV`?'? |XR??UG7_ 5/+{|j?Bnu?Yz7/xz oaqUڧ,~Up;{,կ'tcVhf3?'܃+Y/Tϲ;oĜ 1[NlV/V|-{o袊8B((/÷:ulS>0 67?,-E՗~ۋ][D/~ּ(|5 gN<Ht[Nwƾ$~*n۾4oDͭ$^ o"wuMZ;_>+|g=GQtOxRk+oxF[e4 @߉|Iom}sYk>ݟoºމcOx;aq T쮌ה03 5`(T# +^l,cir3 |/,ωZg >)uaICMކ}bq)NTs S,5B N~57u{&/oW_A׭-o-P5P|O[\𶷢kzO^a_^ tI]iJ3JsQ9TF3fXJ xbp*kSoqMI)Bp:F5)TU*BQEQ]PQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEßJof֊WßJof֊WW c?$_UC?XIgAE|oSa꾑z_Mjf?ӵx6?ZN_8?)|WN?4l(Q?R f?3_Lg߱mN</TcF? ̢+?((((( GG=?H,oi??{i_z_<,ԼY´/)}ό#owi?k2> Yy_ċWش/sѾ}^#'M/WSW|poqYM>Xcx-:j˗W8,y:xjªڳ!HϿW_8k["7 ؼd?oĘ8TbY__=/W{Hnǣ|' ;_ŕ >GOu-+OKxŚ5?V%_%>"O$vV`?'? |XR??UG7_ 5/+{|j?Bnu?Yz7/xz oaqUڧ,~Up;{,կ'tcVhf3?'܃+Y/Tϲ;oĜ 1[NlV/V|-{o袊8B(#񦛨*}o⏃,/u+R=*{#i6-4X>.iZMw.A:Ms"'>z~iΝahZZZ^A}jZuX_Z-崱\Z[$I񺱻^-ť6 E_\Jj?ō=&t][|Qcouͩ^=tO>W'CeXUpҖOb&Y4 ~*uG *CR1_-?~; g1^ioڃůٯO^5_Mjf?ӵxN ~+OC7yG8[. `L|w/Q~_ oU8d{/gdO~ў"dsoW4ou?Ꭱh|;_-/^/|t> s_|/~9~~/y<OO#Q[J~?{ 㿋8g]7=|A/ӼOlt xDxDHoh|*gP`|`>5<#5h^*uٳs_of?q8?jo|A@e|o񵟎.?3_~|&~>~џOm_ t?gO ~O>:|BN~ڿ<@׆φw>!=+>)瀿?3_|Jq1DJoWfQEiQEQEQEQEQEQEQE}CiK-|<%y.o3j:xT^_cmf5- " @/<%yx{Uc/OoI_/ᔾ&O|QK$_šx~~д۝O^"?izj&Ixy0T1J4|J'e'G*n+UaG+᫵c1>}'qNAOeXox.>(sΌ3 J5N'úkT0t+β_k->ִgĺNwZghZYè֋\6ncq=Z,~~_6▭f}Y5o|,x?sx#Q[_)wR_7F- *_K=7Hq~?m#EM5 kMYmZNh~[xr]yRmW G|Q:g5J7Xqb3fsT]4XZ ִgĺNwZghZYè֋\6ncq=Z,~Fq%()FQjQdim4FzhWRz'FЕ:jӓJUiFtS\' JN2Iпk^"֬mEho ]3L>yi:.jR]b|l' X%Qt]Z}G֬gu;?Xm{m+Eͽ;yRE;-cş{yN +[+Y4N ]3G閷7ameGl/x'a?-p.:Y.! *qr C\gRcJr{ Yp3\byEo:*<=3 f*aaTk>JkDžYǧEGQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ŏ੿*߉%µ? "/x~િ|4# h7]?i鶿j|Rdـ4UC?XIgAF53RGe~џs_?ſ'_WO|SybWS_z_Mjf?ӵx6?ZN_8+._x1&(eEWW5Iɟ~;kek>5whqgd~O5o^/eQ_o!EPEPEPEPEPEPEPEPEP?WU~Z_ZdռE_-_.[ ϫFVumOK |GSix's_շW _?< Qi͟/?L|wWuEtC忈>lUj^?/UQ (иC.SŮl1`ov5mhKZ+=EIXwMԬn'YTvgM{_ױ$ux.m5+ح/l/, _5 ['u kzމ~~_6▭f}Y5o|,x?sx#Q[_)wR_7F- m¿~ZG3g+>]]b]_o> |A}6< &y{7cƞ ,?VdXT*\ʪ[jVҥ SSJt*8::'R1?I;τL1:xsVu+Z|Gg&>^'(M!o|:Eί[jYph#浠Aw|=imFNĶ^Now;cFbm֓i0엾~+4LʻիOsG%8u*^QmRSrmTYY_v#0s)pʼ<}L1P`pXƾ0N"ȡ^00Іy*=ʸw+ ( ( ( ( ( ( ( ( ( ( ( ( (>s)M??_V*s)M??_V* !,g?uךg )#?h]~9/)Ã';}#N~-~k; :mPص5ƿ-p;)|V}.Gᓿ7yG8[. (OԂ:OL>_-3_t}gcFS??%8U7ѫxp3(4y ( ( ( ( ( ( ( ( ( ( (>oګ&b~Rմ ϫ&/o'txn}]j2ck4^7k=Hмe;f/zǂ.7xs㖟jvm)óZG#-E_>:V-.GƯ~'[_>,x W2X5XbOuՊ4x&;_Q}9n.|{s8xXN㜳5N5ʾ&X,fQē֧NN+3l'˪xV*_g}?ៈƿO!_]8[k_~(xTVbM<Km[+[x}Jvuo+D~i>#/ jiΝahZZZ^A}jZuX_Z-崱\Z[$IL/15cK `rj)F>U*_)EV*Q*עos)M??_V*s)M??_V* !,g?uךg )#?h]~9/)P2;~2֞Wo xㆍY>ΰ|ooş~/_|a; HRֵo߲W_ ǃ|o ᷇O&Q?R= g???j_t?jwzZxlúُ~t4ڛŷm~!5u|_ gßgE|6?W/Oº_~;x*j~!ӟ6>8'}usᶝ=:OpJϊ|7y/ǟ:OL>_)ǟCEa?Rgx8QEGQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@S]|SmkV׉5i|EjW>k=:h5jVmo}V7^XA լO:?ճf߆?Lt ^o~З]O|ӣٍBK+H?M|Lѯ|%|;|As#;A47Lcxs"i_@i Nj?^l"-GuoĚؾ jᎻk k[' q>`cS}njժVm'S+Ƹ,kJNtaC7FYM// a8B3pÌ\hF|_lVS <;[/c#4WkR|o+CC,x^U֞n5ڶ=սru=؜6" 0ih5(UJ¥)`8ܻ('М%8J}x*_es3fZJf9N3/0X+SoUJk =E^ ?EU.i_Gu-G_#nom~7iEX+౟?+΃^j!,g?uO# U?_4IAbvCӯ&ߵ__ikߧ/x1&(eEWW5Iɟ~;kek>5whqgd~O5o^/eQ_o!EPEPEPEPEPEPEPEPEPEPEPEPEP]ۋŸC -ᯌ}[0_E&k5h)o[^::~׍?W-b|}y kMokec7Gǧ\E彜Vi5+uZ0_ ~^ ~m[M[KonB|~ךu-"*5 [?4U.,5i {>6%5Ŗ kC מRGLJMOEk8TuY?g'o x50RZԣW?ɕ_mJ*S[ 41r9z1G5pY?/Edq¹>sx֡e],^OsxҊHt[Nwƾ$~*n۾4oDͭ$^ o"wuMZ;_>+; ic0u} 2pJ*R:5NS14bxUؚ4ҩN?vcͰtq _(TЫN p6",Vҭ1thc0x1T*ҁEWYQEQEQEQEQEQEQEQEQEQE|Rdـ4U|Rdـ4UC?XIgAF53RGe~џs_?ſ'_WO|SVyׯu$kk;_׍!ioڃůٯO^5oӃR ad<wӋ+DH+Ͽc? 525Iɟ~;k8H~3SQ?'S}72(H((((((((((((( ?v~Z?f#]Wlj~kR=_j Vx eB |͏{y. w=#~<|7Եh֭a<-h>O^1i]ZOX/KHM4)pGZXޕ4)1<#M5S VT.iT6RQ(WxdBru lT/qugz8h0 ŞgaӼyYGOox@?xKKk˘𯊭,u o_j]s^߂Yx'4ol%Kc[uu x=/ՠf}_u-*͜!|-C mSs?<%;Zlx[ź=S7Xm?CI-.êXYj6w}ims!7Qfq']^+:m'ӴkXi1j- ^OWtW[oDuhj=Y&R0xO޷ FX[ |WFy |Sx'08|8l/Vkf`q^Ԅ19/[K*&dg-?~;x3³Vӯ&ߵ__ikN~-~k~+g 'Ɯ_~0?U/| ?j?^=c'W|DUϋ5 x_K쟳..4k#|~x$xǏ >5wh7?ڟ/?)x+_ǿ,h/I/ 2ƃ&J +W¾3Iɟ~;k8H~3SQ?'S}72(H((((((((((((((omO?ak_U_~^*?>o#E#ԿW_#Wg? 94>,|ۭbN?^׾n%cZjcD- >5x7KPͺ/B`je j_:5`G4I^OG13͘p/yy _Y}FViО O_F2e7wRe#t!9R/, 3uqqH#>-/?_Za,~[Z-~hX2M?K?$=݇>*Ex`|?ī H+Ҽ;St~x@'.?e9a^?U-oVHT?q9U׫BUVGRBL2/2bGn+j¬lWEw.Ml<1&cxoh킊(((((((((>Sl0&W?υToO e~Oo< ?_U_K%7NHez,+ !,g?uךg )#?h]~9/)ǃ?+<l :mPص5ƿ4IAbv)Kp2z ɻ?iqQE~g߱mkϿc? 5y$?)_)_׋ÇEWQEQEQEQEQEQEQEQEQEQEQEQEQEQEWz6>'xI>5^2;}]YiE[TD7Qyվ,xf /iMMtG᷼h[@ k/|-j7m7_ JGt wGQ5WӦ4[J-J !)G_&pe ߞU61X:tqxiWTƕtE>p75|?UB'!<,LJ4'8K3aJ<~UW0TY?_xwG^ym/~FVWVVWPjnjZ|hkM喱kV:}eZCZ_֝.$h;QxGdž-;( ' Ii^aWxT_nk)Q_J}xQEQEQEQEQEQEQEQEßJof֊WßJof֊WW c?$W5C?XIgAF@_U?OF<aY`^ioڃůٯO^5_Mjf?ӵxNJ_3?cMQcN/ˈ( k>5wh_'&}kXѯ!N"F0)Mj^?(#B(((((((((((((((ڟ!ǡ~?U>'xI'IoԖmk¾l#Mɥ_rʾ ~m'RM'Kon]Ӽm`u-"'柣4U/ix eiu/kC8DCҝL7)V1hӄb3ғFp{2DgV+a(a<8Juhe1<'fxM< hR?3r~מzVk-7ZA{Iw^*.}km$>iAզH|sT_<.־EK9~4b0?c\05p%eᱸ,E:X.l&.M µ(MYWβVYSE{J3t8Z L~a3J;.Qq`q|>/:uӜy N~57u{&/oW_A׭-o-P5P|O[\𶷢kzO^aO?_6wž 7ީY蚆=_ wlj?O x}>+ kh+e9}?R5=7PSSu V4-bHl;+X|0{Ys|<*֧R1Tfl+*tLNj88U<c//%1~ަCJϰ^XARgE,Dhr>YNkAl6N3.}(B(((((((>Sl0&W>Sl0&Wg )#hC^j!,ovw狞\=SaXU^ioڃůٯO^5_Mjf?ӵxNJ_3?ᓿ7yG8[. !%"kg |m91[d -,֞ƏƏ:?*⯍_/I :㯅 4Huώ^h-Gºtv,#?j?f_ǟo\߳ǿ gWf_x)iڟ/,_j}V5'^k a|Agyg>5wh7?ڟ/?)x+_ǿ,h/I/ 2ƃ&J +W¾3Iɟ~;k8H~3SQ?'S}72(H((((((((((((((($7g ~Z{?)i2EEY=>"Am'YRռ e.7˥|6aWMb#xbu_,oW J$$?iIʔ9ώ>q_~*gG:8C3+#,>ҫ_yJX'HZ|:յ{~Wkk[4 mx>5NrI^[?Etga}\2/m<*PqSiGXJCZtt/NS5N/s̟[ gf?i[&G˱:և0Uy]:ԩceREJk"|0 |Kgo?ec>^TZ\6'XܿF1bFu)Ia9`̗8Ԇ/C8ʫ e0gF"l3PYWէsԫFrynoEW{aEPEPEPEPEPEP)GOZ+ _g*o d'ŏx7Þ⟌h*%kU_$~2~=sz`@3RIec3gC?XIgAF?@_?KFa9ׯu$kk;_׍!ioڃůٯO^5gӃR adcMQcN/ˈ( k>5wh_'&}kXѯ!N"F0)Mj^?(#B((((((((((((((((`?]jui3@%% Ji8F<)i""ݷ x7] %|soWĿj۞ /xu3c-jٺŦiNiwRQKk?Ro6g?b^o/? gZtӍJrF:(=(((((?# b?# bHl:3W_ky౟?+΃@~.=~=87sW?_4IAbvCӯ&ߵ__ikϧ/Ɯ_Q_'A_'&}kXѯ閿:OL>_)ǟCEa?Rgx8QEGQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@} '~~)h߄_O5o-._;Nڅށij-_L¿Ţj?4xVf+ 1x\v"/ ^J=H֡Z Մgtr 󅸏.=Ĺ>ggN.23ɳ|4˱1)aM|5hQVII;5>5x7KPͺ/B`je j_:5`G4I^O_7zj:Oo?`?)'mjPN>)ӭ|)D j|WKKI<i>)Ӽr/dO>$?Ÿn5ጿ:(}ea3Z0M,6kM٭!?iOGWψm/\s_aGHb'gg,lf2 uuZޭ x*Ul.V9Rܫ NukfpN(fXL=8UsBFotp爩d|oOiN. WiP8ZqY<:Xzpkgp0>EbwZ?{={An{GOԴOM }kGo4wBլ쵍 X5{-N bQakR4(TjVJ*uiU(ΝHJP$8Ϩbp6Pt)bp5Zu؜5zqCJSZjSJUiTSg J2MQEjnQEQEQEQE|Rdـ4U|Rdـ4UCX$]?~9 ^z!,gu~|?~=87sW?o4IAbvCӯ&ߵ__ikߧ/Ɯ_~0_o=ǿ2ك?|cJK x|/W_ؗ,tmCzGǤ~[GW|'Ko | 7~ Mi_a@a?W6(| O{7x$}|;_'m[Oh/6)_ ?jg?gு"?"̾?'|S?̿+W_hN+,^W} '&}kXѯ!N"F0)Mj^?(#B(((((((((((((((((>9O+_O?|;oEʹEֺ*-KmcI?/g^᥋NƊ4'/o7 >-sկWWg2[+@(K> K|HW)wO hĝ'G;5+I-_C--|SmssojޟZvXk=ViP_iږ}wV7ֲKmyeym,WVG42Okk5cկ<19抚 5ubX3N#1 ~+28O36 fS9T /SX_iG,+ˉ18}(>((((7iEX,QMV4Ws|SU_tJ x;OZG}OR,?O'?h|k c?$W5}<[}Tw?pgg :mPص5ƿ4IAbv)Kp2z ɻ?iqQE~g߱mkϿc? 5y$?)_)_׋ÇEWQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEVt_[Zռ5o jnh揮ykZ.MmiZ[[i7Cuk4SĎ4S Fpԣ(FQwRViM4WFuRB*uW:5քjRJ\*RNjPN$8N.3qig|Xo>3Þw_GOv:g }=ᯉ_ٞg46P_a?cګFu'JB;ZB/^[6c!Nr i>7sCYugZW#^5p"1 m:Ҧ {waB*I,dqt Q}j~9_57|7/<ۄ8Nj˰#[R\9WV@+T*ΝhŅWZnV_iږ}r^Y^[K-խRAqC4oTT *JU!*u)Ԋ*Bip$e E2MI6iV:QNքUVN:pN9qn3iz:O}zZAe|8^u=ΪoOI|}>0_>=땋/+4zeH CMKOSSմ-wI4-bW/;+[xX54Wt7<G+Nu2~!Qqrrr%Cɳ Tj%Wʧ NPq'W#K8U%>YK pk9΅jN|=? T_O+ϲ ( ( (>s)M??_V*s)M??_V* !,g?uךg )#?h]~9/)ǃ?+<l :mPص5ƿ4IAbv)Kp2z ɻ?iqQE~g߱mkϿc? 5y$?)_)_׋ÇEWQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW5Uj+;j> LjS]|F֮|=i:ΟxzͭxڵÙw]YO}ֺOU|-KOV?/y,.OVNƊ45 z kZO|3]'M;-R4-B,tkEtWIt{7Rxnf QZ3g )FIJ2R%u(tM4it j5pjЯJ *Nj5*uhէ' Ӛԧ8N$dMQL+4Νg?[/;TO"m|c 妏 Que߱}V'K_ou; xYӯ;J+X"V9sRBtzj18j8jЧ_Vjp/0GIմG|k߲G wCLMLE}_ + }Tu/þ5#Ҽ~uGD&l?F]^I@ϡ:Us]I+N>$7_?i/ӦNӯdk{lu>iJtm:T,EZXztt3 <>oB OweNUEQ@Q@|9`M?h+}_|9`M?h+}@7RGdg__5?sgW|sˇ_W|SVyקu$kk;_׍!ioڃůٯO^5gӃR ad<wӋP|UH> <^| ?|Lק6zi% o'Ꮗ"\ZMME9o)˥|Df>|_!W()WUG |q:VΑx~H< }:VxK–hƯ~t (~j?gg<_>">"̾'S_?,_XkzN+]^H '&}kXѯo j?i_S?ǿ~ WhXf_>)f_c+eI4M'A V>}ggg>5whqgd~O5o^/eQ_o!EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP~ڟ?g-_]οωgwcĿ۩?/NJ_k?<@~??x?Ծ fν?oEK~~>վX|: jz|h~$2N Cj>M[O/|-C mSs?<%;Zlx[ź=S7Xm?CI-.êXYj6w}ims?\m.6n #rʧG/ĮdNx*>ӑQVQOGU?jу _k ׈)ҡt2<գ[y:rN|ڦ7UJUugYn?SW+ ( ?i(2Rɵ/ҭg6isOI敤xb(<Ӭ߇>.+kxᗮQ^nk4º>x\Ug-(9fa u)aNjԥ_S eXV3st=X<#JtfXNkFShpy__t1Y^?KMԴgN4{-WIlu-/Tnӵ-:o/dX-n $hdxXݪVnA%aeK{jRZgko{ڦtgo.i^vֽ}?{a>s{>C a>)}kYqWן{O{>^zEVEP)GOZ+ _g*o d'ŏx7Þ⟌h*%kU_$~2~=sz`@7RGd/I?l9/Woxd 0 ]Mקs$ol~^>%c\j5?U^|/xGGκ? w௉~?mžσڟ?|%Y?uMCI?m>:w֗6K wq^#.ϨFuiPВ&*߻j)Q?IxlҾ/z9 瘊o}m24_&XjMJg_1~ǿWÏ3~Ǐ,%l 񧅴^]bx4>? 5+@V|CyhxBEi/|K^};_ pl~!OrfGĜ9cr\'):8ܷ4˱0"U(W89BR4t2( ( ( ( (>s)M??_V*s)M??_V* !,g '^j!,g?uw狟Opx# U :mPص6~ k; :mPص5ƿ,pRa1? ɻ?iqQE~g߱mkϿc? 5y$?)_)_׋ÇEWQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE#_O|d/|Kg#?>6tY|X\x~ſ?XAnϭj? <8"75S O& _µ/?l>Lg߱mf_S?3?{|  eW-Gτ 0 Ş)x¿t}Phׇa6xJCxBY F=_ִĹZEO:&V*>gSR.P<~ g҅9UScIGo Hq8n:8 |O،kѥOFURe?u3(?dG/Q  і~ɟ__l 1=?O߅c@ć_1+9a_231¿eg#ci?~YF?HxwOOӗ,?G0?+FY&9|:l 1=߅c@ć_1+9a_231¿eg#ci?~YF?HxwOOӗ,?G0?+FY&9|:l 1=߅c@ć_1+9a_231¿eg#ci?~YF?HxwOOӗ,?G0?+FY&9|:l 1=߅c@ć_1+9a_231¿eg#ci?~YF?HxwOOӗ,?G0?+FY&9|:l 1=߅c@ć_1+9a_231¿eg#ci?~YF?HxwOOӗ,?G0?+FY&9|:l 1=߅c@ć_1+9a_231¿eg#ci?~YF?HxwOOӗ,?G0?+FY&9|:l 1=߅c@ć_1+9a_231¿eg#ci?~YF?HxwOOӗ,?G0?+FY&9|:l 1=߅c@ć_1+9a_231¿eg#ci?~YF?HxwOOӗ,?G0?+FY&9|:l 1=߅c@ć_1+9a_231¿eg#ci?~YF?HxwOOӗ,?G0?+FY&9|:l 1=߅c@ć_1+9a_231¿eg#ci?~YF?HxwOOӗ,?G0?+FY&9|:l 1=߅c@ć_1zU^xCw | tZ՞x;mOQY}kW>u m&P|C=Ifּ+&4;񮬚_{,?G0?+FY&9|:g;3컊2T1,&7օ/?ZpM_ >5W⧍?h_{O5`~ xYӭ[Z/e9u]F'bASZobҦ,sY wL_&/"|U|q&KĿ>xO |eψ&xwYw-_G4WB kf]yWW0E{_>/u~L|߄u/¾)WJ[C >5_j _=j?4x;m{(+glUx?ox{:Ν /Qhu}S{]/͍vv:ͭψx: /xW >|NѴ->+9f汨Ѽ2\5E~WG оxMt?i;/>&Pek/o-?J?X|׌~)?=W_:GXaD˩Aj_?7v( ( xWÚ\O^^OYW:τo`-|F`MmHuK^0?low ;} b#-#]Ѧ#,ZO'_|Y?ǟgMW/|4Q) i;e~l to]/_,DOϾ2M|ZaNQEW|teoi[8+O_ ?0g#OE?  o'_zGg{|?~xOI;x~?o|@GUc>-N5 _Iִ;g$?x>|SW_oįG?]|O^L|G{^#Ӽ[J[j; LVk={0Z?e$hg^ '#?¤x? #؟W}OQEW|teoi[8+O_ ?0g#OE?  o'_zGg{|?~xOI;x~?o|@GUc>-N5 _Iִ;g$?|kbٯZh`m[,Ÿ~*Լ+}=xŚy_B4]fM:Qѵ[n^NGڟ wg@?f߃^"oy3.'Gğ<#Rx[??~~17i_x>-GQEWk~~~uF|q?:-|'_Ŀ+;U,|3Zփ^xHеRFQӴmVgӯ%+>1ƕ+S.|,ß>|Mؾ8S◅9xර? xwW#ۿ 1`Wo| |_M;Ꮘ|O/HHguF|+yi˧x[k:t?On.{ /~N}ğ,[t)>{6m|:ix[ï|X __wQe~QE,|,Mwƿ2g$~)xß cOjZGjVhjo5=?Loom+/[xVYk?9+C{:w о>kVσ<,|Y /K|V_~~4~ ASKŞ׉50Yb|`пg~}S񧊬5|'>Őx'~ _mtm\`~&[eAXY/`e?F~"-> x_ؚơg Ե 5] S.>iu^\?ğwm?i~~2P?>|E?>/|v /w*_kK?_SǿGOŏī KX1~˟ƿ|| 3֟/xW17~t _+oc/ wX|E/5Woڧ|u<ӼOm{|?/袊( |q'_VE[<[^*)=|LU[Q O ߴOw>.|{='¿zW}#?..=/c,|$-߳W?Р@#AoSX;MhZWo|Jm&>-Ѵ OhY9j9~|0ğ|J~ xC_%_>*>c^Zx:GĿ:xKum; V-SJxWP> Sºot+XΡZg =#]K=FNt魒Qo :YzW?_# ={8> Ue??k/ٛ_Cjj?wo Mk[Iֿd?Ư{IO%)]|Mh ?_"|-x$Oh)о|8|7MCďcZ ]_^3౟?+΃^j!,g?uOx# U :mPص5ƿ4IAbv)Kp2w1&(eEWW|teڃoi٧?+_#OE??o'ڿؚGgQEQEWk~Ҟ F|?:O-|Y;_OT;U|M{Z.YHu.YQӵVo"(~𯀼+>_|~wm;Þ|9[hφ|=Y-"KѴm.N[kh-%( ( |'[h:χm~΍O ¾4|'x:7em_K5xT6cyj> mus[>~߲~5im ,_^7} aM~!xwÚw|U Wt?>#?xIk⧊ :c?>:𞽫~WuRFNuVdo%( K"|$ֱ"~^K›|½FMcᇆ~xr?xIk⧊ :c?>:𞽫~WuRFNuVdo%( K"|$ֱ"~^K›|½FMcᇆ~xr#_? 1/`~o w_ |q_~};;gᏇO=SHHtѼ+gͧxk&htVOEQE,Mwoƿ0|2Gg$)x7ß< /McOiiVhi`4?Sl(5؋/ ~!?f w|.|Y_:/:]^x /'?|9 xY;=FyYii5Q~𯀼+>_|~wm;Þ|9[hφ|=Y-"KѴm.N[kh-%((('~< ߋOGᕷ|Xuïx⟋xş9~/("zz[ Η>(5'Nll.m+Ea|-Ow4/>|??:[|?'CZ|'?AX Nͽ_@ !,guמc )$h]~:/)Ã';}#M>$Ue@>oe`,kCVU|Wh?-;g(+I~/KIymoyyyۿ"?E{}$|oj~9sL|# yOenc-<=b6# ZP!dxZ_yM ٷ#'"X6͡C1'ܒҔ,E>LM6V7~7g!سP71Im2p0?7$OE~I^-I$K+ᤒVI$K$VKk.#_v'B_emAGB_emAEt~v5חI<$TH //do a ׈$> Gu쯵#R?l\|FU/袿uLn UտGoV3}O3~5nHrAIyOƟ_Bg25"'|K}s9O>o+W1rU'+WOV}}; D|98_߳/s&ō/LPo*·Epi(*%Q{e-e/+Vʶ'+W*Ɗ(; D9;}_?,|y o*Կ>#[*QO*_Y">/~̷8/o+*o+O_QE/ӻ :GÞgQ{e-e(s[Lo+cO_QE?ӻ :Gß/f_"M__؟>#[*>#\#_(*ο%Qe.deo+O_S\F?Q?wAg_sTw7,|/?\F?VVk>#[*QGTI#ϗQH?߳-.des&¹Eli(*ο$EٗH7ݍo*·Eti(*ο$EٗH(·Eti_Wm(*ο$EٗH(¸Es%Z]|·Eti(*ο$Eٖ2oX2B¸Eo,__ 7EOY">y(22X2A 7G+VʶQ?wAg_sTw\cWWm?\|FU/袗TI#A^?,|y qYVo+e[)[} D|9;Q{e.dea 7G+VʶR; D9;}^?,y qYVo+e[)OY">/~̿E̟?_q _noCZ]K[(eob??koW~qB_emAE_MNg¼3c`Ϋsq-Kbyn"ӥOUJ)b_=1>\->W<|-Ùg1u8^a_aⱘgqXR7$47$4+?t~w359<~Ao#S K#OL((K#OL((N{u'_#oS~}IW#|=u˿W|a {mj5_o~ooYyO%(ݙZ_|ExoҢ|S:x<&AX=^f set_preferdual

set_preferdual

Sets the desired combination of primal and dual simplex algorithms.

void set_preferdual(lprec *lp, unsigned char dodual);

Return Value

set_preferdual has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

dodual

When TRUE, the simplex strategy is set to SIMPLEX_DUAL_DUAL.
When FALSE, the simplex strategy is set to SIMPLEX_PRIMAL_PRIMAL.
See also get_simplextype

Remarks

The set_preferdual function sets the desired combination of primal and dual simplex algorithms.
set_preferdual with dodual = TRUE is a shortcut for set_simplextype(SIMPLEX_DUAL_DUAL)
set_preferdual with dodual = FALSE is a shortcut for set_simplextype(SIMPLEX_PRIMAL_PRIMAL)
The default is SIMPLEX_DUAL_PRIMAL (6).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_preferdual(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_simplextype

doc/changes5.htm0000644000175000017500000013260010553537242012506 0ustar renerene Changes from version 4 to version 5.1

Changes from version 4 to version 5.1

Main features and changes to v5.1 compared to v4

Overall, the v5 code is faster and more robust than v4. This robustness is for example proven by the fact that many more models can now be solved even without scaling. However, scaling should still be considered. The API has also routine to do a crash of basis (determine a starting point so that solving goes faster). The lp_solve program has been extended with options to handle the new functionality. It now also has options to write the model in the different file formats.
  • The modularization started in v4 has been significantly enhanced.
  • Internal logic and naming is much more in compliance with conventional usage.
  • Advanced pricing using Devex and Steepest Edge for both primal and dual simplexes.
  • Scaling behavior is made more consistent and many more options are available.
  • Presolve has been radically expanded.
  • A crash basis routine has been added to determine a starting point. This can improve solving time.
  • It is now possible to select desired combinations of primal and dual phases 1 and 2.
  • The native etaPFI/inverse has been improved with optimization of column ordering.
  • Alternative inverse/re-factorization libraries can be used by lp_solve. See Basis Factorization Packages
  • Alternative model readers and writers possible via the XLI implementation. See External Language Interfaces
  • B&B code has been made non-recursive (no more stack overflows!).
  • MIP contains many more variable selection and branching strategies, including pseudo-costs.
  • SOS and SC handling is faster (more branches avoided).
  • LP file support is expanded and now also includes full CPLEX LP format support.
  • Building the model via the API interface row by row can be improved spectacular by calling the new API call set_add_rowmode.

Changes in lp_solve program

The lp_solve program has many new options to make use of as many as possible possibilities of lpsolve. There are several extra options, some are extended and some are removed because they are obsolete. See lp_solve for a list of all possible options. Note that on this link there is also a reference to the API call(s) that are used for this option. There you can find more information on the option. See the list above for some of the new features.

What happened with lp2mps, mps2lp ?

These programs are removed. But don't panic, there is another way to convert from one format to another. This via the lp_solve program. This is done because of the support of a new format: The CPLEX-format. Because there are now 3 formats supported, it would have required 6 programs to convert from one format to another. Instead of doing this, lp_solve has new parameters to be able to write the model to a file, and that in all formats. So, lp_solve can read the model in any format and write it back in any format. In that case, it is most likely not whished to also calculate the model and therefore the parameter -parse_only can be used. Here some examples how to convert from one format to another:

lp to mps: lp_solve -parse_only -lp lpfile -wmps mpsfile
mps to lp: lp_solve -parse_only -mps mpsfile -wlp lpfile

It is even possible to generate several formats at the same time:
lp to all formats: lp_solve -parse_only -lp lpfile -wlp lpfile -wmps mpsfile

Changes in API calls

The API is not that much changed, but has been expanded to handle new functionality. Some simplification has taken place, for example in scaling, and a call to auto_scale is not necessary any more.
However the changes in some routines is big enough to break compatibility with version 4. Be aware of this. You must review your source code for the mentioned functions. Especially those with a (!) behind are very important to check. That is also the reason why the Windows dll will be called lpsolve51.dll compared to lpsolve.dll for version 4. Don't just rename this dll and expect that your program will work then.

Changed API calls

  • add_column, str_add_column
    • Return value is now unsigned char instead of int

  • add_constraint, str_add_constraint (!)
    • Return value is now unsigned char instead of int
    • Variable constr_type is now int instead of short
    • The constant LE has now value 1 instead of 0
      The constant EQ has now value 3 instead of 1

  • add_lag_con, str_add_lag_con (!)
    • Return value is now unsigned char instead of int
    • Variable constr_type is now int instead of short
    • The constant LE has now value 1 instead of 0
      The constant EQ has now value 3 instead of 1

  • add_sos (!)
    • Variable sostype is now int instead of short

  • column_in_lp (!)
    • Return value is now int instead of unsigned char

  • del_column
    • Return value is now unsigned char instead of int

  • del_constraint
    • Return value is now unsigned char instead of int

  • get_basis (!)
    • An extra variable is added to the argument list: nonbasic

  • get_bb_floorfirst (!)
    • This function is renamed. Before it was called get_floor_first
    • Return value is now int instead of short

  • get_bb_rule (!)
    • Return value is now int instead of short
    • The function returns different constants for different rules.

  • get_bounds_tighter
    • Return value is now unsigned char instead of int

  • get_col_name
    • When no name is set, the function now returns Cx instead of v_x

  • get_column
    • Return value is now unsigned char instead of int

  • get_constr_type (!)
    • The constant LE has now value 1 instead of 0
      The constant EQ has now value 3 instead of 1

  • get_constraints, get_ptr_constraints
    • Return value is now unsigned char instead of int

  • get_improve (!)
    • Return value is now int instead of short
    • Constant IMPROVE_FULL is renamed to IMPROVE_SOLVE
    • New constant IMPROVE_INVERSE

  • get_infinite (!)
    • The new default infinite value is 1e30 instead of 1e24

  • get_lambda, get_ptr_lambda
    • Return value is now unsigned char instead of int

  • get_maxpivot
    • This function is renamed. Before it was called get_max_num_inv

  • get_mip_gap (!)
    • An extra variable is added to the argument list: absolute

  • get_pivoting (!)
    • This function is renamed. Before it was called get_piv_rule
    • Return value is now int instead of short
    • The function returns different constants for different rules.

  • get_presolve (!)
    • This function is renamed. Before it was called is_do_presolve
    • Return value is now int instead of short
    • The function now returns constants instead of FALSE or TRUE.

  • get_primal_solution, get_ptr_primal_solution
    • Return value is now unsigned char instead of int

  • get_print_sol (!)
    • This function is renamed. Before it was called is_print_sol
    • Return value is now int instead of short
    • The function now also returns the constant AUTOMATIC.

  • get_rh_range (!)
    • The new default range value is 1e30 instead of 1e24

  • get_row
    • Return value is now unsigned char instead of int

  • get_row_name
    • When no name is set, the function now returns Rx instead of r_x

  • get_scaling (!)
    • This function is renamed. Before it was called get_scalemode
    • Return value is now int instead of short
    • The function returns different constants.

  • get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex (!)
    • Return value is now unsigned char instead of int
    • If there are integer variables, then these functions only work if set_presolve is called with parameter PRESOLVE_SENSDUALS before solve.

  • get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution (!)
    • Return value is now unsigned char instead of int
    • If there are integer variables, then these functions only work if set_presolve is called with parameter PRESOLVE_SENSDUALS before solve.
    • get_dual_solution is renamed. Before it was called get_reduced_costs
    • get_ptr_dual_solution is renamed. Before it was called get_ptr_reduced_costs

  • get_upbo (!)
    • The new default upper bound is 1e30 instead of 1e24

  • get_var_branch
    • Return value is now int instead of short

  • get_var_priority (!)
    • This function is renamed. Before it was called get_varpriority

  • get_variables, get_ptr_variables
    • Return value is now unsigned char instead of int

  • get_verbose (!)
    • Return value is now int instead of short
    • Return value can now also be NEUTRAL

  • is_anti_degen (!)
    • Return value is now unsigned char instead of short
    • An extra variable is added to the argument list: testmask

  • is_break_at_first
    • Return value is now unsigned char instead of short

  • is_debug
    • Return value is now unsigned char instead of short

  • is_feasible (!)
    • Return value is now unsigned char instead of int
    • An extra variable is added to the argument list: threshold

  • is_int
    • Return value is now unsigned char instead of int

  • is_lag_trace
    • Return value is now unsigned char instead of short

  • is_presolve (!)
    • This function is renamed. Before it was called is_do_presolve
    • Return value is now unsigned char instead of short
    • An extra variable is added to the argument list: testmask

  • is_SOS_var
    • Return value is now unsigned char instead of int

  • is_trace
    • Return value is now unsigned char instead of short

  • print_constraints (!)
    • An extra variable is added to the argument list: columns

  • print_solution (!)
    • An extra variable is added to the argument list: columns

  • read_lp, read_LP
    • Variable verbose is now int instead of short

  • read_mps, read_MPS
    • Variable verbose is now int instead of short

  • set_anti_degen (!)
    • Variable anti_degen is now int instead of short. Instead of FALSE/TRUE it takes new constants.

  • set_basis (!)
    • An extra variable is added to the argument list: nonbasic

  • set_bb_floorfirst (!)
    • This function is renamed. Before it was called set_floor_first
    • Variable branch_mode is now int instead of short

  • set_bb_rule (!)
    • Variable bb_rule is now int instead of short
    • Variable bb_rule now takes other constants.

  • set_bounds
    • Return value is now unsigned char instead of int

  • set_bounds_tighter
    • Variable tighten is now unsigned char instead of int

  • set_break_at_first
    • Variable break_at_first is now unsigned char instead of short

  • set_col_name
    • Return value is now unsigned char instead of int

  • set_constr_type (!)
    • Return value is now unsigned char instead of int
    • Variable constr_type is now int instead of short
    • The constant LE has now value 1 instead of 0
      The constant EQ has now value 3 instead of 1

  • set_debug
    • Variable debug is now unsigned char instead of short

  • set_epsint (!)
    • This function is renamed. Before it was called set_epsilon

  • set_improve (!)
    • Variable improve is now int instead of short
    • Constant IMPROVE_FULL is renamed to IMPROVE_SOLVE
    • New constant IMPROVE_INVERSE

  • set_int
    • Return value is now unsigned char instead of int
    • Variable must_be_int is now unsigned char instead of short

  • set_lag_trace
    • Variable lag_trace is now unsigned char instead of short

  • set_lowbo
    • Return value is now unsigned char instead of int

  • set_lp_name
    • Return value is now unsigned char instead of int

  • set_mat
    • Return value is now unsigned char instead of int

  • set_maxpivot
    • This function is renamed. Before it was called set_max_num_inv

  • set_mip_gap (!)
    • An extra variable is added to the argument list: absolute

  • set_obj_fn, str_set_obj_fn
    • Return value is now unsigned char instead of int

  • set_outputstream, set_outputfile (!)
    • The function set_outputfile is renamed. Before it was called print_file
    • Variable lp is added. Output is now set per lp.
    • The function set_outputstream is new

  • set_pivoting (!)
    • This function is renamed. Before it was called set_piv_rule
    • Variable pivot_rule is now int instead of short
    • The function uses different constants for different rules.

  • set_presolve (!)
    • This function is renamed. Before it was called set_do_presolve
    • Variable do_presolve is now int instead of short
    • The function uses different constants for different rules.

  • set_print_sol (!)
    • Variable print_sol is now int instead of short
    • Variable print_sol now also takes the value AUTOMATIC.

  • set_rh
    • Return value is now unsigned char instead of int

  • set_rh_range
    • Return value is now unsigned char instead of int

  • str_set_rh_vec
    • Return value is now unsigned char instead of int

  • set_row_name
    • Return value is now unsigned char instead of int

  • set_scaling (!)
    • This function is renamed. Before it was called set_scalemode
    • Variable scalemode is now int instead of short
    • The function uses different constants for different rules

  • set_semicont
    • Return value is now unsigned char instead of int
    • Variable must_be_sc is now unsigned char instead of short

  • set_trace (!)
    • Variable trace is now unsigned char instead of short

  • set_upbo
    • Return value is now unsigned char instead of int

  • set_var_branch
    • Return value is now unsigned char instead of int
    • Variable branch_mode is now int instead of short

  • set_var_weights (!)
    • This function is renamed. Before it was called set_varweights
    • Return value is now unsigned char instead of int

  • set_verbose (!)
    • Variable verbose is now int instead of short
    • Variable verbose can now also be NEUTRAL.

  • solve (!)
    • The return values of this function have changed.

  • write_lp, write_LP
    • Return value is now unsigned char instead of int

  • write_mps, write_MPS
    • Return value is now unsigned char instead of int

New API calls

Removed API calls

doc/set_presolve.htm0000644000175000017500000002140610447454036013525 0ustar renerene set_presolve

set_presolve

Specifies if a presolve must be done before solving.

void set_presolve(lprec *lp, int do_presolve, int maxloops);

Return Value

set_presolve has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

do_presolve

Specifies presolve level. Can be the (OR) combination of any of the following values:

PRESOLVE_NONE (0) No presolve at all
PRESOLVE_ROWS (1) Presolve rows
PRESOLVE_COLS (2) Presolve columns
PRESOLVE_LINDEP (4) Eliminate linearly dependent rows
PRESOLVE_SOS (32) Convert constraints to SOSes (only SOS1 handled)
PRESOLVE_REDUCEMIP (64) If the phase 1 solution process finds that a constraint is redundant then this constraint is deleted. This is no longer active since it is very rare that this is effective, and also that it adds code complications and delayed presolve effects that are not captured properly.
PRESOLVE_KNAPSACK (128) Simplification of knapsack-type constraints through addition of an extra variable, which also helps bound the OF
PRESOLVE_ELIMEQ2 (256) Direct substitution of one variable in 2-element equality constraints; this requires changes to the constraint matrix
PRESOLVE_IMPLIEDFREE (512) Identify implied free variables (releasing their explicit bounds)
PRESOLVE_REDUCEGCD (1024) Reduce (tighten) coefficients in integer models based on GCD argument
PRESOLVE_PROBEFIX (2048) Attempt to fix binary variables at one of their bounds
PRESOLVE_PROBEREDUCE (4096) Attempt to reduce coefficients in binary models
PRESOLVE_ROWDOMINATE (8192) Idenfify and delete qualifying constraints that are dominated by others, also fixes variables at a bound
PRESOLVE_COLDOMINATE (16384) Deletes variables (mainly binary), that are dominated by others (only one can be non-zero)
PRESOLVE_MERGEROWS (32768) Merges neighboring >= or <= constraints when the vectors are otherwise relatively identical into a single ranged constraint
PRESOLVE_IMPLIEDSLK (65536) Converts qualifying equalities to inequalities by converting a column singleton variable to slack. The routine also detects implicit duplicate slacks from inequality constraints, fixes and removes the redundant variable.This latter removal also tends to reduce the risk of degeneracy.The combined function of this option can have a dramatic simplifying effect on some models
PRESOLVE_COLFIXDUAL (131072) Variable fixing and removal based on considering signs of the associated dual constraint
PRESOLVE_BOUNDS (262144) Does bound tightening based on full-row constraint information. This can assist in tightening the OF bound, eliminate variables and constraints. At the end of presolve, it is checked if any variables can be deemed free, thereby reducing any chance that degeneracy is introduced via this presolve option.
PRESOLVE_DUALS (524288) Calculate duals
PRESOLVE_SENSDUALS (1048576) Calculate sensitivity if there are integer variables

maxloops

The maximum number of times presolve may be done. Use get_presolveloops if you don't want to change this value.


Remarks

The set_presolve function specifies if a presolve must be done before solving. Presolve looks at the model and tries to simplify it so that solving times are shorter. For example a constraint on only one variable is converted to a bound on this variable (and the constraint is deleted). Note that the model dimensions can change because of this, so be careful with this. Both rows and columns can be deleted by the presolve.
The maxloops variable specifies the maximum number of times presolve is done. After a presolve is done, another presolve can again result in elimination of extra rows and/or columns. This number specifies the maximum number of times this process is repeated. By default this is until presolve has nothing to do anymore. Use get_presolveloops if you don't want to change this value.
Note that PRESOLVE_LINDEP can result in deletion of rows (the linear dependent ones). get_constraints, get_ptr_constraints will then return only the values of the rows that are kept and the values of the deleted rows are not known anymore. The default is not (PRESOLVE_NONE) doing a presolve. The following code can be used to retrieve the values of all the variables, even if variables are deleted by presolve:

int Norig_columns, Norig_rows, i;
REAL value;

Norig_columns = get_Norig_columns(lp);
Norig_rows = get_Norig_rows(lp);
for(i = 1; i <= Norig_columns; i++) {
  value = get_var_primalresult(lp, Norig_rows + i);
  printf("%f\n", value);
}

Note that there is no possibility to get the values of deleted rows.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_presolve(lp, PRESOLVE_ROWS | PRESOLVE_COLS | PRESOLVE_LINDEP, get_presolveloops(lp));

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_presolve, get_presolveloops, is_presolve

doc/is_feasible.htm0000644000175000017500000000741110242167234013252 0ustar renerene is_feasible

is_feasible

Checks if provided solution is a feasible solution.

unsigned char is_feasible(lprec *lp, REAL *values, REAL threshold);

Return Value

is_feasible returns FALSE (0) or TRUE (1) that indicates if provided solution is feasible.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

values

An array of row/column values that are checked against the bounds and ranges.
The array must have get_Nrows+get_Ncolumns elements. Element 0 is not used.

threshold

A tolerance value. The values may differ that much. Recommended to use get_epsint for this value.

Remarks

The is_feasible function checks if provided solution is a feasible solution. All values of the values array must be between the bounds and ranges to be a feasible solution.
This value is only valid after a successful solve or lag_solve.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL values[1+2];
  unsigned char feasible;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  values[0] = 0.0;
  values[1] = 1.0;
  values[2] = 2.0;
  feasible = is_feasible(lp, values, 0); /* Will return TRUE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_objective, get_working_objective, get_variables, get_ptr_variables, get_constraints, get_ptr_constraints, get_constr_value, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex

doc/set_debug.htm0000644000175000017500000000452710237176662012764 0ustar renerene set_debug

set_debug

Sets a flag if all intermediate results and the branch-and-bound decisions must be printed while solving.

void set_debug(lprec *lp, unsigned char debug);

Return Value

set_debug has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

debug

TRUE or FALSE. Debug or do not debug.

Remarks

The set_debug function sets a flag if all intermediate results and the branch-and-bound decisions must be printed while solving. This function is mend for debugging purposes. The default is not to debug (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_debug(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_debug

doc/bas-format.htm0000644000175000017500000001234210616155236013043 0ustar renerene MPS bas file format

MPS bas file format

The MPS format can also be used to specify some predefined basis for an LP problem, i.e. to specify which rows and columns are basic and which are non-basic.

As in the MPS format, a number of fields are defined on fixed column positions:

Field:    1           2          3         4         5         6
Columns:  2-3        5-12      15-22     25-36     40-47     50-61

The order of a basis file in the MPS format is:

  • NAME indicator card;
  • data cards (can appear in arbitrary order);
  • ENDATA indicator card.

Any line with an asterisk (*) in Column 1 is treated as a comment.

The NAME card can have anything you want, starting in column 15.
lp_solve sets the number of iterations, the number of rows and number of columns of the model to the NAME record.

The eight character names used to specify variables and constraints entities are fixed format. Names are not automatically justified, so blanks are treated just like other characters. For example "ROW1 " is not the same as " ROW1 ". (Note that some optimisers do not permit blanks in names.) No case conversion is performed, so "row1 " is different from "ROW1 ".

Each data card specifies either a pair "basic column--non-basic row" or a non-basic column. All the data cards have the following format.

'XL' in the field 1 means that a column, whose name is given in the field 2, is basic, and a row, whose name is given in the field 3, is non-basic and placed on its lower bound.

'XU' in the field 1 means that a column, whose name is given in the field 2, is basic, and a row, whose name is given in the field 3, is non-basic and placed on its upper bound.

'LL' in the field 1 means that a column, whose name is given in the field 3, is non-basic and placed on its lower bound.

'UL' in the field 1 means that a column, whose name is given in the field 3, is non-basic and placed on its upper bound.

The field 2 contains a column name.

If the indicator given in the field 1 is 'XL' or 'XU', the field 3 contains a row name. Otherwise, if the indicator is 'LL' or 'UL', the field 3 is not used and should be empty.

The field 4, 5, and 6 are not used and should be empty.

ValueStatus
XUVariable 1 is basic; variable 2 is nonbasic at its upper bound
XLVariable 1 is basic; variable 2 is nonbasic at its lower bound
ULVariable 1 is nonbasic and is at its upper bound
LLVariable 1 is nonbasic and is at its lower bound

Field 1: Indicator specifying status of the named variables in Fields 2 and 3.

Field 2: Variable 1 identifier

Field 3: Variable 2 identifier (ignored if Field 1 is UL or LL)

Variable 1 specifies a structural variable identifier which has entered the basis. By convention, this structural variable must displace one of the row variables. Variable 2 is a row variable that has left the basis. No relationship between structural variables entering the basis and row variables leaving the basis is implied within the BAS file.

A basis file in the MPS format acts like a patch: it doesn't specify a basis completely, instead that it is just shows in what a given basis differs from the "standard" basis, where all rows (auxiliary variables) are assumed to be basic and all columns (structural variables) are assumed to be non-basic.

A basis defines a list of basic structural variables and row variables. A structural variable is one of the variables (columns) defined in the MPS problem file. A row variable is actually the slack, surplus, or artificial variable associated with a row. The total number of basic variables-both structural and row-is equal to the number of rows in the constraint matrix. Additionally, the number of basic structural variables is equal to the number of nonbasic row variables. By convention, an MPS basis file is built on the assumption that all row variables are basic and that all structural variables are nonbasic with values at their lower bound. The data records in a BAS file list structural and row variables that violate this assumption. This convention minimizes the size of the BAS file.

Example:

*000000001111111111222222222233333333334444444444555555555566
*234567890123456789012345678901234567890123456789012345678901
NAME          TESTPROB Iterations 0 Rows 3 Cols 3
 XL ZTHREE    LIM2
 UL XONE
ENDATA
doc/get_print_sol.htm0000644000175000017500000000537610246357650013674 0ustar renerene get_print_sol

get_print_sol

Returns a flag if all intermediate valid solutions must be printed while solving.

int get_print_sol(lprec *lp);

Return Value

get_print_sol returns the debug print status. Can by any of following values: Can be any of the following values:

FALSE (0) No printing
TRUE (1) Print all values
AUTOMATIC (2) Print only non-zero values

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_print_sol function returns a flag if all intermediate valid solutions must be printed while solving. Can give you useful solutions even if the total run time is too long. This function is mend for debugging purposes. The default is not to print (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int doprint;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  doprint = get_print_sol(lp); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_print_sol

doc/get_total_nodes.htm0000644000175000017500000000450010237210144014144 0ustar renerene get_total_nodes

get_total_nodes

Returns the total number of nodes processed in branch-and-bound.

long long get_total_nodes(lprec *lp);

Return Value

get_total_nodes returns the total number of nodes processed in branch-and-bound of the last solution.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_total_nodes function returns the total number of nodes processed in branch-and-bound of the last solution.
Is only applicable if the model contains integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int total_nodes;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  total_nodes = get_total_nodes(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_max_level, get_total_iter

doc/dualize_lp.htm0000644000175000017500000000406710310666504013141 0ustar renerene dualize_lp

dualize_lp

Create the dual of the current model.

unsigned char dualize_lp(lprec *lp);

Return Value

Returns TRUE if succeeded.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /*
  .
  .
  .
  */

  dualize_lp(lp);

  /*
  .
  .
  .
  */

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, delete_lp, free_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

doc/get_constr_type.htm0000644000175000017500000000574510237214776014235 0ustar renerene get_constr_type

get_constr_type

Gets the type of a constraint.

int get_constr_type(lprec *lp, int row);

Return Value

get_constr_type returns the type of the constraint on row row. Can by any of the following values:

LE (1) Less than or equal (<=)
EQ (3) Equal (=)
GE (2) Greater than or equal (>=)

If there is an error then the function returns -1.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the constraint type must be retrieved. Must be between 1 and number of rows in the lp.

Remarks

The get_constr_type function returns the constraint type for the specified row.
The default constraint type is LE.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int constr;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  constr = get_constr_type(lp, 1); /* will be 1 (LE) */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_constr_type, set_constr_type, add_constraint, add_constraintex, str_add_constraint, del_constraint

doc/get_infinite.htm0000644000175000017500000000536610237176654013472 0ustar renerene get_infinite

get_infinite

Returns the value of "infinite".

REAL get_infinite(lprec *lp);

Return Value

get_infinite returns the value of "infinite".

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_infinite function returns the practical value for "infinite". This value is used for very big numbers. For example the upper bound of a variable without an upper bound.
The default is 1e30

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL infinite;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  infinite = get_infinite(lp); /* will return 1.0e30 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_infinite, is_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb

doc/set_output.htm0000644000175000017500000001200010617377744013225 0ustar renerene set_outputstream, set_outputfile

set_outputstream, set_outputfile

Defines the output when lp_solve has something to report.

void set_outputstream(lprec *lp, FILE *stream);

unsigned char set_outputfile(lprec *lp, char *filename);

Return Value

set_outputstream has no return value.

set_outputfile returns TRUE (1) if the file could be opened, else FALSE (0).

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

stream

The stream to print the results to. If NULL, then output is stdout again.

filename

The file to print the results to. If NULL, then output is stdout again. If "", then output is ignored. It doesn't go to the console or to a file then. This is usefull in combination with put_logfunc to redirect output to somewhere completely different.

Remarks

The set_outputstream, set_outputfile functions define the output when lp_solve has something to report.
This is done at the same time as something is reported via put_logfunc. The default reporting output is screen (stdout). If set_outputstream is called to change output to another stream, then be aware that the stream is not closed automatically when delete_lp is called. Output must be set again to stdout (or NULL) to close this handle or the handle must be closed by the application via a call to fclose afterwards. This allows the application to still print to the stream even after the lp structure is cleaned up. If set_outputfile is called to change output to the specified file, then the file is automatically closed when delete_lp is called. Note that this was not the case in previous versions of lp_solve. If filename is "", then output is ignored. It doesn't go to the console or to a file then. This is usefull in combination with put_logfunc to redirect output to somewhere completely different.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_outputfile(lp, "log.txt");

  /*
  .
  .
  .
  */

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, put_logfunc, print_lp, print_objective, print_solution, print_constraints, print_duals, print_scales, print_tableau, print_str, print_debugdump, write_lp, write_LP, write_mps, write_freemps, write_MPS, write_freeMPS, write_basis

doc/set_scalelimit.htm0000644000175000017500000000532110237176664014017 0ustar renerene set_scalelimit

set_scalelimit

Sets the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations.

void set_scalelimit(lprec *lp, REAL scalelimit);

Return Value

set_scalelimit has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

scalelimit

The relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations

Remarks

The set_scalelimit function sets the relative scaling convergence criterion for the active scaling mode; the integer part specifies the maximum number of iterations (default is 5).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_scalelimit(lp, 3.1);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_scalelimit, set_scaling, get_scaling, is_integerscaling, is_scalemode, is_scaletype

doc/is_add_rowmode.htm0000644000175000017500000001004010237176656013770 0ustar renerene is_add_rowmode

is_add_rowmode

Returns a flag which of the add routines perform best.

unsigned char is_add_rowmode(lprec *lp);

Return Value

is_add_rowmode returns TRUE or FALSE. If FALSE, then add_column, add_columnex, str_add_column performs best. If TRUE, then add_constraint, add_constraintex, str_add_constraint performs best.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

Default, this is FALSE, meaning that add_column, add_columnex, str_add_column performs best. If the model is build via add_constraint, add_constraintex, str_add_constraint calls, then these routines will be much faster if this routine is called with turnon set on TRUE. This is also called row entry mode. The speed improvement is spectacular, especially for bigger models, so it is advisable to call this routine to set the mode. Normally a model is build either column by column or row by row.
Note that there are several restrictions with this mode:
Only use this function after a make_lp call. Not when the model is read from file. Also, if this function is used, first add the objective function via set_obj_fn, set_obj_fnex, str_set_obj_fn and after that add the constraints via add_constraint, add_constraintex, str_add_constraint. Don't call other API functions while in row entry mode. No other data matrix access is allowed while in row entry mode. After adding the contraints, turn row entry mode back off. Once turned of, you cannot switch back to row entry mode. So in short:
- turn row entry mode on
- set the objective function
- create the constraints
- turn row entry mode off

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char rowmode;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  rowmode = is_add_rowmode(lp); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_add_rowmode, set_add_rowmode, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, add_column, add_columnex, str_add_column, add_constraint, add_constraintex, str_add_constraint

doc/write_lp.htm0000644000175000017500000001056010662056244012635 0ustar renerene write_lp, write_LP, write_lpex

write_lp, write_LP, write_lpex

Write an lp model to a file or via a routine.

unsigned char write_LP(lprec *lp, FILE *stream);

unsigned char write_lp(lprec *lp, char *filename);

unsigned char write_lpex(lprec *lp, void *userhandle, (void *userhandle, char *buf) write_modeldata_routine);

Return Value

The routines return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
write_LP and write_lp write in a file. write_lpex calls routine write_modeldata_routine to pass the data to that must be written. In this routine you can do anything you want with the data. Note that data is provided in undefined shrunks.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

stream

Pointer to FILE structure.

filename

Filename to write the lp model to.

write_modeldata_routine

Routine to write the lp model to. The routine has following definition:
typedef int (__WINAPI write_modeldata_func)(void *userhandle, char *buf);
userhandle is the second parameter passed to write_lpex
buf is a shrunk of data.

Remarks

The write_lp and write_LP functions write the model to filename. write_LP needs a file pointer to an already opened file. write_lp accepts the name of the file. The latter function will generally be more convenient. write_lpex writes the model via a user defined routine.

When stream or filename are NULL, then output is written to output set by set_outputstream, set_outputfile. By default this is stdout.

The model in the file will be in lp-format.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"
int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  write_lp(lp, "model.lp");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_mps, write_freemps, write_MPS, write_freeMPS, MPS_writefileex

doc/is_piv_rule.htm0000644000175000017500000000571110237176660013335 0ustar renerene is_piv_rule

is_piv_rule

Checks if the specified pivot rule is active.

unsigned char is_piv_rule(lprec *lp, int rule);

Return Value

is_piv_rule returns TRUE if the specified pivot rule is active, else FALSE

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

rule

Can be one of the following values:
PRICER_FIRSTINDEX (0) Select first
PRICER_DANTZIG (1) Select according to Dantzig
PRICER_DEVEX (2) Devex pricing from Paula Harris
PRICER_STEEPESTEDGE (3) Steepest Edge

Remarks

This rule can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
The default is PRICER_DEVEX (2).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char piv_rule;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  piv_rule = is_piv_rule(lp, PRICER_FIRSTINDEX);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_pivoting, set_pivoting, is_piv_mode

doc/get_primal_solution.htm0000644000175000017500000001400010351321210015037 0ustar renerene get_primal_solution, get_ptr_primal_solution, get_var_primalresult

get_primal_solution, get_ptr_primal_solution, get_var_primalresult

Returns the solution of the model.

unsigned char get_primal_solution(lprec *lp, REAL *pv);

unsigned char get_ptr_primal_solution(lprec *lp, REAL **ptr_pv);

REAL get_var_primalresult(lprec *lp, int index);

Return Value

get_primal_solution, get_ptr_primal_solution return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
get_var_primalresult returns the value for index.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

pv

An array that will contain the value of the objective function (element 0), values of the constraints (elements 1 till Nrows), and the values of the variables (elements Nrows+1 till Nrows+NColumns).

ptr_pv

The address of a pointer that will point to an array that will contain the value of the objective function (element 0), values of the constraints (elements 1 till Nrows), and the values of the variables (elements Nrows+1 till Nrows+NColumns).

index

index of the constraint/variable.

Remarks

The get_primal_solution, get_ptr_primal_solution, get_var_primalresult functions retrieve the values of the objective function, constraints and variables.
These values are only valid after a successful solve or lag_solve. Function get_primal_solution needs an array that is already dimensioned with 1+get_Nrows + get_Ncolumns elements. get_ptr_primal_solution returns a pointer to an array already dimensioned by lp_solve. Element 0 is the value of the objective function, elements 1 till Nrows the values of the constraints and elements Nrows+1 till Nrows+NColumns the values of the variables. get_var_primalresult requires no array. index is the array element number of the above functions and returns the value for this array element.
Special considerations when presolve was done. When set_presolve is called before solve, then presolve can have deleted both rows and columns from the model because they could be eliminated. This influences get_primal_solution and get_ptr_primal_solution. These functions only report the values of the remaining variables and constraints. However get_var_primalresult returns all values, also the deleted ones by presolve. So index is the original index number as known by the caller.

Note that get_ptr_primal_solution returns a pointer to memory allocated and maintained by lp_solve. Be careful what you do with it. Don't modify its contents or free the memory. Unexpected behaviour would occur. Also note that this memory pointer is only guaranteed to remain constant until a next lp_solve API call is done. You should call this function again to make sure you have again the correct pointer. Otherwise, this pointer could point to invalid memory. This should not be a problem since this call is very efficient.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL pv[1+2+3], *ptr_pv;

  /* Create a new LP model */
  lp = make_lp(3, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  get_primal_solution(lp, pv);
  get_ptr_primal_solution(lp, &ptr_pv);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_constraints, get_ptr_constraints, get_constr_value, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex

doc/get_basis.htm0000644000175000017500000001123711107560215012743 0ustar renerene get_basis

get_basis

Returns the basis of the lp.

unsigned char get_basis(lprec *lp, int *bascolumn, unsigned char nonbasic);

Return Value

get_basis returns TRUE if a basis could be returned, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

bascolumn

An array with 1+get_Nrows or 1+get_Nrows+get_Ncolumns elements that will contain the basis after the call.

nonbasic

If FALSE, then bascolumn must have 1+get_Nrows elements and only contains the basic variables. If TRUE, then bascolumn must have 1+get_Nrows+get_Ncolumns elements and will also contain the non-basic variables.

Remarks

The get_basis function returns the basis of the lp.
This can only be done after a successful solve. If the model is not successively solved then the function will return FALSE.
The array receives the basic variables and if nonbasic is TRUE, then also the non-basic variables. If an element is less then zero then it means on lower bound, else on upper bound.
Element 0 of the array is set to 0.
The default initial basis is bascolumn[x] = -x.
Each element represents a basis variable. If the absolute value is between 1 and get_Nrows, it represents a slack variable and if it is between get_Nrows+1 and get_Nrows+get_Ncolumns then it represents a regular variable. If the value is negative, then the variable is on its lower bound. If positive it is on its upper bound.
Setting an initial basis can speed up the solver considerably. It is the starting point from where the algorithm continues to find an optimal solution.
When a restart is done, lp_solve continues at the last basis, except if set_basis, default_basis, guess_basis or read_basis is called.

Example


#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int bascolumn[1+2]; /* must be 1 more then number of rows ! */

  /* Create a new LP model */
  lp = make_lp(2, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* build model
     .
     .
     .
  */

  solve(lp);
  get_basis(lp, bascolumn, FALSE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_basis, default_basis, read_basis, write_basis, guess_basis, get_basiscrash, set_basiscrash

doc/get_nonzeros.htm0000644000175000017500000000402410237176654013530 0ustar renerene get_nonzeros

get_nonzeros

Returns the number of non-zero elements in the matrix.

int get_nonzeros(lprec *lp);

Return Value

get_nonzeros returns the number of non-zero elements in the matrix.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_nonzeros function returns the number of non-zeros in the matrix.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int nonzeros;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  nonzeros = get_nonzeros(lp); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

doc/get_row.htm0000644000175000017500000001112110351321416012437 0ustar renerene get_row, get_rowex

get_row, get_rowex

Get all (get_row) or only the non-zero (get_rowex) row elements from the matrix.

unsigned char get_row(lprec *lp, int row_nr, REAL *row);
int get_rowex(lprec *lp, int row_nr, REAL *row, int *colno);

Return Value

get_row returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
get_rowex returns the number of non-zero elements returned in row and colno. If an error occurs, then -1 is returned.
An error occurs when row_nr is not between 0 and the number of rows in the lp.
Note that row entry mode must be off, else these functions also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row_nr

Row number of the matrix. Must be between 0 and number of rows in the lp. Row 0 is objective function.

row

Array in which the values are returned. For get_row, the array must be dimensioned with at least 1+get_Ncolumns elements in the lp. For get_rowex, the array must be dimentioned with at least the number of non-zero elements in the row. If that is unknown, then use the number of columns in the lp. The return value of the function indicates how many non-zero elements there are.

colno

Array in which the column numbers are returned. The array must be dimentioned with at least the number of non-zero elements in the row. If that is unknown, then use the number of columns in the lp. The return value of the function indicates how many non-zero elements there are.

Remarks

get_row retrieves all values for the given row.
Element 0 of the row array is not filled. Element 1 will contain the value for column 1, Element 2 the value for column 2, ...
get_rowex retrieves only the non-zero values for a given row.
Returned values in row and colno start from element 0.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL row[1+2]; /* must be 1 greater than number of columns ! */

  /* Create a new LP model */
  lp = make_lp(1, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  get_row(lp, 1, row);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_row, set_rowex, get_mat, get_column, get_columnex, set_column, set_columnex, set_mat, set_rh, set_rh_vec, str_set_rh_vec, add_constraint, add_constraintex, str_add_constraint, add_column, add_columnex, str_add_column

doc/set_epsb.htm0000644000175000017500000000703110237176662012620 0ustar renerene set_epsb

set_epsb

Specifies the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.

void set_epsb(lprec *lp, REAL epsb);

Return Value

set_epsb has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epsb

The value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.

Remarks

The set_epsb function specifies the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.
Floating-point calculations always result in loss of precision and rounding errors. Therefore a very small value (example 1e-99) could be the result of such errors and should be considered as 0 for the algorithm. epsb specifies the tolerance to determine if a RHS value should be considered as 0. If abs(value) is less than this epsb value in the RHS, it is considered as 0.
The default epsb value is 1.0e-10

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epsb(lp, 1.0e-9); /* sets epsb to 1e-9 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_epsb, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap

doc/get_negrange.htm0000644000175000017500000000500110237176654013435 0ustar renerene get_negrange

get_negrange

Returns the negative value below which variables are split into a negative and a positive part.

REAL get_negrange(lprec *lp);

Return Value

get_negrange returns the negative value below which variables are split into a negative and a positive part.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_negrange function returns the negative value below which variables are split into a negative and a positive part. This value is always zero or negative.
In some cases, negative variables must be split in a positive part and a negative part. This is when a negative lower or upper bound is set on a variable. If a bound is less than this value, it is possibly split. The default is -1e6.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL negrange;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  negrange = get_negrange(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_negrange

doc/simpletree.css0000644000175000017500000000135711034236401013152 0ustar renerene.treeview ul{ /*CSS for Simple Tree Menu*/ margin: 0; padding: 0; } .treeview li{ /*Style for LI elements in general (excludes an LI that contains sub lists)*/ margin-left: -2em; background: white url(list.gif) no-repeat left center; list-style-type: none; padding-left: 22px; margin-bottom: 3px; } .treeview li.submenu{ /* Style for LI that contains sub lists (other ULs). */ background: white url(closed.gif) no-repeat left 1px; cursor: hand !important; cursor: pointer !important; } .treeview li.submenu ul{ /*Style for ULs that are children of LIs (submenu) */ margin-left: 2em; display: none; /*Hide them by default. Don't delete. */ } .treeview .submenu ul li{ /*Style for LIs of ULs that are children of LIs (submenu) */ cursor: default; }doc/get_simplextype.htm0000644000175000017500000000553710246360550014236 0ustar renerene get_simplextype

get_simplextype

Returns the desired combination of primal and dual simplex algorithms.

int get_simplextype(lprec *lp);

Return Value

get_simplextype returns the desired combination of primal and dual simplex algorithms.
Can be any of the following values:

SIMPLEX_PRIMAL_PRIMAL (5) Phase1 Primal, Phase2 Primal
SIMPLEX_DUAL_PRIMAL (6) Phase1 Dual, Phase2 Primal
SIMPLEX_PRIMAL_DUAL (9) Phase1 Primal, Phase2 Dual
SIMPLEX_DUAL_DUAL (10) Phase1 Dual, Phase2 Dual

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_simplextype function returns the desired combination of primal and dual simplex algorithms. The default is SIMPLEX_DUAL_PRIMAL (6).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int primal_dual;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  primal_dual = get_simplextype(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_simplextype, set_preferdual

doc/links.htm0000644000175000017500000001433611237105544012132 0ustar renerene Usefull links

Usefull links

A Tour of Linear Programming Entries in the Mathematical Programming Glossary
AMPL
Advanced linear programming
Alternate Optimal Solutions, Degeneracy, Unboudedness, Infeasibility
BAS File Format
Benchmarks for Optimization Software
Communication Networks
Cycling and Resolution
Cycling in the Simplex Method: Example from Chvatal's Text.
Decision Tree for Optimization Software
Practical Optimization: A Gentle Introduction
Linear Solver for OpenOffice.org
Linear Programming
Linear Programming
Linear Programming Frequently Asked Questions
MATLAB
Matlab Clones
MIPLIB 3.0
MPS Format
What is MPS format?
MP-TESTDATA - The NETLIB Problems for MADLIB
Michels site where you can also find older versions
NETLIB LP Test Problems
O-Matrix
Practical Integer Programming
Practical Optimization: A Gentle Introduction
Scilab
The Mechanics of the Simplex Method
The MPS file format
The NETLIB LP Test Problem Set
The Simplex Method
The Simplex Method: Solving Standard Maximization Problems
Tutorials, Books and a Dictionary
NEOS server for optimization
Lp_solve link to Excel
lpsolve reference guide
lp_solve yahoo group
Linear programming - Wikipedia
Web page simplex tool
Integer Programming
Logical Constraints in Integer Programs
doc/is_break_at_first.htm0000644000175000017500000000546010237176656014475 0ustar renerene is_break_at_first

is_break_at_first

Returns if the branch-and-bound algorithm stops at first found solution.

unsigned char is_break_at_first(lprec *lp);

Return Value

is_break_at_first returns if the branch-and-bound algorithm stops at first found solution.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_break_at_first function returns if the branch-and-bound algorithm stops at the first found solution or not. Stopping at the first found solution can be useful if you are only interested for a solution, but not necessarily (and most probably) the most optimal solution.
The default is not (FALSE) stop at first found solution.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char break_at_first;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  break_at_first = is_break_at_first(lp); /* Will return 0 (FALSE) */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_break_at_first, set_break_at_value, get_break_at_value, set_obj_bound, get_obj_bound, set_mip_gap, get_mip_gap

doc/get_row_name.htm0000644000175000017500000000677710466457450013503 0ustar renerene get_row_name, get_origrow_name

get_row_name, get_origrow_name

Gets the name of a constraint (row) in the lp.

char *get_row_name(lprec *lp, int row);

char *get_origrow_name(lprec *lp, int row);

Return Value

get_row_name and get_origrow_name return the name of the specified row. A return value of NULL indicates an error. The difference between get_row_name and get_origrow_name is only visible when a presolve (set_presolve) was done. Presolve can result in deletion of rows in the model. In get_row_name, row specifies the row number after presolve was done. In get_origrow_name, row specifies the row number before presolve was done, ie the original row number. If presolve is not active then both functions are equal.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the name must be retrieved. Must be between 0 and the number of rows in the lp. In get_row_name, row specifies the row number after presolve was done. In get_origrow_name, row specifies the row number before presolve was done, ie the original row number.

Remarks

The get_row_name and get_origrow_name functions return the name of the row.
Row names are optional. If no row name was specified, the function returns Rx with x the row number. row 0 is the objective function.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  char *name;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  name = get_row_name(lp, 1); /* will be R1 since no row name was set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_row_name, set_col_name, get_col_name, get_origcol_name, get_nameindex

doc/set_bb_depthlimit.htm0000644000175000017500000000607010255113026014460 0ustar renerene set_bb_depthlimit

set_bb_depthlimit

Sets the maximum branch-and-bound depth.

void set_bb_depthlimit(lprec *lp, int bb_maxlevel);

Return Value

set_bb_depthlimit has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

bb_maxlevel

Specifies the maximum branch-and-bound depth. A positive value means that the depth is absoluut. A negative value means a relative B&B depth limit. The "order" of a MIP problem is defined to be 2x the number of binary variables plus the number of SC and SOS variables.A relative value of -x results in a maximum depth of x times the order of the MIP problem.

Remarks

The set_bb_depthlimit function sets the maximum branch-and-bound depth.
This is only useful if there are integer, semi-continious or SOS variables in the model so that the branch-and-bound algorithm must be used to solve them. The branch-and-bound algorithm will not go deeper than this level. When 0 then there is no limit to the depth. Limiting the depth will speed up solving time, but there is a chance that the found solution is not the most optimal one. Be aware of this. It can also result in not finding a solution at all.
The default is -50.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_bb_depthlimit(lp, 10);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_bb_depthlimit

doc/datastructures.htm0000644000175000017500000000326711224150125014057 0ustar renerene Data structures

Datastructures

A-matrix

The A-matrix is stored in the lp structure in element matA and is defined in structure MATrec. Only the non-zero elements of this matrix are stored. This is called a sparse matrix. In MATrec, the following elements are of importance in the matrix data:

  • rows
  • columns
  • col_end
  • row_mat
  • row_end
  • col_mat_colnr
  • col_mat_rownr
  • col_mat_value

Elements are stored per column, then per row. col_mat_value containts the values. So first a[1][1], then a[2][1], then a[3][1], ..., a[2][1], a[2][2], ...

doc/is_SOS_var.htm0000644000175000017500000000507610237176660013030 0ustar renerene is_SOS_var

is_SOS_var

Returns if the variable is SOS (Special Ordered Set) or not.

unsigned char is_SOS_var(lprec *lp, int column);

Return Value

is_SOS_var returns TRUE (1) if the variable is a SOS var, FALSE (0) if not.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be checked. It must be between 1 and the number of columns in the lp.

Remarks

The is_SOS_var function returns if a variable is a SOS variable or not. Default a variable is not SOS. A variable becomes a SOS variable via add_SOS. See Special Ordered Sets for a description about SOS variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int isSOS;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  isSOS = is_SOS_var(lp, 1); /* will return 0 since the variable is not an SOS var at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_SOS

doc/get_basiscrash.htm0000644000175000017500000000716510472142620013771 0ustar renerene get_basiscrash

get_basiscrash

Determines a starting base.

int get_basiscrash(lprec *lp);

Return Value

Specifies which basis crash mode is used. Can by any of the following values:

CRASH_NONE (0) No basis crash
CRASH_MOSTFEASIBLE (2) Most feasible basis
CRASH_LEASTDEGENERATE (3) Construct a basis that is in some measure the "least degenerate"

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_basiscrash function returns which basis crash mode must be used. Default is CRASH_NONE.

When no base crash is done (the default), the initial basis from which lp_solve starts to solve the model is the basis containing all slack or artificial variables that is automatically associates with each constraint.

When base crash is enabled, a heuristic ``crash procedure'' is executed before the first simplex iteration to quickly choose a basis matrix that has fewer artificial variables. This procedure tends to reduce the number of iterations to optimality since a number of iterations are skipped. lp_solve starts iterating from this basis until optimality.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int basiscrash;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  basiscrash = get_basiscrash(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_basiscrash, default_basis, get_basis, set_basis, read_basis, write_basis, guess_basis

doc/set_epsperturb.htm0000644000175000017500000000534710237176662014072 0ustar renerene set_epsperturb

set_epsperturb

Specifies the value that is used as perturbation scalar for degenerative problems.

void set_epsperturb(lprec *lp, REAL epsperturb);

Return Value

set_epsperturb has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epsperturb

perturbation scalar.

Remarks

The default epsperturb value is 1e-5

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epsperturb(lp, 1.0e-6); /* sets epsperturb to 1e-6 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_epsperturb, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_mip_gap, get_mip_gap

doc/set_col_name.htm0000644000175000017500000000516710237176662013454 0ustar renerene set_col_name

set_col_name

Set the name of a column in the lp.

unsigned char set_col_name(lprec *lp, int column, char *new_name);

Return Value

set_col_name returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column for which the name must be set. Must be between 1 and the number of columns in the lp.

new_name

The name for the column.

Remarks

The set_col_name sets the name of the column.
The column must already exist. Column names are optional.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_col_name(lp, 1, "col1");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_col_name, get_origcol_name, set_row_name, get_row_name, get_origrow_name, get_nameindex

doc/has_BFP.htm0000644000175000017500000000443610237176656012267 0ustar renerene has_BFP

has_BFP

Returns if there is a basis factorization package (BFP) available.

unsigned char has_BFP(lprec *lp);

Return Value

has_BFP returns TRUE if there is a BFP available, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

There should always be a BFP available, else lpsolve can not solve. Normally lpsolve is compiled with a default BFP. See Basis Factorization Packages for a complete description on BFPs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char hasBFP;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  hasBFP = has_BFP(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_nativeBFP, set_BFP

doc/add_column.htm0000644000175000017500000001345410351333610013110 0ustar renerene add_column, add_columnex, str_add_column

add_column, add_columnex, str_add_column

Add a column to the lp.

unsigned char add_column(lprec *lp, REAL *column);

unsigned char add_columnex(lprec *lp, int count, REAL *column, int *rowno);

unsigned char str_add_column(lprec *lp, char *col_string);

Return Value

add_column, add_columnex, and str_add_column return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

count

Number of elements in column and rowno.

column

An array with 1+get_Nrows (count for add_columnex, if rowno is different from NULL) elements that contains the values of the column.

rowno

A zero-based array with count elements that contains the row numbers of the column. However this variable can also be NULL. In that case element i in the variable column is row i.

col_string

A string with row elements that contains the values of the column. Each element must be separated by space(s).

Remarks

The add_column, add_columnex, str_add_column functions add a column to the model (at the end) and sets all values of the column at once.

Note that for add_column (and add_columnex when rowno is NULL) element 0 of the array is the value of the objective function for that column. Column 1 is element 1, column 2 is element 2, ...

str_add_column should only be used in small or demo code since it is not performant and uses more memory.

add_columnex has the possibility to specify only the non-zero elements. In that case rowno specifies the row numbers of the non-zero elements. Both column and rowno are then zero-based arrays. This will speed up building the model considerably if there are a lot of zero values. In most cases the matrix is sparse and has many zero value. Note that add_columnex behaves the same as add_column when rowno is NULL.
For add_columnex, column and rowno can both be NULL. In that case an empty column is added.

Thus it is almost always better to use add_columnex instead of add_column. add_columnex is always at least as performant as add_column.

Note that if you have to add many columns, performance can be improved by a call to resize_lp.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL column[1+3];     /* must be 1 more than number of rows ! */
  REAL sparsecolumn[3]; /* must be the number of non-zero values */
  int rowno[3];

  /* Create a new LP model */
  lp = make_lp(3, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  column[0] = 1.0; /* the objective value */
  column[1] = 2.0;
  column[2] = 0.0;
  column[3] = 3.0;
  add_column(lp, column);
  
  rowno[0] = 0; sparsecolumn[0] = 1.0; /* the objective value */
  rowno[1] = 1; sparsecolumn[1] = 2.0;
  rowno[2] = 3; sparsecolumn[2] = 3.0;
  add_columnex(lp, 3, sparsecolumn, rowno);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, set_column, set_columnex, del_column, set_add_rowmode, is_add_rowmode, resize_lp, add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex, get_column, get_columnex, get_row, get_rowex, get_mat, column_in_lp

doc/set_pivoting.htm0000644000175000017500000001221210256364026013515 0ustar renerene set_pivoting

set_pivoting

Sets the pivot rule and mode.

void set_pivoting(lprec *lp, int pivoting);

Return Value

set_pivoting has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

pivoting

The pivot rule and mode. Can be one of the following rules:

PRICER_FIRSTINDEX (0) Select first
PRICER_DANTZIG (1) Select according to Dantzig
PRICER_DEVEX (2) Devex pricing from Paula Harris
PRICER_STEEPESTEDGE (3) Steepest Edge

Some of these values can be combined with any (ORed) of the following modes:

PRICE_PRIMALFALLBACK (4) In case of Steepest Edge, fall back to DEVEX in primal
PRICE_MULTIPLE (8) Preliminary implementation of the multiple pricing scheme.This means that attractive candidate entering columnsfrom one iteration may be used in the subsequent iteration, avoiding full updating of reduced costs. In the current implementation, lp_solve only reuses the 2nd best entering column alternative
PRICE_PARTIAL (16) Enable partial pricing
PRICE_ADAPTIVE (32) Temporarily use alternative strategy if cycling is detected
PRICE_RANDOMIZE (128) Adds a small randomization effect to the selected pricer
PRICE_AUTOPARTIAL (512) Indicates automatic detection of segmented/staged/blocked models.It refers to partial pricing rather than full pricing. With full pricing, all non-basic columns are scanned, but with partial pricing only a subset is scanned for every iteration. This can speed up several models
PRICE_LOOPLEFT (1024) Scan entering/leaving columns left rather than right
PRICE_LOOPALTERNATE (2048) Scan entering/leaving columns alternatingly left/right
PRICE_HARRISTWOPASS (4096) Use Harris' primal pivot logic rather than the default
PRICE_TRUENORMINIT (16384) Use true norms for Devex and Steepest Edge initializations

Remarks

The set_pivoting function specifies the pivot rule (rule for selecting row and column entering/leaving) and mode. The rule is an exclusive option and the mode is a modifier to the rule. This rule/mode can influence solving times considerably. Depending on the model one rule/mode can be best and for another model another rule/mode.
The default is PRICER_DEVEX | PRICE_ADAPTIVE (34).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_pivoting(lp, PRICER_FIRSTINDEX);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_pivoting, is_piv_rule, is_piv_mode

doc/Euler1.jpg0000644000175000017500000022030711164443650012136 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?M1|̿ I_| k%|AmG 5FOxٵGU5gV߇4 gя/0<ɼFUI`JS oi?O SFG5M;B&rĻM)2CuZ8K\ %O0G`/8T(ᡖԌUxDa8߃ƏEWυ18c 8l[S1Ϊa!O **c3}Rg|.#FtυDhn~;x_gvOO6/ßGjV8mou7:{[oM%}?bOj{:%s}>umsI=?uueEs)na i~G\\!ObwF{W Gq^7x:!"| B";Ũ>*x ,=uY|z5)СXl濷9PC,?vxkg"4o7^g^:?h/=MW}ώ>>ڎ/zƁaZ|^ -mA|YA/RId>~_k\hW-|е}?Sc|>+o7tzi⎡oۋRé/|*>(xa˸36[Z8~e9Ź[,0UyfSy^d7[-_b|=7 8.Bx?vxkg"4o7^c_?WW 4q?>i>IӴ[V?"lOa׼\5 =u?Mm7/i|g ~쳦k*829 }K SG ;S/Rbs:UUhx<̩bc) (K b)`"}vxkg"4o7G. ,]FH:|?xfÏ7<1@VIӛEF:e5 Ŵ^kZMlnO_5O a]?5KO< WWuixLҵ &Pҵ;5(mk:9{;cx[0 ~M>|FLʆ&XZL&'FJ*pV3RQZ^m~UybhXxjRuIaքjP]QTVR*rʤM. ,]F% ѿ}/&&JUg>_O% ѿ(hϯ4Sn?_Naeg⦏'7uе6O [K]Os?Z &Nӯ<+~+m?>gH__ !Ꮙ~i4/3|@,Z["Uc.xDN9.`lnVWy.ṣWuSV9|9WT+is<."' NQNXі L,q.[Nyl*bW_O1':~F3 8N"TQ^U#/ .Y>ƨ% ??z.||X>6|kg/w/cOOҿg7t5}ju_ ?U[Ǻ΃e?^7zEϋiq|ǟ #$ױA&MGOOGOnx㏀<)f=?6Ӈng U|&mR͡Cejefv %',,,ʕ**5*CZq .\jWsUZX ฃ/1uㅄ'o,XΒt`, R+S_^>]}Q KP?V)kW>2[#"P) O W>|COC<+/0SCh~xŚM+?4-7 }gTMggj:ge\K(V .ў'4:caCQͰetqPJ&-ЫN_+<:"~m 8O%Lo`1V7UxT'$>9% ??|7Dg'SMic6{H8j<)ïf7\Ţok%6<;4:[Yȓ2j&~O_=_š|. o^"]B>+sj: kWtm?Jiڗ %]]iA=,o ׫J '^"YZ3+ҧ CJ8.|HEzkßf:(Tө^J>BiRcS%^jTjgCj^>]}WxT7Ŀ獴?mx?>|%ON4Oz~hi:eH~ק^^[\+|⟉:WOi'\?s~ۧ)ngxK/4#Oյ KOj:u^[[G,ɓ}GSE~b]ߵ>jYؿki,?g\ٟ=~YϴT9=nǶCj^>]}Wa{_?]8ߋb uo{|;5[Þ&7_[>gUҼI/^?x?5o  -[Z|o}]7÷lo RN/n a -xb̷::uQeTp0f] NuJaO͸ 2\D8b(M<7?SJ(bՕ8eCmIʊjn]_/ .Y>ƨ% ??rHڿJ&m 5/>M -j{k@Eց&<7)Դ2( jGSJ0} 2?~+|h~?,i>/u? ]}Q K>ğ>!w i=oZ\~*PW4V#SNuWMWG};M-Ě||a+/_[/oݧuٯ|s"W0m?}sjKrQ|r6oU bMV.G[30r~a^ _2JF# F7SU'>ae!B'1UNiWW)WaaySu*R^u(b!K?xow!O5Qc¥F9hN;g|Wux#~|D'~&i-8_ h_4%uּzm%tBmKAz֓tf57Κ,԰@澏 C*Ў'& ??w{Ÿ!.hC&7Wd OOgOy#]gm#)H'& ??w{Ÿ!.hC&7Wd OOgOy#]gm#)H'w> AG> |np\>TX1*K_ur`c{o  g~|ZymK}$-$AA/?S_qNMƸNἫ~.lV77XY9 P9M:TO(u9U\yY8k;Fsf\Eͱ8 42ʆLԖ#9cTR I974Z5^TnfU\2~Ъ#'^],]\mDp-i)_VɣWDQzYxf<qڈe܄T_rq_jχB@{?&F, ?ZRD$;dZ";?4l_2q%eYv fa L#,;V*s|<lOX_dOG fXf|QBtcjVO %^S5b,E:\V\<\~_W[:a]yY?h# r@k6o-_|?"%Rng sW;IQa_ F|K/7|Hρ46Ҿ x[}vėbŢ?nOI;_G~8|Qh ǖ9&t}H$nma>|5.~]:kgkj6i5=~e~:fw)_3z \MR:9t?|SK*xZ?b1(ѤZ47 ³X8cszir~ޥ5NRN3_ws|5O^7՗=x).m3&yK,Hcyz0fnO|hVl~rpd4qAb09;C)d|6o)|f?%4ydOq+ -ϞF%攴1rMz燿-S6p^. ۬5)ȏpX#mm nkH̸aH!1m CͫKU)fxXҡJd#R5*5F.u)N:pq18뉜_MPhRfYJRU0RHaj8œT.2?X]Qm,Sq{;Amk3;W`ؿ[uo$ޏCGSvVZU.Cs ƗZ~"K5Y%uw@.!inh6|^PĿP!v.0q 8ʗaWaZ|3΍|,:RRvH[UŜ#qUՖ+2:0xjì=,N:l-zs7g{ +2~!J彅o?E{" +(<Ul?%^~kO~=55⟄-|"R5-߄}RIIimuUa5ؽ~~_g\x3Q^4m|xJų T~+>!?._uALR$zmts1c~ڢqx'1‘_I ,p|G$>ψ8_2"+Qs^!q\sØ7z00vTb#^,W_=Y.q;$,Q[ IڕGFSZ5F\kJt'F9K/ /  I~34uz:nr%NJDҬw9⿃/x& s'[Zſ犾)|@lX1ׂ(ǚq/Ih[F͎kշ ܷypO3wŬ*G+#Q~>~Y뜝'O~8+/ c^8=PkĸOXis9s\6$˱y.gq6]93^TaR8ѧF0~w8(q.'ɨS|GVʥ,6*iRapYnQ FF,3JuSW_b_ #㿊nG PW?o|]jcνo%qiVLeĽ{ᯊtOKԣ<9/ß(?/|]H ̾?œ@ਟ~~h?I ڗ[O,Ƨ (7yq7Þh2?zѠl[8=rg933|GUOqF9BVJUo_^EbrX=zgّql*3[-`t<^A5S<+FJ8M9ƼPfqJtA}ON +w.YWz_ƟZ|"|>Xx|y퉯|N+Qշ_𽎃%B*~_Z?[O|:|S+7NxbF{x]u xTgFѼ%hx"?9 F/ٳ+7 ?f{ w8ʳ3fMCjg%>\kepbTh1Z28J:|0YSU8̱x1)O+36IΰL=9*u㣌NSྐྵOgW?ltwm={U>/.4w ,w4_?pfk[dm|v爣K-{.n/1>'|:*2>OW5o ׊4_⯇jzީwZ-챯[rZGq_+7 ?f{Þh2?p]/o } x3K8"p$cÞ1k ўj5Q 3/CuuO|^>Zf{[wᾹմ,,׆/o9&dR fA~s_?g=D4 q_ >9p \6_wb0ie|\Sx8L|\\jbj:_u|3?*|7P;*n?{nUj~+׬UEV%j$|H5ozTZVk_QKQ_|aIdߴ'_o M# 㯊_xF 1g|;Ru/~#xk{_Vo4~͟=Ye6߯8>]晦o9xln/2q] 9^t+ej,0m X?Ӳ Ap #Ϊ,g_c"~Mzkx=<ƴ' fA ٗ|3N=#JGoxwŖ٧t_< 6/xcB4?U^%E~Mg!g?ho_ZWuHW5O?-245i:{-\:umGWӢos_?g=?_Vo4~͟1[>p.ue9SF}⦡b]U0ԧP`_Rjʔy'ǹ~/-Y8|f;+WYVI.)aFq+ks(# ѝJUXiJi3Wh7ŻagOƛ/ gGSӾ]/O = |r?Ms 7g+4?ZT 1 0Xx/7B{|hk~?;=+,e~-|P𝏂<'_]YYub ;ZD0Iwk:md?4%3k )D>4M$㿉_ON~| /)RоsUơY,dx?9 F/ٛ_+'~fo{**_q9 Y\/Yq֎)?u:iVU%:|L~FXuIp]o.ESco8V#$iTsnϣ (93N2}|\Fs~׿O~#Ծ5k?o?Zg#}S''ASY4QxQE dž.Dz_} _ڣb,:k_}s7UiIcO?fW/Sw&4v*K.-x~ԢѴo?οVO3h:Y?3ݯ| DX |O~Y[mῄ)a?Z?|!t杯k~ Mx_ :x?m--beF|dgyĚ/z/lɼOi 9?o~0xk]s_??7=?οVO3k ^O1? O aq|OJ֧U CXj1ElzqƖ+岩q=HcxlG^֯xftg,] Sּa{-kmJ{/[dž5x$k_ǖ:o/^ZS|[qv h1>|C'>|2 kxN־*|B)M}kX7SO֧m7GKos_??7=?οVO3k; ѮMq7xiaxj ֏D-cFW_0R&[u14poQp3z3ub)CXa)ժ,LixBU| )K?l/?gZ} Ǎ|{u7 GGSm;Ǿ8wP^~*c^=<%vߴOt|b?e?MDž>" =ګAA ZZW'ƫG_@_Gľ3cukÝଟguџf_--Υ)~9XLYZ$p WW|+/2LcSq`qCjxa<akqSs*G;'QSU&7j': /1f?!ĿK)sv/3aS|sn|MkkKMEu^'eπ63"NJ>~?n_#cT?J5ZOÏ xW~8|F ^^SҾ ѼoeΣGp>Re|Z~R<_ړ7aǬiw.'+Hq{j7tZNgtl. #[DL%t =3O6M{ xm >0q/oq,m,{S\W_ҷx,V."`3 e'*_QiV3U׭Q9aBnThl?u3|%c"ߋZ5ZM[R~*Tzԭ~/k_i>6ex}>|]{A񗋵O~xco?zNĞuџfG9 F/ٛ}(qv3l-lT8+w\uŹ_S*ͰL.#uNX&^63QmSXW˸/eY1xl]:ogRN6ҡV,-_(? {sotG/?dO ,->{=^lLJ ;ḵYp% jXK)d+iRa`ai.Ǎ8_.87.%be,\A&9*T̪c+siND8}|^3eOG#S9?~Ý?ggbs?W?0G<rK_4}?IN|?+Z57O_o+O4أi;?f{}xKkS? %OWd#S9?M<+5vѝ?߳G=?V3hGL77?~3 _4}?IN|?+Z57O_o+O4أi;?f{}xKkS? %OWd#S9?M<+5vѝ?߳G=?V3hGL77?~3 _4}?IN|?+ihG2?^4jWIB0%_?\No uOğ?e햏x/Iu2h~= .uYk6ҋ}>L].>d źW1 Yjڧ{Wѵ}#\үw^*Kcxw5_xGKMWEhn\[_&dJ]G31KR(!"8j"*q~kVMg `)b~8 r3.#hV|SOxY GVrbaYa(O7 0߇lE<2,&q|Gq1 JqɌ+zmwR5eF 5hrzo>xS׍,?f~>?b x;~*{/j-߈~muoEO閆O i쬭>،ת|6־2i/-8FCsQ뵸^^s/KnH ~pAv[x?`)Ư#Budğ Ie*QHoKxxψ^fy/e5kW3ցV>9|fͤ^|?' iמq rvv'/? e φ_|c㟍ca=5>χi=Cm%3O𵭅j^uZmfѩcUD,~ UGx _9מMPbW"Ge/ܠ|o(R3\A<2ɣx#?^ejxʞ}. Y7EO _K *c,˖ю9^xss\ҩG3<>.l%Tg,XS59ºQ.xҊ^p<]q?e%Ā0~FrGCr}jź?/F^ G:ޫyk*gZA2!Q"yMͷ϶ʹN?->_xT|=\A;7ٷL𞟢xCH4>ͤI𿄴Fݝ}?$'w7s8##=1uF{e،P^ \7J+pOcZ'[mZzJ)T҇< ĹKxOq>Sf?5IԴ*6.,E?{:9g/5υcU6rjP>=#͵Ǘwo ?fh o#G{㜿ŏp|_1 FBPTQ%\:Ο述WK{3|vQvai~җaݳ 42YO/ke}q<Yx|Ma&żck*tͩ?׼G{gq7MU_Mjf?~ӕxW!7?X]w5wKp2~ྞe |]~QE(W~< "|C3Pľ./4+ᗄO#&Q 'SDk~ĘЙG|a?a`?;g}E| 'SDk~ĘЙG$Oc7Be8?<wه|#Q $Oc7Bes7s\Լ[ZxÚTͼ|\m#cԵ l"M|k}" jɖ{TdӦ35NuZZ^9ZO2JeG;R7NVxMSY)i~I^M/vqO+I?j#_$o?$~*p6y?ϳ/`>wOڧ12I?j#_$o?p6y?ϳ@#? :h$~+s>ϋ߳Z|?x/jk][jvoُ>6At\o#WԴmgTMy 1u9Sl]ZjͦMFV&Z‹JUՎ%J5%U*ԕM^)ɯh$~(5?L|FLϜ 9;>`>wOڧ12I?j#_$o?p6y?ϳ@#? :hMm/5O4^xZ7tOf=O5Yg׵>so02 :h$~(5?L|FLg>so00X03>~5?L|FLOڧ12ͿÞ`>wz?9k/[~:x_jEڗɸ=?t4 KAxW c^!?$~*cg*,պSPW,)K\'UwRK8q&[RUc 9ەUq*囥NRwV׽k)% $Oc7Be~?FgI _8?<wٚ?u@_?IT&>#&Q 'SDk~ĘЙG|a?a`?;g}E| 'SDk~ĘЙG$Oc7Be8?<wه|#Q 5/閿g >(o.+#H-CGƟSez_/ZH5s5?L|FL{(R͚SM {JEg2vm6"ebNw(զīߣRtjFSjBQxOڧ12I?j#_$oʯͿÞX03>~5?L|FLOڧ12ͿÞ`>wOڧ12I?j#_$o?p6y?ϳ@#i5}KO~Oڧ12{TK5*B33 (<5u$k[Ӷt-JjTsSNiXXBT+K)RWNIOC>/;O \KZ? L;w?%|A=?C?Cn?vgq`~ǾP~ЏOzX8硈+џ,J:rc8FQ|di$Gxጇ⸋4*r҅eZ)T'jrg7?K&O`w6?ZN\?N >+M<wӋ+DH+RlOHn+-m ?_+_H5<xkg;09w?\/fr\}Q _\8o(>((+yZkڿٛ3?;w/Gyj>"y/>?Pt?#WC3¿wa''~.>;CoMCcg^LO?AƜXSU(;B((-¿wnw^ijnh}Úlnڿ>"hykw$W%Wn}/_sMQ^?Wg_3P1{psH@+ ( (<e|9~ڿgOX}: OA>(h³wWL4پ[??W^w ?~'V~. '0_{qS+2 (Т((+͟<a/?&^fj?kON#W ïG(yy⧃,>_'aX~ ޟj³w??;u@L7A8Oé. (ࢊ((yZkڿٛ3?;w/Gyj>"y/>?Pt?#WC3¿wa''~.>;CoMCcg_@LgaxNĜXTV8+ ( (<-¿wnw^ijnh}Úlnڿ>"hykw$W%Wn}/_sMQ^?Wg_3P  `p-˿ ϟd5oٟ |`{s{LV߾  ?wO6?h*٨Ͽ[q &~'? jfxx6?[!kpRa1? nq\@QE(|;@j^Wix u/E]g+^k q lgxfG5_?Ng_ofz~zW5_%U|Ӵ > ^|Z~6x{?[Cux[R{~+j 5 C{MCXѭ&K(?V~J~ޏO43;vxzO.~a59e񵳟7G_,ү<+J W^1ռy-R28s8΋8>-gsv5OϖʲU|9AO xuбXiRnp~骔qqRlqF<~wASUU0(?aoۧq> ?eU^nڜVwN7ߊ^_4t}gGt/x/]WxOŚǤQEQE O-CgAl_  wW# A5Y}iŨ~:m_;aynw& 3/&' N,W yQEuEPEP^C_;i/?>6omwGc{_Y<ϵw; C+h|+g?|>e|9N(l} 3/N]ArO `=8j `9egQEwQ@Q@2>fw~? l_3C⧃,>NyiP_' ?Y+&^}Úln-h|Te~ ï;O?ٿ_jۿk+?zrC`/=8`X?Q]ghQEQEϊ w/?| aw''z d#}RSneo,?nO?YO:⏠W& 'ia[Q]gpQEQE O-CgAl_  wW# A5Y}iŨ~:m_;aynw& 3/W& 3bN,*nePQEvQ@Q@C_;i/?>6omwGc{_Y<ϵw; C+h|+g?|>e|9N(l} 3/N]Azr`?p_ 08rzg߲gfkUφaf_o̻@_&3ٿ|s<ko~5mQ,?#/7a~?MjfHi NxmPط6~ M^UNJ_3?cMQcN/ˈ(#<_;$·' ,>-AG_\h>8u ź7%}ľռ5I[-%[GY<^]>"_>9!}GTx_-c泬&ծA&C-GRӼO۫i1Km&=RcGnKkhwxWYSK_H5<xkg;09w>.c?ox eVZ/JJ^bO,W|ac?>-~~gCjumgž+ѵ :wW %:zd*ZTIE6S[I6ݯk1SךjIE7%)MEIvMk?_}Ծ ?_4/c3b+7_]ះ/j_SCWů fy?|AO/bg®g% ~۞g-~4oxEBgY:Aj:>WYc߉k^~!kOy/? 5@3-~ (%y×n/)M?a}ᏇGA. (W_X|m/!ixRҴ7?O f y/>?Pt?#WC3¿wa''~.>;CoMCcg^LNXO5peo??B; φ~w|AO_?*i_'krv??|Z?`g _ٿd/'* 9};Rھ-|TNx3߲ag?w?D}>,'Q3-~ (%y×n/)M?aEuC@XO&ٙo ?IC/φ~w|AO_?*i_'krv??|Z?`g _ٿd/'*}C@XO&f[BP~K>~ßG4 iAug<*x_Fv67v~AZV xD< ?u7 9};Rھ-|TNx3߲ag?w?DOa7ۿAKgjc<awOoW$? ށ\`~b`p⧖e8Oe C_φ~w|AO_?*i_'krv??|Z?`g _ٿd/'* 9};Rھ-|TNx3߲ag?w?D}>,'Q3-~ (%?k9wSVx ?0^Onk aF WiZo%㿅_|3ះ/j_SCWů fy?|AO/bg®g^lyi}27W_|Gbwhghyڿ]ONn?G+ l Gp_8f[_ rvy?_}Ծ ?_4/c3b+7_]ះ/j_SCWů fy?|AO/bg®gQ]P of[BP~K<ះ/j_SCWů fy?|AO/bg®gy×n/)M?aEP п?_1Ú37> {9S% K%?o-/jZVGPމOLះ/j_SCWů fy?|AO/bg®gϴ?n_6~ ߋϷie?P+a? G?8-??%ߒ?gyڗk⦟lwvٞO,_ef ?؟"^|3ۼK hjcSO?;_~;o'/?~_OU  +5@_J}ǟ|3ۼK hjcSO?;_~;o'/?~_OU />rv??|Z?`g _ٿd/'*}C@XO&f[BP~K<ះ/j_SCWů fy?|AO/bg®gy×n/)M?a"hykw$W& j?8̳-˿?J;_q&3ٿ|s<ko~5ɟj߳?W>+/=ջ@_?@?9O5r2{?~_Mjf?ӵx6?[ kp+})|V].GcMQcN/ˈ( qԼ7 ۿiRZ fn+?j~߇kP:~?$ w=_[CºWŸZAmx_?WӼYپ_;3vRw( ܻ%kZ7//;/aS]W"W6~k˞zEWz_RkKoLо,FZ_uF ^i"B_=GÖ^)7-ig:(<' ¾ׁ|Mx'ƞѼYOYӼG_xWzuxg:=摯x]/,MY.SNxnɗqeRi~ϟ#?/|Agi><O/QUg}?/5K#]^xZwQ|G1?W➩N~5R{Aϟ?SOo3Nv<76wz W|; N|Ui:υ"y/>?Pt?#WC3¿wa''~.>;CoMCcg^LO?AƜXSU(;B((-¿wnw^ijnh}Úlnڿ>"hykw$W%Wn}/_sMQ^?Wg_3P1{psH@+ ( (<e|9~ڿgOX}: OA>(h³wWL4پ[??W^w ?~'V~. '0_{qS+2 (Т((+͟<a/?&^fj?kON#W ïG(yy⧃,>_'aX~ ޟj³w??;u@L7A8Oé. (ࢊ((yZkڿٛ3?;w/Gyj>"y/>?Pt?#WC3¿wa''~.>;CoMCcg_@LgaxNĜXTV8+ ( (<-¿wnw^ijnh}Úlnڿ>"hykw$W%Wn}/_sMQ^?Wg_3P  `p-˿ ϟd5oٟ |`{s{LV߾  _w_5h٨Ͽ[ 3 9mPط6~ k; :mPص5ƫ鿯җgx1&(eEWWC^Waxߴ-m ?_ |Ik q lgxfG5_?Ng_ofv<5??~xWZcw`xo|o[S|w<+egƺŧ?k?^sx CnD׿K׍>,|WCگ𽎥~I]kzZ>|K OKҼ7Z|>*w^M8h!qy,E*0 uTERᰮzSS';ƥ9$nXy|c¸)2ɨ' ΎRgSS"!V3K >ԩR +T= ( ( ?QW?h$k%_U|~Zw>8NO.!_WP[KOҵczƣi*⯈_|mE? #W ke 37ě ß~j7SG>6?i ]ֻoxoľ#& W^}w ~Gf ON]}K+w ,ψ4~_woOI.|h;n?&un#|Ytl?x_ڇxJ#-焼e}RV?ocn#/'&º] 0(ϼw3/d3(?%}W?;'~2G__O-mcgLt^xvn~A>}RV?ocn#/'&º>G1A`С>l̿@~#wO_#z´a/weig?| 3y?}KP'=KZigwOeZ> ;B2O?ϳ=-¿wnw^ijnh}Úlnڿ>"hykw$y?}KP'=KZigwOeZ> Ͼs+ ?  J HxkKn ?"Ju/5_-_~;վ3 6װ/0caCK oa22>~#wO_#z´a/weig?| 3y?}KP'=KZigwOeZ> f;(ϼw3/d3(?%}W?;'~2G__O-mcgLt^xvn~A>}RV?ocn#/'&º>G1A`С>l̿@~#wO_#z´a/weig?| 3y?}KP'=KZigwOeZ> ;B2O?ϳa7ۿAKgjc<awOoW$? ށ_?|XG4? Aug~&WkԸVx&< k~\φzGxvn~A>}RV?ocn#/'&º6ױ>/0caCGw_2_z3ۼujcԾ'd&Xۿ+K?_O_:?|_ O?},|D|?/?W]] 1C}ٙ'ٞEyGm'/CھG/i >>_">ho?g+~#wO_#z´a/weig?| 3?ɋ w3fe̞fz3ۼujcԾ'd&Xۿ+K?_O_:?|_ O?},|D|?/?WGh&/1?; 2y}jW>*x2_~|L~%؟G+?ci_ۿQ ]*xjo6>ygov>#!/hmlV|3׿rx[/|Lxvn~A>}RV?ocn#/'&ºchl{cP0x,̿[!Wxvn~A>}RV?ocn#/'&º/ǩ|+O?NLW G?]uvbofe̞fz3ۼujcԾ'd&Xۿ+K?_O_:?|_ O?},|D|?/?WGh&/1?; 2y}Wxvn~A>}RV?ocn#/'&º/ǩ|+O?NLW G?]] 0hPx6f_aϴ?n_6~ ߋϷie?P+ xguO/g~&W{_ KKA-+JԼ?{Kuoh2~#wO_#z´a/weig?| 3& GA؟8‡we28@~#wO_#z´a/weig?| 3y?}KP'=KZigwOeZ> f;(ϼw3/d3(?%}W?;'~2G__O-mcgLt^xvn~A>}RV?ocn#/'&º>G1A`С>l̿@~#wO_#z´a/weig?| 3y?}KP'=KZigwOeZ> ;B2O?ϳ Oyi}o?kj}yj_?|1W~A ?L֗: SE_)fV_?@?9O5r1 0W?Kӯ&ߵ__ikN~-~kpRa1? nq\@QE(?{~ -Ok"Ėk7py^ wasUx?ox^qԼ7 ۿiRZ fn+?j~߇ٛG(W6+_ѿ5yy5}{ Vp턢 7/ŝ _\8o6Z( ( ( <'x ^ׁ|M~ ѼYOY|9 Úxg:=͞BMY-u/Q^~E!y_Zt߳⏇YAgZwG*-Lw7?|Ar;+!jភMCR|'1s~ ?O)> ;OYyZ,صK?@#?x;gk?xkᗀ>Eyߋ >8BS_ Q_2xX<;axz_#Fj53P.+" (+h|+g?|>e|9N(l} 3/N]Azy[ O4پ 폵f|E> ߋH5Ia Oa?1Ԍ (ࢊ((&^}Úln-h|Te~ ï;O?ٿ_jۿk+?zyϰsM % ;ui7+ Cw؟|Qg@Hb?  + ( (<RSneo,?nO?YO:⏠WW>*x2_~|L~%؟G+?ci_ۿQ apÄx?:rࢊ+ ( (<iŨ~:m_;aynw& 3/W2>#۾M??7+gw/3__.???f|E IŀO ̿c (Т((h|+g?|>e|9N(l} 3/N]Azy[ O4پ 폵f|E> ߋH5@L 0fW"ܻpLLV߾  _w_oZd5oٟ {_{{o'Uaɾc :mPص5ƿ4IAbvJ_3?cMQcN/ˈ( qԼ7 ۿiRZ fn+?j~߇kP:~?$ w=_[CºWŸZAmx_?WӼYپ_;3vRw( ܻ%kZ7//;/aS]W"W6~k˞zEWzEPEPEPEP+ \ U+xOsy[GOt8u14ĹWYNqVz_+~'o|>}on /83g WyfjqZ;c: ~)xfQWl_PQQмiw_U?k__߷OP~3W|3Yѵ8|N&ucso3m}U_/i}k6h^4^_4 9] Oxg@M|5nf|c[Ma4Rue|?~xP𞁬|8fkᏌ~#P^C_;i/?>6omwGc{_Y<ϵw; C+h|+g?|>e|9N(l} 3/N]ArO `=8j `9egQEwQ@Q@2>fw~? l_3C⧃,>NyiP_' ?Y+&^}Úln-h|Te~ ï;O?ٿ_jۿk+?zrC`/=8`X?Q]ghQEQEϊ w/?| aw''z d#}RSneo,?nO?YO:⏠W& 'ia[Q]gpQEQE O-CgAl_  wW# A5Y}iŨ~:m_;aynw& 3/W& 3bN,*nePQEvQ@Q@C_;i/?>6omwGc{_Y<ϵw; C+h|+g?|>e|9N(l} 3/N]Azr`?p_ 08rzg߲gfkUφb~ ٯ=ս@;&ɫ~o\n/;O[ߴ [}a?gMw[6?ZN_wu$kk;_׍_Ӂ[Ku? ǃnq\@QE()^|][I[K:G;W g >Myus3oM_DѮ40{H|7I}|/# x3࿉O4m3Q+ S@mFI|QitOi1lwlEdx<Ҽo^>7|l/][kGN-ğ>? ,:_M[IkZiƳw4R^ 7?|1Mᯇ{CMݏt??/i>*񞣧m [{=(&K;|_9|) O,Dh27YhS҄I8<_Kidjdy.WU0NyO<&;|VBee:Z( ( ( ( ( (: ^W|u_x~6_4ox;>ux~*mx{sg> е{;=SFt]GKmmn`)W6t[uq\²Axsw"hykw$ !?fo*g;V7گQOĿ>!J3)X>&*hgo8g< hOkoޝ}㏂ YϏ^1tO|/𧈼?"񎕩^*5-[|e^7֥|Rm oԵOIY/eZ:8C`n XΡ)B3f^)IxVermJt7Z6˜sQ9B5# O8/h?g~ZW??;'~__w*mlh|L^x3w?n~-|A}MVٟ?og}a]/;w?>&oxm:_Q^yO_=7[fhwO wǦ+N3?.W ?b ۼ_tjc~g'dy_x+KC]_O _cf[ϰsM % ;ui7+ Cw؟|Qg@,xcqxr9n ^H>*\XZXO7iZ4A3?Ag~ZW??;'~__w*mlh|L Mob1/8h3̷_0=xOů:| 3C} /K?®/Xwg%WxocCg,^ _ӷuYo*x2_~|L~%؟G+?ci_ۿQ ]Lj~3A>|`Mi}#!/Kj?f[Mo~gioAg~ZW??;'~__w*mlh|LɆ _>p_qa1uf7[ +<;y? k>Ǧ+N3?.W ?b ۼ_tjc~g'dy_x+KC]_z[1N߭f;eWx3w?n~-|A}MVٟ?og}a]/;w?>&/<;y? k>Ǧ+N3?.W ?bY@͡,̷՟xOů:| 3C} /K?®/Xwg%WxocCg,S5>_ϴ?n_6~ ߋϷie?P+ xcz31y_^,^½:N77'Դ+R¾.|LEz wg%WxocCg,^L&/?Ӌ/?3̷8VQ^yO_=7[fhwO w&/<;y? k>Ǧ+N3?.W ?bY@͡,̷՟τ Oyi}o?kj}yj_?|1Lj~?}AY¿lf۟ٿ~}+UԾ&|Ue[o&x⯠x3w?n~-|A}MVٟ?og}a]/;w?>&bk}Gt}FYf.n] '?V~W3M[g~5u1x?k?տf7_|7_'W~r0j3Ve&; -N~-~k; :mPص5ƫ鿯җgx1&(eEWWC^Waxߴ-m ?_ |Ik q lgxfG5_?Ng_of(K?c}[}/E]g+O- n?A ,km`/a;r~n]l__WgJ.+rY__P5yy~Oc_e+=P(((((({ K/|?E_`(#/1@4~_I.|hᖯ?&kak|Ytl4ڇxJ)gko{7? \(~2e~{ox}37ě o)ְjG>6? jֻoxoľV=ֹ&?|i fU 8k)u dh_뺽㿁;mnf mJ;U>R;G揧jvZg~ xW~EQE/>6og?>*x2?kםH5ߵb GCe|9~ڿgOX}: OA>(h³wW$?߱? q_QEvQ@Q@^lyi}27W_|Gbwhghyڿ]ONn?G++͟<a/?&^fj?kON#W ïG(rafOUpQEwQ@Q@ϴ?n_6~ ߋϷie?P+yZkڿٛ3?;w/Gyj>"r`? v$_Q]ghQEQE o?>3w۾x2KWwC>fw'>׿C_'~. =-¿wnw^ijnh}Úlnڿ>"hykw$W&`o3+n]`8OG|&ɫ~o\n/;O[ߴ sgfkUφb~ ٯ=ս@NFF}ܰOpioڃůٯO^5_Mjf?ӵx8?)|WOc7yG8[. (OԂ=RcGnKkhwxWYSK_H5<xkg;09wdW|M_xfhQ5H|?|Y?ڷ|e][YmgzΩ_C8oQ|=SI-վv[;>))yZY4^ľ"~kUφi@M;ÿO?Yx>:/Ax/7< :*x2_~|L~%؟G+?ci_ۿQ apÄx?:rࢊ+ ( (<iŨ~:m_;aynw& 3/W2>#۾M??7+gw/3__.???f|E IŀO ̿c (Т((h|+g?|>e|9N(l} 3/N]Azy[ O4پ 폵f|E> ߋH5@L 0fW"ܻpLLV߾  _w_5hd5oٟ {_{{o'UaɽC?Kӯ&ߵ__ikN~-~kpRa1? ǃnq\@QE(2WAeno?Vi;|S  & O^OQ|c:ς!-w⿈ qu{ZgŞ3O(x;U^Ծ"پi=G#^ѼE-K<'i֞*ҼU)h$ǁ=~(߶O_vO OG~5˞.ż 3=φu[EA,DŽ>x'O4Սw*Qk{Z}yy19m{r ˗hR~myy18~K{׿?5չy_7XÑ4l՜:oT ~ t+M ߁tMp3gso>&xrv|%y?`e _ٿk/'-| Qco)cFG%ïGxSj~8uiW|!,?>?bp/?yt_8_22<9c;MھT<Nx2OuߵnhxC?KωwA_? ~*jg?'k<sºWo< G%ށEuc' Uy_~>&xrv|%y?`e _ٿk/'-<9c;MھT<Nx2OuߵnhxC?K91*2ZX~ ?53 ]x+7ۿg,~i_?W_ \iAbhg wQG&;pE[_}yK_ߋӾ*xjh # ?_.ψntK ?#'!^ Jt߆~9?#-gy3Ö?n߈//MCa.W^ _??h3ԯ6|Teۼ>y>#Kۿ?;?<_V~.''Ɇ;cpp* O2gׂ~2-˿fyX~ ?53 ]x+7ۿg,~i_?W_ \iAbhg wQ]| oo;}eAx7矯ωwA_? ~*jg?'k<sºWo< G%X~ ?53 ]x+7ۿ@Lw?7̿/y3Ö?n߈//MCa.W^ _??h3yo⦡cw?~w+efwC؟~]QɎ'Vy_~ |X^# A ï W½:eO! Դ+MßH .x~L7<9c;MھT<Nx2OuߵnhxC?K^}w ~Gf ON]}K+w ,ψ\(cpxA؟8yׁ}̿__8K_?yo⦡cw?~w+efwC؟~\^|Lۼ7 gjcKSP?;_~˟?;׈?~_OZ? . +A8O"o̿/y3Ö?n߈//MCa.W^ _??h3yo⦡cw?~w+efwC؟~]QɎ'Vy_~>&xrv|%y?`e _ٿk/'-<9c;MھT<Nx2OuߵnhxC?K91*2ZLJ_oy>g⧋>w}c\|ZC'ҵ]7gK< wxރy3Ö?n߈//MCa.W^ _??h3Kyۿ_ڿۿi7ۿ;,ψg;w ɀ;8/'`ϘyŖS̿re?K_d5oٟ {_{{wLV߾  _w_5h٨Ͽ[q 3 :mPص5ƿ4IAbv/x1&(eEWWC^Waxߴ-m ?_ |Ik q lgxfG5_?Ng_of(K?c}[}/E]g+O- n?A ,km`/a;r~n]l__WgJ.+rY__P5yy~Oc_e+=P((((((((((اߴ7?io٧"?[FW_? ]Yx>:/Ax/7< :*x2_~|L~%؟G+?ci_ۿQ apÄx?:rࢊ+ ( (<iŨ~:m_;aynw& 3/W2>#۾M??7+gw/3__.???f|E IŀO ̿c (Т((h|+g?|>e|9N(l} 3/N]Azy[ O4پ 폵f|E> ߋH5@L 0fW"ܻpLLV߾  _w_5hd5oٟ {_{{o'UaɽC?Kӯ&ߵ__ikN~-~kpRa1? ǃnq\@QE(?{~ -Ok"Ėk7py^ wasUx?oxֿk❶Aү o>:îOyw&|Џo폋zO~!:<-|'񶇬^YŦ%]|/# x3࿉O4m3Q+ S@mFI|QitOi1lwlEN?2hsr, FNѯIX΋u:U|<4q8̻ü0]zSAV,4ZNNaqjƆ&hRrQEzơEPEPEPEPEPEPEPEPEPEPEP_WO_wۧx칣xBÿTuo7ӵ>? >5_W-M_ >4?[|To?|1qQ@?xWǾώ o>4xzΝ? ¾#ӭx>!o4{yghΗyujuյ+t@E/ >8W%[h#ּIyh@|W߷O|P~33Yѵ8t1ޝkcso3m}+¿6/i}Ώ^4^⯇*5袊JgOX}OٿھO??C?Cg?ww>^^lyi}27W_|Gbwhghyڿ]ONn?G+ lPpG4˂(((^}w ~Gf ON]}K+w ,ψ^ϴ?n_6~ ߋϷie?P+^?S'?72Վ((;B((?Kyۿ_ڿۿi7ۿ;,ψg;w  o?>3w۾x2KWwC>fw'>׿C_'~. =08/9_r=33M[g~5u1x?k?տf7_|7_'Wr0j3V|e&; -N~-~k; :mPص5Ư)Kp2{ ɻ?iqQE~|}?JD/"ռc'ſ~"i~jl EcVox'"G⟌YxĺVHN>WÏ_|=ĺڗxQtKa-l|%>/׾|CWC^Waxߴ-m ?_ |Ik q lgxfG5_?Ng_of||BuaZSu'S:Uy^Yɵ'6=uˇygʨ`8#"4!OPdU %A> +a+U6Z( ( ( ( ( ( ( ( ( ( ( ( ( ?$~?Nߊ|U>7fqiw0𕞡6⍶It 'o=?K|a☼;'WwO~\6RT($e(I&gE뤢ԢM42e䔢e(I)&8JIBQ^i9W^e+$+@|AqFƿe9>;A|DC|O' mgus3x#wk_#zo·a;3 eihy 3/SZ>!x_O~ ׆f5#QH.,o-l4wywŞxW^յ xF|7]m?_ׁ=#^ѼE-Kß _mW|3:]#GW| УX _ ~_Q|_ϡ?1s̿]Lj~3A>|`Mi}#!/Kj?f[Mo~gioAg~ZW??;'~__w*mlh|LjW>*x2_~|L~%؟G+?ci_ۿQ `l{Q'/3̿[Y ۼ_tjc~g'dy_x+KC]_KxOů:| 3C} /K?®/XEuJ'o}Þe~_vywg%WxocCg,R#wk_#zo·a;3 eihy 3/QGԨ>/ ?;y5~} ۼ_tjc~g'dy_x+KC]_KxOů:| 3C} /K?®/XER/Hg9_gLj/gb Y½O?zuooO?Pt?#WC3¿wa''~.>;CoMCcg_@L {~;?qe}aSfy q_]yO_=7[fhwO w/ vg9_gx3w?n~-|A}MVٟ?og}a]/;w?>&/<;y? k>Ǧ+N3?.W ?b}J!C~c_ݞyO_=7[fhwO waQ'Y˿yq2/ϟd5oٟ ||ayswLV߾  _w_62?'UaɽC?Kӯ&ߵ__ikN~-~kpRa1? ǃnq\@QE(?{~ -Ok"Ėk7py^ wasUx?ox^qԼ7 ۿiRZ fn+?j~߇ٛG(W6+_ѿ5yy5}{ Vp턢 7/ŝ _\8o6Z( ( ( ( ( ( ( ( ( ( ( ( ( ( (?!w1i>*|?>|8s틯]PQ7kzǯx~Bx ?Q?ů9j+^t߳YOm|O wuY|AOKjH|?i%#]|#_L}?z>"|Aӄ%RQVufTwoj)'f^8FѲokp r(FҭQU4*tTQ*qR^Q^?ڗ|*x~x^wӵ}9縱/hZxO:vI|)F&ivVhQEQEy/>?Pt?#WC3¿wa''~.>;CoMCcg_@?e|Gj}?gjhfoW?d^gۿ]hm lɂ /ؓ QEuEPEP%Wn}/_sMQ^?Wg_3P  Oyi}o?kj}yj\aEw?&3ٿ|s<ko~5ɟj߳?W>+fV_@?9O5r>2{?~_Mjf?ӵx6?ZNW_8cX~=?4l(Q?R (K?c}[}/E]g+O- n?A ,km`/>.wkb_x[^ x/gO 'e <1˯ړV' g) |4zm⦓5úT:DŽ5o4v"kJO%kwşx>+Wqx^R?f=  ¾%^->x; &48}:S+So石9caPrjtM /K_qv]R e)b=*yqףF>yqIaT*PxТ+<Т((((((((((((((( Y??|90> Cokv)#Úo[mjiG55^V?4m_iU_UZk~ ~ o ME&D_ύ+ŚBǺFuŞ/+Akh o¾j٣czOƿsGtA 75#wGD|kf_@,5h 5]e ithsy3Ö?n߈//MCa.W^ _??h33 Jn\VnhTJҒe$M]jkFr`Tc0Fb(qR\Дԕ(ukF@g,~i_?W_ \iAbhg qy3Ö?n߈//MCa.W^ _??h3>'`,_xx2>#۾M??7+gw/3__.???f|E <934osg⧈>N~G5-+J|?/H< .>9 X~ ?53 ]x+7ۿL?gۄ{M|&xrv|%y?`e _ٿk/'-<9c;MھT<Nx2OuߵnhxC?K7 40aº}C_;i/?>6omwGc{_Y<ϵw; C+?<8 4um+?_<[xkn%|A>>([[~>>ωwA_? ~*jg?'k<sºWo< G%ܘ ~8/'bhϘ|3<7. bϊ}~ɟj߳?W>+/=ջ@;&ɫ~o\n;O[`a?g8Mw]6?ZN_wu$kk;_׍_ӃR ad<wӋ+DH+u/+0H$Yۃ3#xů}Ŀ?{~ -Ok"Ėk7py^ wasUx?oxݰԝ 9B7. Z֍Tl%~_Uȕ~,/_'s}^E螨QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQExOŞ*3 Ax1𞳨s^W5mc&ψt{=_A6Z:^km}csJy8<++NsQ~+7,Q\]xKN߈xVze55'<sGq|[:> ^|3 (j^Odw?󣢀?0O!wO)5~Wb_^?|v9{i/:Q?2g~x |G |2][.XY/`e?F~"-> x_ؚơg Ե 5] S.>iu^\ϴ?n_6~ ߋϷie?P+yZkڿٛ3?;w/Gyj>"r`? v$_Q]ghQEQE o?>3w۾x2KWwC>fw'>׿C_'~. =-¿wnw^ijnh}Úlnڿ>"hykw$W&`o3+n]`8OG|&ɫ~o\n/;O௷V?sgfkUφb~ ٯ=ս@NFF}ܰOpioڃůٯO^5_Mjf?ӵx8?)|WOc7yG8[. (OԂ=RcGnKkhwxWYSK_H5<xkg;09w qi/&|8 wUȼ kǪv>nÿ._ ~?wgA/_tgF| ;ՍωR͵ WgXhƝxz~ xW~,п]tQ_fox:ſ$N/^0_;W7 o ÏhV/>tF\"NjUiJQVIThƌ Ԫ׬oZy\u$urwo( B((?Kyۿ_ڿۿi7ۿ;,ψg;w  o?>3w۾x2KWwC>fw'>׿C_'~. =08/9_r=33M[g~5u1x?k?տf7_|7_?0> AZ??Mw[6?ZN_wu$kk;_׍i_8cX~=?4l(Q?R>~j''RWwⶍGǶ|)w/%|x[,qO[sGּ x+ӼYjյ=&g~$_GD1|5ռ sഖi6vbKc&-KCU˟./<_:o&OM#?~wP ZG4go=CLln` ?moS_q |όCv_v /V_߶G//~/|z?tOWw_j/~7~1iBͮ4/i|P=pï_5_ gVrFfݹ):JIYfU+$'+hvRt q ' .dM7^r$қڴZ_Ex?t|?x'Ş3o >-c~&gmkZG|>txSTޝ>_^ڿĉ~# ۼ_tjc~g'dy_x+KC]_poxm9_Q^yO_=7[fhwO wh|+g?|>e|9N(l} 3/N]Az|#~_gyf AgÞ)[Ӿ/nfcWRW[nFyO_=7[fhwO w;Fk}?PN]Co-?JӴhvkuxW~!|=Oy[ O4پ 폵f|E> ߋH5@?Kyۿ_ڿۿi7ۿ;,ψg;w ɀq&L[Q?~ɟj߳?W>+f\ɟj߳?W>+fV_@?9O5r>2{?~_Mjf^5_Mjf?ӵx8?)|WOc7yG8[. (OԂ=RcGnKkhwxWYSK_H5<xkg;09wx^tE 5ExO:v_xWV|)Y޳iwu8 Vgϋhh4}[h⟂եxAK-WF^fTӼ;OT}LxOŞ*3 Ax1𞳨s^W5mc&ψt{=_A6Z:^km}csJ1C_;i/?>6omwGc{_Y<ϵw; C+#o 3~-6߅޽q]xWT֝מ"յ=_B^#ӼYx?f]ς lX{ (ss{4s[0廵{] Gl>(Tn[˗ҵw&3ٿ|s<ko~5ɟj߳?W>+/=ջ@NFF}ܰsOpioڃůٯO^5_Mjf?ӵx8?)|WOc7yG8[. (Oԏkoxo }nj*^jQwk |=Iex@7͚K.%?gk\\|G>wxk>ŕÛsğ|PM߄[qx"O5h^)?|Shxɯ߇,?o~:hjuM_~<C|L.|#x_vSx)$Wl<yU*ʕLF_NTiӫ5M9SXJ~'%qU9K?~.wԖ*rTxqJ5s}|p9u_:Uє1x俳'B8+(\z+(|_ Oo~(.yώ:[H~ɫKiW~϶浛|%?;7u[ ?| ŏx&x^+`xK/Vğ˚IѾ1izu -e_Uu(קFZՔ*W JWMrT6)B0)l V71u\,3)8qTqq,ž.51+CER gc?_>dz+(z+i"*j<-Oj=oG5ح!T//4w <']fP궞-e ?#G>5~;?־ ?>|Ak;%°|Lԟ )o ſggܾgj>VH/x._[a.rRU9$EǙI5cZPIfjK6[VY"Qs*agéc!4WQ]͟EWQ@Eŏ!r4o_o0&'$&4>Ҵö+T߀7m~zoJW~|;t↛E*|A_Q|U;~:I~>->;"մOڗ&?<[-Vis7SXW2lMJ *R95J*-An6~'f|=|.iO?q2T+ [aQץ L偩1q*Xzu%OX +(z+(+Vyh~_0á| m迳bd*GSr}*wtRT乣GLa>3e<=<ʍj ƨt.73T՜kB_Ew.=P__)Nmh|..g^ OOo/k //~j,ij~&x#C h>ʭGIAJ5ZTڄe'RjmF2iߞr,c)9+$8cjb)C p8dgB:bcV_ 5*JzؚS.w(şc՟?khg_?_0 1© G1W}@͂TL%|/$iI{hN h<;oxWtZRj~Νj>ΌhѣZveRU'RVrQ=*έ9㰸'N1XV]U71TjfY]x⾹VUQa8n3*W%2~*g-~4ş>xE]&i~Aj:>7Fգ߉k^+W^Oga/??|%?;7u[ ?| ŏx&x^+`xK/Vğ˚IѾ1izu -e_럫8\D*zg TԤ!.ux87+1=pE|%.o)p4`*S*3U gN!BJhVkB}V4/~ſ|/}|QO췖_:>xOV/Ǩjk>}imyoyWVΏwO6?h*A>;O௷V?a^-Us,'S*.)A0c+^$)'ø 2RWT<4*ѧ*\`a6bou$kk;_׍!ioڃůٯO^5_8cX~7cMQcN/ˈ( (((((((((((((((((((((((((~ ٯ=ջ@Wx??>E'f}rʌ!7#_ ^,Ǫ|O>i׶χWw/N>x-lGC)t0_0o?g wEq߃>xŹY^uĹz53<Xx,-¥xpxj aiVJs(qAWqNm˨1H`g53 ul[T<^3R*z jA92WOß3]_QE|4}[K K_XxW%ofOw^_# sFa'sGF6N֊(F=[OK Oͳ+/# sFa'sGF͘]:E/`W+K?0?fF֏+đu?Z>g_Lo~73l;/Ra90͒u¾јIZ(?Fg^Xx/8>lOwd<'1I]Yҏ'?rW_uQI}>{%կ set_obj_in_basis

set_obj_in_basis

Specifies if the objective is in the matrix or not.

void set_obj_in_basis(lprec *lp, unsigned char obj_in_basis);

Return Value

set_obj_in_basis has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

obj_in_basis

TRUE or FALSE. Objective is in matrix or not.

Remarks

The set_obj_in_basis function specifies if the objective is in the matrix or not.
The default is that the objective is in the matrix.

By default, the objective function is stored as the top row in the constraint matrix When this function is called with obj_in_basis = FALSE then it is moved out into separate storage. When out of the basis, the computation of reduced costs is somewhat slower. In the late versions of v5.5, there is now the option to calculate reduced cost in the textbook way, i.e. completely independently of the basis.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_obj_in_basis(lp, FALSE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_obj_in_basis

doc/del_constraint.htm0000644000175000017500000000557610351334154014025 0ustar renerene del_constraint

del_constraint

Remove a constraint from the lp.

unsigned char del_constraint(lprec *lp, int del_row);

Return Value

del_constraint returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
An error occurs when del_row is not between 1 and the number of rows in the lp.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

del_row

The row to delete. Must be between 1 and the number of rows in the lp.

Remarks

The del_constraint function deletes a row from the model. The row is effectively deleted, so all rows after this row shift one up.
Note that row 0 (the objective function) cannot be deleted. There is always an objective function.

Note that if you can also delete multiple constraints by a call to resize_lp.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  del_constraint(lp, 1);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also resize_lp, make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_constraint, add_constraintex, str_add_constraint

doc/get_obj_bound.htm0000644000175000017500000000541410237176654013620 0ustar renerene get_obj_bound

get_obj_bound

Returns initial "at least better than" guess for objective function.

REAL get_obj_bound(lprec *lp);

Return Value

get_obj_bound returns the initial "at least better than" guess for objective function.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_obj_bound function returns the initial "at least better than" guess for objective function. This is only used in the branch-and-bound algorithm when integer variables exist in the model. All solutions with a worse objective value than this value are immediately rejected. This can result in faster solving times, but it can be difficult to predict what value to take for this bound. Also there is the chance that the found solution is not the most optimal one.
The default is infinite.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL obj_bound;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  obj_bound = get_obj_bound(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_obj_bound, set_break_at_value, get_break_at_value, set_mip_gap, get_mip_gap

doc/changes55.htm0000644000175000017500000002305510272542636012577 0ustar renerene Changes from version 5.1 to version 5.5

Changes from version 5.1 to version 5.5

Main features and changes to v5.5 compared to v5.1

Why a jump from version numbers 5.1 to 5.5 ? This is done to indicate that this is more than just another update. The solver engine was revised and optimised in such a way that performance has improved considerably. Numerical stability is also better resulting in more models that can be solved. The LUSOL bfp is now also the default. In the past, the etaPFI bfp package was the default, but for larger models this leads faster to numerical instabilities and performance problems.

Overall, the v5.5 code is faster and more robust than v5.1. This robustness is for example proven by the fact that many more models can now be solved even without scaling.

The API hasn't changed very much. There are a couple of new routines and one routine has an extra argument. Some constants got new values.

  • Fundamental internal change to the solver engine resulting in better performance and numerical stability. Both the LP solver and the B&B solvers are enhanced.
  • Optimised MILP branch truncation, with reduced cost fixing.
  • LUSOL bfp is now the default.
  • Presolve is improved in functionality and performance.
  • Better handling of degeneracy, with more options.
  • Store and read options from a file make it easier to set options.
    See read_params and write_params
  • Partial pricing for the primal simplex now works.
  • Full support for xli_ZIMPL v2.0.3.
  • The objective function is no longer stored as part of the constraint matrix.
  • Dual-long step code is in place, but not fully activated yet.
  • General code cleanup.
  • Added OBJSENSE and OBJNAME headers in the free MPS format (See MPS file format).
  • The MathProg xli driver has now the ability to generate a model.
  • New API routines, see further.

Note the store and read options from a file. This can be a very nice new feature. lp_solve has a lot of options and with this new addition it is much easier to set these options. People can start looking for the best options that work for their models very easily and it could help to find even better default options.

Changed API calls

  • get_basis
    • Return value is now unsigned char instead of void

  • get_total_iter
    • Return value is now long long instead of long

  • get_total_nodes
    • Return value is now long long instead of long

  • put_abortfunc
    • Argument newctrlc is now from type lphandle_intfunc instead of ctrlcfunc

  • put_logfunc
    • Argument newlog is now from type lphandlestr_func instead of logfunc

  • put_msgfunc
    • Argument newmsg is now from type lphandleint_func instead of msgfunc

  • set_anti_degen
    • New constants are added: ANTIDEGEN_RHSPERTURB, ANTIDEGEN_BOUNDFLIP

  • set_basiscrash
    • New constant added: CRASH_LEASTDEGENERATE

  • set_bb_rule
    • Constant NODE_GUBMODE was not documented.
    • New constants are added: NODE_RCOSTFIXING, NODE_STRONGINIT

  • set_improve (!)
    • Constants are deleted: IMPROVE_FTRAN, IMPROVE_BTRAN, IMPROVE_SOLVE, IMPROVE_INVERSE
    • New constants are added: IMPROVE_SOLUTION, IMPROVE_DUALFEAS, IMPROVE_THETAGAP, IMPROVE_BBSIMPLEX

  • set_pivoting (!)
    • Constants are deleted: PRICE_AUTOPARTIALCOLS, PRICE_AUTOPARTIALROWS, PRICE_AUTOMULTICOLS, PRICE_AUTOMULTIROWS
    • New constants added: PRICE_AUTOPARTIAL, PRICE_AUTOMULTIPLE, PRICE_HARRISTWOPASS, PRICE_TRUENORMINIT

  • set_presolve (!)
    • There is a new third argument: maxloops
    • PRESOLVE_DUALS has a new value. Before it was 128, now it is 524288
    • PRESOLVE_SENSDUALS has a new value. Before it was 256, now it is 1048576
    • New constants are added: PRESOLVE_KNAPSACK, PRESOLVE_ELIMEQ2, PRESOLVE_IMPLIEDFREE, PRESOLVE_REDUCEGCD, PRESOLVE_PROBEFIX, PRESOLVE_PROBEREDUCE, PRESOLVE_ROWDOMINATE, PRESOLVE_COLDOMINATE, PRESOLVE_MERGEROWS, PRESOLVE_IMPLIEDSLK, PRESOLVE_COLFIXDUAL, PRESOLVE_BOUNDS

New API calls

Removed API calls

doc/set_XLI.htm0000644000175000017500000000502110461510302012276 0ustar renerene set_XLI

set_XLI

Set External Language Interfaces package.

unsigned char set_XLI(lprec *lp, char *filename);

Return Value

set_XLI returns TRUE if the call has succeeded, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

filename

The name of the XLI package.

Remarks

The set_XLI function sets the External Language Interface (XLI). This call is normally only needed when write_XLI will be called. read_XLI automatically calls this routine. See External Language Interfaces for a complete description on XLIs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_XLI(lp, "xli_MathProg");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_XLI, has_XLI, is_nativeXLI

doc/get_variables.htm0000644000175000017500000001057410237215300013610 0ustar renerene get_variables, get_ptr_variables

get_variables, get_ptr_variables

Returns the values of the variables.

unsigned char get_variables(lprec *lp, REAL *var);

unsigned char get_ptr_variables(lprec *lp, REAL **ptr_var);

Return Value

get_variables, get_ptr_variables returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

var

An array that will contain the values of the variables.

ptr_var

The address of a pointer that will point to an array that will contain the values of the variables.

Remarks

The get_variables, get_ptr_variables functions retrieve the values of the variables.
These values are only valid after a successful solve or lag_solve. Function get_variables needs an array that is already dimensioned with get_Ncolumns elements. get_ptr_variables returns a pointer to an array already dimensioned by lp_solve. Element 0 will contain the value of the first variable, element 1 of the second variable, ...

Note that get_ptr_variables returns a pointer to memory allocated and maintained by lp_solve. Be careful what you do with it. Don't modify its contents or free the memory. Unexpected behaviour would occur. Also note that this memory pointer is only guaranteed to remain constant until a next lp_solve API call is done. You should call this function again to make sure you have again the correct pointer. Otherwise, this pointer could point to invalid memory. This should not be a problem since this call is very efficient.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL var[2], *ptr_var;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  get_variables(lp, var);
  get_ptr_variables(lp, &ptr_var);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_objective, get_working_objective, get_constraints, get_ptr_constraints, get_constr_value, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex

doc/O-Matrix1.jpg0000644000175000017500000010626410251404700012514 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?^Z׌a~ھy4K-:ܮX]'NmiC D?>$YA"JF=6ܬ,$ 6L8?) 12>|C3ᮃ^.^'^m3ՖMKJҼZ&ou?QD6:ޫkioc:۷c{- Aox0׉ [O/|m!IUz)Fa'.Wd<g/Q> Mψ%KKY{H>&I/؉E(1Ss/;\ͽ?K08_R<-S7;2f3 |C<Լan ëqcXxj843Ƭtye\O?j>=1~ˋ&k__g_|C7_7?a ލC|AO?!V{xXPp7Y{Ù~gnegIpMpfUO4կ3ڮ +ڭW§ P*]\䔳EGӧsҥ`qq..NPa\XjU>TB>'[ioZ''ğ?_?|[KQx_~|,~ ƵĶ=wTԼ[ е?zׄ?νnzekXa#<- S/5υl7oǟ?)}6Jhk;o >!xş tږ@мAqwiz%u5[>ѿ6O|G㏀~<|׼i;|'gXkg x׾.iq^12Y.6|R8EM(| ?-_G4O Y-}7 zxρ2|"k/??x9z>eOǿm?{ƾ&o<5⫯Z:_"/O VZ- kV>e~l-kYʹ׺ΛUy c\&Xr9iĹ^qy>sKȲx8,22~;0؉,TQe%O#8GAk/E'[O7߀0xk?h~˚_'Q_~)x[_xDIt-3Wk+ W[}KzW>*跶(oK9n4Ux;&rg/0'CNhVSPRjs<e٤NAk/E'[n-h˿QN? bzeo+%3ioZ_j??mҏ쌽̣/eg۽X ?J_˵N|O?#n_Z?#n_Z?Y)c(  ?f#y~/5o ֟G5o ֟_5g? 0m~O<S7kOE7kOEQҏ|6@}C?q?Y_}) Gr5" Gr5"~Y(GG>_Bp>,y/>AhAk,t~yg/F _PPObk6iߊ|QO$v^olo&^"|?dιVz>zֿhZƩce?Kv?u]ե޷WkqȰ>3xZTF¬mO1<ppp q䧐ee9VN(0X)b25JT湶*yS1U})NtA'peYe }\oʽ\Lhj¤a0r{_9M.hRqj\}#4iloxG'?l"A  㞀5O1#iuoۛf-ρlLD_$`N=7ĝ{R KϾB  =_힩wq< ଄F8 ~[Tx8CU׆%~hE9*qSNIg깿[QSXۜi{\?^6rqf['{W__ď>%+_0VEuu|=7:ÿx2W-|Yq kk^H LԵ OR~.i<7߶_o$lUb2?b q_(']fal"u;IY?0 `6rH __&_-#=|oĉ>|!guZMT> |.W_Fnm4Kk=&(exΎa,/ y3rn c#W+93OOOĔhQxJRJ+bNOc*bq0 gxi:ΰ} sBA:eַyTӍE 4/9ҙ!%\}SRReݎ'w%>z|=7V%Y閖?"{-CL5 9!g|ܽs2@l3Gt؎GKr R+qy1pmü1β4N Mc|Bcz߇Iq\CB1ų\$o LmmeX# 㧍ӎZn%zU"*)WG0t75Y?ت}8jORPs(g<=m;_moۃVj~,'ԗ6$ ^_杨 s6a Y+f {j `%Cprd#%} x["gp&_Xsq̸+p4#N&Ce*K 5)ҥ gxif9WeY~[0ѩ 6J|)ƜjN\$j1?l?ah?:~>/!X]ýoSqEico:O[bHI/7|77g[K;g?Ow4-x-S񿁼;+[E6-+iwviOj}_^1OnO7 xz߄?|uM/č_Xl6e:]1_h %VwW_~[Qdc6d$cFv#xX *,rrZ\u2ԝ10ЖFz;cr^?J3, l."c2lg*E[,XXܷ8#)ԥ,Z3x.+ (yw[o ~Z^(fDo{{:+m[liއizmNGGޗhھap/lo|Shv>9~_|4¿ [_xU|euC>xό|}Ꮘ_]o> ~:];Pռ}yGjfs! lvOF'Oӓ :Tp2.pF#f3;3jazI{6+3:a01o |/\:ḎRx:NKphd:,CQ~Wڊo'_W?*_(4o ᷀~YC;šZYY:OX)yךjZlfK O;' Gqw'j^7hQw0vׅ V}{!T? _ 1ES4g8*B qk G\L?峎iR8+'ȱm>KOfЌ3L ΖYgQ(bs,CO\I( F+qY .sBQQfxjt9ҥO/WLe:VOǟ*|M/P @7>|ŠE|D?i> FCGng^k+w?~߷OÿE>b/;u ? ?$f|Oտ4ks/ _ KZg>>aA4f|CtWP2YTJjEeZy6_ 1ES4g8* xw"q<ϲ >D9,N#,b~~OVWO(Kº1eOs}$sL5d2qؘNJV)ju5ey۝Ztt,> 2/5nٓվ:Gڿ UA^xR~⇍<3<i>,.U߉㨼O^kmJ?|(+طu{G|0|#tO#N^{J7O =|^xxM+v~ƪnDgC}cipUǿB0X f<3fV_<aL:2l.kO5}Gʜ=VH*ϤfyV{6 2l೼|djeؼV?-R|Tv&/sqb+Ú2G ?aofφI.oQ3~:Q*?QF?~Ɵ_|l_{?HOx)'ż7gab1saF+VUÖ G УR)')|xU 8)-8,YNaV|v+R\N+WRUQiB(~,G"yG|F?~Ɵ_|lGC}}]4½:P*>[%$o O_E(X(¿u(O uU?cO/6}.^qmKIf=>Ƕ7QQ3~:Q*?QF?~Ɵ_|lB]4½:P*?z}7?m ???o??O5_cipTW 1ES5Å8.}|[eLs^ ?4_p_Hw.~.?~jEOWC W 1ES5ÅWMѫ t8ot y?߄꟧q=SUF?~ƿp7!T|oGMѫ t8ot y?߄꟧q=SUF?~ƿp7!T|oGMѫ t8ot y?߄꟧q=SUF?~ƿp7!T|oGMѫ t8ot y?߄꟧q=SUF?~ƿp7!T|oGMѫ t8ot y?߄꟧q=SUF?~ƿp7!T|oGMѫ t8ot y?߄꟧q=SUF?~ƿp7!T|oGMѫ t8ot y?߄OՏ(!Iczҡa5_(ߊ=E'qLu?ࣿUc/~9_KߣJ¯m_5GS ~[~_w# C{Ewc/qo?vSLĿD7P_~0??oM~:Q*QG?^rGMѧ ty?_pK(y/|?oM7O_&wO( ߎ_(u?ࣿUc/~9&Gk:t< /8%<_7O_&F/_wc/q:Q*Q}i:f_O?__/F/_`?Hxټo1/ GM9U#ya1K+4v_S ;E_18|2>*gƟثNcnb?ŏz΍Zcx/xc~֬eZ׉t}[A,SӮݣ?3J_}br\ŋ3- >y]:쯇4׶~oiO_ |o'WOkq|<<_߇rg?]:IVeQ4'MkXKeg5cw/:U]@Hp0` NDF*0dO TsF^,ʍX$¼lx{4 -#GßV_^oϦx橧jw,fލuV avs<[Ǐ؇D?G_ 9o!c3x$M?QtT|9xge} +YU8AQ:·~jeSʼcbܟ#&sf|#=a^_Nj0UvbeJtr֍n/ \? prc3<e 7T-G K ^ҕHԩe^`߳WOxk?kǎx_I'/ 𶏡ZO>,Y}RK6Kakic?q=}e񄮟G١W?oq<iEIHg~c4o$/XCy?x@-\Kggxc^;3^]P׶Q$Z7 ọVI45XD#qi?TmJF_7QD9ψJoZIS nXw*J}>JvJ.HMtw؂i#d2b[x. 42`ӸWڇ1yI.ϨMqog6^&ac1c;mӤv}9o[ZeʐF8/VZk=h/؊ Y.%ѥ񶇨.!x.[FVOrKg`<'7 ZŠTէ|Y^:YOhƽTN5*\ׇ'joO O5ujЭNON<Ҵ&S#j,- am NA߀[FH}=#~Ƶ]#x*&=tۿh~dx4EU!5P]yqyK?1|$\8s .J;.|;MRkҭO|qN8fqGcX2Mʎ'QiRJ9+(_0oB~;q_еJoH_>O Ev (?F ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (?p__??h$*ه}_[ۧ\ pg o|%|;~M|27~26(͗ f:W-_?I& 8gҿ&,Y|1n8Kş (?E ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (?q}| r3Es_+7^ٞ] ˘"Ǎ? gJ+h|p_> o%Gw */Z?eW_xW+6_+ȋNox3߷_ |R7 |) t7ī?7]e\>6g{ ct>&~п bmi~$~~WRw5ߊ_%??ٟ|E/|?'?ú7Yi?AZ[X2ͽ_ xk_k'?|IH7=e4|?|fe_7wf[+J>?d34~_NV_Qs^Mcg =#^mtsYӭaud``,%&GҞ*< 9i>f~TV[GJMx{,׵{?k7qXr:S}?EQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE)W}9| )J??xOf{Ow<2-8ˌZɂx&Ysfo6Lq7_C5N})!|Yc ?p?gyşY/o&>/O?C)j^᧋Ũ+¿?۾ }4OW_eOywKǿ d_ bLt_ XX_ 5O~&'m?۬f> IG|)icÞ?q|O~8j?~:SQ(|N?hO|E=S?{x~q6_C^"_ ,~8xOS¿_H xVOSڧ.j^W< C>i 4;fKm:Qk+Nx_*ŷ?dYYuG^Ӡ|Y˛0+4jgك⧂dն'o>*S:T:Ρ~ۿx~H\ͿtFQtRXhך>QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE)VtY?oG~ _ɺxd[\gFl]_m'/gJ+i9|p}hgҿ'>,Y|1n8Kş (?E  Y& ;Ma~5kRu< Vƿi~,o+x_1t}WAMF ~)xfN_PN4mcNмiw¿<+?h@sE~`(૟qR_о?|u{]Gwoi|?Wv|-ZvNn @/ ?((((((((((((((((((((((*8q~? g xIO23ˍ_mYu`9z+ U_JoH_>O7%bQ_~ۛ[}77@ EPG:?h~_7LtmN+G Xo/ _i|?Wuz_iƍi<W|' ~U 8k)u dh_뺽㿁;mnf mJ;U>R;G揧jvZg~ xW5}27?k_k\/Uį!ÚwσWZޑ}ো//i ZZ[jG?1i3E| ~?_qgA/*tgFӼwzuωR͵ hؾ:>xz~,~(((((((((((((((((((((*~? K8U?q7E<&3o8ˌӛ?O0__=~Ε Wɂ*Ytbϥ7/?Vb ~'g oxfOz7F.?j_ |UmofCoto7/كG/_[IW-C'~0|!lKOK k??ƭ7}<_| CW8ouoU )?Kw @~_&M=k1g ]gGYZxF|@|Ioh:/-,P>,^7ixMgc=gN|Y__xg:=摯x^/,MY.SNxokg\GOg;ãI?eSAx{J_ ?-Oڃşg|S'~<!A|Wxt֡[f'GOo+x_G!<3}iZy_BѮMFn4-Ҵ뗖򤢊(( G\uƿ_|?WFiM:k}?PQWu]Co-?Jukux!|=~߷O|P~33Yѵ8t1ޝkcso3m}+¿6/i}Ώ^4^⯇*5Ư%sJֿ ]U_:ux㏁4뫙BmG_u+Q<j:֙⯇*sE| ~?_qgA/*tgFӼwzuωR͵ hؾ:>xz~,~((((((((((((((((((((*89R+7^ٞ] Xo$ύ?)͑u`9z+ U_JoH_>O7%bQ_~ۛ[}77@ EPEPEP G%h_.* wWӼ u~q  h꺇ߊZ~5NLW|B{on /83g WyfjqZ;c: ~)xfQWl_PQQмiw_U?k_G+/_$W@>8x~9~v<^էECY/@?k~0ϋ4 K}9j/~5垑`д;=WJ|+ºN_j6|6n~5R{Aϟ?SOo3Nv<76wz W|; N|Ui:υ~ۛ[}((((({q6EOY|xky:VY'_A^Y Ht'¿|+֡j:7o? _/ > T>&/34jsqcymsg}og^ е{=Gþ,t'^ VSz6MT?7 o%Mb O>)l|+OZ< _'ĿSK7ÿYcQçG;{VuҀ?j' ¾ׁ|Mx'ƞѼYOYӼG_xWzuxg:=摯x]/,MY.SNxn ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (?q|~?n?J?Of_w\4-a8>5֫7?6L?qW_C`9z+wM) GxI&ㄿY8+P:;PQsݳaϵ_?twfhh(((((o8g_MiQƟ#W2^j=g毯|׵{˝gMQn/ 4}? V~,|+x|iŞ;~g|G[k7|Ci"Tѵ.N4kV(((((((((((((((((J?q|~?nx8/Mτg%uG?_jsi?|sg:W1_?I& 8gҿ'~,Y|1n8Kş +,Gω +xcOxsR!_ <#;*o?,?x+ߋ?igR$~~GG ?nool?_o#}_~|?Wi||EHgW໿[35z%ƕO/2|rǎh_>j:o«;sii(టw ._-w?d&/&OHwk C3BҴe4+((((((((o8g_MiQƟ ~\ƑX|!<=?᝖⮏mH|QAG ?nool?~l-Q@Q@Q@Q@Q@Q@Q@Q@u"?1%?ij_o4i!js?WW_:_r/3 _OO(_[٣&A;^MF?c/|Uu ~EPEPEPEPEPEPEPEPEPEPEPEPEPEPEP~?oG~ G)VtYp_ K놏/gƿfɂ*Ytb6L?qW_CN)!|Yc ?p?gQE~~G ?nool?~l-Q@Q@Q@Q@Q@Q@Q@Q@Q@u"?1%?ij_o4i!js?WW_:^GK~,lv# J"iӠ/|Mψ:y_AO'iW+mR6 _]@dߴEPEPEPEPEPEPEPEPEPEPEPEPEP~_oH~ QG)V ~  u? ?|?,MWI& 8gҿyO0__=~Ε W9gW$q_,ݜ@QE (W((ٿg:;PQsݳaϴ@QEQEQEQEQEQEQEQEQEQEQEu"@2%?ij_p4?i!js@WW_:WM?pNw~F%'Fi^*|/״_ǿj, 6~G0~Զ<㟊>!យEO?ߍߵ߅+mO>!Ao'OZ )?_?twfk|b/|]NdO_;G<Z O_~ ?/Y~_xu~=M;sٖ?'Ak)u IOƿi~,Ӭ|UW!1t}W^,Agkvͮk:u6:l^LLQEQEQEQEQEQEQEQEQEQEQExOŞ*3 Ax1𞳨s^W5mc&ψt{=_A6Z:^km}csJo73_)wt_?~KӼ9_¾Ӥ<{-.;=#Aw:ſ5uZ_ixx;_O?x^*ώ ox/ xzΣxO^mx>!l}gghΗykz0E* W ]]#W5/_84xW4/5O KH~0h:Eγo&mk]iֺl^ NEQEQEQEQEQEQEQEQEQEQE_s[g/_E')WAfxx3Mׄg$s'V\iqVn$]m'/gJ+i?|sg:W1_қRş+1_?_M سvq~z Ε%OZ#:uzׅ9h1]OM4 ~8xw)|cu]7O>)C߈e~_ Go x_&o_Olo1z薞0ȸd߇@> h>|,Q=_ _>sE~~|?|])(w_>'k'>"wX)wOٽy?|8{/_//O|E|GcM_x㇇?(?ڿuj )SŗZu/ +?f?{P5h:E/4 Y=NdJӭ+877@ EPEPEPEPEPEPEPEPEPEPEPEP]Yx>:/Ax/7< :xWHj_ |䱾 ;Þ|+:KSǾ4gs[I[ZZu_F`ׁ~Sg &mh,w|'>WUFX3W|Ajvzw_XsR\}G k?h8?~1u[K𮉧~ui[?~}cyg> u{=;Bx{IÞ*w5 jӾ*i >KQEQEQEQEQEQEQEQEQEQE?j_Š_9R+7^ٞ] X_#ύ U_<m'/gJ+SBef+Qɸ/ (+~l~W((ٿg Z( ( ( ( ( ( ( ( ( ( ( ( ( ?2_~/|+:&j)ō͝摮]/5~!ӵo ºOφSK(\_WSiz^Wh|+Ǐ=~5毯|u{=WJռUkZ_jΝ6Sz_  2|+>&/34 Aqcymsg}oyktGþ,t[¾2𮭬Sz6gTq5z56E¿|xky:iڮ'_A^^jwWt[_Ui֡o??w((((((((/9R(*8+7^ٟ] X_$ύ U_<m'/gJ+SBef+Qɸ/ (+~l~W((ٿg Z( ( ( ( ( ( ( ( ( ( ( ( ( ( ?2_~/|+:&j)ō͝摮]/5~!ӵo ºOφSK(\_WSiz^Wh|+Ǐ=~5毯|u{=WJռUkZ_jΝ6Sz_  2|+>&/34 Aqcymsg}oyktGþ,t[¾2𮭬Sz6gTgs|g?j?~czO$ïxk>/;aj|0>!~!? tZ1fiۺQ@Q@Q@Q@Q@Q@Q@Q@8U~>~8q?_ g?E<&3k YYu`9z+ M_JoH_>O7%bQ_~ۛ[}77@ EPEPEPEPEPEPEPEPEPEPEPEPEPEPEP__߷OP~3W|3Yѵ8|N&ucso3m}U_/i}k6h^4^_4/(QW?g+Wk"<+|~xQO.!ӿ*WP[KOҴǚ>i__|_ ~?wgA/_tgF| ;ՍωR͵ WgXhƝxz~ xW~,п G\_ƿ_@F>;Fk}?PN]Co-?JӴhvkuxW~!|=HQ@Q@Q@Q@Q@Q@Q@9U>!q1Es[g_(?xOf{Ow<2-8eƟfgx&Ytf6L?qW_CN})!|Yc ?p?gQE~~|Kw @~_&M=k1g ]gGYZxF|@|Ioh:/-,P>,^7ixMgc=gN|Y__xg:=摯x^/,MY.SNxokg\GOg;ãI?eSAx{J_ ?-Oڃşg|S'~<!A|Wxt֡[f'GOo+x_G!<3}iZy_BѮMFn4-Ҵ뗖򤢊((((((((((((((((aoۧt~ ?e+¾nڜWZ>'xQ7ߊ^ӿ*4ӵXӴ/x/] OŚP\(૟qR_о?|u{]Gwoi|?Wv|-ZvNn @/ ?n; Gx3g fjq]j>MF ~)xfN_PN4mcNмiw¿<+?h_5|~~h ] mwᗉ{Gg_h׼Uo 7K<{/x^+z׎M4//KZz*>Ku[CͳV¿F·5h:{Q@ƿ ҟўA'NV_ |u?:>i~ 5;}fK5:QWQH& _f_?hi ռĿ~1'k_xR¿^:cUt^i徍kk6qm [<|bYK??lg_QEQE)VtY?oG~ _ɺxd[\gFl]_m'/gJ+i?|sg:W1_қRş+1_?_M سvqEW'_Xl_ĿO߶>xOεU]o⯆|A 1Y 5 յ{ 1o Qux~sm{swi:~`|0Y = /X 0#> /, ??@@YE& c\W{  i g?ZK+,L? o&_G L__1QI((WQ@@YE& c\WEe4Mq_ _o+??/i7P1QI((WQ@@YE&򸯘<3~4s9;,|: ?D~%+-7QWuG%O=[  q/.ßߌр~?ϟ~?؟?᥿ N4~?/MqG@YE& &f?C}Dem+_gf_TΟź [F?/i7e4⿿((Wc s~?7 G>^*' ⫭YеmtW15?xº<+ڎKQ7u7#i_6*w;5-#]Bk7wiOhiiT O&|# 6IϩmI0?f >Djυ>|??_ |χEr Gjgo5=CSoong/nP~^ f)Bokw57 j 2ᮗC&:4k{; ¾=|u_xƞ ox;>tWŞmx{sykt=SFt˭;TӮng)[?_?O_G3?*>__x/xoƷ^I3ob}{BmC>!iKB{_>%?J7n|???>+Y𿌼sׄ?f¿&|Jx~!^)B<+xst]xOTO~ ]7V:v_xgPu{Hz֍qyok:Um7W#Gs+N;w ]*QEj~_Ɗ?Jߧg/4Wn'?/G_Êu$]m'/gJ+i?|sg:W1_қRş+1_?_M سvqEW'^?z_ |uww6'gGixQ&c躦/6? ꍬVI[QׇɹѴm((((((+<'~ >)٧kW$~1xï|S&>#񇋿5i-W%^-ӴwWS=/Sºhρ?x'I4|ki࿊|Ucj=xE״?Y6q6vrڍS{PEPEPEPEPEPk~Ҟ F|?:O-|Y;_OT;U|M{Z.YHu.YQӵVo"_,~4~? '& :I #?S>xs^W5mc&ψt4-^Tѵ.Q.`U~wP- /4G 7!dI'#?mdWH?l/ٯºg?'V׋5O|i࿅~ԼU}iZ=xEt^ik7rj7vXruPPEP~?oG G)VtYg xIO7eƟ߭gɂ*Ytb |.vZRG ƿپ!^x~(?U~mtOEH&l$:Νp?x7 h۰ g35/ѓƮ7.+,=,F7*ˎ=}k *tiƯs.*h'*rJ85)r2YpC|?浳|.c\/JV*ɫũѫR_7FI]:Ra?dkO[+%śOVkL?;8C|A:_'lCOß3;Z?M>_Ed|)o0!>_!GuEOß3;ZO+0?WG~δM>_Ed|)?+pGqA1?0?fF֏+đu$DVK7ŸA!e;_'lC r?$_?OWY', 70?!>_!GuEWß3#wK90͓u$fSU79?gTW|90?W_ rq/OS+%řWF[79?gTW92WOß3;Z&H"_Yo"??/yΨ# r?$_(¾&`Gt$DVK7Ÿ/V pyVguEOß3!%wI90͓u$fSU;8C|A:o'_J~Φ'Ēt$DNK7Ÿ/V?/yh# sF`$nh¾јIZ?LD|)En 1_'F͘I+gZ_'lC&H"_YV՘V pba_$C/F͘]:g'%śOVh?*Oq[ԇ?+~ј:90͓u$DNK7Ÿ/V?/yΨ# sFa'sGF6N֗I+o?Va[?;8C|C10?fw?a??di)Y/, {1WpyΨ# sFa'sGF6N֏OWY', 71V?/:_'lCOß3;Z?M>oho>_[0!>_ GuEOß3;Z?0?fw?Ě}"?fSѿهEn1?+~ј:90͓u$DVI7Ÿ>?+pGgqH ?+~ј:90͓u$fSUA"cR5ba??dh~ј:g'%śOVh?+pGgqHǟ<  2Yo(bXl#*0+p818-wOa֣(T 6SX'8W^|-Y ̱:iQuUUS55(doc/set_bounds.htm0000644000175000017500000000677111127442611013160 0ustar renerene set_bounds

set_bounds

Set the lower and upper bound of a variable.

unsigned char set_bounds(lprec *lp, int column, REAL lower, REAL upper);

Return Value

set_bounds returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable on which the bounds must be set. It must be between 1 and the number of columns in the lp.

lower

The lower bound on the variable identified by column.

upper

The upper bound on the variable identified by column.

Remarks

The set_bounds function sets a lower and upper bound on the variable identified by column.
Setting a bound on a variable is the way to go instead of adding an extra constraint (row) to the model. Setting a bound doesn't increase the model size that means that the model stays smaller and will be solved faster.
Note that the default lower bound of each variable is 0. So variables will never take negative values if no negative lower bound is set. The default upper bound of a variable is infinity (well not quite. It is a very big number, the value of get_infinite).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_bounds(lp, 1, 1.0, 2.0);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_lowbo, get_lowbo, set_upbo, get_upbo, set_unbounded, is_unbounded, is_negative

doc/CPLEX-format.htm0000644000175000017500000004320211127434416013146 0ustar renerene CPLEX lp files

CPLEX lp files

The CPLEX LP file format provides a facility for entering a problem in a natural, algebraic LP formulation from the keyboard. The problem can be modified and saved from within lpsolve. This procedure is one way to create a file in a format that lpsolve can read. An alternative technique is to create a similar file using a standard text editor and to read it into lpsolve.

The CPLEX LP format is provided as an input alternative to the MPS file format. An LP format file may be easier to generate than an MPS file if your problem already exists in an algebraic format or if you have an application that generates the problem file more readily in algebraic format (such as a C application).

Note that the CPLEX LP format is not the same as the lpsolve LP format. See LP file format for a description about the native lpsolve lp format. To read/write this format from lpsolve, you need an XLI (see External Language Interfaces). The XLI for the CPLEX format is called xli_CPLEX.

Options

The XLI accepts several options:

Reading

  -objconst      Allow constants in the objective (default).
  -noobjconst    Don't allow constants in the objective.

Note that CPLEX doesn't allow constants in the objective (until at least v10). However, the lp_solve XLI does allow it by default. Use the option -noobjconst if these should not be allowed. The parser will then give an error.

Writing

  -objconst      Allow constants in the objective.
  -noobjconst    Don't use constants in the objective (default).

Note that CPLEX doesn't allow constants in the objective (until at least v10). However, the lp_solve XLI does allow it when the option -objconst is used. By default or when the option -noobjconst is used, a constant in the objective is translated to a variable objconst_term with a bound equal to the constant set to it. So no error is generated when there is a constant.

Example

lp_solve -rxli xli_CPLEX input.lpt
lp_solve -mps input.mps -wxli xli_CPLEX output.lpt -wxliopt "-objconst"

Syntax Rules of LP File Format

lpsolve will accept any problem saved in an ASCII file provided that it adheres to the following syntax rules.

  1. Anything that follows a backslash (\) is a comment and is ignored until a return is encountered. Blank lines are also ignored. Blank and comment lines may be placed anywhere and as frequently as you want in the file.

  2. In general, white space between characters is irrelevant as it is skipped when a file is read. However, white space is not allowed in the keywords used to introduce a new section, such as MAX, MIN, ST, or BOUNDS. Also the keywords must be separated by white space from the rest of the file and must be at the beginning of a line. The maximum length for any name is 255. The maximum length of any line of input is 510.

Skipping spaces may cause lpsolve to misinterpret (and accept) an invalid entry, such as the following:

 x1 x2 = 0

If the user intended to enter that example as a nonlinear constraint, lpsolve would instead interpret it as a constraint specifying that one variable named x1x2 must be equal to zero.

  1. The problem statement must begin with the word MINIMIZE or MAXIMIZE, MINIMUM or MAXIMUM, or the abbreviations MIN or MAX, in any combination of upper- and lower-case characters. The word introduces the objective function section.

  2. Variables can be named anything provided that the name does not exceed 255 characters, all of which must be alphanumeric (a-z, A-Z, 0-9) or one of these symbols: ! " # $ % & ( ) / , . ; ? @ _ ` ' { } | ~. Longer names are truncated to 255 characters. A variable name cannot begin with a number or a period.

The letter E or e, alone or followed by other valid symbols, or followed by another E or e, should be avoided as this notation is reserved for exponential entries. Thus, variables cannot be named e9, E-24, E8cats, or other names that could be interpreted as an exponent. Even variable names such as eels or example can cause a read error, depending on their placement in an input line.

Also, the following characters are not valid in variable names (in order to allow for quadratic objective information): ^, *, [ and ].

  1. The objective function definition must follow MINIMIZE or MAXIMIZE. It may be entered on multiple lines as long as no variable, constant, or sense indicator is split by a return. For example, this objective function 1x1 + 2x2 +3x3 can be entered like this:

    1x1 + 2x2
    + 3x3
    
    
    but not like this:

    1x1 + 2x
    2 + 3x3         \ a bad idea
    
    

    because the second style splits the variable name x2 with a return.

  1. The objective function may be named by typing a name and a colon before the objective function. The objective function name and the colon must appear on the same line. Objective function names must conform to the same guidelines as variable names (Rule 4).

  2. The constraints section is introduced by the keyword SUBJECT TO. This expression can also appear as such that, st, S.T., or ST. in any mix of upper- and lower-case characters. One of these expressions must precede the first constraint and be separated from it by at least one space.

  3. Each constraint definition must begin on a new line. A constraint may be named by typing a name and a colon before the constraint. The constraint name and the colon must appear on the same line. Constraint names must adhere to the same guidelines as variable names (Rule 4). If no constraint names are specified, lpsolve assigns the names R1, R2, R3, etc.

  4. The constraints are entered in the same way as the objective function; however, a constraint must be followed by an indication of its sense and a right-hand side coefficient. The right-hand side coefficient must be typed on the same line as the sense indicator. Acceptable sense indicators are <, <=, =<, >, >=, =>, and =. These are interpreted as <=, <=, <=, >=, >=, >= and =, respectively.

    For example, here is a named constraint:

    time: x1 + x2 <= 10
    
    

  1. The optional BOUNDS section follows the mandatory constraint section. It is preceded by the word bounds or bound in any mix of lower- and upper-case characters.

  2. Each bound definition must begin on a new line. The format for a bound is ln <= xn <= un except in the following cases:

    Upper and lower bounds may also be entered separately as:

    ln <= xn
    xn <= un

    with the default lower bound of 0 (zero) and the default upper bound of +infinite remaining in effect until the bound is explicitly changed.

    Bounds that fix a variable can be entered as simple equalities.
    For example, x5 = 5.6 is equivalent to 5.6 <= x5 <= 5.6.

    The bounds positive infinity and negative infinity must be entered as words: +infinity, -infinity, +inf, -inf.

    A variable with a negative infinity lower bound and positive infinity upper bound may be entered as free, in any mix of upper- and lower-case characters, with a space separating the variable name and the word free.
    For example, x7 free is equivalent to -infinity <= x7 <= +infinity.

  1. The file must end with the word end in any combination of upper- and lower-case characters, alone on a line. This word is not required for files that are read in to lpsolve, but it is strongly recommended. Files that have been corrupted can frequently be detected by a missing last line.

  2. To specify any of the variables as general integer variables, add a GENERAL section; to specify any of the variables as binary integer variables, add a BINARY section. The GENERAL and BINARY sections follow the BOUNDS section, if one is present; otherwise, they follow the constraints section. Either of the GENERAL or BINARY sections can precede the other. The GENERAL section is preceded by the word GENERAL, GENERALS, or GEN in any mix of upper- and lower-case characters which must appear alone. The following line or lines should list the names of all variables which are to be restricted to general integer values, separated by at least one space. The BINARY section is preceded by the word BINARY, BINARIES, or BIN in any mix of upper- and lower-case characters which must appear alone on a line. The following line or lines should list the names of all variables which are to be restricted to binary integer values, separated by at least one space. Binary variables are automatically given bounds of 0 (zero) and 1 (one), unless alternative bounds are specified in the BOUNDS section, in which case a warning message is issued.

    Here is an example of a problem formulation in LP format where x4 is a general integer:

    Maximize
     obj: x1 + 2 x2 + 3 x3 + x4
    Subject To
     c1: - x1 + x2 + x3 + 10 x4 <= 20
     c2: x1 - 3 x2 + x3 <= 30
     c3: x2 - 3.5 x4 = 0
    Bounds
     0 <= x1 <= 40
     2 <= x4 <= 3
    General
     x4
    End
    
    

  1. To specify any of the variables as semi-continuous variables, that is as variables that may take the value 0 or values between the specified lower and upper bounds, use a SEMI-CONTINUOUS section. This section must follow the BOUNDS, GENERALS, and BINARIES sections. The SEMI-CONTINUOUS section is preceded by the keyword SEMI-CONTINUOUS, SEMI, or SEMIS. The following line or lines should list the names of all the variables which are to be declared semi-continuous, separated by at least one space.
  2. Semi-continuous
    x1 x2 x3
    

  3. To specify special ordered sets, use a SOS section, which is preceded by the SOS keyword. The SOS section should follow the Bounds, General, Binaries and Semi-Continuous sections. Special ordered sets of type 1 require that, of the variables in the set, one at most may be non-zero. Special ordered sets of type 2 require that at most two variables in the set may be non-zero, and if there are two non-zeros, they must be adjacent. Adjacency is defined by the weights, which must be unique within a set given to the variables. The sorted weights define the order of the special ordered set. For MIP branch and cut, the order is used to determine how the variables are branched upon. The set is specified by an optional set name followed by a colon and then either of the S1 or S2 keywords (specifying the type) followed by a double colon. The set member names are listed on this line or lines, with their weights. Variable names and weights are separated by a colon, for example:
  4. SOS
      set1: S1:: x1:10 x2:13
    

doc/set_bb_rule.htm0000644000175000017500000001463410534655120013277 0ustar renerene set_bb_rule

set_bb_rule

Specifies the branch-and-bound rule.

void set_bb_rule(lprec *lp, int bb_rule);

Return Value

set_bb_rule has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

bb_rule

The branch-and-bound rule. Can by any of the following values:

NODE_FIRSTSELECT (0) Select lowest indexed non-integer column
NODE_GAPSELECT (1) Selection based on distance from the current bounds
NODE_RANGESELECT (2) Selection based on the largest current bound
NODE_FRACTIONSELECT (3) Selection based on largest fractional value
NODE_PSEUDOCOSTSELECT (4) Simple, unweighted pseudo-cost of a variable
NODE_PSEUDONONINTSELECT (5) This is an extended pseudo-costing strategy based on minimizing the number of integer infeasibilities
NODE_PSEUDORATIOSELECT (6) This is an extended pseudo-costing strategy based on maximizing the normal pseudo-cost divided by the number of infeasibilities. Effectively, it is similar to (the reciprocal of) a cost/benefit ratio
NODE_USERSELECT (7)  

One of these values may be or-ed with one or more of the following values:

NODE_WEIGHTREVERSEMODE (8) Select by criterion minimum (worst), rather than criterion maximum (best)
NODE_BRANCHREVERSEMODE (16) In case when get_bb_floorfirst is BRANCH_AUTOMATIC, select the oposite direction (lower/upper branch) that BRANCH_AUTOMATIC had chosen.
NODE_GREEDYMODE (32)  
NODE_PSEUDOCOSTMODE (64) Toggles between weighting based on pseudocost or objective function value
NODE_DEPTHFIRSTMODE (128) Select the node that has already been selected before the most number of times
NODE_RANDOMIZEMODE (256) Adds a randomization factor to the score for any node candicate
NODE_GUBMODE (512) Enables GUB mode. Still in development and should not be used at this time.
NODE_DYNAMICMODE (1024) When NODE_DEPTHFIRSTMODE is selected, switch off this mode when a first solution is found.
NODE_RESTARTMODE (2048) Enables regular restarts of pseudocost value calculations
NODE_BREADTHFIRSTMODE (4096) Select the node that has been selected before the fewest number of times or not at all
NODE_AUTOORDER (8192) Create an "optimal" B&B variable ordering. Can speed up B&B algorithm.
NODE_RCOSTFIXING (16384) Do bound tightening during B&B based of reduced cost information
NODE_STRONGINIT (32768) Initialize pseudo-costs by strong branching

Remarks

The set_bb_rule function specifies the branch-and-bound rule for choosing which non-integer variable is to be selected. This rule can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
The default is NODE_PSEUDONONINTSELECT + NODE_GREEDYMODE + NODE_DYNAMICMODE + NODE_RCOSTFIXING (17445).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_bb_rule(lp, NODE_FIRSTSELECT);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_bb_rule, put_bb_nodefunc

doc/set_semicont.htm0000644000175000017500000000632710237176664013521 0ustar renerene set_semicont

set_semicont

Set the type of the variable. semi-continuous or not.

unsigned char set_semicont(lprec *lp, int column, unsigned char must_be_sc);

Return Value

set_semicont returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be set. It must be between 1 and the number of columns in the lp.

must_be_sc

TRUE (1) if the variable must be semi-continuous, FALSE (0) if not.

Remarks

The set_semicont function defines if a variable is semi-continuous or not. By default, a variable is not semi-continuous. The argument must_be_sc defines what the status of the variable becomes.
Note that a semi-continuous variable must also have a lower bound to have effect. This because the default lower bound on variables is zero, also when defined as semi-continuous, and without a lower bound it has no point to define a variable as such. The lower bound may be set before or after setting the semi-continuous status. See semi-continuous variables for a description about semi-continuous variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_lowbo(lp, 1, 2.0);
  set_semicont(lp, 1, TRUE); /* sets variable 1 to semi-continuous */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_semicont, set_lowbo

doc/set_upbo.htm0000644000175000017500000000573611127442647012644 0ustar renerene set_upbo

set_upbo

Set the upper bound of a variable.

unsigned char set_upbo(lprec *lp, int column, REAL value);

Return Value

set_upbo returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable on which the bound must be set. It must be between 1 and the number of columns in the lp.

Remarks

The set_upbo function sets an upper bound on the variable identified by column.
Setting a bound on a variable is the way to go instead of adding an extra constraint (row) to the model. Setting a bound doesn't increase the model size that means that the model stays smaller and will be solved faster.
The default upper bound of a variable is infinity (well not quite. It is a very big number, the value of get_infinite).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_upbo(lp, 1, 1.0);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_upbo, set_lowbo, get_lowbo, set_bounds, set_unbounded, is_unbounded, is_negative

doc/get_Nrows.htm0000644000175000017500000000516210237176654012767 0ustar renerene get_Nrows

get_Nrows

Returns the number of rows (constraints) in the lp.

int get_Nrows(lprec *lp);

Return Value

get_Nrows returns the number of rows (constraints) in the lp.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_Nrows function returns the number of rows (constraints) in the lp.
Note that the number of rows can change when a presolve is done.
Therefore it is advisable to use this function to determine how many rows there are in the lp instead of relying on an own count.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int Nrows;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  Nrows = get_Nrows(lp); /* Will return 1 */

  set_presolve(lp, PRESOLVE_ROWS);
  solve(lp);

  Nrows = get_Nrows(lp); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_Norig_rows, get_Lrows, get_Ncolumns, get_Norig_columns, get_orig_index, get_lp_index

doc/SOS.htm0000644000175000017500000006754510512274012011460 0ustar renerene Special Ordered Sets

Special Ordered Sets (SOS)

Special Ordered Sets of Type One

A Special Ordered Set of type One (SOS1) is defined to be a set of variables for which not more than one member from the set may be non-zero in a feasible solution. All such sets are mutually exclusive of each other, the members are not subject to any other discrete conditions and are grouped together consecutively in the data.

The normal use of an SOS1 is to represent a set of mutually exclusive alternatives ordered in increasing values of size, cost or some other suitable units appropriate to the context of the model. This representation is a discrete programming extension of the separable programming model. There is a strong implied assumption that a non-linear function represented in this way is single valued over the range of its argument.

Consider a function g(y) represented by the points P1,...,PK as shown in figure 2.

image\img00341.gif

Figure 2

 

Given the tabulated coordinates image\img00342.gif k=1,...,K, the function g(y) may be represented as

  image\img00343.gif     (1)

where

  image\img00344.gif     (2)

  image\img00345.gif     (3)

The discrete function can take only one of the image\img00346.gif possible values weighted by the variables image\img00347.gif, of which only one can be non-zero, and that must have the value one.

This requirement could be expressed by restricting each xk to be a binary variable but the alternative of defining them collectively as a special ordered set of type one, which is a direct statement of their nature, leads to a more efficient solution process.

The weighting variables xk are called special ordered set type one variables and the rows (1), (2), and (3) are called function rows, reference rows and convexity rows respectively. Should the SOS1's not represent a modelling of discrete, separable variables then none of these rows need actually exist, but there is an advantage to the system if it is aware of the reference rows at least.


Special Ordered Sets of Type Two

A Special Ordered Set of type Two (SOS2) is a set of consecutive variables in which not more than two adjacent members may be non-zero in a feasible solution. All such sets are mutually exclusive of each other, the members are not subject to any other discrete conditions and each set is grouped together consecutively in the data.

SOS2s were introduced to make it easier to find global optimum solutions to problems containing piecewise linear approximations to a non-linear function of a single argument (as in classical Separable Programming). The overall problem has an otherwise LP or an IP structure except for such non-linear functions.

Consider the function image\img00348.gif illustrated in Figure 3 as a piecewise linear function in one variable defined over the closed intervals image\img00349.gif, where the coordinates image\img00350.gif, represent points P1,...,PK.

 

image\img00351.gif

Figure 3

 

Any point image\img00352.gif in the closed interval image\img00353.gif may be written as

image\img00354.gif

where

image\img00355.gif.

Similarly, as image\img00356.gif is linear in the interval, it can be written as

image\img00357.gif.

This leads to the representation of image\img00358.gif using a set of weighting variables, image\img00359.gif, by the equality

  image\img00360.gif     (4)

where

  image\img00361.gif     (5)

  image\img00362.gif.    (6)

Plus the added condition that not more than two adjacent variables can be non-zero at any one time.

The weighting variables xk are called the special ordered set type two variables and the rows (4), (5), and (6) are called function rows, reference rows and the convexity rows respectively, as in equations (1), (2) and (3) of Topic "Special Ordered Sets of Type One". Should the SOS2's not represent separable functions then none of these rows need actually exist, but there is an advantage to the system if it is aware of the reference rows at least.

 

The lp_solve implementation of SOS is the following:

A specially ordered set of degree N is a collection of variables where at most N variables may be non-zero. The non-zero variables must be contiguous (neighbours) sorted by the ascending value of their respective unique weights. In lp_solve, specially ordered sets may be of any cardinal type 1, 2, and higher, and may be overlapping. The number of variables in the set must be equal to, or exceed the cardinal SOS order.

lp_solve supports Special Ordered Sets via the API interface, in the MPS format and in the lp format (from release 4.0.1.11).

Below is a representation of a SOS in an MPS file, where each SOS is defined in its own SOS section, which should follow the BOUNDS section.

0        1         2         3         4
1234567890123456789012345678901234567890
SOS
 Sx CaseName  SOSName.  SOSpriority.
    CaseName  VarName1  VarWeight1..
    CaseName  VarName2  VarWeight2..

    CaseName  VarNameN  VarWeightN..

x at the second line, position 3, defines is the order of the SOS. Due to limitations in the MPS format, N is restricted to the 1..9 range. Each SOS should be given a unique name, SOSName. lp_solve does not currently use case names for SOS'es and the CaseName could be any non-empty value.

Below is a representation of a SOS in an lp file.

sos
SOS: VarName1: VarWeight1, VarName2: VarWeight2, ..., VarNameN: VarWeightN <= 1: SOSpriority;

In the lp format, the VarWeights are optional:

sos
SOS: VarName1, VarName2, ..., VarNameN <= 1: SOSpriority;

In that case, the order of the variables define the VarWeights. So above is equal to:

sos
SOS: VarName1: 1, VarName2: 2, ..., VarNameN: N <= 1: SOSpriority;

Also the SOSpriority is optional. In that case the order in which the SOS constraints are specified give them a priority.

The SOSpriority value determines the order in which multiple SOS'es are analysed in lp_solve.

VarWeight determines the adjacency of the variables. This is an importand piece of information. Remember that the SOS definition defines that the non-zero variables must be adjacent. The VarWeight values define this adjencency.

SOS1 Example:

ROWS
 L  c1
 L  c2
 N  COST
COLUMNS
    x1        c1                 -1.   c2                  1.
    x1        COST               -1.
    x2        c1                 -1.   COST               -1.
    x3        c1                  1.   c2                  1.
    x3        COST               -3.
    x4        c1                  1.   c2                 -3.
    x4        COST               -2.
    x5        COST               -2.
RHS
    RHS       c1                 30.   c2                 30.
BOUNDS
 UP COLBND    x1                 40.
 UP COLBND    x2                  1.
 UP COLBND    x5                  1.
SOS
 S1 SOS       SOS                 1.
    SOS       x1                  1.
    SOS       x2                  2.
    SOS       x3                  3.
    SOS       x4                  4.
    SOS       x5                  5.
ENDATA


In lp format:

min: -x1 -x2 -3 x3 -2 x4 -2 x5;
c1: -x1 -x2 +x3 +x4 <= 30;
c2: +x1 +x3 -3 x4 <= 30;
x1 <= 40;
x2 <= 1;
x5 <= 1;

sos
SOS: x1,x2,x3,x4,x5 <= 1;

The SOS definition says that either x1 or x2 or x3 or x4 or x5 may be taken. It also says that x1 is adjacent to x2 which is adjacent to x3 which is adjacent to x4 which is adjacent to x5.

The solution is:
Value of objective function: -90

Actual values of the variables:
x1                   0
x2                   0
x3                   30
x4                   0
x5                   0

SOS2 Example:

ROWS
 L  c1
 L  c2
 N  COST
COLUMNS
    x1        c1                 -1.   c2                  1.
    x1        COST               -1.
    x2        c1                 -1.   COST               -1.
    x3        c1                  1.   c2                  1.
    x3        COST               -3.
    x4        c1                  1.   c2                 -3.
    x4        COST               -2.
    x5        COST               -2.
RHS
    RHS       c1                 30.   c2                 30.
BOUNDS
 UP COLBND    x1                 40.
 UP COLBND    x2                  1.
 UP COLBND    x5                  1.
SOS
 S2 SOS       SOS                 1.
    SOS       x1                  1.
    SOS       x2                  2.
    SOS       x3                  3.
    SOS       x4                  4.
    SOS       x5                  5.
ENDATA


In lp format:

min: -x1 -x2 -3 x3 -2 x4 -2 x5;
c1: -x1 -x2 +x3 +x4 <= 30;
c2: +x1 +x3 -3 x4 <= 30;
x1 <= 40;
x2 <= 1;
x5 <= 1;

sos
SOS: x1,x2,x3,x4,x5 <= 2;

The SOS definition says that two consecutive variables from x1, x2, x3, x4, x5 may be taken. It also says that x1 is adjacent to x2 which is adjacent to x3 which is adjacent to x4 which is adjacent to x5.

The solution is:
Value of objective function: -91

Actual values of the variables:
x1                   0
x2                   1
x3                   30
x4                   0
x5                   0

SOS3 Example:

ROWS
 L  c1
 L  c2
 N  COST
COLUMNS
    x1        c1                 -1.   c2                  1.
    x1        COST               -1.
    x2        c1                 -1.   COST               -1.
    x3        c1                  1.   c2                  1.
    x3        COST               -3.
    x4        c1                  1.   c2                 -3.
    x4        COST               -2.
    x5        COST               -2.
RHS
    RHS       c1                 30.   c2                 30.
BOUNDS
 UP COLBND    x1                 40.
 UP COLBND    x2                  1.
 UP COLBND    x5                  1.
SOS
 S3 SOS       SOS                 1.
    SOS       x1                  1.
    SOS       x2                  2.
    SOS       x3                  3.
    SOS       x4                  4.
    SOS       x5                  5.
ENDATA


In lp format:

min: -x1 -x2 -3 x3 -2 x4 -2 x5;
c1: -x1 -x2 +x3 +x4 <= 30;
c2: +x1 +x3 -3 x4 <= 30;
x1 <= 40;
x2 <= 1;
x5 <= 1;

sos
SOS: x1,x2,x3,x4,x5 <= 3;

The SOS definition says that three consecutive variables from x1, x2, x3, x4, x5 may be taken. It also says that x1 is adjacent to x2 which is adjacent to x3 which is adjacent to x4 which is adjacent to x5.

The solution is:
Value of objective function: -93.75

Actual values of the variables:
x1                   0
x2                   1
x3                   30.75
x4                   0.25
x5                   0

SOS4 Example:

ROWS
 L  c1
 L  c2
 N  COST
COLUMNS
    x1        c1                 -1.   c2                  1.
    x1        COST               -1.
    x2        c1                 -1.   COST               -1.
    x3        c1                  1.   c2                  1.
    x3        COST               -3.
    x4        c1                  1.   c2                 -3.
    x4        COST               -2.
    x5        COST               -2.
RHS
    RHS       c1                 30.   c2                 30.
BOUNDS
 UP COLBND    x1                 40.
 UP COLBND    x2                  1.
 UP COLBND    x5                  1.
SOS
 S4 SOS       SOS                 1.
    SOS       x1                  1.
    SOS       x2                  2.
    SOS       x3                  3.
    SOS       x4                  4.
    SOS       x5                  5.
ENDATA


In lp format:

min: -x1 -x2 -3 x3 -2 x4 -2 x5;
c1: -x1 -x2 +x3 +x4 <= 30;
c2: +x1 +x3 -3 x4 <= 30;
x1 <= 40;
x2 <= 1;
x5 <= 1;

sos
SOS: x1,x2,x3,x4,x5 <= 4;

The SOS definition says that four consecutive variables from x1, x2, x3, x4, x5 may be taken. It also says that x1 is adjacent to x2 which is adjacent to x3 which is adjacent to x4 which is adjacent to x5.

The solution is:
Value of objective function: -233.75

Actual values of the variables:
x1                   40
x2                   1
x3                   50.75
x4                   20.25
x5                   0

SOS5 Example:

ROWS
 L  c1
 L  c2
 N  COST
COLUMNS
    x1        c1                 -1.   c2                  1.
    x1        COST               -1.
    x2        c1                 -1.   COST               -1.
    x3        c1                  1.   c2                  1.
    x3        COST               -3.
    x4        c1                  1.   c2                 -3.
    x4        COST               -2.
    x5        COST               -2.
RHS
    RHS       c1                 30.   c2                 30.
BOUNDS
 UP COLBND    x1                 40.
 UP COLBND    x2                  1.
 UP COLBND    x5                  1.
SOS
 S5 SOS       SOS                 1.
    SOS       x1                  1.
    SOS       x2                  2.
    SOS       x3                  3.
    SOS       x4                  4.
    SOS       x5                  5.
ENDATA


In lp format:

min: -x1 -x2 -3 x3 -2 x4 -2 x5;
c1: -x1 -x2 +x3 +x4 <= 30;
c2: +x1 +x3 -3 x4 <= 30;
x1 <= 40;
x2 <= 1;
x5 <= 1;

sos
SOS: x1,x2,x3,x4,x5 <= 5;

The SOS definition says that five consecutive variables from x1, x2, x3, x4, x5 may be taken. It also says that x1 is adjacent to x2 which is adjacent to x3 which is adjacent to x4 which is adjacent to x5.

The solution is:
Value of objective function: -235.75

Actual values of the variables:
x1                   40
x2                   1
x3                   50.75
x4                   20.25
x5                   1
doc/AMPL.htm0000644000175000017500000005753711247035305011553 0ustar renerene Using lpsolve from AMPL

Using lpsolve from AMPL

AMPL?

AMPL (A Mathematical Programming Language) is a high-level language for describing mathematical programs. AMPL allows a mathematical programming model to be specified independently of the data used for a specific instance of the model. AMPL's language for describing mathematical programs closely follows that used by humans to describe mathematical programs to each other. For this reason, modellers may spend more time improving the model and less time on the tedious details of data manipulation and problem solution.
To start, AMPL needs a mathematical programming model, which describes variables, objectives and relationships without referring to specific data. AMPL also needs an instance of the data, or a particular data set. The model and one (or more) data files are fed into the AMPL program. AMPL works like a compiler: the model and input are put into an intermediate file that can be read by a solver. The solver actually finds an optimal solution to the problem by reading in the intermediate file produced by AMPL and applying an appropriate algorithm. The solver outputs the solution as a text file, which can be viewed directly and cross-referenced with the variables and constraints specified in the model file.

We will not discuss the specifics of AMPL here but instead refer the reader to AMPL (A Mathematical Programming Language) at the University of Michigan Documentation and the AMPL website http://www.ampl.com.

AMPL and lpsolve

One of the possible solvers that can be used by AMPL is lpsolve. However note that AMPL allows also defining non-linear models. These are not solvable by lpsolve because lpsolve can only handle MILP models. A message will be given if the AMPL model results in a model that cannot be handled by lpsolve.

To make this possible, a driver program is needed: lpsolve(.exe). This program must be put in the AMPL directory and AMPL can call the lpsolve solver. The newer versions of the lpsolve(.exe) driver call lpsolve via the shared library (lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux). This has the advantage that the lpsolve driver program doesn't have to be recompiled when an update of lpsolve is provided. The shared library must be somewhere in the path. That is all.

Solve a model from AMPL via lpsolve

In the following text, ampl: before the AMPL commands is the AMPL prompt. Only the text after the : must be entered.

To select the lpsolve solver, the following command must be executed in AMPL:

ampl: option solver lpsolve;

To solve the model, the following command must be executed in AMPL:

ampl: solve;

Options can be passed to lpsolve. For example to enable scaling, the following command must be executed in AMPL:

ampl: option lpsolve_options 'scale';

Multiple options can be specified by separating them with at least one space:

ampl: option lpsolve_options 'scale scalemode=7 verbose';

A list of all options is given at the end of this document.

An example

ampl: model diet.mod;
ampl: data diet.dat;
ampl: option solver lpsolve;
ampl: option lpsolve_options 'scale scalemode=7';
ampl: solve;

This gives as result:

LP_SOLVE 5.5.0.15: scale
scalemode=7
LP_SOLVE 5.5.0.15: optimal, objective 88.2
1 simplex iterations

solve_result_num

AMPL has a parameter that is used to indicate the outcome of the optimisation process. It is used as follows

ampl: display solve_result_num

solve_result_num can take the values shown in following table which also presents a short explanation for each value.

Interpretation of solve_result_num.
Value Message
0 the solution is optimal
100 suboptimal solution
200 infeasible problem
300 unbounded problem
500 solution status is unknown
501 failure
502 integer programming failure

Restart

This is also new with version 5. Before, when lpsolve was used from AMPL, the model was each time completely resolved at each AMPL solve command. The last base was not used to do further iterations. This is specific to AMPL because lpsolve is called as a seperate program each time a solve is done and to make restart possible the last base must be provided again to lpsolve to start from there again. From version 5 on this is now implemented by default. This means if a solve is done immediately after a previous solve that no iterations are needed and the solution can be given immediately. This can be shown via an example:
ampl: model diet.mod;
ampl: data diet.dat;
ampl: option solver lpsolve;
ampl: solve;

This gives as result:

LP_SOLVE 5.5.0.15: optimal, objective 88.2
3 simplex iterations

Note that 3 iterations were needed to solve the model. Now solve the model again:

ampl: solve;

This gives as result:

LP_SOLVE 5.5.0.15: optimal, objective 88.2
0 simplex iterations

Note now that no iterations are needed to solve the model. This because the result of the previous solve is used as a starting point for the new solve. It is even allowed to add or deleted variables and constraints in the model, lpsolve will still try to start from the last result to continue.

If, for some reason, you don't want this and let lpsolve resolve the model from scratch, there are two possibilities to let lpsolve ignore the starting base. Either via an lpsolve option or an AMPL option.

The lpsolve option that can be set is:

ampl: option lpsolve_options 'coldstart';

The AMPL option that can be set is:

ampl: option send_statuses 0;

One of both is enough.

Now solve the model again:
ampl: solve;

This gives as result:

LP_SOLVE 5.5.0.15: coldstart
LP_SOLVE 5.5.0.15: optimal, objective 88.2
3 simplex iterations

Note that again 3 iterations are needed to solve the model.

Special considerations for integer models. From the moment that a model contains integer variables, the B&B algorithm must be used to solve this. This algorithm must go trough a tree of possible solutions each time a solve is done. The last base of the best integer solution can not be used as a starting base for a resolve. This is not an lpsolve limitation, but a B&B algorithm property...
For this reason, by default, AMPL doesn't provide a starting to the solver and solve is done from scratch. By default... However, a compromise can be implemented by the solver. And this is also done in lpsolve. Solving integer models is always started with solving the non-integer model. When this is done, the non-integer variables are made integer via the B&B algorithm. lpsolve returns the base of the non-integer model and this base is used as a starting base for the model at the next solve. As said, this is a compromise because it results in a fast solve of the non-integer model, but the B&B algorithm must still be executed. So even if no modifications are done to the model and solve is done again, there will be iterations needed by the B&B algorithm to solve the integers. Because this must be explicitly implemented in the solver, AMPL doesn't provide the starting base by default for integer models. It must explicitly be activated:

ampl: option send_statuses 2;

Only then, lpsolve will get a starting base when there are integers.

Example:

ampl: model multmip3.mod;
ampl: data multmip3.dat;
ampl: option solver lpsolve;
ampl: solve;

This gives as result:

LP_SOLVE 5.5.0.15: optimal, objective 235625
1986 simplex iterations
592 branch & bound nodes: depth 21

Note that 1986 iterations were needed to solve the model. Now solve the model again:

ampl: solve;

This gives as result:

LP_SOLVE 5.5.0.15: optimal, objective 235625
1986 simplex iterations
592 branch & bound nodes: depth 21

The same as above. So no restart was done. Now activate the starting base for integer models and solve again:

ampl: option send_statuses 2;
ampl: solve;

This gives as result:

LP_SOLVE 5.5.0.15: optimal, objective 235625
1922 simplex iterations
592 branch & bound nodes: depth 21

Note that less iterations are needed, but not 0 as in non-integer models. These are the iterations needed for the B&B algorithm.

lpsolve options

lpsolve accepts a lot of options. Some options are just on/off switches and for there you just specify the option keyword (for example scale). Other options need a value and this is specified by an equal (=) sign after the option keyword and then the value (for example scalemode=7). Multiple options can be specified by separating them by a space (for example scale scalemode=7).

These options can be displayed from the command line by entering the following:

lpsolve -=

Here is a list of the possible lpsolve options:

bb=...           branch-and-bound rule: one of
  		    0 (default) for lowest indexed non-integer variable
  		    1 for selection based on distance from the current bounds
  		    2 for selection based on the largest current bound
  		    3 for selection based on largest fractional value
  		    4 for simple, unweighted pseudo-cost of a variable
  		    5 this is an extended pseudo-costing strategy based on
                      minimizing the number of integer infeasibilities
  		    6 this is an extended pseudo-costing strategy based on
                      maximizing the normal pseudo-cost divided by the
                      number of infeasibilities
  	       plus
  		    8 for weight reverse mode
                   16 when cauto is used, select the oposite direction that
                      autoselect had chosen
  		   32 for greedy mode
  		   64 for pseudo cost mode
  		  128 select the node that has already been selected before
                      the most number of times
  		  256 for randomize mode
  		 1024 when mode 128 is selected, switch off this mode when
                      a first solution is found
  		 2048 for restart mode
  		 4096 select the node that has been selected before the
                      fewest number of times or not at all
bfp=...          set basis factorization package
cauto            in IPs, algorithm decides which branch being taken first
cfirst           in IPs, take ceiling branch first
coldstart        ignore starting base
crash=...        determines a starting base: one of
  		    0 (default) none
  		    2 most feasible basis
debug            debug mode
degen            perturb degeneracies
degenx=...       anti-degen handling: one of
  		    0 (default) no anti-degeneracy handling
  		    1 check if there are equality slacks in the basis and
                      try to drive them out in order to reduce chance of
                      degeneracy in Phase 1
                    2 ColumnCheck
                    4 Stalling
                    8 NumFailure
                   16 LostFeas
                   32 Infeasible
                   64 Dynamic
                  128 During BB
depth=...        set branch-and-bound depth limit
dual             prefer the dual simplex for both phases
eps=...          tolerance for rounding to integer
epsb=...         minimum tolerance for the RHS
epsd=...         minimum tolerance for reduced costs
epsel=...        minimum tolerance for rounding values to zero
epsp=...         value that is used as perturbation scalar for
               degenerative problems
f                specifies that branch-and-bound algorithm stops at first
               found solution
ga=...           specifies the absolute MIP gap for branch-and-bound
gr=...           specifies the relative MIP gap for branch-and-bound
improve=...      the iterative improvement level: one of
  		    0 improve none
  		    1 Running accuracy measurement of solved equations based on
                      Bx=r (primal simplex), remedy is refactorization.
  		    2 Improve initial dual feasibility by bound flips
                      (highly recommended, and default)
  		    4 Low-cost accuracy monitoring in the dual, remedy is refactorization
                    8 By default there is a check for primal/dual feasibility at optimum
                      only for the relaxed problem, this also activates the test at the node level
n=...            specify which solution number to return
o=...            specifies that branch-and-bound algorithm stops when
               objective value is better than value
objno=...        objective number: 0 = none, 1 (default) = first
obound=...       a lower bound for the objective function
               may speed up the calculations
parse_only       parse input file but do not solve
piv=...          simplex pivot rule: one of
  		    0 select first
  		    1 select according to Dantzig
  		    2 (default) select Devex pricing from Paula Harris
  		    3 select steepest edge
piva             temporarily use first index if cycling is detected
pivf             in case of Steepest Edge, fall back to DEVEX in primal
pivla            scan entering/leaving columns alternatingly left/right
pivll            scan entering/leaving columns left rather than right
pivm             multiple pricing
pivr             adds a small randomization effect to the selected pricer
presolve         presolve problem before start optimizing
presolvel        also eliminate linearly dependent rows
presolver        if the phase 1 solution process finds that a constraint is
               redundant then this constraint is deleted
prim             prefer the primal simplex for both phases
printsol=...     print solution: one of
  		    0 (default) print nothing
  		    1 only objective value
  		    2 obj value+variables
  		    3 obj value+variables+constraints
  		    4 obj value+variables+constraints+duals
  		    5 obj value+variables+constraints+duals+lp model
  		    6 obj value+variables+constraints+duals+lp model+scales
  		    7 obj value+variables+constraints+duals+lp model+scales+
                      lp tableau
prlp             print the LP
psols            print (intermediate) feasible solutions
psolsa           print (intermediate) feasible solutions (non-zeros)
r=...            max nbr of pivots between a re-inversion of the matrix
rparname=...     parameter file to read options from
rparoptions=...  options parameter file
scale            scale the problem
scalemode=...    scale mode:  one of
  		    1 for scale to convergence using largest absolute value
  		    2 for scale based on the simple numerical range
  		    3 (default) for numerical range-based scaling
  		    4 for geometric scaling
  		    7 for Curtis & Reid scaling
  	       plus
  		   16 for scale to convergence using logarithmic mean
                      of all values
  		   32 for also do Power scaling
  		   64 to make sure that no scaled number is above 1
  		  128 to scale integer variables
simplexdd        set Phase1 Dual, Phase2 Dual
simplexdp        set Phase1 Dual, Phase2 Primal
simplexpd        set Phase1 Primal, Phase2 Dual
simplexpp        set Phase1 Primal, Phase2 Primal
timeout=...      timeout after sec seconds when not solution found
trace            trace pivot selections
trej=...         minimum pivot value
verbose          verbose mode
version          report version details
wafter           write model after solve (usefull if presolve used)
wantsol=...      solution report without -AMPL: sum of
		1 ==> write .sol file
		2 ==> print primal variable values
		4 ==> print dual variable values
		8 ==> do not print solution message
wfmps=...        write to MPS file in free format
wlp=...          write to LP filename
wmps=...         write to MPS file in fixed format
wparname=...     parameter file to write options to
wparoptions=...  options parameter file
wxli=...         write file with xli library
wxliname=...     xli library
wxliopt=...      options for xli library

lpsolve command line options

Normally, the lpsolve program is called from AMPL. However the program can also be called stand-alone. When the command is invoked without an option or with the option -?, a list of the possible options is shown:

usage: lpsolve [options] stub [-AMPL] [<assignment> ...]

Options:
        --  {end of options}
        -=  {show name= possibilities}
        -?  {show usage}
        -e  {suppress echoing of assignments}
        -s  {write .sol file (without -AMPL)}
        -v  {just show version}

stub and the -AMPL option is used when the program is called from AMPL.
The -v option shows the version of lpsolve.
The -= option shows all the options that can be passed to lpsolve from within AMPL.
These options can also be specified in an environment variable lpsolve_options.

To call the lpsolve command to solve a model, you first must have a stub file that can be read by lpsolve. This stub file can be created by AMPL as follows:

ampl: model models\diet.mod;
ampl: data models\diet.dat;
ampl: write bdiet;
ampl: quit

This created a binary file diet.nl. As an alternative the command write gdiet; can be used. This creates an ascii file that also can be read. However it is somewhat slower to read, especially when the models are larger.

This creates a file diet.nl in the current directory. This file is the stub file needed by lpsolve:

lpsolve lpsolve diet.nl

This gives:

LP_SOLVE 5.5.0.15: optimal, objective 88.19999999999999
3 simplex iterations

Options can be passed to lpsolve via the environment variable lpsolve_options:

set lpsolve_options=scale scalemode=7 verbose

Then the result of the previous lpsolve command is:

scale
scalemode=7
verbose
Model name:  '' - run #1
Objective:   Minimize(R0)

Submitted:
Model size:        4 constraints,       8 variables,           39 non-zeros.
Constraints:       0 equality,          0 GUB,                  0 SOS.
Variables:         0 integer,           0 semi-cont.,           0 SOS.

Using DUAL simplex for phase 1 and PRIMAL simplex for phase 2.

Optimal solution with dual simplex at iteration          1

lp_solve solution         88.2 final at iteration        1,       0 nodes explor
ed

Excellent numeric accuracy ||*|| = 1.13687e-013

 Memo: Largest [etaPFI v1.0] inv(B) had 0 NZ entries, 0.0x largest basis.
      In the total iteration count 1, 0 (0.0%) were minor/bound swaps.
      There were 0 refactorizations, 0 triggered by time and 0 by density.
             ... on average 1.0 major pivots per refactorization.
      Total solver time was 0.000 seconds.
LP_SOLVE 5.5.0.15: optimal, objective 88.19999999999999
1 simplex iterations

In this mode, the lpsolve option wantsol shows the solution:

set lpsolve_options=wantsol=2
lpsolve diet.nl

This gives:

wantsol=2
LP_SOLVE 5.5.0.15: optimal, objective 88.19999999999999
3 simplex iterations

variable  value
_svar[1]  0
_svar[2]  0
_svar[3]  0
_svar[4]  0
_svar[5]  46.666666666666664
_svar[6]  0
_svar[7]  -3.552713678800501e-15
_svar[8]  0

The -e option results in not echoing the options passed to lpsolve:

set lpsolve_options=wantsol=2
lpsolve -e diet.nl

This gives:

LP_SOLVE 5.5.0.15: optimal, objective 88.19999999999999
3 simplex iterations

variable  value
_svar[1]  0
_svar[2]  0
_svar[3]  0
_svar[4]  0
_svar[5]  46.666666666666664
_svar[6]  0
_svar[7]  -3.552713678800501e-15
_svar[8]  0

lpsolve options can also be passed at the command line, they don't overrule the lpsolve_options environment variable, they are added:

set lpsolve_options=wantsol=2
lpsolve diet.nl "verbose scale"

This gives:

wantsol=2
verbose
scale
Model name:  '' - run #1
Objective:   Minimize(R0)

Submitted:
Model size:        4 constraints,       8 variables,           39 non-zeros.
Constraints:       0 equality,          0 GUB,                  0 SOS.
Variables:         0 integer,           0 semi-cont.,           0 SOS.

Using DUAL simplex for phase 1 and PRIMAL simplex for phase 2.

Optimal solution with dual simplex at iteration          1

lp_solve solution         88.2 final at iteration        1,       0 nodes explor
ed

Excellent numeric accuracy ||*|| = 1.13687e-013

 Memo: Largest [etaPFI v1.0] inv(B) had 0 NZ entries, 0.0x largest basis.
      In the total iteration count 1, 0 (0.0%) were minor/bound swaps.
      There were 0 refactorizations, 0 triggered by time and 0 by density.
             ... on average 1.0 major pivots per refactorization.
      Total solver time was 0.000 seconds.
LP_SOLVE 5.5.0.15: optimal, objective 88.19999999999997
1 simplex iterations

variable  value
_svar[1]  0
_svar[2]  0
_svar[3]  0
_svar[4]  0
_svar[5]  46.66666666666666
_svar[6]  0
_svar[7]  0
_svar[8]  0

Compile the AMPL driver

Besides the specific lpsolve files, you also need the AMPL solvers files that must be linked with it. These AMPL solvers files can be downloaded from various locations. The easiest way is via ftp://netlib.bell-labs.com/netlib/ampl/solvers.tar. untar them in directory lp_solve_5.5/extra/AMPL. This will put the files in lp_solve_5.5/extra/AMPL/solvers. Then in the solvers directory, gunzip all the files with extension .gz.
Then, still in the solvers directory, execute the appropriate Makefile.
For example under Windows:
nmake /f makefile.vc
Under Unix this would be:
make -f makefile.u
This will generate amplsolv.lib under Windows and amplsolver.so under Unix systems. However, Under windows, you must first create a file details.c by hand. It must contain the following single line:
char sysdetails_ASL[] = "MS VC++ 6.0";
See README for more information how to build the AMPL solvers files.

Then install the files from archive lp_solve_5.5_AMPL_source.tar.gz
When this is done, goto the lpsolve directory and execute the appropriate makefile. There are two possibilities: generate a driver that links lpsolve statically and one that links lpsolve dynamically. When linked dynamically, the lpsolve dll or shared library is used at runtime. When linked statically, the lpsolve static library is linked at compile time with the AMPL lpsolve driver. For example:
nmake /f makefile5dyn.vc
Under Unix this would be:
make -f makefile5dyn.u
This will generate lpsolve.exe (Windows) or lpsolve (Unix). Put this in the AMPL directory.

doc/is_maxim.htm0000644000175000017500000000434510237176660012625 0ustar renerene is_maxim

is_maxim

Returns objective function direction.

unsigned char is_maxim(lprec *lp);

Return Value

is_maxim returns a boolean value indicating if the objective direction is maximize (TRUE) or minimize (FALSE).

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The default of lp_solve is to minimize, except for read_lp, read_LP where the default is to maximize.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  ret = is_maxim(lp); /* will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_maxim, set_minim, set_sense

doc/get_Lrows.htm0000644000175000017500000000542011022520252012736 0ustar renerene get_Lrows

get_Lrows

Returns the number of Lagrangian rows in the lp.

The Lagrangian solver does not work. Do not use this call.

int get_Lrows(lprec *lp);

Return Value

get_Lrows returns the number of Lagrangian rows in the lp.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The Lagrangian solver does not work. Do not use this call.

The get_Lrows function returns the number of Lagrangian rows in the lp.
A Lagrangian row is added via add_lag_con.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL row[1+2];
  int Lrows;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  row[1] = 1.0;
  row[2] = 1.0;
  add_lag_con(lp, row, LE, 1.0);

  Lrows = get_Lrows(lp); /* Will return 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_Nrows, get_Norig_rows, get_Ncolumns, get_Norig_columns, get_orig_index, get_lp_index, add_lag_con, lag_solve

doc/is_unbounded.htm0000644000175000017500000000564211127442451013467 0ustar renerene is_unbounded

is_unbounded

Returns if the variable is free.

unsigned char is_unbounded(lprec *lp, int column);

Return Value

is_unbounded returns TRUE (1) if the variable is defined as free, FALSE (0) otherwise.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be checked. It must be between 1 and the number of columns in the lp.

Remarks

The is_unbounded function returns if a variable is free or not. Free means a lower bound of -infinity and an upper bound of +infinity. Default a variable is not free because default it has a lower bound of 0 (and an upper bound of +infinity). See free variables for a description about free variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int free;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  free = is_unbounded(lp, 1); /* will return 0 since the variable is not set as free at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_upbo, set_upbo, set_lowbo, get_lowbo, set_bounds, set_unbounded, is_negative

doc/Octave.htm0000644000175000017500000033407611244025401012230 0ustar renerene Using lpsolve from Octave

Using lpsolve from Octave

Octave?

GNU Octave is a high-level language, primarily intended for numerical computations. It provides a convenient command line interface for solving linear and non-linear problems numerically, and for performing other numerical experiments. It may also be used as a batch-oriented language.

GNU Octave is also freely redistributable software.

We will not discuss the specifics of Octave here but instead refer the reader to the Octave website and GNU Octave Repository.

Octave and lpsolve

lpsolve is callable from Octave via a dynamic linked function. As such, it looks like lpsolve is fully integrated with Octave. Matrices can directly be transferred between Octave and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for Octave (especially for matrix support). So you have full control to the complete lpsolve functionality via the octlpsolve Octave driver. If you find that this involves too much work to solve an lp model then you can also work via higher-level script files that can make things a lot easier. See further in this article.

Note that your version of Octave must support dynamic linking. To find out if it does, type the command:

octave_config_info ("ENABLE_DYNAMIC_LINKING")

at the Octave prompt. Support for dynamic linking is included if this expression returns the string "true".

If this is not the case, then Octave is not able to call dynamic linked routines and as such also not lpsolve. In that case you must recompile Octave with dynamic linked routines enabled. Under Linux, the following commands must be executed for this:

configure --enable-shared
make

See Installing Octave for more information.

Under Windows, dynamic linking should already be active. If not, then Octave must be recompiled. The following document can help in this process: README.Windows

The octave dynamic linked routine is in a file with extension .oct. It is impossible to provide a precompiled octlpsolve.oct file with the lpsolve distribution because the structure of the .oct files change often on new releases of Octave and are not compatible with each other. Therefore you must build the driver yourself. Look at the end of this document how to do this.

Installation

A driver program is needed: octlpsolve (octlpsolve.oct). This driver must be put in a directory known to Octave (in one of the directories from the Octave 'path' command) and Octave can call the octlpsolve solver.

This driver calls lpsolve via the lpsolve shared library (lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux) (in archives lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). This has the advantage that the octlpsolve driver doesn't have to be recompiled when an update of lpsolve is provided.

So note the difference between the Octave lpsolve driver that is called octlpsolve and the lpsolve library that implements the API that is called lpsolve55.

There are also some Octave script files (.m) as a quick start.

To test if everything is installed correctly, enter octlpsolve in the Octave command window. If it gives the following, then everything is ok:

octlpsolve  Octave Interface version 5.5.0.6
using lpsolve version 5.5.0.15

Usage: [ret1, ret2, ...] = octlpsolve('functionname', arg1, arg2, ...)

However, if you get the following:

error: 'octlpsolve' undefined near line 2 column 1

Then Octave cannot find octlpsolve.oct

If you get the following:

error: Failed to initialise lpsolve library.

Then Octave can find the octlpsolve driver program, but the driver program cannot find the lpsolve library that contains the lpsolve implementation. This library is called lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux. Under Windows, the dll should be in a directory specified by the PATH environment variables and under Unix/Linux in directory /lib, /usr/lib or a directory defined by LD_LIBRARY_PATH.

Solve an lp model from Octave via octlpsolve

In the following text, octave:> before the Octave commands is the Octave prompt. Only the text after octave:> must be entered. Note that the default prompt also contains an incrementing number starting from one each time Octave starts. For this documentation, the default Octave was changed with the following command: PS1 = "\\s:> "

To call an lpsolve function, the following syntax must be used:

octave:> [ret1, ret2, ...] = octlpsolve('functionname', arg1, arg2, ...)

The return values are optional and depend on the function called. functionname must always be enclosed between single or double quotes to make it alphanumerical and it is case sensitive. The number and type of arguments depend on the function called. Some functions even have a variable number of arguments and a different behaviour occurs depending on the type of the argument. functionname can be (almost) any of the lpsolve API routines (see lp_solve API reference) plus some extra Octave specific functions. Most of the lpsolve API routines use or return an lprec structure. To make things more robust in Octave, this structure is replaced by a handle or the model name. The lprec structures are maintained internally by the lpsolve driver. The handle is an incrementing number starting from 0. Starting from driver version 5.5.0.2, it is also possible to use the model name instead of the handle. This can of course only be done if a name is given to the model. This is done via lpsolve routine set_lp_name or by specifying the model name in routine read_lp. See Using model name instead of handle.

Almost all callable functions can be found in the lp_solve API reference. Some are exactly as described in the reference guide, others have a slightly different syntax to make maximum use of the Octave functionality. For example make_lp is used identical as described. But get_variables is slightly different. In the API reference, this function has two arguments. The first the lp handle and the second the resulting variables and this array must already be dimensioned. When lpsolve is used from Octave, nothing must be dimensioned in advance. The octlpsolve driver takes care of dimensioning all return variables and they are always returned as return value of the call to octlpsolve. Never as argument to the routine. This can be a single value as for get_objective (although Octave stores this in a 1x1 matrix) or a matrix or vector as in get_variables. In this case, get_variables returns a 4x1 matrix (vector) with the result of the 4 variables of the lp model.

Note that you can get an overview of the available functionnames and their arguments by entering the following in Octave:

>> help octlpsolve.m

An example

(Note that you can execute this example by entering command per command as shown below or by just entering example1. This will execute example1.m. You can see its contents by entering type example1.m)

octave:> lp=octlpsolve('make_lp', 0, 4);
octave:> octlpsolve('set_verbose', lp, 3);
octave:> octlpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
octave:> octlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
octave:> octlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
octave:> octlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);
octave:> octlpsolve('set_lowbo', lp, 1, 28.6);
octave:> octlpsolve('set_lowbo', lp, 4, 18);
octave:> octlpsolve('set_upbo', lp, 4, 48.98);
octave:> octlpsolve('set_col_name', lp, 1, 'COLONE');
octave:> octlpsolve('set_col_name', lp, 2, 'COLTWO');
octave:> octlpsolve('set_col_name', lp, 3, 'COLTHREE');
octave:> octlpsolve('set_col_name', lp, 4, 'COLFOUR');
octave:> octlpsolve('set_row_name', lp, 1, 'THISROW');
octave:> octlpsolve('set_row_name', lp, 2, 'THATROW');
octave:> octlpsolve('set_row_name', lp, 3, 'LASTROW');
octave:> octlpsolve('write_lp', lp, 'a.lp');
octave:> octlpsolve('get_mat', lp, 1, 2)
ans = 78.260
octave:> octlpsolve('solve', lp)
ans = 0
octave:> octlpsolve('get_objective', lp)
ans = 31.783
octave:> octlpsolve('get_variables', lp)
ans =

  28.60000
   0.00000
   0.00000
  31.82759

octave:> octlpsolve('get_constraints', lp)
ans =

   92.3000
    6.8640
  391.2928

Note that there are some commands that return an answer. To see the answer, the command was not terminated with a semicolon (;). If the semicolon is put at the end of a command, the answer is not shown. However it is also possible to write the answer in a variable. For example:

octave:> obj=octlpsolve('get_objective', lp)
obj = 31.783

Or without echoing on screen:

octave:> obj=octlpsolve('get_objective', lp);

The last command will only write the result in variable obj without showing anything on screen. get_variables and get_constraints return a vector with the result. This can also be put in a variable:

octave:> x=octlpsolve('get_variables', lp);
octave:> b=octlpsolve('get_constraints', lp);

It is always possible to show the contents of a variable by just giving it as command:

octave:> x
x =

  28.60000
   0.00000
   0.00000
  31.82759

Don't forget to free the handle and its associated memory when you are done:

octave:> octlpsolve('delete_lp', lp);

Using model name instead of handle

From driver version 5.5.0.2, it is possible to use the model name instead of the handle. From the moment the model has a name, you can use this name instead of the handle. This is best shown by an example. Above example would look like this:
octave:> lp=octlpsolve('make_lp', 0, 4);
octave:> octlpsolve('set_lp_name', lp, 'mymodel');
octave:> octlpsolve('set_verbose', 'mymodel', 3);
octave:> octlpsolve('set_obj_fn', 'mymodel', [1, 3, 6.24, 0.1]);
octave:> octlpsolve('add_constraint', 'mymodel', [0, 78.26, 0, 2.9], 2, 92.3);
octave:> octlpsolve('add_constraint', 'mymodel', [0.24, 0, 11.31, 0], 1, 14.8);
octave:> octlpsolve('add_constraint', 'mymodel', [12.68, 0, 0.08, 0.9], 2, 4);
octave:> octlpsolve('set_lowbo', 'mymodel', 1, 28.6);
octave:> octlpsolve('set_lowbo', 'mymodel', 4, 18);
octave:> octlpsolve('set_upbo', 'mymodel', 4, 48.98);
octave:> octlpsolve('set_col_name', 'mymodel', 1, 'COLONE');
octave:> octlpsolve('set_col_name', 'mymodel', 2, 'COLTWO');
octave:> octlpsolve('set_col_name', 'mymodel', 3, 'COLTHREE');
octave:> octlpsolve('set_col_name', 'mymodel', 4, 'COLFOUR');
octave:> octlpsolve('set_row_name', 'mymodel', 1, 'THISROW');
octave:> octlpsolve('set_row_name', 'mymodel', 2, 'THATROW');
octave:> octlpsolve('set_row_name', 'mymodel', 3, 'LASTROW');
octave:> octlpsolve('write_lp', 'mymodel', 'a.lp');
octave:> octlpsolve('get_mat', 'mymodel', 1, 2)
ans = 78.260
octave:> octlpsolve('solve', 'mymodel')
ans = 0
octave:> octlpsolve('get_objective', 'mymodel')
ans = 31.783
octave:> octlpsolve('get_variables', 'mymodel')
ans =

  28.60000
   0.00000
   0.00000
  31.82759

octave:> octlpsolve('get_constraints', 'mymodel')
ans =

   92.3000
    6.8640
  391.2928

So everywhere a handle is needed, you can also use the model name. You can even mix the two methods. There is also a specific Octave routine to get the handle from the model name: get_handle.
For example:

>> octlpsolve('get_handle', 'mymodel')
0

Don't forget to free the handle and its associated memory when you are done:

octave:> octlpsolve('delete_lp', 'mymodel');

In the next part of this documentation, the handle is used. But if you name the model, the name could thus also be used.

Matrices

In Octave, all numerical data is stored in matrices; even a scalar variable. Octave also supports complex numbers (a + b * i with i=sqrt(-1)). octlpsolve can only work with real numbers. For example:
octave:> octlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);

Most of the time, variables are used to provide the data:

octave:> octlpsolve('add_constraint', lp, a1, 1, 14.8);

Where a1 is a matrix variable.

Most of the time, octlpsolve needs vectors (rows or columns). In all situations, it doesn't matter if the vectors are row or column vectors. The driver accepts them both. For example:

octave:> octlpsolve('add_constraint', lp, [0.24; 0; 11.31; 0], 1, 14.8);

Which is a column vector, but it is also accepted.

An important final note. Several lp_solve API routines accept a vector where the first element (element 0) is not used. Other lp_solve API calls do use the first element. In the Octave interface, there is never an unused element in the matrices. So if the lp_solve API specifies that the first element is not used, then this element is not in the Octave matrix.

Sets

All numerical data is stored in matrices. Alphanumerical data, however, is more difficult to store in matrices. Matrices require that each element has the same size (length) and that is difficult and unpractical for alphanumerical data. In a limited number of lpsolve routines, alphanumerical data is required or returned and in some also multiple elements. An example is set_col_name. For this, Octave sets are used. To specify a set of alphanumerical elements, the following notation is used: { 'element1', 'element2', ... }. Note the { and } symbols instead of [ and ] that are used with matrices.

Maximum usage of matrices/sets with octlpsolve

Because Octave is all about matrices, all lpsolve API routines that need a column or row number to get/set information for that column/row are extended in the octlpsolve Octave driver to also work with matrices. For example set_int in the API can only set the integer status for one column. If the status for several integer variables must be set, then set_int must be called multiple times. The octlpsolve Octave driver however also allows specifying a vector to set the integer status of all variables at once. The API call is: return = octlpsolve('set_int', lp, column, must_be_int). The matrix version of this call is: return = octlpsolve('set_int', lp, [must_be_int]). The API call to return the integer status of a variable is: return = octlpsolve('is_int', lp, column). The matrix version of this call is: [is_int] = octlpsolve('is_int', lp)
Also note the get_mat and set_mat routines. In Octave these are extended to return/set the complete constraint matrix. See following example.

Above example can thus also be done as follows:
(Note that you can execute this example by entering command per command as shown below or by just entering example2. This will execute example2.m. You can see its contents by entering type example2.m)

octave:> lp=octlpsolve('make_lp', 0, 4);
octave:> octlpsolve('set_verbose', lp, 3);
octave:> octlpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
octave:> octlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
octave:> octlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
octave:> octlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);
octave:> octlpsolve('set_lowbo', lp, [28.6, 0, 0, 18]);
octave:> octlpsolve('set_upbo', lp, [Inf, Inf, Inf, 48.98]);
octave:> octlpsolve('set_col_name', lp, {'COLONE', 'COLTWO', 'COLTHREE', 'COLFOUR'});
octave:> octlpsolve('set_row_name', lp, {'THISROW', 'THATROW', 'LASTROW'});
octave:> octlpsolve('write_lp', lp, 'a.lp');
octave:> octlpsolve('get_mat', lp)
ans =

   0.00000  78.26000   0.00000   2.90000
   0.24000   0.00000  11.31000   0.00000
  12.68000   0.00000   0.08000   0.90000

octave:> octlpsolve('solve', lp)
ans = 0
octave:> octlpsolve('get_objective', lp)
ans = 31.783
octave:> octlpsolve('get_variables', lp)
ans =

  28.60000
   0.00000
   0.00000
  31.82759

octave:> octlpsolve('get_constraints', lp)
ans =

   92.3000
    6.8640
  391.2928

Note the usage of Inf in set_upbo. This stands for 'infinity'. Meaning an infinite upper bound. It is also possible to use -Inf to express minus infinity. This can for example be used to create a free variable.

To show the full power of the matrices, let's now do some matrix calculations to check the solution. It works further on above example:

octave:> A=octlpsolve('get_mat', lp);
octave:> X=octlpsolve('get_variables', lp);
octave:> B = A * X
B =

   92.3000
    6.8640
  391.2928

So what we have done here is calculate the values of the constraints (RHS) by multiplying the constraint matrix with the solution vector. Now take a look at the values of the constraints that lpsolve has found:

octave:> octlpsolve('get_constraints', lp)
ans =

   92.3000
    6.8640
  391.2928

Exactly the same as the calculated B vector, as expected.

Also the value of the objective can be calculated in a same way:

octave:> C=octlpsolve('get_obj_fn', lp);
octave:> X=octlpsolve('get_variables', lp);
octave:> obj = C * X
obj = 31.783

So what we have done here is calculate the value of the objective by multiplying the objective vector with the solution vector. Now take a look at the value of the objective that lpsolve has found:

octave:> octlpsolve('get_objective', lp)
ans = 31.783

Again exactly the same as the calculated obj value, as expected.

Using string constants

From driver version 5.5.0.15 on, it is possible to use string constants everywhere an lp_solve constant is needed or returned. This is best shown by an example. In the above code we had:
octave:> lp=octlpsolve('make_lp', 0, 4);
octave:> octlpsolve('set_verbose', lp, 3);
octave:> octlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
octave:> octlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
octave:> octlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);

Note the 3rd parameter on set_verbose and the 4th on add_constraint. These are lp_solve constants. One could define all the possible constants in Octave and then use them in the calls, but that has several disadvantages. First there stays the possibility to provide a constant that is not intended for that particular call. Another issue is that calls that return a constant are still returning it numerical.

Both issues can now be handled by string constants. The above code can be done as following with string constants:

octave:> lp=octlpsolve('make_lp', 0, 4);
octave:> octlpsolve('set_verbose', lp, 'IMPORTANT');
octave:> octlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 'GE', 92.3);
octave:> octlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 'LE', 14.8);
octave:> octlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 'GE', 4);

This is not only more readable, there is much lesser chance that mistakes are being made. The calling routine knows which constants are possible and only allows these. So unknown constants or constants that are intended for other calls are not accepted. For example:

octave:> octlpsolve('set_verbose', lp, 'blabla');
error: BLABLA: Unknown.

octave:> octlpsolve('set_verbose', lp, 'GE');
error: GE: Not allowed here.

Note the difference between the two error messages. The first says that the constant is not known, the second that the constant cannot be used at that place.

Constants are case insensitive. Internally they are always translated to upper case. Also when returned they will always be in upper case.

The constant names are the ones as specified in the documentation of each API routine. There are only 3 exceptions, extensions actually. 'LE', 'GE' and 'EQ' in add_constraint and is_constr_type can also be '<', '<=', '>', '>=', '='. When returned however, 'GE', 'LE', 'EQ' will be used.

Also in the matrix version of calls, string constants are possible. For example:

octave:> octlpsolve('set_constr_type', lp, {'LE', 'EQ', 'GE'});

Some constants can be a combination of multiple constants. For example set_scaling:

octave:> octlpsolve('set_scaling', lp, 3+128);

With the string version of constants this can be done as following:

octave:> octlpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_INTEGERS');

| is the OR operator used to combine multiple constants. There may optinally be spaces before and after the |.

Not all OR combinations are legal. For example in set_scaling, a choice must be made between SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC or SCALE_CURTISREID. They may not be combined with each other. This is also tested:

octave:> octlpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_RANGE');
error: SCALE_RANGE cannot be combined with SCALE_MEAN

Everywhere constants must be provided, numeric or string values may be provided. The routine automatically interpretes them.

Returning constants is a different story. The user must let lp_solve know how to return it. Numerical or as string. The default is numerical:

octave:> octlpsolve('get_scaling', lp)
ans = 131

To let lp_solve return a constant as string, a call to a new function must be made: return_constants

octave:> octlpsolve('return_constants', 1);

From now on, all returned constants are returned as string:

octave:> octlpsolve('get_scaling', lp)
ans = SCALE_MEAN|SCALE_INTEGERS

Also when an array of constants is returned, they are returned as string when return_constants is set:

octave:> octlpsolve('get_constr_type', lp)
ans =
{
  [1,1] = LE
  [1,2] = EQ
  [1,3] = GE
}

This for all routines until return_constants is again called with 0:

octave:> octlpsolve('return_constants', 0);

The (new) current setting of return_constants is always returned by the call. Even when set:

octave:> octlpsolve('return_constants', 1)
ans = 1

To get the value without setting it, don't provide the second argument:

octave:> octlpsolve('return_constants')
ans = 1

In the next part of this documentation, return_constants is the default, 0, so all constants are returned numerical and provided constants are also numerical. This to keep the documentation as compatible as possible with older versions. But don't let you hold that back to use string constants in your code.

Script files

Octave can execute a sequence of statements stored in diskfiles. Script files mostly have the file type of ".m" as the last part of their filename (extension). Much of your work with Octave will be in creating and refining script files. Script files are usually created using your local editor.

Script files can be compared with batch files or scripts. You can put Octave commands in them and execute them at any time. The script file is executed like any other command, by entering its name (without the .m extension).

The octlpsolve Octave distribution contains some example script files to demonstrate this.

To see the contents of such a file, enter the command 'type filename'. You can also edit these files with your favourite text editor (or notepad).

example1.m

Contains the commands as shown in the first example of this article.

example2.m

Contains the commands as shown in the second example of this article.

example3.m

Contains the commands of a practical example. See further in this article.

example4.m

Contains the commands of a practical example. See further in this article.

example5.m

Contains the commands of a practical example. See further in this article.

example6.m

lp_solve.m

This script uses the API to create a higher-level function called lp_solve. This function accepts as arguments some matrices and options to create and solve an lp model. See the beginning of the file or type help lp_solve or just lp_solve to see its usage:

 LP_SOLVE  Solves mixed integer linear programming problems.

   SYNOPSIS: [obj,x,duals] = lp_solve(f,a,b,e,vlb,vub,xint,scalemode,keep)

      solves the MILP problem

              max v = f'*x
                a*x <> b
                  vlb <= x <= vub
                  x(int) are integer

   ARGUMENTS: The first four arguments are required:

            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) = -1  ==> Less Than
                      e(i) =  0  ==> Equals
                      e(i) =  1  ==> Greater Than
          vlb: n vector of lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
         keep: Flag for keeping the lp problem after it's been solved.
               If omitted, the lp will be deleted when solved.

   OUTPUT: A nonempty output is returned if a solution is found:

          obj: Optimal value of the objective function.
            x: Optimal value of the decision variables.
        duals: solution of the dual problem.

Example of usage. To create and solve following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

octave:> [obj, x]=lp_solve([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])
obj = 3
x =

  1
  2

lp_maker.m

This script is analog to the lp_solve script and also uses the API to create a higher-level function called lp_maker. This function accepts as arguments some matrices and options to create an lp model. Note that this scripts only creates a model and returns a handle. See the beginning of the file or type help lp_maker or just lp_maker to see its usage:

octave:> help lp_maker

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            x >= vlb >= 0
            x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Example of usage. To create following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

octave:> lp=lp_maker([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])
lp = 0

To solve the model and get the solution:

octave:> octlpsolve('solve', lp)
ans = 0

octave:> octlpsolve('get_objective', lp)
ans = 3

octave:> octlpsolve('get_variables', lp)
ans =

  1
  2

Don't forget to free the handle and its associated memory when you are done:

octave:> octlpsolve('delete_lp', lp);

lpdemo.m

Contains several examples to build and solve lp models.

ex.m

Contains several examples to build and solve lp models. Also solves the lp_examples from the lp_solve distribution.

A practical example

We shall illustrate the method of linear programming by means of a simple example, giving a combination graphical/numerical solution, and then solve both a slightly as well as a substantially more complicated problem.

Suppose a farmer has 75 acres on which to plant two crops: wheat and barley. To produce these crops, it costs the farmer (for seed, fertilizer, etc.) $120 per acre for the wheat and $210 per acre for the barley.The farmer has $15000 available for expenses. But after the harvest, the farmer must store the crops while awaiting favourable market conditions. The farmer has storage space for 4000 bushels.Each acre yields an average of 110 bushels of wheat or 30 bushels of barley. If the net profit per bushel of wheat (after all expenses have been subtracted) is $1.30 and for barley is $2.00, how should the farmer plant the 75 acres to maximize profit?

We begin by formulating the problem mathematically. First we express the objective, that is the profit, and the constraints algebraically, then we graph them, and lastly we arrive at the solution by graphical inspection and a minor arithmetic calculation.

Let x denote the number of acres allotted to wheat and y the number of acres allotted to barley. Then the expression to be maximized, that is the profit, is clearly

P = (110)(1.30)x + (30)(2.00)y = 143x + 60y.

There are three constraint inequalities, specified by the limits on expenses, storage and acreage. They are respectively:

120x + 210y <= 15000
110x + 30y <= 4000
x + y <= 75

Strictly speaking there are two more constraint inequalities forced by the fact that the farmer cannot plant a negative number of acres, namely:

x >= 0,y >= 0.

Next we graph the regions specified by the constraints. The last two say that we only need to consider the first quadrant in the x-y plane. Here's a graph delineating the triangular region in the first quadrant determined by the first inequality.

octave:> X = 0.1:0.1:125;
octave:> Y1 = (15000 - 120.*X)./210;
octave:> bar(X, Y1);

Source

Now let's put in the other two constraint inequalities.

octave:> X = 0.1:0.05:40;
octave:> Y1 = (15000. - 120*X)/210;
octave:> Y2 = max((4000 - 110.*X)./30, 0);
octave:> Y3 = max(75 - X, 0);
octave:> Ytop = min([Y1; Y2; Y3]);
octave:> bar(X, Ytop);

Source

The red area is the solution space that holds valid solutions. This means that any point in this area fulfils the constraints.

Now let's superimpose on top of this picture the objective function P.

octave:> hold on
octave:> X=15:25:40;
octave:> title('Solution space and objective')
octave:> plot(X,(6315.63-143.0*X)/60.0);
octave:> hold off

Source

The line gives a picture of the objective function. All solutions that intersect with the red area are valid solutions, meaning that this result also fulfils the set constraints. The more the line goes to the right, the higher the objective value is. The optimal solution or best objective is a line that is still in the red area, but with an as large as possible value.

It seems apparent that the maximum value of P will occur on the level curve (that is, level line) that passes through the vertex of the polygon that lies near (22,53).
It is the intersection of x + y = 75 and 110*x + 30*y = 4000
This is a corner point of the diagram. This is not a coincidence. The simplex algorithm, which is used by lp_solve, starts from a theorem that the optimal solution is such a corner point.
In fact we can compute the result:

octave:> x = [1 1; 110 30] \ [75; 4000]
x =

   21.875
   53.125

The acreage that results in the maximum profit is 21.875 for wheat and 53.125 for barley. In that case the profit is:

octave:> P = [143 60] * x
P = 6315.6

That is, $6315.6.

Note that these command are in script example3.m

Now, lp_solve comes into the picture to solve this linear programming problem more generally. After that we will use it to solve two more complicated problems involving more variables and constraints.

For this example, we use the higher-level script lp_maker to build the model and then some lp_solve API calls to retrieve the solution. Here is again the usage of lp_maker:

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            x >= vlb >= 0
            x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Now let's formulate this model with lp_solve:

octave:> f = [143 60];
octave:> A = [120 210; 110 30; 1 1];
octave:> b = [15000; 4000; 75];
octave:> lp = lp_maker(f, A, b, [-1; -1; -1], [], [], [], 1, 0);
octave:> solvestat = octlpsolve('solve', lp)
solvestat = 0
octave:> obj = octlpsolve('get_objective', lp)
obj = 6315.6
octave:> x = octlpsolve('get_variables', lp)
x =

  21.875
  53.125

octave:> octlpsolve('delete_lp', lp);

Note that these command are in script example4.m

With the higher-level script lp_maker, we provide all data to lp_solve. lp_solve returns a handle (lp) to the created model. Then the API call 'solve' is used to calculate the optimal solution of the model. The value of the objective function is retrieved via the API call 'get_objective' and the values of the variables are retrieved via the API call 'get_variables'. At last, the model is removed from memory via a call to 'delete_lp'. Don't forget this to free all memory allocated by lp_solve.

The solution is the same answer we obtained before. Note that the non-negativity constraints are accounted implicitly because variables are by default non-negative in lp_solve.

Well, we could have done this problem by hand (as shown in the introduction) because it is very small and it can be graphically presented.
Now suppose that the farmer is dealing with a third crop, say corn, and that the corresponding data is:

cost per acre$150.75
yield per acre125 bushels
profit per bushel$1.56

With three variables it is already a lot more difficult to show this model graphically. Adding more variables makes it even impossible because we can't imagine anymore how to represent this. We only have a practical understanding of 3 dimentions, but beyound that it is all very theorethical.

If we denote the number of acres allotted to corn by z, then the objective function becomes:

P = (110)(1.30)x + (30)(2.00)y+ (125)(1.56) = 143x + 60y + 195z

And the constraint inequalities are:

120x + 210y + 150.75z <= 15000
110x + 30y + 125z <= 4000
x + y + z <= 75
x >= 0,y >= 0, z >= 0

The problem is solved with lp_solve as follows:

octave:> f = [143 60 195];
octave:> A = [120 210 150.75; 110 30 125; 1 1 1];
octave:> b = [15000; 4000; 75];
octave:> lp = lp_maker(f, A, b, [-1; -1; -1], [], [], [], 1, 0);
octave:> solvestat = octlpsolve('solve', lp)
solvestat = 0
octave:> obj = octlpsolve('get_objective', lp)
obj = 6986.8
octave:> x = octlpsolve('get_variables', lp)
x =

   0.00000
  56.57895
  18.42105

octave:> octlpsolve('delete_lp', lp);

Note that these command are in script example5.m

So the farmer should ditch the wheat and plant 56.5789 acres of barley and 18.4211 acres of corn.

There is no practical limit on the number of variables and constraints that Octave can handle. Certainly none that the relatively unsophisticated user will encounter.Indeed, in many true applications of the technique of linear programming, one needs to deal with many variables and constraints.The solution of such a problem by hand is not feasible, and software like Octave is crucial to success.For example, in the farming problem with which we have been working, one could have more crops than two or three. Think agribusiness instead of family farmer.And one could have constraints that arise from other things beside expenses, storage and acreage limitations. For example:

  • Availability of seed.This might lead to constraint inequalities like xj < k.
  • Personal preferences. Thus the farmer's spouse might have a preference for one variety over another and insist on a corresponding planting, or something similar with a collection of crops; thus constraint inequalities like xi < xj or x1 + x2 > x3.
  • Government subsidies. It may take a moment's reflection on the reader's part, but this could lead to inequalities like xj > k.

Below is a sequence of commands that solves exactly such a problem. You should be able to recognize the objective expression and the constraints from the data that is entered. But as an aid, you might answer the following questions:

  • How many crops are under consideration?
  • What are the corresponding expenses? How much is available for expenses?
  • What are the yields in each case? What is the storage capacity?
  • How many acres are available?
  • What crops are constrained by seed limitations? To what extent?
  • What about preferences?
  • What are the minimum acreages for each crop?
octave:> f = [110*1.3 30*2.0 125*1.56 75*1.8 95*.95 100*2.25 50*1.35];
octave:> A = [120 210 150.75 115 186 140 85;
        110 30 125 75 95 100 50;
        1 1 1 1 1 1 1;
        1 -1 0 0 0 0 0;
        0 0 1 0 -2 0 0;
        0 0 0 -1 0 -1 1];

octave:> b = [55000;40000;400;0;0;0];
octave:> lp = lp_maker(f, A, b, [-1; -1; -1; -1; -1; -1],
                          [10 10 10 10 20 20 20], [100 Inf 50 Inf Inf 250 Inf], [], 1, 0);
octave:> solvestat = octlpsolve('solve', lp)
solvestat = 0
octave:> obj = octlpsolve('get_objective', lp)
obj =  7.5398e+04
octave:> x = octlpsolve('get_variables', lp)
x =

   10.000
   10.000
   40.000
   45.652
   20.000
  250.000
   20.000

octave:> octlpsolve('delete_lp', lp);

Note that these command are in script example6.m

Note that we have used in this formulation the vlb and vub arguments of lp_maker. This to set lower and upper bounds on variables. This could have been done via extra constraints, but it is more performant to set bounds on variables. Also note that Inf is used for variables that have no upper limit. This stands for Infinity.

Note that despite the complexity of the problem, lp_solve solves it almost instantaneously. It seems the farmer should bet the farm on crop number 6.We strongly suggest you alter the expense and/or the storage limit in the problem and see what effect that has on the answer.

Another, more theoretical, example

Suppose we want to solve the following linear program using Octave:

max 4x1 + 2x2 + x3
s. t. 2x1 + x2 <= 1
x1 + 2x3 <= 2
x1 + x2 + x3 = 1
x1 >= 0
x1 <= 1
x2 >= 0
x2 <= 1
x3 >= 0
x3 <= 2

Convert the LP into Octave format we get:

f = [4 2 1]
A = [2 1 0; 1 0 2; 1 1 1]
b = [1; 2; 1]

Note that constraints on single variables are not put in the constraint matrix. lp_solve can set bounds on individual variables and this is more performant than creating additional constraints. These bounds are:

l = [ 0 0 0]
u = [ 1 1 2]

Now lets enter this in Octave:

octave:> f = [4 2 1];
octave:> A = [2 1 0; 1 0 2; 1 1 1];
octave:> b = [1; 2; 1];
octave:> l = [ 0 0 0];
octave:> u = [ 1 1 2];

Now solve the linear program using Octave: Type the commands

octave:> lp = lp_maker(f, A, b, [-1; -1; -1], l, u, [], 1, 0);
octave:> solvestat = octlpsolve('solve', lp)
solvestat = 0
octave:> obj = octlpsolve('get_objective', lp)
obj = 2.5000
octave:> x = octlpsolve('get_variables', lp)
x =

  0.50000
  0.00000
  0.50000

octave:> octlpsolve('delete_lp', lp)

What to do when some of the variables are missing ?
For example, suppose there are no lower bounds on the variables. In this case define l to be the empty set using the Octave command:

octave:> l = [];

This has the same effect as before, because lp_solve has as default lower bound for variables 0.

But what if you want that variables may also become negative?
Then you can use -Inf as lower bounds:

octave:> l = [-Inf -Inf -Inf];

Solve this and you get a different result:

octave:> lp = lp_maker(f, A, b, [-1; -1; -1], l, u, [], 1, 0);
octave:> solvestat = octlpsolve('solve', lp)
solvestat = 0
octave:> obj = octlpsolve('get_objective', lp)
obj = 2.6667
octave:> x = octlpsolve('get_variables', lp)
x =

   0.66667
  -0.33333
   0.66667

octave:> octlpsolve('delete_lp', lp)

Overview of API routines

Note again that the Octave command 'help octlpsolve.m' gives an overview of all functions that can be called via octlpsolve with their arguments and return values.

Note that everwhere where lp is used as argument that this can be a handle (lp_handle) or the models name.

  • add_column, add_columnex
    • return = octlpsolve('add_column', lp, [column])
    • return = octlpsolve('add_columnex', lp, [column])
    • Both have the same interface from add_column but act as add_columnex
  • add_constraint, add_constraintex
    • return = octlpsolve('add_constraint', lp, [row], constr_type, rh)
    • return = octlpsolve('add_constraintex', lp, [row], constr_type, rh)
    • Both have the same interface from add_constraint but act as add_constraintex
  • add_SOS
    • return = octlpsolve('add_SOS', lp, name, sostype, priority, [sosvars], [weights])
    • The count argument in the API documentation is not needed in Octave since the number of elements is derived from the size of the sosvars and weights matrices. These must have the same size.
  • column_in_lp
    • return = octlpsolve('column_in_lp', lp, [column])
    • No special considerations.
  • copy_lp
    • lp_handle = octlpsolve('copy_lp', lp)
    • No special considerations.
  • default_basis
    • octlpsolve('default_basis', lp)
    • No special considerations.
  • del_column
    • return = octlpsolve('del_column', lp, column)
    • No special considerations.
  • del_constraint
    • return = octlpsolve('del_constraint', lp, del_row)
    • No special considerations.
  • delete_lp
    • octlpsolve('delete_lp', lp)
    • No special considerations.
  • free_lp
    • octlpsolve('free_lp', lp)
    • lp is not changed as in the lpsolve API since it is a read_only input parameter. So it acts the same as delete_lp.
  • get_anti_degen
    • return = octlpsolve('get_anti_degen', lp)
    • No special considerations.
  • get_basis
    • [bascolumn] = octlpsolve('get_basis', lp {, nonbasic})
    • The bascolumn argument in the API documentation is here the return value. The nonbasic argument is optional in Octave. If not provided, then 0 is used.
  • get_basiscrash
    • return = octlpsolve('get_basiscrash', lp)
    • No special considerations.
  • get_bb_depthlimit
    • return = octlpsolve('get_bb_depthlimit', lp)
    • No special considerations.
  • get_bb_floorfirst
    • return = octlpsolve('get_bb_floorfirst', lp)
    • No special considerations.
  • get_bb_rule
    • return = octlpsolve('get_bb_rule', lp)
    • No special considerations.
  • get_bounds_tighter
    • return = octlpsolve('get_bounds_tighter', lp)
    • No special considerations.
  • get_break_at_value
    • return = octlpsolve('get_break_at_value', lp)
    • No special considerations.
  • get_col_name
    • name = octlpsolve('get_col_name', lp, column)
    • [names] = octlpsolve('get_col_name', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • get_column get_columnex
    • [column, return] = octlpsolve('get_column', lp, col_nr)
    • [column, return] = octlpsolve('get_columnex', lp, col_nr)
    • The column argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_constr_type
    • return = octlpsolve('get_constr_type', lp, row)
    • [constr_type] = octlpsolve('get_constr_type', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • get_constr_value
    • return = octlpsolve('get_constr_value', lp, row {, primsolution})
    • The primsolution argument is optional. If not provided, then the solution of last solve is used.
  • get_constraints
    • [constr, return] = octlpsolve('get_constraints', lp)
    • The constr argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_dual_solution
    • [duals, return] = octlpsolve('get_dual_solution', lp)
    • The duals argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In Octave, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_epsb
    • return = octlpsolve('get_epsb', lp)
    • No special considerations.
  • get_epsd
    • return = octlpsolve('get_epsd', lp)
    • No special considerations.
  • get_epsel
    • return = octlpsolve('get_epsel', lp)
    • No special considerations.
  • get_epsint
    • return = octlpsolve('get_epsint', lp)
    • No special considerations.
  • get_epsperturb
    • return = octlpsolve('get_epsperturb', lp)
    • No special considerations.
  • get_epspivot
    • return = octlpsolve('get_epspivot', lp)
    • No special considerations.
  • get_improve
    • return = octlpsolve('get_improve', lp)
    • No special considerations.
  • get_infinite
    • return = octlpsolve('get_infinite', lp)
    • No special considerations.
  • get_lowbo
    • return = octlpsolve('get_lowbo', lp, column)
    • [return] = octlpsolve('get_lowbo', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • get_lp_index
    • return = octlpsolve('get_lp_index', lp, orig_index)
    • No special considerations.
  • get_lp_name
    • name = octlpsolve('get_lp_name', lp)
    • No special considerations.
  • get_mat
    • value = octlpsolve('get_mat', lp, row, col)
    • [matrix, return] = octlpsolve('get_mat', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix in the first return value. The return code of the call is the second return value.
  • get_max_level
    • return = octlpsolve('get_max_level', lp)
    • No special considerations.
  • get_maxpivot
    • return = octlpsolve('get_maxpivot', lp)
    • No special considerations.
  • get_mip_gap
    • return = octlpsolve('get_mip_gap', lp, absolute)
    • No special considerations.
  • get_nameindex
    • return = octlpsolve('get_nameindex', lp, name, isrow)
    • No special considerations.
  • get_Ncolumns
    • return = octlpsolve('get_Ncolumns', lp)
    • No special considerations.
  • get_negrange
    • return = octlpsolve('get_negrange', lp)
    • No special considerations.
  • get_nonzeros
    • return = octlpsolve('get_nonzeros', lp)
    • No special considerations.
  • get_Norig_columns
    • return = octlpsolve('get_Norig_columns', lp)
    • No special considerations.
  • get_Norig_rows
    • return = octlpsolve('get_Norig_rows', lp)
    • No special considerations.
  • get_Nrows
    • return = octlpsolve('get_Nrows', lp)
    • No special considerations.
  • get_obj_bound
    • return = octlpsolve('get_obj_bound', lp)
    • No special considerations.
  • get_objective
    • return = octlpsolve('get_objective', lp)
    • No special considerations.
  • get_orig_index
    • return = octlpsolve('get_orig_index', lp, lp_index)
    • No special considerations.
  • get_origcol_name
    • name = octlpsolve('get_origcol_name', lp, column)
    • [names] = octlpsolve('get_origcol_name', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • get_origrow_name
    • name = octlpsolve('get_origrow_name', lp, row)
    • [names] = octlpsolve('get_origrow_name', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • get_pivoting
    • return = octlpsolve('get_pivoting', lp)
    • No special considerations.
  • get_presolve
    • return = octlpsolve('get_presolve', lp)
    • No special considerations.
  • get_presolveloops
    • return = octlpsolve('get_presolveloops', lp)
    • No special considerations.
  • get_primal_solution
    • [pv, return] = octlpsolve('get_primal_solution', lp)
    • The pv argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_print_sol
    • return = octlpsolve('get_print_sol', lp)
    • No special considerations.
  • get_ptr_constraints
    • Not implemented.
  • get_ptr_dualsolution
    • Not implemented.
  • get_ptr_primal_solution
    • Not implemented.
  • get_ptr_sensitivity_obj, get_ptr_sensitivity_objex
    • Not implemented.
  • get_ptr_sensitivity_rhs
    • Not implemented.
  • get_ptr_variables
    • Not implemented.
  • get_rh
    • return = octlpsolve('get_rh', lp, row)
    • [rh] = octlpsolve('get_rh', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • get_rh_range
    • return = octlpsolve('get_rh_range', lp, row)
    • [rh_ranges] = octlpsolve('get_rh_range', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • get_row get_rowex
    • [row, return] = octlpsolve('get_row', lp, row_nr)
    • [row, return] = octlpsolve('get_rowex', lp, row_nr)
    • The row argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In Octave, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_row_name
    • name = octlpsolve('get_row_name', lp, row)
    • [names] = octlpsolve('get_row_name', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • get_scalelimit
    • return = octlpsolve('get_scalelimit', lp)
    • No special considerations.
  • get_scaling
    • return = octlpsolve('get_scaling', lp)
    • No special considerations.
  • get_sensitivity_obj, get_sensitivity_objex
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = octlpsolve('get_sensitivity_obj', lp)
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = octlpsolve('get_sensitivity_objex', lp)
    • The objfrom, objtill, objfromvalue, objtillvalue arguments in the API documentation are here the return values. Note that Octave allows the return of fewer variables. For example if only objfrom and objtill are needed then the call can be [objfrom, objtill] = octlpsolve('get_sensitivity_obj', lp). The unrequested values are even not calculated.
    • Since the API routine doesn't calculate the objtillvalue value at this time, Octave always returns a zero vector for this.
    • The return code of the call is the last value.
    • get_sensitivity_obj and get_sensitivity_objex are both implemented, but have the same functionality.
  • get_sensitivity_rhs, get_sensitivity_rhsex
    • [duals, dualsfrom, dualstill, return] = octlpsolve('get_sensitivity_rhs', lp)
    • [duals, dualsfrom, dualstill, return] = octlpsolve('get_sensitivity_rhsex', lp)
    • The duals, dualsfrom, dualstill arguments in the API documentation are here the return values. Note that Octave allows the return of fewer variables. For example if only duals is needed then the call can be [duals] = octlpsolve('get_sensitivity_rhs', lp). The unrequested values are even not calculated.
    • The return code of the call is the last value.
    • get_sensitivity_rhs and get_sensitivity_rhsex are both implemented, but have the same functionality.
  • get_simplextype
    • return = octlpsolve('get_simplextype', lp)
    • No special considerations.
  • get_solutioncount
    • return = octlpsolve('get_solutioncount', lp)
    • No special considerations.
  • get_solutionlimit
    • return = octlpsolve('get_solutionlimit', lp)
    • No special considerations.
  • get_status
    • return = octlpsolve('get_status', lp)
    • No special considerations.
  • get_statustext
    • return = octlpsolve('get_statustext', lp, statuscode)
    • No special considerations.
  • get_timeout
    • return = octlpsolve('get_timeout', lp)
    • No special considerations.
  • get_total_iter
    • return = octlpsolve('get_total_iter', lp)
    • No special considerations.
  • get_total_nodes
    • return = octlpsolve('get_total_nodes', lp)
    • No special considerations.
  • get_upbo
    • return = octlpsolve('get_upbo', lp, column)
    • [upbo] = octlpsolve('get_upbo', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • get_var_branch
    • return = octlpsolve('get_var_branch', lp, column)
    • [var_branch] = octlpsolve('get_var_branch', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • get_var_dualresult
    • return = octlpsolve('get_var_dualresult', lp, index)
    • No special considerations.
  • get_var_primalresult
    • return = octlpsolve('get_var_primalresult', lp, index)
    • No special considerations.
  • get_var_priority
    • return = octlpsolve('get_var_priority', lp, column)
    • [var_priority] = octlpsolve('get_var_priority', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • get_variables
    • [var, return] = octlpsolve('get_variables', lp)
    • The var argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_verbose
    • return = octlpsolve('get_verbose', lp)
    • No special considerations.
  • get_working_objective
    • return = octlpsolve('get_working_objective', lp)
    • No special considerations.
  • guess_basis
    • [basisvector, return] = octlpsolve('guess_basis', lp, [guessvector])
    • In the API, element 0 of guessvector is not used and values start from element 1. In Octave, there is no unused element in the matrix.
    • In the API, element 0 of basisvector is not used and values start from element 1. In Octave, there is no unused element in the matrix.
  • has_BFP
    • return = octlpsolve('has_BFP', lp)
    • No special considerations.
  • has_XLI
    • return = octlpsolve('has_XLI', lp)
    • No special considerations.
  • is_add_rowmode
    • return = octlpsolve('is_add_rowmode', lp)
    • No special considerations.
  • is_anti_degen
    • return = octlpsolve('is_anti_degen', lp, testmask)
    • No special considerations.
  • is_binary
    • return = octlpsolve('is_binary', lp, column)
    • [binary] = octlpsolve('is_binary', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • is_break_at_first
    • return = octlpsolve('is_break_at_first', lp)
    • No special considerations.
  • is_constr_type
    • return = octlpsolve('is_constr_type', lp, row, mask)
    • No special considerations.
  • is_debug
    • return = octlpsolve('is_debug', lp)
    • No special considerations.
  • is_feasible
    • return = octlpsolve('is_feasible', lp, [values] {, threshold})
    • The threshold argument is optional. When not provided, the value of get_epsint will be taken.
  • is_free is_unbounded
    • return = octlpsolve('is_free', lp, column)
    • return = octlpsolve('is_unbounded', lp, column)
    • [free] = octlpsolve('is_free', lp)
    • [free] = octlpsolve('is_unbounded', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • is_infinite
    • return = octlpsolve('is_infinite', lp, value)
    • No special considerations.
  • is_int
    • return = octlpsolve('is_int', lp, column)
    • [int] = octlpsolve('is_int', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • is_integerscaling
    • return = octlpsolve('is_integerscaling', lp)
    • No special considerations.
  • is_maxim
    • return = octlpsolve('is_maxim', lp)
    • No special considerations.
  • is_nativeBFP
    • return = octlpsolve('is_nativeBFP', lp)
    • No special considerations.
  • is_nativeXLI
    • return = octlpsolve('is_nativeXLI', lp)
    • No special considerations.
  • is_negative
    • return = octlpsolve('is_negative', lp, column)
    • [negative] = octlpsolve('is_negative', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • is_piv_mode
    • return = octlpsolve('is_piv_mode', lp, testmask)
    • No special considerations.
  • is_piv_rule
    • return = octlpsolve('is_piv_rule', lp, rule)
    • No special considerations.
  • is_presolve
    • return = octlpsolve('is_presolve', lp, testmask)
    • No special considerations.
  • is_scalemode
    • return = octlpsolve('is_scalemode', lp, testmask)
    • No special considerations.
  • is_scaletype
    • return = octlpsolve('is_scaletype', lp, scaletype)
    • No special considerations.
  • is_semicont
    • return = octlpsolve('is_semicont', lp, column)
    • [semicont] = octlpsolve('is_semicont', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • is_SOS_var
    • return = octlpsolve('is_SOS_var', lp, column)
    • [SOS_var] = octlpsolve('is_SOS_var', lp)
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into an Octave matrix.
  • is_trace
    • return = octlpsolve('is_trace', lp)
    • No special considerations.
  • is_use_names
    • return = octlpsolve('is_use_names', lp, isrow)
    • No special considerations.
  • lp_solve_version
    • versionstring = octlpsolve('lp_solve_version')
    • The octlpsolve API routine returns the version information in 4 provided argument variables while the Octave version returns the information as a string in the format major.minor.release.build
  • make_lp
    • lp_handle = octlpsolve('make_lp', rows, columns)
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
  • print_constraints
    • octlpsolve('print_constraints', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Octave (Windows) this means that the output is not shown.
    • The same information can also be obtained via octlpsolve('get_constraints', lp). This shows the result on screen.
  • print_debugdump
    • return = octlpsolve('print_debugdump', lp, filename)
    • No special considerations.
  • print_duals
    • octlpsolve('print_duals', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Octave (Windows) this means that the output is not shown.
    • The same information can be obtained via octlpsolve('get_dual_solution', lp). This shows the result on screen.
  • print_lp
    • octlpsolve('print_lp', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Octave (Windows) this means that the output is not shown.
  • print_objective
    • octlpsolve('print_objective', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Octave (Windows) this means that the output is not shown.
    • The same information can be obtained via octlpsolve('get_objective', lp). This shows the result on screen.
  • print_scales
    • octlpsolve('print_scales', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Octave (Windows) this means that the output is not shown.
  • print_solution
    • octlpsolve('print_solution', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Octave (Windows) this means that the output is not shown.
    • The same information can also be obtained via octlpsolve('get_variables', lp). This shows the result on screen.
  • print_str
    • octlpsolve('print_str', lp, str)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Octave (Windows) this means that the output is not shown.
  • print_tableau
    • octlpsolve('print_tableau', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Octave (Windows) this means that the output is not shown.
  • put_abortfunc
    • Not implemented.
  • put_logfunc
    • Not implemented.
    • However, the octlpsolve driver sets a log function to redirect the output of lpsolve from stdout (which is not visible in Windows Octave) to the command window of Octave. As such, all reported output can be seen in Octave. How much output is seen is controlled by the verbose level that can be defined by set_verbose or can be specified in the read_ routines.
  • put_msgfunc
    • Not implemented.
  • read_basis
    • [ret, info] = octlpsolve('read_basis', lp, filename)
    • No special considerations.
  • read_freemps, read_freeMPS
    • lp_handle = octlpsolve('read_freemps', filename {, options})
    • lp_handle = octlpsolve('read_freeMPS', filename {, options})
    • In the lpsolve API, read_freemps needs a FILE handle. In Octave it needs the filename and thus acts the same as read_freeMPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_lp, read_LP
    • lp_handle = octlpsolve('read_lp', filename {, verbose {, lp_name}})
    • lp_handle = octlpsolve('read_LP', filename {, verbose {, lp_name}})
    • In the lpsolve API, read_lp needs a FILE handle. In Octave it needs the filename and thus acts the same as read_LP.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not provided then NORMAL is used.
    • lp_name is optional. If not provided then no name is given to the model ('').
  • read_mps, read_MPS
    • lp_handle = octlpsolve('read_mps', filename {, options})
    • lp_handle = octlpsolve('read_MPS', filename {, options})
    • In the lpsolve API, read_mps needs a FILE handle. In Octave it needs the filename and thus acts the same as read_MPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_params
    • return = octlpsolve('read_params', lp, filename {, options })
    • options is optional.
  • read_XLI
    • lp_handle = octlpsolve('read_XLI', xliname, modelname {, dataname {, options {, verbose}}}
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • dataname is optional. When not provided, '' (NULL) is taken. '' is taken as NULL.
    • options is optional. When not provided, '' is taken.
    • verbose is optional. If not specified, then NORMAL is used.
  • reset_basis
  • set_basisvar
    • octlpsolve('set_basisvar', lp, basisPos, enteringCol)
    • No special considerations.
  • set_add_rowmode
    • return = octlpsolve('set_add_rowmode', lp, turnon)
    • No special considerations.
  • set_anti_degen
    • octlpsolve('set_anti_degen', lp, anti_degen)
    • No special considerations.
  • set_basis
    • return = octlpsolve('set_basis', lp, [bascolumn], nonbasic)
    • In the API, element 0 of bascolumn is not used and values start from element 1. In Octave, there is no unused element in the matrix.
  • set_basiscrash
    • octlpsolve('set_basiscrash', lp, mode)
    • No special considerations.
  • set_bb_depthlimit
    • octlpsolve('set_bb_depthlimit', lp, bb_maxlevel)
    • No special considerations.
  • set_bb_floorfirst
    • octlpsolve('set_bb_floorfirst', lp, bb_floorfirst)
    • No special considerations.
  • set_bb_rule
    • octlpsolve('set_bb_rule', lp, bb_rule)
    • No special considerations.
  • set_BFP
    • return = octlpsolve('set_BFP', lp, filename)
    • No special considerations.
  • set_binary
    • return = octlpsolve('set_binary', lp, column, must_be_bin)
    • return = octlpsolve('set_binary', lp, [must_be_bin])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds
    • return = octlpsolve('set_bounds', lp, column, lower, upper)
    • return = octlpsolve('set_bounds', lp, [lower], [upper])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds_tighter
    • octlpsolve('set_bounds_tighter', lp, tighten)
    • No special considerations.
  • set_break_at_first
    • octlpsolve('set_break_at_first', lp, break_at_first)
    • No special considerations.
  • set_break_at_value
    • octlpsolve('set_break_at_value', lp, break_at_value)
    • No special considerations.
  • set_col_name
    • return = octlpsolve('set_col_name', lp, column, name)
    • return = octlpsolve('set_col_name', lp, [names])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_column, set_columnex
    • return = octlpsolve('set_column', lp, col_no, [column])
    • return = octlpsolve('set_columnex', lp, col_no, [column])
    • Both have the same interface from set_column but act as set_columnex
  • set_constr_type
    • return = octlpsolve('set_constr_type', lp, row, con_type)
    • return = octlpsolve('set_constr_type', lp, [con_type])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_debug
    • octlpsolve('set_debug', lp, debug)
    • No special considerations.
  • set_epsb
    • octlpsolve('set_epsb', lp, epsb)
    • No special considerations.
  • set_epsd
    • octlpsolve('set_epsd', lp, epsd)
    • No special considerations.
  • set_epsel
    • octlpsolve('set_epsel', lp, epsel)
    • No special considerations.
  • set_epsint
    • octlpsolve('set_epsint', lp, epsint)
    • No special considerations.
  • set_epslevel
    • octlpsolve('set_epslevel', lp, epslevel)
    • No special considerations.
  • set_epsperturb
    • octlpsolve('set_epsperturb', lp, epsperturb)
    • No special considerations.
  • set_epspivot
    • octlpsolve('set_epspivot', lp, epspivot)
    • No special considerations.
  • set_free set_unbounded
    • return = octlpsolve('set_free', lp, column)
    • return = octlpsolve('set_unbounded', lp, column)
    • No special considerations.
  • set_improve
    • octlpsolve('set_improve', lp, improve)
    • No special considerations.
  • set_infinite
    • octlpsolve('set_infinite', lp, infinite)
    • No special considerations.
  • set_int
    • return = octlpsolve('set_int', lp, column, must_be_int)
    • return = octlpsolve('set_int', lp, [must_be_int])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lowbo
    • return = octlpsolve('set_lowbo', lp, column, value)
    • return = octlpsolve('set_lowbo', lp, [values])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lp_name
    • return = octlpsolve('set_lp_name', lp, name)
    • In Octave, when you name a model, this name can be used everywhere where lp is specified. This to access the model via the name instead of via a handle.
  • set_mat
    • return = octlpsolve('set_mat', lp, row, column, value)
    • return = octlpsolve('set_mat', lp, [matrix])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows to set the whole matrix (all rows/columns) at once. This is the most performant way to provide the constraint matrix. The matrix must be two-dimentional.
  • set_maxim
    • octlpsolve('set_maxim', lp)
    • No special considerations.
  • set_maxpivot
    • octlpsolve('set_maxpivot', max_num_inv)
    • No special considerations.
  • set_minim
    • octlpsolve('set_minim', lp)
    • No special considerations.
  • set_mip_gap
    • octlpsolve('set_mip_gap', lp, absolute, mip_gap)
    • No special considerations.
  • set_negrange
    • octlpsolve('set_negrange', negrange)
    • No special considerations.
  • set_obj
    • return = octlpsolve('set_obj', lp, column, value)
    • return = octlpsolve('set_obj', lp, [values])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables. It is then the same as set_obj_fn
  • set_obj_bound
    • octlpsolve('set_obj_bound', lp, obj_bound)
    • No special considerations.
  • set_obj_fn, set_obj_fnex
    • return = octlpsolve('set_obj_fn', lp, [row])
    • return = octlpsolve('set_obj_fnex', lp, [row])
    • Both have the same interface from set_obj_fn but act as set_obj_fnex
    • In the API, element 0 is not used and values start from element 1. In Octave, there is no unused element in the matrix.
  • set_outputfile
    • return = octlpsolve('set_outputfile', lp, filename)
    • In the API description it says that setting filename to NULL results in writing output back to stdout. In Octave under Windows, output to stdout it not shown. However it results in closing the file. Use '' to have the effect of NULL.
  • set_outputstream
    • Not implemented.
  • set_pivoting
    • octlpsolve('set_pivoting', lp, pivoting)
    • No special considerations.
  • set_preferdual
    • octlpsolve('set_preferdual', lp, dodual)
    • No special considerations.
  • set_presolve
    • octlpsolve('set_presolve', lp, do_presolve {, maxloops})
    • The maxloops argument is optional in Octave. If not provided, then infinite is used.
  • set_print_sol
    • octlpsolve('set_print_sol', lp, print_sol)
    • No special considerations.
  • set_rh
    • return = octlpsolve('set_rh', lp, row, value)
    • return = octlpsolve('set_rh', lp, [values])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows. Note that in this case, the value of row 0 is not specified in the matrix.
  • set_rh_range
    • return = octlpsolve('set_rh_range', lp, row, deltavalue)
    • return = octlpsolve('set_rh_range', lp, [deltavalues])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_rh_vec
    • octlpsolve('set_rh_vec', lp, [rh])
    • In the API, element 0 is not used and values start from element 1. In Octave, there is no unused element in the matrix.
  • set_row, set_rowex
    • return = octlpsolve('set_row', lp, row_no, [row])
    • return = octlpsolve('set_rowex', lp, row_no, [row])
    • Both have the same interface from set_row but act as set_rowex
    • In the API, element 0 is not used and values start from element 1. In Octave, there is no unused element in the matrix.
  • set_row_name
    • return = octlpsolve('set_row_name', lp, row, name)
    • return = octlpsolve('set_row_name', lp, [names])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_scalelimit
    • octlpsolve('set_scalelimit', lp, scalelimit)
    • No special considerations.
  • set_scaling
    • octlpsolve('set_scaling', lp, scalemode)
    • No special considerations.
  • set_semicont
    • return = octlpsolve('set_semicont', lp, column, must_be_sc)
    • return = octlpsolve('set_semicont', lp, [must_be_sc])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_sense
    • octlpsolve('set_sense', lp, maximize)
    • No special considerations.
  • set_simplextype
    • octlpsolve('set_simplextype', lp, simplextype)
    • No special considerations.
  • set_solutionlimit
    • octlpsolve('set_solutionlimit', lp, simplextype)
    • No special considerations.
  • set_timeout
    • octlpsolve('set_timeout', lp, sectimeout)
    • No special considerations.
  • set_trace
    • octlpsolve('set_trace', lp, trace)
    • No special considerations.
  • set_upbo
    • return = octlpsolve('set_upbo', lp, column, value)
    • return = octlpsolve('set_upbo', lp, [values])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_use_names
    • octlpsolve('set_use_names', lp, isrow, use_names)
    • No special considerations.
  • set_var_branch
    • return = octlpsolve('set_var_branch', lp, column, branch_mode)
    • return = octlpsolve('set_var_branch', lp, [branch_mode])
    • In Octave, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_weights
    • return = octlpsolve('set_var_weights', lp, [weights])
    • No special considerations.
  • set_verbose
    • octlpsolve('set_verbose', lp, verbose)
    • No special considerations.
  • set_XLI
    • return = octlpsolve('set_XLI', lp, filename)
    • No special considerations.
  • solve
    • result = octlpsolve('solve', lp)
    • No special considerations.
  • str_add_column
    • Not implemented.
  • str_add_constraint
    • Not implemented.
  • str_set_obj_fn
    • Not implemented.
  • str_set_rh_vec
    • Not implemented.
  • time_elapsed
    • return = octlpsolve('time_elapsed', lp)
    • No special considerations.
  • unscale
    • octlpsolve('unscale', lp)
    • No special considerations.
  • write_basis
    • octlpsolve('write_basis', lp, filename)
    • No special considerations.
  • write_freemps, write_freeMPS
    • return = octlpsolve('write_freemps', lp, filename)
    • return = octlpsolve('write_freeMPS', lp, filename)
    • In the lpsolve API, write_freeMPS needs a FILE handle. In Octave it needs the filename and thus acts the same as write_freemps.
  • write_lp, write_LP
    • return = octlpsolve('write_lp', lp, filename)
    • return = octlpsolve('write_LP', lp, filename)
    • In the lpsolve API, write_LP needs a FILE handle. In Octave it needs the filename and thus acts the same as write_lp.
  • write_mps, write_MPS
    • return = octlpsolve('write_mps', lp, filename)
    • return = octlpsolve('write_MPS', lp, filename)
    • In the lpsolve API, write_MPS needs a FILE handle. In Octave it needs the filename and thus acts the same as write_mps.
    • No special considerations.
  • write_XLI
    • return = octlpsolve('write_XLI', lp, filename {, options {, results}})
    • No special considerations.

Extra Octave routines

These routines are not part of the lpsolve API, but are added for backwards compatibility. Most of them exist in the lpsolve API with another name.

  • [names] = octlpsolve('get_col_names', lp)
    • The same as get_col_name. Implemented for backwards compatibility.
  • [constr_type] = octlpsolve('get_constr_types', lp)
    • The same as get_constr_type. Implemented for backwards compatibility.
  • [int] = octlpsolve('get_int', lp)
    • The same as is_int. Implemented for backwards compatibility.
  • return = octlpsolve('get_no_cols', lp)
    • The same as get_Ncolumns. Implemented for backwards compatibility.
  • return = octlpsolve('get_no_rows', lp)
    • The same as get_Nrows. Implemented for backwards compatibility.
  • name = octlpsolve('get_objective_name', lp)
    • The same as get_row_name with row=0. Implemented for backwards compatibility.
  • [row_vec, return] = octlpsolve('get_obj_fn', lp)
    [row_vec, return] = octlpsolve('get_obj_fun', lp)
    • The same as get_row with row 0. Implemented for backwards compatibility.
  • name = octlpsolve('get_problem_name', lp)
    • The same as get_lp_name. Implemented for backwards compatibility.
  • [costs] = octlpsolve('get_reduced_costs', lp)
    • The same as get_dual_solution. Implemented for backwards compatibility.
  • [names] = octlpsolve('get_row_names', lp)
    • The same as get_row_name. Implemented for backwards compatibility.
  • [obj, x, duals, return] = octlpsolve('get_solution', lp)
    • Returns the value of the objective function, the values of the variables and the duals. Implemented for backwards compatibility.
    • The return code of the call is the last value.
  • value = octlpsolve('mat_elm', lp)
    • The same as get_mat. Implemented for backwards compatibility.
  • [handle_vec] = octlpsolve('print_handle')
    • Returns a vector with open handles. Can be handy to see which handles aren't closed yet with delete_lp or free_lp.
  • lp_handle = octlpsolve('read_lp_file', filename {, verbose {, lp_name}})
    • The same as read_LP. Implemented for backwards compatibility.
  • lp_handle = octlpsolve('get_handle', lp_name)
    • Get the handle for this model from the models name. If an unknown model name is given (or already deleted), -1 is returned.
  • return_constants = octlpsolve('return_constants'[, return_constants])
    • Returns the setting of return_constants and optionally sets its value.

Compile the octlpsolve driver

Windows

To compile the Octave driver under Windows, the cygwin environment is needed. The following document describes what is needed for this: README.Windows. It may not be needed to build the Octave sources to compile the binary file, but the proposed cygwin and octave packages are needed to build a .oct file.
The build must be done from the cygwin prompt from the directory where the lpsolve octave files are located.
To make the compilation process easier, a script file can be used: ccc.win32
To make for release, just enter ./ccc.win32 and everything is build.

Unix/Linux

The build must be done from a shell prompt from the directory where the lpsolve octave files are located.
To make the compilation process easier, a script file can be used: ccc
To make for release, just enter sh ccc and everything is build.

All platforms

This compiles three source files: lpsolve.cpp, octave.cpp and hash.cpp
Then these are linked together to generate the octlpsolve.oct file.
The optional arguments to ccc are used for development. Source files can be provided and then only these are compiled. For example hash.cpp should only be compiled once while developing. So specifying lpsolve.cpp as first argument will only compile this file and then link everything. This makes the build process a bit faster. Also the option -DDEMO can be added to add the demo command to test some functionality of lpsolve. This is also only for debugging. Also the option -DDEBUG can be added. This to print some debug information while executing octlpsolve. Should only be used for debugging purposes.

See also Using lpsolve from MATLAB, Using lpsolve from O-Matrix, Using lpsolve from Sysquake, Using lpsolve from Scilab, Using lpsolve from FreeMat, Using lpsolve from Euler, Using lpsolve from Python, Using lpsolve from Sage, Using lpsolve from PHP, Using lpsolve from R

doc/del_column.htm0000644000175000017500000000554410351334142013126 0ustar renerene del_column

del_column

Remove a column from the lp.

unsigned char del_column(lprec *lp, int column);

Return Value

del_column returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
An error occurs when column is not between 1 and the number of columns in the lp.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column to delete. Must be between 1 and the number of columns in the lp.

Remarks

The del_column function deletes a column from the model. The column is effectively deleted, so all columns after this column shift one left.
Note that column 0 (the right hand side (RHS)) cannot be deleted. There is always a RHS.

Note that if you can also delete multiple columns by a call to resize_lp.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h" 

int main(void) 
{
  lprec *lp;

  /* Create a new LP model */ 
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  del_column(lp, 1);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also resize_lp, make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_column, add_columnex, str_add_column

doc/get_status.htm0000644000175000017500000000444710237177146013204 0ustar renerene get_status

get_status

Returns an extra status after a call to a function.

int get_status(lprec *lp);

Return Value

Extra status which indicates type of problem after call to function.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_status function returns an extra status after a call to a function. Some functions return FALSE when they have failed. To have more information on the reason of the failure, this routine can be used to get an extended error code.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int spx_status;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /*
  .
  .
  .
  */

  spx_status = get_status(lp);

  return(0);
}

lp_solve API reference

See Also free_lp, make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

doc/get_improve.htm0000644000175000017500000000577710244174352013343 0ustar renerene get_improve

get_improve

Returns the iterative improvement level.

int get_improve(lprec *lp);

Return Value

get_improve returns the iterative improvement level. Can by any of the following values:

IMPROVE_NONE (0) improve none
IMPROVE_SOLUTION (1) Running accuracy measurement of solved equations based on Bx=r (primal simplex), remedy is refactorization.
IMPROVE_DUALFEAS (2) Improve initial dual feasibility by bound flips (highly recommended, and default)
IMPROVE_THETAGAP (4) Low-cost accuracy monitoring in the dual, remedy is refactorization
IMPROVE_BBSIMPLEX (8) By default there is a check for primal/dual feasibility at optimum only for the relaxed problem, this also activates the test at the node level

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

improve


Remarks

The default is IMPROVE_DUALFEAS + IMPROVE_THETAGAP (6).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int improve;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  improve = get_improve(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_improve

doc/lp_solve_5.5.0.15.chw0000644000175000017500000010070111247522375013575 0ustar renereneITSF` |{ "|{ "`8LaT .!"T Uncompressed MSCompressed{7FC28940-9D31-11D0LZXC Cd;)X44 */'absolute valuesadd_column add_columnexadd_constraint'add_constraintex4add_lag_con Aadd_SOS NBasis Factorization Packages[Calling the lpsolve API from your applicationhChanges from version 4 to version 5.1uChanges from version 5.1 to version 5.5column_in_lp copy_lp CPLEX lp filesdefault_basis del_columndel_constraintdelete_lpDIMACS maximum flow problemsDIMACS minimum assignment problemsDIMACS minimum cost flow problemsDownloaddualize_lpExternal Language Interfaces+Formulation of an lp model in lpsolve8free variablesEfree_lpRFrequently Asked Questions_get_anti_degenlget_basisy%get_basiscrashget_bb_depthlimitget_bb_floorfirstget_bb_ruleget_bounds_tighterget_break_at_valueget_col_nameget_columnget_columnexget_constr_typeget_constr_valueget_constraintsget_dual_solution "get_epsb!/get_epsd"<get_epsel#Iget_epsint$Vget_epsperturb%cget_epspivot&pget_improve'}get_infinite(get_lambda)get_lowbo*get_lp_index+get_lp_name,get_Lrows-get_mat.get_max_level/get_maxpivot0get_mip_gap1get_nameindex2 get_Ncolumns3get_negrange4&get_nonzeros53get_Norig_columns6@get_Norig_rows7Mget_Nrows8Z!get_obj_bound9gget_objective:tget_orig_index;get_origcol_nameget_origrow_name<get_pivoting=get_presolve>get_presolveloops?get_primal_solution@get_print_solAget_ptr_constraintsget_ptr_dual_solution get_ptr_lambda)get_ptr_primal_solution@get_ptr_sensitivity_objBget_ptr_sensitivity_objexB*get_ptr_sensitivity_rhs 7get_ptr_variablesCDget_rhDQget_rh_rangeE^get_rowFkget_row_name<xget_rowexFget_scalelimitGget_scalingHget_sensitivity_objBget_sensitivity_objexBget_sensitivity_rhs get_simplextypeIget_solutioncountJget_solutionlimitKget_statusLget_statustextM8Z$get_timeoutNget_total_iterO!get_total_nodesP.get_upboQ;get_var_branchRHget_var_dualresult Uget_var_primalresult@bget_var_prioritySoget_variablesC|get_verboseTget_working_objectiveUGNU LESSER GENERAL PUBLIC LICENSEGNU MathProgguess_basisVhas_BFPWhas_XLIXInfeasible modelsinteger variablesIntroductionis_add_rowmodeY is_anti_degenZis_binary[%is_break_at_first\2is_constr_type]?is_debug^Lis_feasible_Yis_infiniteafis_intbsis_integerscalingcis_lag_tracedis_maximeis_nativeBFPfis_nativeXLIgis_negativehis_obj_in_basisiis_piv_modej"#is_piv_rulekis_presolvelis_scalemodemis_scaletypenis_semicontois_SOS_varp)is_traceq6is_unbounded`Cis_use_namesrPlag_solves]LINDO lp filesjLinear programming basicswLinear Programming FAQlp file formatlp_solve API referencelp_solve commandlp_solve Yahoo grouplp_solve_versiontLPFMLlpsolve distributed filesLPSolve IDEmake_lpumps bas file formatmps file formatMPS_writefileexv Presolve-print_constraintsw:print_debugdumpxGprint_dualsyTprint_lpzaprint_objective{nprint_scales|{print_solution}print_str~print_tableaudej$%put_abortfuncput_bb_branchfuncput_bb_nodefuncput_logfuncput_msgfuncQuick startratio'sread_basis read_freemps read_freeMPS$ read_lp1 read_LP> read_mpsK read_MPSX read_paramse read_XLIr reset_basis reset_params resize_lp scaling semi-continuous variables sensitivity set_add_rowmode set_anti_degen set_basis set_basiscrash set_basisvar set_bb_depthlimit set_bb_floorfirst set_bb_rule( set_BFP5 set_binaryB set_boundsO set_bounds_tighter\ set_break_at_firsti set_break_at_valuev set_col_name dej 'set_column set_columnex set_constr_type set_debug set_epsb set_epsd set_epsel set_epsint set_epslevel set_epsperturb set_epspivot set_improve set_infinite, set_int9 set_lag_traceF set_lowboS set_lp_name` set_matm set_maximz set_maxpivot set_minim set_mip_gap set_negrange set_obj set_obj_bound set_obj_fn set_obj_fnex set_obj_in_basis set_outputfile set_outputstream set_pivoting set_preferdual# set_presolve0 set_print_sol= set_rhJ set_rh_rangeW set_rh_vecd set_rowq set_row_name~ <!set_rowex set_scalelimit set_scaling set_semicont set_sense set_simplextype set_solutionlimit set_timeout set_trace set_unbounded set_upbo set_use_names set_var_branch' set_var_weights4 set_verboseA set_XLIN solve[ special ordered setsh str_add_columnu str_add_constraint str_add_lag_con  str_set_obj_fn str_set_rh_vec time_elapsed unscale Usefull links Using lpsolve from AMPL Using lpsolve from Euler Using lpsolve from FreeMat Using lpsolve from JavaUsing lpsolve from MATLABUsing lpsolve from OctaveUsing lpsolve from O-Matrix+t_row_name~ Using lpsolve from PHP8Using lpsolve from PythonEUsing lpsolve from RRUsing lpsolve from Sage_Using lpsolve from ScilablUsing lpsolve from Sysquakeywrite_basiswrite_freempsvwrite_freeMPSvwrite_lpwrite_LPwrite_lpexwrite_mpsvwrite_MPSvwrite_paramswrite_XLIXpress lp filesZimpl str_add_lag_con  str_set_obj_fn str_set_rh_vec time_elapsed unscale Usefull links Using lpsolve from AMPL Using lpsolve from Euler Using lpsolve from FreeMat Using lpsolve from JavaUsing lpsolve from MATLABUsing lpsolve from OctaveUsing lpsolve from O-Matrix+t_row_name~ Zget_basiscrashget_obj_bound9get_timeoutNis_piv_rulekput_abortfuncset_columnset_rowexUsing lpsolve from PHP $bFVOf/'ITSPT  j].!"TPMGL^/ /$HHTitleMap ! /$OBJINST4/$WWAssociativeLinks//$WWAssociativeLinks/PROPERTY:/$WWKeywordLinks//$WWKeywordLinks/BTREE,L/$WWKeywordLinks/DATA "/$WWKeywordLinks/MAP>J/$WWKeywordLinks/PROPERTYx ::DataSpace/NameList4<(::DataSpace/Storage/MSCompressed/Content,::DataSpace/Storage/MSCompressed/ControlData)::DataSpace/Storage/MSCompressed/SpanInfo/::DataSpace/Storage/MSCompressed/Transform/Listp&_::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/i::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/ResetTablealp_solve_5.5.0.15zz doc/BFP.htm0000644000175000017500000001470410237502644011421 0ustar renerene Basis Factorization Packages

Basis Factorization Packages

Basis Factorization Package (shortened as BFP) is a unique lp_solve feature. Considerable effort has been put in this new feature and we have big expectations for this. BFP is a generic interface model and users can develop their own implementations based on the provided templates. We are very interested in providing as many different BFPs as possible to the community.

Until version 4, lp_solve always used the product form of the inverse (etaPFI) to perform its matrix pivot changes. However there are other methods like LU decomposition. Each method has its advantages and disadvantages. Some are faster/slower, other are numerical more/less stable. The speed and stability of a solver depends considerably on the BFP. One model will be solved better with one BFP and another with another BFP.
The following is a personal comment on the different BFPs by Kjell Eikland:

"Personally, I go for numerical robustness and size capability LUSOL is the one to beat. The LUSOL code has tremendous features for tackling even the toughest models, balancing accuracy and fill-in to a phenomenal extent. I have experimented with a maximum update limit before refactorization of 1500, and even at that level LUSOL was much more reliable than etaPFI!LUSOL does extremely well with some classes of very tough models, such as the PILOT models. For simple, not too large network-like models with little fill-in, etaPFI can be extremely fast and maintain accuracy if the numerics are not too bad. etaPFI v2 is typically both faster and numerically more robust and can handle much more challenging models than v1. The main reason is that v2 typically has quite a bit less fill-in and better pivot management, which automatically leads to better speed and accuracy. GLPK has an LU implementation model that is conceptually/numerically inferior to LUSOL, but updating and btran can be faster.For medium size models of a higher than average toughness, GLPK is definitely a good choice. However, in my experience GLPK is not robust from the perspective of memory management.With some unusually hard models prone to fill-in it simply bombs, which is not good in a production environment.Accuracy management is limited to refactorization (just like etaPFI)."

lp_solve version 5.5 has the LUSOL engine built in as default. In addition two other BFPs are included for both Windows and Linux: bfp_LUSOL.dll, bfp_etaPFI.dll for Windows and libbfp_LUSOL.so, libbfp_etaPFI.so for Linux. The standalone bfp_etaPFI is v2.0 and includes advanced column ordering using the COLAMD library, as well as better pivot management for stability. For complex models, however, the LU factorization approach is much better, and lp_solve now includes LUSOL as one of the most stable engines available anywhere. LUSOL was originally developed by Prof. Saunders at Stanford, and it has now been ported to C and enhanced by Kjell Eikland.

These BFPs are not statically linked, but are dynamically loaded when requested (except for the default LUSOL engine). It is even possible for people to write their own BFP. Under Windows, a BFP is provided as DLL (bfp_*.dll), under UNIX/LINUX as a dynamic linked library (libbfp_*.so).
To change the BFP with lp_solve, use the option -bfp <filename>. Via the API, use set_BFP. filename is the name of the dynamic linked library. It is possible to provide a path to this name to be sure that the BFP from the specified location is used. If no path is given, then it depends on the OS where it will be searched.

Under Windows, the following search order is used:

  1. Current directory.
  2. A semi-colon-separated (;) list of directories in the user's PATH environment variable.

Under Unix/Linux, following search order is used:

  1. A colon-separated (:) list of directories in the user's LD_LIBRARY_PATH environment variable.
  2. The list of libraries specified in /etc/ld.so.cache (which is generated from /etc/ld.so.conf).
  3. /lib, followed by /usr/lib. Note the order here; this is the reverse of the order used by the old a.out loader. The old a.out loader, when loading a program, first searched /usr/lib, then /lib (see the man page ld.so(8)). This shouldn't normally matter, since a library should only be in one or the other directory (never both), and different libraries with the same name are a disaster waiting to happen.

Under Unix/Linux it is standard that a library has the lib prefix and a .so postfix. Under Windows there is no prefix and a .dll postfix.
To make the calling structure for BFPs uniform across different types of OS, lp_solve automatically adds the prefix and postfix if not provided. So the following commands are valid for both Windows and Unix/Linux:

lp_solve -bfp bfp_LUSOL input.lp
lp_solve -bfp ./bfp_LUSOL input.lp

The latter makes sure that the BFP is searched in the current directory, especially for Unix/Linux.

A third BFP based on GLPK may be included later, but license issues must first be resolved. In the interim, you may experiment with the working sample BFP interface files for GLPK.

If you compile BFPs yourself, make sure that under Windows, you use __stdcall convention and use 8 byte alignments. This is needed for the BFPs to work correctly with the general distribution of lp_solve and also to make sharing BFPs as uncomplicated as possible.

doc/LINDO-format.htm0000644000175000017500000003752510611760742013154 0ustar renerene LINDO lp files

LINDO lp files

The LINDO LP file format provides a facility for entering a problem in a natural, algebraic LP formulation from the keyboard. The problem can be modified and saved from within lpsolve. This procedure is one way to create a file in a format that lpsolve can read. An alternative technique is to create a similar file using a standard text editor and to read it into lpsolve.

The LINDO FILE format is provided as an input alternative to the MPS file format. An LP format file may be easier to generate than an MPS file if your problem already exists in an algebraic format or if you have an application that generates the problem file more readily in algebraic format (such as a C application).

Note that the LINDO FILE format is not the same as the lpsolve LP format. See LP file format for a description about the native lpsolve lp format. To read/write this format from lpsolve, you need an XLI (see External Language Interfaces). The XLI for the LINDO format is called xli_LINDO.

Options

The XLI accepts no options at this time.

Example

lp_solve -rxli xli_LINDO input.lpt
lp_solve -mps input.mps -wxli xli_LINDO output.lpt

Syntax Rules of the LINDO FILE Format

lpsolve will accept any problem saved in an ASCII file provided that it adheres to the following syntax rules.

The MPS file format is a column-oriented format. If a row-oriented format is more convenient, then the LINDO file format is of interest. The list of rules is rather short and easy to learn.

Flow of Control

The objective function must always be at the start of the model and is initiated with any of the following keywords:

MAX MIN
MAXIMIZE MINIMIZE
MAXIMISE MINIMISE

The end of the objective function and the beginning of the constraints are signified with any of the following keywords:

SUBJECT TO
SUCH THAT
S.T.
ST

The end of the constraints is signified with the word END.

Formatting

Variable names are limited to eight characters. Names must begin with an alphabetic character (A to Z), which may then be followed by up to seven additional characters. These additional characters may include anything with the exception of the following: ! ) + - = < >. As an example, the following names are valid:

XYZMY_VARA12SHIP.LA

whereas the following are not:

THISONEISTOOLONGA-HYPHEN1INFRONT

The first example contains more than eight characters, the second contains a forbidden hyphen, and the last example does not begin with an alphabetic character.

You may, optionally, name constraints in a model. Constraint names must follow the same conventions as variable names. To name a constraint, you must start the constraint with its name terminated with a right parenthesis. After the right parenthesis, you enter the constraint as before. As an example, the following constraint is given the name XBOUND:

    XBOUND) X < 10

Only five operators are recognized: plus (+), minus (-), greater than (>), less than (<), and equals (=). When you enter the strict inequality operators greater than (>) and less than (<), they will be interpreted as the loose inequality operators greater-than-or-equal-to () and less-than-or-equal-to (), respectively. This is because many keyboards do not have the loose inequality operators. Even for systems having the loose operators, they will not be recognized. However, if you prefer, you may enter ">=" (and "<=") in place of ">" (and "<").

Parentheses as indicators of a preferred order of precedence are not accepted. All operations are ordered from left to right.

Comments may be placed anywhere in a model. A comment is denoted by an exclamation mark. Anything following an exclamation mark on the current line will be considered a comment. For example:

    MAX 10 STD + 15 DLX   ! Max profit
    SUBJECT TO
    ! Here are our factory capacity constraints
    ! for Standard and Deluxe computers
        STD < 10
        DLX < 12
    ! Here is the constraint on labor availability
        STD + 2 DLX < 16
    END

Comments are allowed, but they will not be stored with the model. Therefore, if later an equivalent model will be written, the comments will be removed.

Constraints and the objective function may be split over multiple lines or combined on single lines. You may split a line anywhere except in the middle of a variable name or a coefficient. The following would be mathematically equivalent to our example (although not quite as easy to read):

    MAX
        10
        STD  + 15 DLX  SUBJECT TO
    STD
    <
    10
    DLX < 12  STD + 2
    DLX < 16 END

However, if the objective function appeared as follows:

    MAX 10 ST
    D + 1
    5 DLX
    SUBJECT TO

then an error would be returned because the variable STD is split between lines and the coefficient 15 is also.

Only constant values--not variables--are permitted on the right-hand side of a constraint equation. Thus, an entry such as:

    X > Y

would be rejected. Such an entry could be written as:

    X - Y > 0

Conversely, only variables and their coefficients are permitted on the left-hand side of constraints. For instance, the constraint:

    3X + 4Y - 10 = 0

is not permitted because of the constant term of -10 on the left-hand side. The constraint may be recast as:

    3X + 4Y = 10

By default, all variables have lower bounds of zero and upper bounds of infinity.

Optional Modeling Statements

In addition to the three required model components of an objective function, variables, and constraints, a number of other optional modeling statements may appear in a model following the END statement. These statements and their functions appear in the table below:

Model Statement Function
FREE <Variable> Removes all bounds on <Variable>, allowing <Variable> to take on any real value, positive or negative.
GIN <Variable> Makes <Variable> a general integer (i.e., restricts it to the set of nonnegative integers).
INT <Variable> Makes <Variable> binary (i.e., restricts it to be either 0 or 1).
SLB <Variable> <Value> Places a simple lower bound on <Variable> of <Value>.Use in place of constraints of form X = r.
SUB <Variable> <Value> Places a simple upper bound on <Variable> of <Value>.Use in place of constraints of form X = r.
TITLE <Title> Makes <Title> the title of the model.

Next, we will briefly illustrate the use of each of these statements.

FREE Statement

The default lower bound for a variable is 0. In other words, unless you specify otherwise, variables are not allowed to be negative. The FREE statement allows you to remove all bounds on a variable, so it may take on any real value, positive or negative.

The following small example illustrates the use of the FREE statement:

    MIN 5X + Y
    ST
        X+Y>5
        X-Y>7
    END
    FREE Y

Had we not set Y to be a free variable in this example, the optimal solution of X = 6 and Y = -1 would not have been found. Instead, given the default lower bound of 0 on Y, the solution X = 7 and Y = 0 would be returned.

GIN Statement

By default, all variables are assumed to be continuous. In other words, unless told otherwise, variables are assumed to be any nonnegative fractional number. In many applications, fractional values may be of little use (e.g., 2.5 employees). In these instances, you will want to make use of the general integer statement, GIN. The GIN statement followed by a variable name restricts the value of the variable to the nonnegative integers (0,1,2,...).

The following small example illustrates the use of the GIN statement:

    MAX 11X + 10Y
    ST
        2X + Y < 12
        X - 3Y > 1
    END
    GIN X
    GIN Y

Had we not specified X and Y to be general integers in this model, the optimal solution of X = 6 and Y = 0 would not have been found. Instead, X and Y would have been treated as continuous and returned the solution of X = 5.29 and Y = 1.43.

Note also that simply rounding the continuous solution to the nearest integer values does not yield the optimal solution in this example. In general, rounded continuous solutions may be nonoptimal and, at worst, infeasible. Based on this, one can imagine that it can be very time consuming to obtain the optimal solution to a model with many integer variables. In general, this is true, and you are best off utilizing the GIN feature only when absolutely necessary.

INT Statement

Using the INT statement restricts a variable to being either 0 or 1. These variables are often referred to as binary variables. In many applications, binary variables can be very useful in modeling all-or-nothing situations. Examples might include such things as taking on a fixed cost, building a new plant, or buying a minimum level of some resource to receive a quantity discount.

The following small example illustrates the use of the INT statement:

    MAX -100X + 20A + 12B
    ST
        A - 10X < 0
        A + B < 11
        B < 7
    END
    INT X     !Make X 0/1

Had we not specified X to be binary in this example, a solution of X = .4, A = 4, and B = 7 for an objective value of 124 would not have been returned. Forcing X to be binary, you might guess that the optimal solution would be for X to be 0 because .4 is closer to 0 than it is to 1. If we round X to 0 and optimize for A and B, we get an objective of 84. In reality, a considerably better solution is obtained at X = 1, A = 10, and B = 1 for an objective of 112.

In general, rounded continuous solutions may be nonoptimal and, at worst, infeasible. Based on this, one can imagine that it can be very time consuming to obtain the optimal solution to a model with many binary variables. In general, this is true and you are best off utilizing the INT feature only when absolutely necessary.

SUB and SLB Statements

If you do not specify otherwise, LINDO API assumes variables are continuous (bounded below by zero and unbounded from above). That is, variables can be any positive fractional number increasing indefinitely. In many applications, this assumption may not be realistic. Suppose your facilities limit the quantity produced of an item. In this case, the variable that represents the quantity produced is bounded from above. Or, suppose you want to allow for backordering in a system. An easy way to model this is to allow an inventory variable to go negative. In which case, you would like to circumvent the default lower bound of zero. The SUB and SLB statements are used to alter the bounds on a variable. SLB stands for Simple Lower Bound and is used to set lower bounds. Similarly, SUB stands for Simple Upper Bound and is used to set upper bounds.

The following small example illustrates the use of the SUB and SLB:

    MAX 20X + 30Y
    ST
        X + 2Y < 120
    END
    SLB X 20
    SUB X 50
    SLB Y 40
    SUB Y 70

In this example, we could have just as easily used constraints to represent the bounds. Specifically, we could have entered our small model as follows:

    MAX 20X + 30X
    ST
        X + 2Y < 120
        X > 20
        X < 50
        Y > 40
        Y < 70
    END

This formulation would yield the same results, but there are two points to keep in mind. First, SUBs and SLBs are handled implicitly by the solver, and, therefore, are more efficient from a performance point of view than constraints. Secondly, SUBs and SLBs do not count against the constraint limit, allowing you to solve larger models within that limit.

TITLE Statement

This statement is used to associate a title with a model. The title may be any alphanumeric string of up to 74 characters in length. Unlike all the other statements that must appear after the END statement, the TITLE statement may appear before the objective or after the END statement of a model.

Here is an example of a small model with a title:

    TITLE Your Title Here
    MAX 20X + 30Y
    ST
        X < 50
        Y < 60
        X + 2Y < 120
    END
doc/Scilab3.jpg0000644000175000017500000015646710252630554012276 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?G&Wޱi:̶>϶_K\\Zi kkķ$ik0tw"ylhoחsʰZZiX,qA ^iejFU^E-& fwM.u+Lg Y.d2E//JϵO߀ 6º,"ƿzY^|Wok[O_xi׉|o ՍϊiMqs>geG(ST=,vIE F&VhӜRIbc^wNI>\' gsƦ!8Lx^.y3Kƪ㇆fX,>G8`Y186|c߉ |axo ou 6]%au5K-.T#ԧҭ.xtm`Mc$7u0y9<=^o> *^ǀ>(_| Cg/n!xZ#4/,ַv s_4ko-?ߊ) 3 x*cxÌ|<Ud19f#GXO^CO, xUW4c8(?8g'%̃a2uJ7 fcN3_!5\}\+OF ??'U_sq+ß!~ͺ޳Yd{ᯈ5|u|JգRdcTmEiٺD? e?ZF /_ t]|tg=g__O5oz/tO7c6ŚwciH Qn\L+xN_-rwm4\-(Y\%VYX|;oxF}%~!|J xoZ/<V|D?g#0ݙ'Î#l 'ۯ?)Př ?zO xω o*?cxo]G\ttX[YOiz|S̿e;_. lޓZ~Z/7 /$D|K xRҾ|?LJ;UaX,3c>׈3\ׇx*0X>ɨƹ'cgJNgctGA]z9E<1s<-*`"q6\G.EC?0QVXa?Lu]^uԼw3NO'oT >+h47O]д- 7S K G[|G{|Iim>%MkÞ*{5+#Q~?x⦅S^SM>i|~_>(x|'|{麗:-64w|;o)<|u;~$"<1ߍ^?>3N?QgOx.woōCg,-+xk$j;"I,f#1+f?!e'T1.ʩ† +K6a<"ZcV]CV <8\[+fLE6v]%j-]]-|9PXxT<|??ׅo6gu~̿Yğ#{ߵO6tluo>!ck? ~hy[x/A𻩖97XȰ4+W;¬9rω82^Y_O0<^'3TduJg)b,.kx7COeYqZ_K 1ףw'z|#.ΟिO KׄQ&h_wZn'_\N)罹QgúN{ö~͢OVƟ~]{@nmFig8ly\>wy~o=RBWe<Mĵ(c!Aoļ9*J yejjS1:>3<S^caq9B&Y'B3ܛ=eJS|.* tv?2׿Xc4ccfz[w_y ό7}Wme?2׿Mb}o7?Ə1_S?e Gk?o&L7Xcsq!4{ Wo52#䍿L7G&ZOO9ߐ=+j_oF&ZO-{~'~Cho?/}L|ayy#o-{~ ?Sksq!4}o7?ƏaZm[>0| ?Sh^59ߐ>7G-O _x}S-o>^^H^4eocby>ό7//$mek~7QB誯FnߟQa6[ۻ6?/ֿ'Zk?_#}.a?>.Zkk~g>__-i͏K?/ֿ'>gKQa?>.Zkk~g>__-i͏K?/ֿ'>gKQa?>.K /<=5|E񗄵{1><=axOTмL<;-s_Yh6yQ-k7CE c쉤,i eI{?NW'nkǟ_Gwۧ~mkGktGLz$l$ORv#WG#1qLfacʗ&2_uoi߳W+ bN^gmү7/|,M#hgi k,hZ-lk:f޹~^4{Ӧ^.N]UHeEdx|8hE#xMF׵3&؆ox/? &`n?m^ s޿E?d''8UK5˯~:֩åj^ uAn/cR[-J#,-ǜYF[2fԸ_82̳'9CW2X.x9ゝyTB|gE>24s\#[ R*XLA8Ʋêc*R~Ț,RJ~~W~@?cv$1࿍>Aſ>|./31"__?){>(߄h6GÏxzO}ŷ:uėKcV2?ߴ|_|<ٟ'x_c8ךĽ{K|=ctkC^+?7?d_6X|B0/g)<:8/K8?p<ϲ~#&ɱh8Zy~> =ps:X_e;(!Opc1N#ègG JjW)X>eX Gaqb0I> ~WSGgon|o??>k6H/%h4߱?$?>,_VO|"|Seh6Vi뚭~Um:8m7)}_xK*BZ4%m? Qyal+ ~??No씇WqQ_x0lGL:QrlxT(ҧA㧇_K XziP^>Oo-~y|2Cr\-VUeyeU:qaҥ VIMx>I"ở Zk{M OJm: bZ]i36j/=:^`J;p|I2[-R{]=ŽI+(|E%@fo# am/Y;ǟ xG'~x:>&o4{O8Uj TE-4qj'?7EmWrW5 Wax?~0T2<5 Nt(_UכRԹjn\PQþCe1G a,YjZ\elD!+F-SJ>V۴?Wևhįx_5H> |/WK_C[{}E78SG+Kpqxl&_qkS9Z8 p 0OW 8JQJxR:_PlnUe3XzM l~&K;#cg_10i#+?}s[5֙b~I.4x3ܚiO[W/~"~-'<5 ~kSV\[?i_%''[~ x/^i>Ko>3|h6OE(to|9<n|Yyu}_dz'Aw|kE>o4-_-o>*||//kڷ{M+DдM*S}NOtkˈmE|d?-? yO㲜,0rLwY^y?}2/:U*CUc#]"_W Bc%aғ48wpl6kyv>aQupYk(T䴪bcfp𳣋CZ蟴Wσx w?x3zY|~>,k%< |Uo/k¿58|=x":5[GX+Zkƅgi|K:O~RN̾*u9i>2𞉣/5_Ok.-/F_E78?/Omoqc_B5n-c`{8,/ xKD\gnXF'¿ّkI>4MRCUƯ:~ iC^K~ @ {]SG7AvGhf^ мEW> mo>C2O}/x772&GS36>pO7q\NaQ`2*סp՝(}6YO҃.9o .]s aYUgyk2)`357BW؊!\_v_6t%c~_>/J_$ؼAG.}y7k׿n+<  ~9Y~̟G?x?ݯo ~$/?|_;BS?շ ~'GihC[{}E78s; G8L3 >W&iO&\ 8ul\.aÜ9ٞGqڨGoX4x#`3\n"3PN&_ ߄|d?-? -pvoͲ O0YfGØ2q^̸7qxƾ;[/FF(e?13{q/s,e[G\ <4T_OMȍƪi:^BrrKŒs9@yϯ5O>_ ߄?Wo_qFU7:m•koěxd7G,?:Wp4d^}=Zk/~!~^%U02o+[|[&0^Ai_kd^}z_C!jK:C[{uS'"7ov*N?M:Wp5O>? ߄|d?-_ Q02o+[|[&0^Ai_kd^}z_C!jK:C[{uS'"7ov*N?M:Wp5O>? ߄|d?-_ Q02o+[|[&0^Ai_kd^}z_C!jK:C[{uS'"7ov*N?M:Wp5O>? ߄|d?-_ Q02o+[|[&0^Ai_kd^}??/!~^%Q=¯r412㎛Go󾷨<_V4rޒ_kcXxƏkA~?Zk8 ~?Zk8 }7E~>7!×;W_?G5k{?d-?_h{?d-?_h}7E~>?N<^܇^_Ʊ0?/!p!p*ee7J~_8{r9zӿ_{|4cXxƿA]UFA]UFїx)_s$ Nkc=a?_wW9?_wW9?_F_ DQ~_7!×;{mOhٯRC k*#GC k*#_X/s/✣(gjd9~*WLږ TɩF"Xl=JkV*SЅGZѢC2Ō"p+-<3,V;/"xX8R](U W(*pRQ)L~ZgfW:C}[ kׅOxOӼQe?o]F×χ|E|l^o 㗅tzƟg:fJԿgEÇgEÇ}.k:ڵ~C˱xUh!??StM#⇀I:E~'勺WAϬwWϱI-[|~uO˿?.mi؃7Eqiw #L.{/0Zx[Yѵ Wtq?~pH8ED_鳟 Og#^&q3' qq8x̻Þ!yżK4ox4^\ 4rTs*bc_ȼ&W8#ܗfy0'˪e3SU`2~'9`qXbY`eOxwG<7!~Ѿ#j>:+do[m$%J^izOk|IE2K~Ӿ'gxIvoOC>94۫k3;^%=~"Ya#ҿŞ2o}ƙ 2>"|-OO}7^i.7؇!X70N> z}z (F3O ~0QO,d=`%O"s,5yUZye]ƺJ!8OOxlu\_EkqV&=|G}^8 UV}a(aUㅋ6jӟ?GđaoۯxkW o>)iWKo_ ^i?~cshnYƯx76:[5k~f%iwwYx|5?/ǻi%_$d<9K݀ĆYjJ: i³?4)AѿW )?D52}+cQe "WU#R.Քg'x6M?mwS x/|-|tBGaU?᫾+\Z~~:/oo߲=oimW߲/7|S?g| ?X_ ?c OOoڲYߊ~(|<-O^㗆l|%WiZvm+{ߴ?j~Eo}_>TОWwB-3V'tM=/E77SWG]h ?L%4fQ]/R@״=r+MYҵ4j6sͥ'o&Q*XSYuu䒢J3_MJ ֋y-_mtG#_DŽto+sw~'~7~ 0o?x`؝~jy|!Cn_wAB'm1OxJx_=e|Gƿ:iU/~Cl~ֱc ϧCoog]R~"Ҽ%]kR+Cķƥ40nJNᇛ-h5O[RI=d];N |F/O|m|E༿-X&|Rhi>[,]?­w~!|o Ox?ǿ&Ckz4eA=g\s~1 >)xK#O~Gᆓo#ZUfKU_-.X|7~<5YKsE>]Ĺ|~_T~'~7ݟſ|+# ~C\w?‹^/  KN)t~-o? [ߴo~4|V~|~#L'Pc'kڷ9$},*IԽ֦қ#<& 9ˑQM?{XӒ{A' BֿlSmb讞۴[hcgy/ßB'|{Q/C)Q|#x @?Iϊ?>G_ X,_{߶̬? ''_? _ [#@|?f?|T~ԺljmyƯ?xKo<<|$/ǟzǍI]y>_+>&_Qʋ鵯nWV+nPrgwֺkZ?wMh{⟊>)|'l4 .=)|1~xG_>#1FO_x:>"j=߃>*|-S^2GoDAO+~|(ľ- g%Wh wScqړf?g5oڗf\xº㟆|wſ*[_ּm|89O-ߧ>¿:Heٻ~.o|E_^|{szƃssG #K㯁E~|DO>)ĵVM)Io(ՌN-K^q>{Ϳg;mZ8?_[}+I"Wl|MY9`rry96Njk_nux{_)4 NkKA/Onj.|=o0G4#gk'= /+^>.i |^|n]kLfc.%7?鷚xN _A,mo/naEH,nK־,x']կEq'~ZguoV>1>6t6Ծ!|=OZh^)| x]E{OhM]Y%'Zj0*ҜcMꭥ_܎oǯ xCO|%#~־ҮxLD|Mj5񯈮,[M^ ׼[^HP_^ծ.]Jo{~YSĺ<8<{TxƞҾ$x'Ğu?,N5h隦o"komn}Eoa+{hT986-]跺5+ʤy\RWOK (3(((Cc]~ ~_~0kώt|v?g:U[joIƟO-AuO㇍aW7J .73? ,J| Z4WßMB~!o<[¸i*Oߍrj>?fٓ|?fx]+Ɨ~_jۧƿ lٿ㵅;W+Oxԟ> V4럊Zo(ςx[?~}"?|{ _N⟋/ ,|W|im|cn3Z|/ū<'x7ƟP5?|o_|}>?hǍ>~^,{|9d?wA{o?^0{ Dmo_OVuğ#0k)?ٛd< ךŸ7~i_n5lj>/Vk]m{Aş_OZ% 0|?߈4OH Ú]lwP-<ᕎPOJO(wۿշx*vh S=|Qfώ >~7@{W-x^Onbπ 77X~??Zߴw~ΛCG߅hRীR-j?^* 7OUOBտgp%ŽG~xO%x`yo_"|_sƞ~W/n |wO_4_/C^(t;VLϊ/ٶz%KSoTh[ŏ#]Z[?/Ǎ//W]4{@WP~oV4[32O7k1fj>g@jZO|'O"(ګ bmxQxχ$hߴL~$迴g*| :-z_? 3gMsWkP/0WOO0|'0~?oxڗQ> x3[? |?4 ~xwGߌ?'QO/ާ7[ia п/~$|@/7~(OxPAdxH瀼^Rx3 <kxOA `P?XO $g7 p_gsM{ض'og D ?`OO&YtfwM) Gn8Kş (?E ( _g_o xf''hۋ 3xNY럈/x__W_ _wƯ\ > 3gx>?+ƿ_?moߴ xFCe?e,-5LZGw;⟌ |RоˮG4ӂ][~Lo@?O诀??hD e,#Nq_2#Nq_2??hD e,诀??hD e,#Nq_2#Nq_2??hD e,诀??hD e,#Nq_2#Nq_2??hD e,诀??hD e,#Nq_2#Nq_2??hD e,诀??hD e,#Nq_2#Nq_2??hD e,诀??hD e,#Nq_2#Nq_2??hD e,诀??hD e,#Nq_2#Nq_2??hD e,诀??hD e,#Nq_2#Nq_2??hD e,诀??hD e,#Nq_2#Nq_2??hD e,诀??hD e,#Nq_2#Nq_2?Q|KK u_22G| Ú<]cxw 9Wjٚg.QEQEQE5?u/s_t)\_'SqYOj<dP~3S_V%,F~e`9z+ M_|қRş+1_ ?p?gQE~~',xg#OjiOhH?)[ƿA ~A}?[gh_ ~ |4ᗅuOm/OM ŚΝ O¾Ӯu!.lgyk:ΩykizuK*g|{%^7i~Tx;>tWŞ<=o G5E垩k:]֝iV73O?EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP_X_R0#Y5}_X_R0#Y5}EPEPEPQS6g?/R (yٍɟ_u7?MxGTra5cg?W)x,xa?%7ɂx&Ysf6L?qW_CJoH_><$q_,ݜ@QE (QE~`E:c[bw~|?dt#mkh~*cLǿW9x? < 6KY+^?O&o?+7ȯ?gG42O > 7ߌ?)/.8GƟj' ^ IO N߱׋?c/_ ]ŏޛ G|R,]ORoƯ OFt}{}g+Z=CJC+y~-S hO^uqE5O#fmk? ?׿?w ~ۿ)Cw0|~j)OOitڇ {Wz]ֳqgo:U)s0QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQe,?~#WQe,?~#PQEQEQE5?u/s_t)\_'S6g?/R (yٍɟ_,Y|0$q_,ݜ@QE (W ?"E—|?k ~^?' >$~zYxO? fxx/? |G 0hh]YhLjUφxOo~2s k677Qco躯tO>_M'_I?/|?/'xOFӼ9_ Wß|}{>mgh>д;=/FѴ;];Kӭmlm(kA_)g>(hUdOogxÿ>[^?\~x?G z&௄,~$|2g#^4oj~𞑬xwÑ^gD,]<3??'TPxNN?d/xYy>)|,x+~ |MG{^w~ |9xnP5 #wOOڗQ{>*x⧇7~xgW_.?n:/?O7< :w+ N<=o G5E垩k:]֝iV73OW,🊿ex Ɵ|i gƟOQ7:׌iه-毮^5ӟ4G㮣u~??}?pW??xWǾώ o>4xzΝ? ¾#ӭx>!o4{yghΗyujuյ+tQEQEQEQEQEQEQEQEQEQEWV/Eu_V/Eu@EQEQE6?#S~0O?13T+7nx+΃?>?WQ?A8QO8#XSN?س?ɂ*Ytb6L?qW_CJoH_><$q_,ݜ@QE (QE:w<+ok> :.x/[]K.xBW5<=z 6Ν)'=ψ/4 tx^=U֝|ycsoxYi bYg|Cz\!uM^Sय़GWj((((_](;ß2cJ-O_bW'Kh?ۚ~oo|k1,?f?o ~Ŀ|+o :x~;S^>3 6~ _Cgރ_j?5S '⧇k[Y|')GԴk#^,o@?f*7/>ύ?hz6?x'^#nu~߳t[k_]j+?f? iZ]F\g n' ¾ׁ|Mx'ƞѼYOYӼG_xWzuxg:=摯x]/,MY.SNxn gU(g4Ok>4goڏUxQּeO~> m5}wyx)j?us9k(|/>ߢ ¾=|u_xƞ ox;>tWŞmx{sykt=SFt˭;TӮng)[(((((((((,य़`Gj,य़`Gj(((nx+΃?>?WQ?A#_F炿<#S~0O?13T+7?9?qoQꟙm'/gJ+i?|sg:W1_;gW'g(OB/_ t.?ڷٚ /vz>!|??aoԟ ?|+>GzGYG},Oº3xG|g ?(?c_ |mO&|'V Y,[id? |?G_Vk=Bo_ѐ6K=g/"MUg$YYmko13/ºCgNj<{O7uOxQдx]bkA_)g>((((((~,WUx _ ŞGÞ*🊼9k7|C4-^Tѵ.Q.`Uw߲֣{oK3>'']#NuGxNW|Aj>#㷃:PxU|1OxS4#m?2ot[Dmi#kÚ_"G|E_O_ٚWiCNG-+?o; q.q/fK oI~|NtӴok/<'xPxKO~-^2OѧMumxwÿ 4__!]x] QW1|ψ*sx|^j5^P_91SO~:7Z?hsP_w}?xWǾώ o>4xzΝ? ¾#ӭx>!o4{yghΗyujuյ+s ~,|,M O0|2G#?~ß< /McP Zig`4CLl`|S?Mߴ݄;x~״ڏKGؿY~~JqxC_]7/ x`袊((((((((++ Yfd:F+ Yfd:F袊((j_F炿<#S~0O?13T+7nx+΃?>?WQ?A8QO8#XSN?س?ɂ*Ytb6L?qW_CJoH_><$q_,ݜ@QE (QEV~5to־n|xQ_uA\1'_~5u|MƚOsXOw6h 6U yW6O ^*Ϗz^X&< G]Ӡ/'˛t{?Sय़GWj(((((((((e[T1?hߌ{x/!qoA𯎵oS5έľVN|AZ5摯k7e𞣢; 5>ǂm|?_62 k,/?A1xB]F!+('񆱡gvx{:_ESN}߱CAYy'O G'-?n׾7ƍ wG3o)b -CMzW{~;) !~^oe{M[=8xLRxBŵ׀hw^~??> :ҿ? {<9o ook &)g |k/۾O}OOুn4k_٫_?_ _?hCœ_j츾 6KKi <tVMS\MGRO(7u ZoΩ_\V^ uO>>🉯< ox&]Yw|YY;|=mwHk=R~'Y;߂ >e?F~|-o>ÿzơ-g >t ]wS߬jzu/X)R?#Z+5|EPEPEPEPEPEPEPEPEPEPEP]Ucſς~-}k Mf}_~'?e/_IzwgmW!="GxN)?'o{_Mx y tyAuxxO㷃?&<x'e|=k?i,<^=cxpx./x6VX|'OgO uJ?>7ïfk'1> xsMguoiG4WٚkO}S`ا}~EQEQEQEQEQEQEWV/Eu_V/Eu@EQEQEԿxGTra5cg?WoK(WJ|~/&W f7&Pqp1fxs¾4c>&7u=#AYjγ^Z^ks}}sʿ 6g|{$x&<Ogc=gN|Y_yxg:=摯x]/,MY.SNxoSय़GWj(((((((((((4# ⟈?߄˭_;]oI+OxsHux~*mx{sg> е{;=SFt]GKmmn`)T??????>"sV>o|<?vկEgx_0xD>/o.Ρɀــɀ}EPEPEPEPEPEP_X_R0#Y5}_X_R0#Y5}EPEPEPSR7<gAR (yٍɟ_u/s_t)\_'A~ JŸr8|7O̿6L?qW_C`9z+SBef+QM سvqEW'_[|`||3_?)kod>0X狵m7B ~6ğ~6ß G?Cc>_ŏ%h>h߀~;~?g/~|[ψ?d#>?-m ⏇#W_?xWǾώ o>4xzΝ? ¾#ӭx>!o4{yghΗyujuյ+=#~*xV aFxO&ᵍ9^9)?z;&ff&QEQEQEQEQEQe,?~#WQe,?~#PQEQEQE5?u/s_t)\_'R7<gAR (yٍɟ_g()I'#WTi?|sg:W1_?I& 8gҿߥ7/?Vb ? ?p?gQE~~QE V/Jo֊_ 4𯉼\Hg ꗞg];]Ӯt χ <'o ((((((((((((@OK)4]_o ٚ>Mguoii~Zz}픳KPl&?^~j~ɧAߏ Ht_ZǺ?j~145O) ψ!?_ ^߶KֿcK 5QX]ՇmZ:&n Wx3᧎>$i >L߆?c/_4 ɿbߊ~"C? -5߳~@ _꺥~9?.|{7QEQEQEQEQe,?~#WQe,?~#PQEQEQE5?u/s_t)\_'R7<gAR (yٍɟ_g()I'#WTi?|sg:W1_?I& 8gҿߥ7/?Vb ? ?p?gQE~~Q_Ox⎣9ɿ>c~K/=m_olxV_ğ?hf\ӛE|ֵ/ğP?-`;_ bK?lh_ïZ?OLd>6o~>+|L?gS_-؊߲_o#/ګ\7i^/htox[%*Au~6jo~|]wP|y^!|3cŞ='SW[:iZt]  e-D5}SAwx? AWʿ?/Qտ>&x>}4}w"l+| ÚtJ /xf+-^ \<'_W׆|?Oτchw+ NCx{X5E旬ڥ֝iW67O,M5#umOV x?2Eo,|'<im>7׆~$cO>4Ʃ@xOŞ*|UៃM|4oߴO5G~*OGh ikW7 {W)1Ӟ+.և?~: (~o? WǾ7|u>4?;Ś6? ¾#Ӯtg-4{yy:6guju͍|?xQW~b74u>*m7ae\j5^ONxP~:7Z@/w}EPEPEP_X_R0#Y5}_X_R0#Y5}EPEPEPSR7<gAR (yٍɟ_u7os'\_'A^ ?#XO?9q_ z~e`9z+ U_|қRş+1_n8Kş (?E ( o+7 YgdE|Feϊ+k|?;,6 *N7cOǺ?jgcK/5 NTmb? ms)'Z79k񏇼'mGƞмU?ǟK>1<'-_ŞvѼMxzAm_xO×7R`QEQEQEQEQEQEQEQEQEQEQEQEQEQE^Uc3t؟-g/ۣ#ZR:~ЭEx?~%?K k/>z7? gٿ[>?&mykt/YѵK;;TӮloX> |ig~1w4m;~g|G\!ω=[^i"KtmRN4뫛i&~,W ox#W|U=FEoOxZkڽOُ^uun?'_C~((,य़`Gj,य़`Gj(((m3O?WQ?A#_F炿<#S~0O?13T+|??:8sQm'/gJ+i?|sg:W1_9gWO7%bQ_W4_ڏj|tw|`e?Eg|so?٧X5ψ|?9'kؾkw߉>"|$>ـ~WX)R?#Z+5/%w!0~)i -ƍk5x+_~'yxkWO?ivZ=:'<3c.?ɪk? _) I?x W׿mڿY< ˟ xz5|MOx×3ˣ7><+>gs/M g]|AEPEPEPEPEPEPEPEPEPEPEPEPEPEP_o:o/M?WgZ> k+7`ַ_|F)ŚBǺFڮ?ZgO4!x׆f_Ny,o-l} gwŞ*u xFѼIj]W?XG[O&j??x7쥬x_AŴ^))i>|Q}m7Ÿ u|~txO¾=𯉼 ƞ ,ѴWŞs>&mykt/YѵK;;TӮloX>@[ O//1NJ??; Soj5־0,_=ߋ?Q@Q@|bYK??lg_|bYK??lg_Q@Q@Q@OK(WJ|~/&W f7&~FԿxGTra5cg?W(-g+~uopT?2O0__=~Ε Wɂ*YtbsM) Gn8Kş (?E OoG&a,#O٧࿃>Y]ƿ+NHÚ,ۯ('Y;߂ >e?F~|-o>ÿzơ-g >t ]wS߬jzu/X)R?#Z+5ϋ4jx;>tWŞǟk7|Ci"Tѵ.N4kV(((((((((((((((\?mk_??PhچI5ZU͏ǭ3> u _xN SŚ O%oh?~UxqW|'Jм#m^+x֧m ڏWúw5 G sEy^ƿ% 0|?o/^&4OH Úo<#cxO?WQ?A#?n~ Oj<dP~3S_V%,F~e`9z+ U_|қRş+1_ ?p?gQE~~Q_kRK)M ~ x'3@xsWڣ'4.x~ѿ u?Kk'➣u_#l~}_ bK?lh_ ?|'o;_㻏xƉkSK?HScL|NƏiO5 /ga_)g>((((((((((((((((???s !Z_֛O(h?2ua 5/gdž5E_O?x^*ώ ox/ xzΣxO^mx>!l}gghΗykz0E*k aW?`χ|VA/|&*o C/SLc[?Om6X Ӽ{mT$|?~?h~7ؿ &gH3/~ _g Omڿ~wm;Þ|9?3hzF HmKӴ: h"f )M_ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( `U 'w)lu'Q|'][9z;_|nj|CsG״ԼMt|cy/x } ¾=|u_xƞ ox;>tWŞmx{sykt=SFt˭;TӮng)[ Y&!sKO''G㏁6~ Gm?Ş5x7 ?WQ?A#OF%O~0O?13T+rrO9mbz_I& 8gҿyO0__=~Ε W})!|YaI&ㄿY8+P(gtxW.|AgxφuK ^U:]φ|u]gÞ6_ ]Şj+mx{Y{;;? m;RO(7{^ij w,g{⫭;B.:ֳ?xZ.]WxP5#^#_Ǻ% lW}W4&sw_elW*k3Əv-ko?]oX}_L|yE>|AĝJk_ |)=Ln++ Yfd:F+ Yfd:F袊((jN? ?j<dP~:Q9 __L?FoL ?E/\'dr8Գ 5_?2>`O_&Ytfo6Lq7_C5JoH_><$q_,ݜ@QE (WQO ƿxk> 񶐿?eM3j>,|s0xC'?4[mK\˚ xnx<+k?4/xW񵟃5߷-'o&xwŸ~7a k&xC?VᯋE{/_UZOP/꿴d:7-Yijࣞ8?lCo^_ mCd_Y ź7uKQ[xZŞ1Vӿ?~]E& |;? O/?hߍg.\zG/|!~&Q|axG^#"347z?1||Wƨ>4xWW39` cVk CĽ ~<9׊>|:toP¶W|7h^>E1QI+%;4K G?>wP2x⟃|'K/λXY^Ÿe"0FB &sQ@@YE& c\W^g◁>|,▻/eK/5o|?kj5 C3Bҵ=be4` ">? @xs_2'~O/ O?tF~ W'%o o_*hhD楩xG'"n|?MAmgvGΧVSyEe4Mq_y/°&XEgxo?(ߌG cO|9Y?AZ|y?|,w˨xߏ2׋3}1QI+w{¿n߱ۗƹC~~ƿ~8Ik~Ӿ ߇]saA^^Vc;ៀ4_A#V7? _o+d'_᧋>)~&|E'2wi{6':.ЭflEe{kP1QI+fxmOM~3_;9 C7&o##[Cϊ^"߅| ? ~ٚ ?k~m"+,>>ޝMW?>Wm @>AVZmuڟƚ7{xWSf _~~ԺAo_!N?I>db(W _o+?g~>|< IO >5;Kec7¿<t}W^,Agkvͮk:u6:l^Mx OgO|ROMG/OeM*~u/|:ÿmO.u ][[$ ??/i7Y|9_xG<{>u/𭟊izu3yx/6 h5ό|c? [KhZBjG INa `@ _o+3S>-ϞᏈ߲_Qo{_ fߴ?;Ǟ*xO/jO>0~_O߉_ǟo|S}o =c|Y G$ki@5 x>#k? ~οtoЧŏ_~7?zgxñx1QI+;G5-K/ >,wO2o?xC⟌'/΅XYexG"3M> ާs/Q@@YE&򸯟2>"A A@x_2W / O?u/I W'𯉼CO=:Η_ V^4t:~׉_x}>1`o--!o5K_ ]O[?G?jg/&|SOƏ >-P~ʺO7+c}7OMwR~9_H _o+??/i7oOhVn|-W4ψ>kh7?g/ݯ|W&?o Y?ïk>/YI|;/|= OR^x~ !xP~1^?⏈ ?:*O`|?m ??/i7Pf3ïx9 $/'P~fJ~ C[b}Is_ڿoe4⿥V?|ӿi*~͞oO Q>2L⯅?d_ ~j߲?[xŸ|c{4o1okO|B)cP|,s|?e@||:o~;x~<++ />eo/ƙ{?i+/_ i_Þ#&3ه /߄`sf/"ciU~f|MG_Kbw'NmoE| Gh|A6 _x6_sxO ~*|+oK>1?=<' SH[ڧ|ihZڥGmk.y_WK¿6iK? 7xW4|uNj4.}+g#ԟ~|f6 ?d|+Ϯ_|CM_sNo|J~_@h_~;o>|?O??,fǿϏ~#]Zƿ?g@oZ/x>_2sG?Þ ( (?:QC)WQ?A#_F炿<#S~0O?13T+??:8sQm'/gJ+i?|sg:W1_9gWO7%bQ_Q@?৅h?z/ $dkW|-xox3Ǻ6 [h?OZu|{gNJ|%# ~|1qi>G~[񗌼MPEP\<3x¾&vs =#Ş|3^xOŞ*twN|3>AԲ,wt/xsQ[mcΗAQ@0|+⯈_Ugx5kGQgQ4mkz?M⟌?|Qk3|BumoмPEP__Jocg߂ſ? O:&NxO ~:k>*5OxCo)|h~ʺ'P⛡{ (sEQEQE~pj_M/~ZgOs|?g7 O ?ǀ|'û|[?<x~=#~]x4t|6!'((Qk /7??7e[>27Nk?|UH5M!/(|Yg_ |h?` ;%<3@r^+ѯ+6þ;5꟣P'[O >|[/-u=c[w9O:ψ _G?Ou]OX?ڵ=BYe (hڏ+oh,}{΍vWSNglux&-cF񏃼YY;hCwHk.렢?8> xW|g2 rx>%W.xg^)Ox{>%Vό{~𿃾wQ΃> NxWH ((gtxW.|AgxφuK ^U:]φ|u]gÞ6_ ]Şj+mx{Y{;;>oxVfړGcρ?lfNN]_' ~̞;?ss'kmFk)<GO ϟ ^#~x'~ t EQE5?k7߅ύE#U'|wN|:χ-߀n|]s|PA?%W0=z?Wǟ>-@)|aI o㿊;'>|''τs/φ?43z?xO k~2񗉽(+22j/m?.~ |D ?>1׬|RYwᏋþ{M? F4[x5?ي*+_>0~џ>&xM\ zOgx)ws7-gQx= OEQEQE5?u/s_t)\_'SqYOj<dP~3S_V%,F~e`9z+ U_|қRş+1_ ?p?gQE~~QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE5u?os)\_'SsXOj<dP~3S_V%,F~^&߲_ x?/'oΥ#7N!o[{h+k}=ěD4O|s_!|aφ7?9|:U+ZIԜR U_Gtz~? 8=e.kWxW_xW_᮪tO^^~H'?]rnE;¿B nE;¿B uTQڟrc/WxW_xW_᮪=oSX,~t_q |4} |5QG?jrAܿ9_|s_!|aφ|s_!|aφ(O^^~H9c}+S+/?S+/?UE޷,?r/~w>>w>ꨣ?9yy _E۾9N0G۾9N0]U{z//?$Xw?)hw?)ko[~䃖?]rnE;¿B nE;¿B uTQڟrc/WxW_xW_᮪=oSX,~t_q |4} |5QG?jrAܿ9_|s_!|aφ|s_!|aφ(O^^~H9c}+S+/?S+/?UE޷,?r/~w>>w>ꨣ?9yy _E۾9N0G۾9N0]U{z//?$Xw?)hw?)ko[~䃖?]rnE;¿B nE;¿B uTQڟrc/WxW_xW_᮪=oSX,~t_q |4} |5QG?jrAܿ9_|s_!|aφ|s_!|aφ(O^^~H9c}+S+/?S+/?UE޷,?r/~w>>w>ꨣ?9yy _E۾9N0G۾9N0]U{z//?$Xw?)hw?)ko[~䃖?]rnE;¿B nE;¿B uUohg"յ k\ֵx oIZ&4rCisj:~ꚥ\Djmﵵmdm$mv.Xy[G?|uqҧ,7|BœqaS2*|J0xzQ(BQk xw)_ѥ^ש NQY8\ի_S"Qn#O>"Rn#}S:sM_G7 ?M_G7 F3A[;'z^Jy+DGADus߂j<aDπQj<aDπQFw?kg~_$ az-3"Rn#{S:"SmG>?|莯vW &|vW &|CgwR_ i^_? ?%?&i7?# |莯vW &|vW &|F3-\,oi4_חK @ڃ O?%/&~Oa5"gO`(a5"gO`)06ѝZ9+5L7O~JMo GRJ_M~o~ GWw; H>G; H>GC_ ŭԓ|@vaV^߁a)6]#O GR9O NO'_?&#L ?&#L /F3-\OEҹ^_e(7?O'I)7?P)_?&#L ?&#L ?F3A[;' ^Jy+cPԟl'}S>sM_G7 ?M_G7 ?}-l7 ?4t[.Q_/G @ ?OK @ڃ Oa5"gO`(a5"gO`(ak;/zXW/Q_? %/&GAu/DG?D}~ð?o3'0ð?o3'005ѝZߗI<]\/Or0 |莣"Sm'}S:sM_G7 ?M_G7 ?}-lO|@ il/E{? ?%?&i7?#%/&?j7?#;y?y?!ѯI__]\/Or0 |莣"SmG>|莯vW &|vW &|F3A[;' iw^_~J_M~o~ GQ)7?P)_?&#L ?&#L  >gxwRO' ҹ^_c)7?P)GDGADu~ð?o3'0ð?o3'006ѝZ9+]\/Or"Rn#{S:K @ڃ Oa5"gO`(a5"gO`(^}:;vԕ}w-p?_"Rn#{S:K @ڃ Oa5"gO`(a5"gO`(ak;/W\/O~J_M~o~ GQ)7?P)_?&#L ?&#L  >gxwRO_>z+?s߂J_M~o~ GWw; H>G; H>GC_ ŭԓ,oZz-3"Rn#{S:K @ڃ Oa5"gO`(a5"gO`(al;rW~V>z+?s߂J_M~o~ GWw; H>G; H>K!ѳW;/]\/Or0 |莣"SmG>|莯vW &|vW &|C_ ŭԓ@ i^_? %/&?j7?#?莯vW &|vW &|F3A[;']Op?WK @ڃ O?%/&?j7?#;y?y?!ѯI ?Zz+?s߂ aMZ|Bni;Y x6OUĐx-%%⇊m[wVmeEG?&#L ?&#L 5Ѿ?>*gy.[Z\PG|@valbwugY_잟ESFE[¾+|; x+ᷴ|Qη]woŚ-t}#Ho (yٍɟG; H>_dx_G;wB!i>/hdž }+Bt-*Kt-Kt'Ml-᷆8 set_column, set_columnex

set_column, set_columnex

set a column in the lp.

unsigned char set_column(lprec *lp, int col_no, REAL *column);

unsigned char set_columnex(lprec *lp, int col_no, int count, REAL *column, int *rowno);

Return Value

set_column, set_columnex return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

col_no

The column number that must be changed.

count

Number of elements in column and rowno.

column

An array with 1+get_Nrows (count for set_columnex, if rowno is different from NULL) elements that contains the values of the column.

rowno

A zero-based array with count elements that contains the row numbers of the column. However this variable can also be NULL. In that case element i in the variable column is row i.

Remarks

The set_column, set_columnex functions change the values of an existing column in the model at once.

Note that add_column, add_columnex, str_add_column add a column to the model, making the number of columns one larger. These functions change an existing column.

Note that for set_column (and set_columnex when rowno is NULL) element 0 of the array is row 0 (the objective function), element 1 is row 1, ...

set_columnex has the possibility to specify only the non-zero elements. In that case rowno specifies the row numbers of the non-zero elements. And in contrary to set_column, set_columnex reads the arrays starting from element 0. This will speed up building the model considerably if there are a lot of zero values. In most cases the matrix is sparse and has many zero value.

Thus it is almost always better to use set_columnex instead of set_column. set_columnex is always at least as performant as set_column.

It is more performant to call these functions than multiple times set_mat.

Note that unspecified values by set_columnex are set to zero.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL column[1+3];     /* must be 1 more than number of rows ! */
  REAL sparsecolumn[2]; /* must be the number of non-zero values */
  int rowno[2];

  /* Create a new LP model */
  lp = make_lp(3, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  column[0] = 1.0; /* the objective value */
  column[1] = 2.0;
  column[2] = 0.0;
  column[3] = 3.0;
  set_column(lp, 1, column); /* changes the values of existing column 1 */
  
  rowno[0] = 0; sparsecolumn[0] = 1.0; /* the objective value */
  rowno[1] = 1; sparsecolumn[1] = 2.0;
  rowno[2] = 3; sparsecolumn[2] = 3.0;
  set_columnex(lp, 2, 3, sparsecolumn, rowno); /* changes the values of existing column 2 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_column, get_columnex, add_column, add_columnex, str_add_column, add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, set_add_rowmode, is_add_rowmode, get_constr_type, is_constr_type, del_constraint, add_column, add_columnex, str_add_column, get_column, get_columnex, get_row, get_rowex, get_mat

doc/Scilab1.jpg0000644000175000017500000014173210252627126012262 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?r~2xWE"EO|@5(M$kgن7)Ye,x[iKb/eӾ!1*'ğ Ƿ Cj a1p3%h|ɷh_=,X #Vl8m~6x3nWm4v3Wl:NxHAeůgJgGYd1yO.0S13*G+Y3*fP5OZ4GSRmOQ}. V#u:ff/icj %O[_XZhWZ1PONrI9ÞӾ,x]/?jZ4xJVUwٷඳxwy׈^|x+ _/%c>5VផÚf{#?!|amgOMS;%?|"I",[*bf\U 5c */ux-g~]^=Yhi⏆ |=_?f:?E!ߎu2m/{# ]ox>1ƿoNM;἞*?ksúǭ7 >]i?~ܿ \KBV,n<`kt+%OD٘\֦IW Ja*a0S]l5JR,VrM?ȿ]^=YWba{>7xK^?kgoO/x=O_ CEҾ<, / d$t kwf _yF~?-٫Vck+Ro uߌB'iC-9f|cŷ|||u6RgſWKW_~2x~>%kÿx"?GXu/t='c+L]7 |n?j/zǭgxSDv_ 7h61wIş[>xC?ľՏ_Mϊ2>?lО"~j>'uC+NZ_=S௃.->o _Fk^m`\ge\8Ye8|t+ӝ:7`iK QV2,5yH/s,ElU:x|>ykm||M)ɪ\=+Eco|8|'?~U?>?xo_~?IyQ 0Y^ g|xH:'tdh:Ιៈ e0)-b>;Zn7 OwVe-|#`> x{D˝_č3N5oHw|5wgh NcNEqc C29NW%Tb`燔*`U=LkP̡1X//<(͸6r\Q Fx/-XSCFTQW ,EIaW^?ux-g~N4٣oO5!oO?<Cÿ &=DŽf=g?9>;mL_ /o5O ~/ lL'x^[73 Ou/v]>)t迻o_"sjuzy'OMi1}>Re~N^qCmC(j^ey}_nt}J_Osw`vӫ痧zo.ůP?ux-{ڇ&W}_WG?R\,]) 1k6?2]^8^ɕ_g<|7Gԥ>i1}> i}:yz~>G Z LW?b׿mey>/#)Ϛ}?Oe~N^o/>*~'xžiAoxgx k!Op&3_|IsFek6v7pjV:3ӕȏy&#q9\ϊ8;TIݜ^2~x,yr-fF>a}H$ f$_bή_K>; <(acqPі/xҡ]*SbqJuVR_yi`'¸jc[_3UJըKN ֆ3()4RNV_/y⯃ş_ 4}'ſ<);}MNߍ|)ǏGSVHt{OXůM}ڧtkcɤK|c|51_^t{l=[៍UO:ǥ6uk 7χ|Wg^i-;nsbmG q׉|6`rLr"Ͳp:K(UCx5<ۍq㉩ڋ}kFIpLJ>b1y&exisR?)cqn8|YoNK,EeΫ{*7Q~ih\["g@B9V0< dLJx|Qu'~)75/-~ ~6x~-|`G%񭾣jՠ9t-K[o~(|hO ?iOw7'֭8Vᓬ"OS0jn:qL?w⯆OU$kŁl [1u[e;VXд#Suh`ZaSySoC~?Vktizv{5be$UiRuJ+Zpq0y>_y|Kx|7Kę|uγxSp V}G eas<__!x[>_I&Ǟux9~H{/j>|~%h7:_ďkFĺ>NytrXt_))#M/!o0|&Ug$q4x8gXjXJT0Eʎ8”,|ÿʹap9v"xM\*[1FyNjJ#cCgyy.Cflk:/ muN{ædkmWLG|x|Ulc4[G.\t$`O},sGW,+xrܿ$UEW[?V+N ̪SP{*5~3>\).'¬\9ƹe,¾gs,>3je<8)U6mqPbZ8::_˯?t+>4|` 1vsEMK/"+>yE̷~037,nnmvكɇ.> :VFOC#~<_Z_:_R|A_o=mCyƑ7|K~̖N:~@o'$;?(9+~|k.N-fq; Ui}'%Sc,㍳ s*ن3xk:X^9beu_r >|9`ܷ' 8 |V+xtr2o.>ue+b+ҡ&IW5iЅt ࠰|?~ zD>>U?߈<'߆VFmj{^w><~G}C΍?7C 'ax^o7 oS 'Oǟ|PⱫx=~\zO

?f۳]ckE՗k+կisg/ITZxy{.^$ҴuΟ9i ?_Iqo|Em8^x'_:Gᮕx~3k?H#L(x1_o):Nf^s7ğ_<*_FQxc_OJS.O\' Tgaͩ!eUVbRz{&['cxM t\r|ӄn3'2,Za u0UhT8,n:&Zx?? h[? Py,_5¾Gϊ|6>)|i[x+ mO!?S5gTg(5 ]S. k'G|O᫝R+Bon.&]6a_O_|??#L*[c%%|ExQVCO g_8|oq&wq|5[fAbb1uJ՝l$nqH%f<1Ǜ<θk B(iKraX~RmXpRBS{zE|A*&9Ӷ6q95 <*_FSOrnHg~H(WZ} TĨppޛ5z7_ߓ???G'?wĩxB'$\?rz7rG-~M+w|QG#<_hw|QG#<_h}bo7yJ_!E?G-~M(rz7r_w|q3w|q3G'?wĩxB'$\?rz7rG-~M+w|QG#<_hw|QG#<_h}bo7yJ_!E?G-~M(rz7r_w|q3w|q3G'?wĩxB'$\?rz7rG-~M+w|QG#<_hw|QG#<_h}bo7yJ_!E?G-~M(rz7r_w|q3w|q3G'?wĩxB'$\?rz7r>'Q8$I3<}y<9/FxIQ~?I$M~Я:,GM 7GȰkm }S阾_"EL'3x2!WHeU $үh[_į/I5Cӗ_yODF[_~;^*(?W4}-TW*^<Гj/L<51ȟG#Q5 ;^*(vUG?mQ $үh[_?Ty& 9N_yWj/c?ƏF?kvUG?mQx2*H_>!R_ĩxBLOr0_"EL'3x2!WHeGT/GJO|CoR.P=9a_OmiOq_exK O|AO~&ե5xH_]vD>j4T{= c'? 4|5~> Ӽe Լ6iz4-p4/~;֬5y]^\vf4 Ok߄+o:3n5ʼnnƍOMӾt@7_fXb4aA57 ~(QW'Qˏ5,_䙛 +2Zٗ e½Y"`՗/t)_~0vASqL.o**411`MJxn]׈4J%6Ioğ"? 6KkmY$+7`gEm6ѺvΊ4ʊ $mxwJి'%@ֺ''xsú=-iZ&L|q<Ӵ6M,K~;W}3q hV:Uݴg-.VILӠ+;-^X-ed>S뷰h Ⱦ|GMj qa}rǞt$^mU_v#3ڌ؃^-+c6e^EicjbҙhNLfT&Mj.bM?sTLޞ/#cqv. a0?*FHԣ^k,:TqL' p</lkf+G__*TJiBpUUKit"[^?,| x΃^n.4]x7Tķ:ti#^ k"AqC RH~|XLh| k? \j Ծ~|Qa:qK,5ׄ|M\IyjP/LU躯2k+I}/?SW~߳:oiQ|/|"f׎Iۍ#|/Y7EψwU5C6OoC}k/h͞g~ۻ3SƟwmo//kOڣ}(7|&7~&Ѽ#W_ؓ'n|CVizgK#|5~)m|bqSQk8DE욶ڴﳯ$WZf_uxKN!-7i:k{|75| I e-Ga=?do: iYEevό{,VhO9/[`x9 ⏆Qi_ov&?í#Eo O7>]O? |/ǧ.Z&&:m?[{k5UL-H5dҌb+$*Kr4ۜ!OG|Jw|WNj:Ҵ-; ~(L1h?k jWx7:Ki_L UƟػƿ,f&|cam?l-kӯwq?vh4m_goڋru_ ?e~ xO [kiZ#kx7:V RKs({*wy=%iIs{;?rM9&{.׽WZ/|; GQ>QWu}_C.k&|:oi і~:W|#||%aqM[e^"?Ob!W-௏ ~Ɵ]|__P|M~zƟ^x_wE6qFO? >\xOšOt ;^Ν_ ^FxE@WNӴk?i۳Ⱅcjr|Q劻ZRru%In Eu"m㯕{=Si~4rogƞӗZ~?_~4?_w@. Ke?'}NPM Gi~ѿ7^x?4_^ t 뺯5}s<=:VSu[J쭤ŭrigv[gO#5NIx7#|-rǟz-QPf&Weo*Yo/øxnQ̷vo<' |+x*H|9h#OxWxs++ K3GįAt;I|ensqW+G&y#vr-^iT㇨v䠴oTm7e)99wushWGj-4?WmOc[}Ur/5sG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsG̊+_{ o[{h5_/_xsGɟ-Oץ?i?k_m4}Z Ouj6%?2kaM~"Hs#s0Q@ $cI$$IMfeQ>9|gEW4]|-Z>m?+ٌM/ 5??~'}wcoa~QH9Ca#*Jd)@/~&k |hVЭQ|Mw5;+?x~5е5㙼 ?i>=wC߃`ӿ Rֿa~8_B|EB ? x?ſjE}[io~/Nc*Mxkiӧ '7iP|rRVmFKloUf9+馿'{⧉_>|lt+j8~B5džl 2^߂A߀t-?o]C7Ii"?lsVNW쇦=N{?P{ 1$O__ k˻GZx|ůBJZODŽOP?e{"w/9>+xc'xߏ &Mhߴe|cQ5j?m_d3v:5&iŪn4{I&MiMZra$|Z_WӲeu01|+5_kGǟm3k&桩YǞ;<vGM_O|9x/&k/ |h IЮQM 4+x~ ~qд8Kiw+ uw |C%~O>H~ߌ+<k "뿲?^c#Wh^!u|[s+7ß>\(i={iůB?i_'_ |[P1,|At^~+xSY4=wǏ>Kd^Ѿ3gww8nnuٳn"[{LJiS=xg͵0oEn_\kV1Mo]~Eι\Mx+Ctca==F[['/5\M#g'+FxYρa_Ҽ7k^Cž:O*Qԭ7ڶ?|Y֝aw௃A_m_d3v|S/G:U5[);M/07 |K𷎼S1xᮭj2-?Zx7E`x3*J\G/Nsu*Yɶ쮗4dKv|a~ezrߵ_ [OC>Ś7~|k] 7+⎇ߌ 6Ӵ]Co s4|-iկ٧Y:g|;4}w=X>]mw)Mr迖]QE}qQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@^Dc^~ם_O?hk?^Dc^~ם_O?hk?C-ʿ(x]G ٻc Ri>6| ~ xWF\x^_i:OSAq~/ߍ;j^ R8?|W]Z}Z&eEj_zƿ??57ǝv?MV\[Kyt?J28N4p? 87>x-vvIx)YS(\fa~2efxN~|(s/G|^N_/|/+BҿuWSֵ/A[Qn|ˉo?dlOBxOz? ~_ZD4] 㵞xwF4}z i7kt ;=n[5/j+/JNQ[$4n޷]%It}JʟwxŸڷu_70J7[r]oc/LΝk 2_uNx7P=!~5?<5=㟁 >oK|5𽗁|lj_ {Jд]wUK6}Vo6i?khI*R')s՜kK+$QJ*$ M++/{ח 2f=]Oo/=[Ӽ-˫7\ޗ/%$z$)5X6 :֓y⟵ߵq/ρx?ڟR?40/O-[E| _ |uT-":)K#?dO[[4 Nסߤ~ڟnxS9|_VWw|Aj𾓯Ki^ЛJwqY7~&neߡ¿ _,MLC9ie_QEEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP'Q;X׷hun<CZz'Q;X׷hun<CZP? rJ Q'Tf_nOixN~-ͿӵyW|6?Zt]N ~+g 'nq\@QE(W/3#;7Bc??~8ß 쓥N:xM"~>3 q|2OȺT᭄Rz?+*W텡~ßf_ ~>xƿO?ڣe?ז~ؾ8QžO:蚟~ s^Zê|FiXI>*x/b؂W0h |KnZg#?|Eh] L?(((((((((((((((((((($ f:9$ f:9(( (O:7 Pg޽ (O:7P!i޿kܩP𣆿On"33 9Ab5yW6?ZN]M~+>N??4l(R?R (/?f/`>~ʟ!x|Qa;+s_ sş<)9w`|%D~]X~WW Gߏ<OQ_*|~_f /?Z?-_o~ x:Naxֱ?^O #|A_8Kc<{vuvgɿ|w? mmEi^1+: (?aoۧq> ?eU^nڜVwN7ߊ^_4t}gGt/x/]WxOŚQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEwQe~wQe~QEQE N?_Z'y xRlǟ/y/ß?೟O_ 4?Od~ʟt+߅o2}3oz<oWҵ;?`(qˢf>,xw0xώjw ,'͎=i,f\ݽ?77m;^_\ _X( h?5ϊ{_XiچíxᎹ=O7k)3Q>|8-{eh?>dW|M_xfhQ5H|?|Y?ڷ|e][YmgzΩ݀ 毃_~_?`nt7oׅ<+㟈Z"_A_v ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (>N,`ÚN,`Ú ( (?!? D#;p |? D#;p |֟([P?:'k2_nOixN~-~k; :mPص5ƻ~)|WN/?4l(Q?R (S M xMhi|RzyGGͩh<#`E7/^nޏaFuلlǟoKu௃g? h?_5s߃.x_W~0I5/~ (x@Rǟ>|q~? |Kᗊ?^Ob~ʟ|;axz_#Fj53P.+"A(sKXx|U5&_~~zƣk/Vo^xV֯4wyxJ/XxsQ/}Ɩ4_W2?㿌JM:o|AGψ,M''I;:ߊ iyk״U>&> |S> j__h?*||M_xfiNWмAjz|Y?O'YmĚ6{Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@'_M?0Y}_'_M?0Y}@Q@Q@^Dc^~ם_ikO^Dc^~ם_ikOC-ʿ(x]G ٹ7 :mPص5ƿ4IAbvp+})|V].Gᓏ7yG8[. (OԂ8 _W@0|+⯈_Ugx5kGQgQ4mkz?M⟌?|Qk3|BumoмTtw_f Q@Q@~(૟wWR*о?|u{;| ]\oj?@|-Z=cQn|?W/6?g S׈Aς@Mό 5#{xWA4t.]7<7_W^\Y |+?_ 4~_woOI.|h;n?&un#|Ytl?x_ڇxJ=b;#^^^x&Ӽ9_i4~1x(((((((((((((((($ f:9$ f:9(( (O:7P!i޽ (O:7P!i޿qW?v/7Y'@~f_Mjf?ӵx6?ZN]M~+>N/?4l(R?R (_> oH|?7ş H|S࿅~1>,x?i SWj>' Y/};F=_^$I_>,~i/ <3o|9>Y#G5}W]y3i>5x_|9dg97sX~! >$%0|ySwx g4?mG֫u')ٿ?g(((~,WUx _ ŞGÞ*🊼9k7|C4-^Tѵ.Q.`U5f*G~ a;_-ƝX0gxf^ax*βof ŪY/~)C ?__ VO+XY/`e?F~"-> x_ؚơg Ե 5] S.>iu^\PEPEPEPEPEPEPEPEPEPEPEPEPEPEPIEO7us_IEO7us_EPEP'Q;X׷hun<CZz'Q;X׷hun<CZPW.ʿ(3u7G4nr?iN~-~k; :mPص5ƻ+g 'nq\@QE(~P|lej?*G㏇|AZ?g> |ZԼgMfo H?d|Lּh o?{~7W3ߴg_|5Z/ǍwAokWG$ĩo 5χQ?τ >g?l>|???:[|?'eO"#=7H _Uu?>Ƨjw^m/)ٿ?g(((((>;]t^/įfox=ǎN/^0_ _h7 o ?XAhWZׇ>߷O|P~33Yѵ8t1ޝkcso3m}+¿6/i}Ώ^4^⯇*5Ư`(qˢf>,xw0xώjw ,'͎=i,f\ݽ?77m8h%6x߉ |7Hƿs_/XΫ{h'0|?'GïZ]?i ( ( ( ( ( ( ( ( ( ( ( ( (>N,`ÚN,`Ú ( (?!? D#;p |֟? D#;p |֟vUiAw3?79B~f_Mjf?ӵx6?ZN]NJ_3?ᓏ7yG8[. (OԂ+Ecg%?ߌ¤u/xsDW<"+Zg?l^Ծ j3~K?>;>_ۿ5yWg$.4x`i_SJxWP> Sºot+XΡZg =#]K=FNt魒Qoe:77@4QEQEQEQEQEQE{eh?>dW|M_xfhQ5H|?|Y?ڷ|e][YmgzΩj5nxWs o h_ |{} gvRx#_ fI~&q]xS¾9M>- 5.J((;|w k*k?l?N>kvx_J_!{[=;*ζ񔺏!GX׾8_UxxOŞ|34O 'y?~>gŏ|A<h|R,&> |S> 44P|k5>!x׆f_Ny,o-l} gwŞ*u xFѼIj]W+?/tH_Hx~%u-u5;עy{|։G^wc?>;B҃?Qg4?fnr?iN~-~k; :mPص5ƻ+g 'nq\@QE(Q@/y?~>gŏ|A<h|R,'-|?|-|`< gĝ/ڇïR~e>x+_h4 EPEPEPEPEPEPEPEPEPEPIEO7us_IEO7us_EPEP'Q;X׷hun<CZz'Q;X׷hun<CZPW.ʿ(3u6~sCNgf#֛O4IAbvCӯ&ߵ__ik)Kp2q1&(eEWWCb| dg k Gϥx▙_g)_٫!?`ğ~6)O/٧ƖmOğ< xjm/Q@?Wi_l-w- 2|/s5) ,lxB:LJe+A3D<cÞ :/?O7< :w+ N<=o G5E垩k:]֝iV73O}d~G:/ٗWu?7euqxï/c 4mڅ?, ϋ4+kß |c?aoۧq> ?eU^nڜVwN7ߊ^_4t}gGt/x/]WxOŚQEQEQEQEQEQEQEQEwQe~wQe~QEQE O[Z'y(dֳ^ =X׿ohu?n;CZP? rJ QGT?fn/ix6?ZN_wu$kk;_׍v8?)|WN/?4l(Q?R ( _8Mg?l?_@o 74jo6} ׋>,|q~t3S}bPm,;ou_ Gunooc?h((((((((((h'Gڃ_"<+΍uw5|-k;*α}COK;Xѵ;B @Y+ #_<++x7OsyK ;PӴ8u14ǶFqVz_|B¿ A j:F\X[\[i"Q<';V𯌼+k>^oY4/!/k?k~ о;:,?Q4E= QG¿ΓM\|s ]|[1|knEPEPEPEPEPEPEPIEO7us_IEO7us_EPEP'Q;X׷hun<CZz'Q;X׷hun<CZP? rJ Q'Tf_nOixN~-~k; :mPص5ƻ~+g 'nq\@QE(4??Vf/@u|COпaύ?/?g#y|S೟NMy? ~%4+Tş x_oZVh|-F{hVvZe::77@4QEQEQEQEQEQEQEQEQEQEQEQE /ƿT~ o^m|UQ`mkj摮^/4/ E j>|9e⟏xƟ~6x #?c~,|+x|iŞ;~g|G[k7|Ci"Tѵ.N4kV+?qc_8k}{ik~ #_-{om 蚴>w'_j__h?*||M_xfiNWмAjz|Y?O'YmĚ6{Q@Q@Q@Q@Q@Q@'_M?0Y}_'_M?0Y}@Q@Q@^Dc^~ם_ikO^Dc^~ם_O?hk?C-ʿ(x]G PxuRԾj;?eOeS_WvVV"?/+G5EZgWۛX}( ( ( ( ( ( ( ( ( ( ( ( ( ?QW?h$k%_U|~Zw>8NO.!_WP[KOҵczƣi*⯈_|mE? #W ke 37ě ß~j7SG>6?i ]ֻoxoľ#& W~hh➓\w#M ~H~ 𿇵:Ε/x"1U"30S|+g4 9 i|{zwF{HUMSW|xs|ib8=EPEPEPEPEPIEO7us_IEO7us_EPEP'Q;X׷hun<?k?^Dc^~ם_ikOC-ʿ(x]G ٹȿ/?3ӯ&ߵ__ikN~-~kߧ/Ɯ_Q_'A_?y\~?~5xA>~ <PL?j_ o>2p~|_7ίt O zį|]W>$xW_s>犴o^xg^6M?xFӧV_j>~ m?4? j:<㙾!`L}\q猼G 9dş | ▥W߅*| -u0|2۲_yZ>dx-WB?k k_w> ռAuS>x/_u/_iV}mCt"FwZŜƝiV3\g?Gunooc?h(((((((((((((+Of ?k i{Lƽ3߆!u4gCφz^7 K^)L.W.)?cۊoK+ß?G߳/<eYj7g_b,!}ᯈAᯆ^  ~,|,M O0|2G#?~ß< /McP Zig`4CLl`(((($ f:9$ f:9(( (O:7P!i޽ {o??C/y_?z(]Pg8lG7ioڃůٯO^5_Mjf?ӵxwӃR adcMQcN/ˈ( (>%ss=7<gSSnu_~M{\ϦM#oGOV{U@tw_fxz~,ࢿs.Tk>:kuw_6i_ƿ6:xxŚvsv*D#|8PEPEPIEO7us_IEO7us_EPEP/Q?X׿ohu_n<CZz/Q?X׿ohu?n?F_!g޿qWv7V"xN~-~k7 9mPط6CN]NJ_3?ᓏ7yG8[. (OԂ_ٯ3Z5o?/_t *Լ+z׎CfXt"FyoZ捧\j2[C}->^go>8,S▅ G/e//|@?h_>4i ?OBtbj5 +ؠߵ_ß_g?~~=/~??>i,j?4-?f]_ 2ak? a_Qg+7> F/>,|,~)|/<3o9">wYw-_G4WB kf]yWW0Ef(> į|hF|d7p|T~'~! >iSiZG.akt/¤XH??h|tci? 75 #?5 [O#_ MKP/(ޑM?].^hge׆<;mh;>/5}wU? | Úh_Wg□i_qgo>8,S▅ G/e//|@?h_>4i ?OBtbj5 +ؠ(<9O.  )i})7_wZ^߇7d2G7_{W>xs'|t?_okg'!_lH?#WWxo> x?<]kw KCOX_zω5 wfee |^ 4-WL z+/iz=># Oo?g[_!_؟h#/J#ׇ+eOKN>3?{=jPо7 |#o=b/|`|Eп"$^ PcH_Yk~"?{7o4~2ק_gO.7/>ϋ>h_~|qiUQ]wPOi@Eχ>?Sd)_-iW'wXH'Mk}@Eǃ~,:G>8@~)|R?J|4)e - :gm_Gg꺟P#-Ow/_>%@?7E[/?߇}Cú'i ??[G 2Ͳ_(???_ׅ'kZ,[}YxvO|c+&˯S7O|2fGJ0~:kb?Ojڟ'/? oC 7#dxWM~?HYz|bYK?`L5/%$W wφ>_2? ~xgOX'i-CW#OWS/OP{}>N,`ÚN ,~?G%?;k&>xs9G [{[_?/o((_/7?/C'w_z_/?wo??C/y_?z_&$Ľ;ž?5~((A)7{o?{/_Y G߲?O} ImX+~{cw/֡;#DW_O4O_&Wo((Xি7{o~|ž0~ 7&>0xO=? h쓠x#Ts⟆8 m/ÏX?qOg?e_7_Ɓ߆?/؏º?_~z}kொG5>04|rx^O Oߊuׇ EQEQE_d~:]ß?o5_߲ |Bh~1>XW<| ?z Y3⟅tf/?sl߶{w?^"7;F?W_?EQEo~*{7~ψ4Ugsk_4+kҟSw~!~ؿ^獾/h|'Q{՟>*;z3&ۯ/+!o/'o(>'xC^|[O@>׿b/ e__"x;?ك~;^xŐxW_t/>'Vψi mkK:#ZXY#[ ( x߶g'V|`>;Fe5º Y iVƞ66=NDxg#qg(" > 0|`𿍼0|U&xQ2{exjcx_* <_s?|3}?U/|oӴmoCxPEP_?>s CW| ~%ּS?#1ԥ4S^  xO_7IY⿅5?ύߴş߷P‘7alkL?X6_'L/ S7-.>.~վ1{(vӿwb/ e__"x;?ك~;^xŐxW_t/>'Vψi mkK:#ZXY#[ ( !hx#I~zƟn~Ϭ7{|`M(\^6yo?w fwd| ߳c~_T/'?lf/pnſض'=gφ~1?h4/+7EQEQE~By{|։G^wc?>;עy{|։G^wc?>;#P*u2~uGNef$֗4IAbvCӯ&ߵ__ik)Kp2qx1&(eEWQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE N?_Z'y(dֳ^N?_Z'y(eֳ_ J ]G Pٺȿ/G'!WRώ&MWŚ|GUg }>(iw_o{@|A5 mr,w<=/ dxܣ_o{ic&i$oϻ$Dk_xܨKA5>O//cK#~}'4#^*(Dk_GEX yy~/{_?> W6G4#^**:(MO}H_ߟvI ׊/=?> W6QG;j}^_ƗGOh?FU Q ׊/=ʎ?S_p4?7ݒ@|A5 mrh?FU TtQ>_o{@|A5 mr,w<=/ dxܣ_o{ic&i$oϻ$Dk_xܨKA5>O//cK#~}'4#^*(Dk_GEX yy~/{_?> W6G4#^**:(MO}H_ߟvI ׊/=?> W6QG;j}^_ƗGOh?FU Q ׊/=ʎ?S_p4?7ݒ@|A5 mrh?FU TtQ>_o{@|A5 mr,w<=/ dxܣ_o{ic&i$oϻ$Dk_xܨKA5>O//cK#~}'4#^*(Dk_GEX yy~/{_?> W6G4#^**:(MO}H_ߟvI ׊/=?> W6QG;j}^_ƗGOh?FU Q ׊/=ʎrM"E<qƬI#TDE݈UUhY;Kb*=﷗[~// g⇌&{_LAK@!{H- KhqUA I/B@? jO?;Ư8;_&N#.[,˲+rܒSδZe:yҫVq|_Ȱ?X.bib1Ub$l#Fz3'F.))Fd?N᱿c<_O7c~x7$o !??o;??ougWCM~euƯ37L}"F{>?doI? | i!=o;hm:[W1>g/WO_loFğ߱/?'O`o9_{_f_-G_+|i?y_f[|E /޼߁} 8'_ G+GByv5Quž4ᣁa/WO_loFğ߱/?'O`a7+~GB{߿v~5Sm:[W[|E /޼߁} 8'_ G+Kr_ 4Ķzo_go/_:2?O᱿c<_O7c~x7$o1 jO?`a7+K%Eo?ho+o_loFğ߱/?'O`9oO iuƯ37L}\[7WO_?O᱿c<_O7c~x7$o!=ܯgX_U'Byv5Quž5េc  8'__ G-I~+~?hm:[W>mEž#t} 8'_? G+~Kr߷ TĶ? S_?F{=?doI? ?r T'7kgCU-GO+|j?y]?ظ+zx??doI? | jO`o9_?[~V~}@<b3޶_G67qG#O loFğ~`'1 j!<o;?m:_1qg]?{??doI? | i!=o;hm:[W>#t^_u8'G67qG#O 0Wñ+| i%Eo_go+o_?=N߱/?'?᱿c<_O7r_ 4'7cWCM%m:~Y?>0^zF{?O᱿c<_O7c~x7$o!=o;hO`o9_-G_+|j?y_f>ͮ-x+zӯ~67qG#O loFğ~`'7cWCM G+~GKo_1;j#t^_u8'G67qG#O 0Wñ+| i%Eo_go+|E /޼߁} 8'_? G+~GB{߿v>4uƯ37<=@<_y8'G67qG#O 0Wñ+| iuƟ4p7L=#~c~x7$o?doI?By_f?Wó/Koׯ7_^_ட=N߱/?'?᱿c<_O7r_ 4'7cWCM-G^[W>#t^_u8'G67qG#O 0Wñ+| i%Eo_go/a@<޼߁} izφljOٶoJO$ig~,]^|5γ'Dq#k:Ɩ4GJk<]oB{߿v>4r_ 4ѿO|fR<(շ_gGi'<_˽>GP?h-|y YW FOZænaY,*Ե}#[V*ף>$ﵝK 2~GYw :FOKt]OP߳I pA `ٓ]ω~,oIԴ _Ʒ㿈~,kQ|\}^k}zhI Eq}u>,` <3_ft08V%TU3> 0T#cQ)G"ׄSRԦNp,"QJn䴰MLmH*xjJ,ΤJ,doc/is_anti_degen.htm0000644000175000017500000001044010237235724013575 0ustar renerene is_anti_degen

is_anti_degen

Returns if the degeneracy rule specified in testmask is active.

unsigned char is_anti_degen(lprec *lp, int testmask);

Return Value

is_anti_degen returns TRUE or FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

testmask

ANTIDEGEN_NONE (0) No anti-degeneracy handling
ANTIDEGEN_FIXEDVARS (1) Check if there are equality slacks in the basis and try to drive them out in order to reduce chance of degeneracy in Phase 1
ANTIDEGEN_COLUMNCHECK (2)  
ANTIDEGEN_STALLING (4)  
ANTIDEGEN_NUMFAILURE (8)  
ANTIDEGEN_LOSTFEAS (16)  
ANTIDEGEN_INFEASIBLE (32)  
ANTIDEGEN_DYNAMIC (64)  
ANTIDEGEN_DURINGBB (128)  
ANTIDEGEN_RHSPERTURB (256) Perturbation of the working RHS at refactorization
ANTIDEGEN_BOUNDFLIP (512) Limit bound flips that can sometimes contribute to degeneracy in some models

Remarks

The is_anti_degen function returns a flag if the degeneracy rule specified in testmask is active.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char anti_degen;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  anti_degen = is_anti_degen(lp, ANTIDEGEN_FIXEDVARS | ANTIDEGEN_PERTURB); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_anti_degen, get_anti_degen

doc/get_statustext.htm0000644000175000017500000000467510237177146014114 0ustar renerene get_statustext

get_statustext

Returns the description of a returncode of the solve function.

char *get_statustext(lprec *lp, int statuscode);

Return Value

The description of a returncode of the solve function

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

statuscode

Returncode of solve

Remarks

The get_statustext function returns a comprehensible description of a returncode of the solve function.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /*
  .
  .
  .
  */

  ret = solve(lp);

  printf("%s\n", get_statustext(lp, ret));
  return(0);
}

lp_solve API reference

See Also free_lp, make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, solve

doc/DIMACS_mcf.htm0000644000175000017500000003446310427457614012612 0ustar renerene DIMACS minimum cost flow problems

DIMACS minimum cost flow problems

DIMACS (Center for Discrete Mathematics and Theoretical Computer Science (see http://dimacs.rutgers.edu/)) has formulated some 'challenges' for some specific problem instances (see http://dimacs.rutgers.edu/Challenges/). One of these challenges is network flows and matching - the first DIMACS implementation challenge.

One of these network flows are minimum cost flow problems:

Given a directed network with upper and lower capacities on each of its arcs, and given a set of external flows (positive or negative) that need to be routed through this network, find the minimal cost routing of the given flows through this network. Here, the cost per unit of flow on each arc is assumed to be known.

Network Structure

  • A network is a directed graph with n nodes and m arcs.
  • Nodes are identified by integers 1...n.
  • Graphs do not have to be symmetric: if an arc (v,w) is in the graph, the reverse arc (w,v) does not have to be in the graph.
  • Parallel arcs are not allowed.
  • Self-loops are not allowed.
  • Arc capacities are 32-bit signed integers.
  • The source and the sink are distinct.
  • The sink may be unreachable from the source.

There is a specific file format available for these kinds of problems:

The DIMACS minimum-cost flow format requires that bounds on feasible arc flows be integer-valued (the LOW and CAP fields described below). All files contain only ASCII characters with information collected on each line, as described below. A line is terminated with an end-of-line character. Fields in each line are separated by at least one blank space. Each line begins with a one-character designator to identify the line type.

The following information makes up a DIMACS minimum-cost flow input file:

  • comment lines
  • problem line
  • node descriptors
  • arc descriptors

As noted above, information is collected into lines, which begin with one-character designators. We describe each type of information line in turn.

  1. Comment Lines: Comment lines give human-readable information about the file and are ignored by programs. Comment lines can appear anywhere in the file. Each comment line begins with a lower-case character c.
        c This is an example of a comment line.
  2. Problem Line: There is one problem line per input file. The problem line must appear before any node or arc descriptor lines. For minimum-cost flow network instances the problem line has the following format:
        p min NODES ARCS

    The lower-case character p signifies that this is a problem line. The three-character problem designator min identifies the file as containing specification information for a minimum-cost flow problem. The NODES field contains an integer value specifying n, the number of nodes in the network. The ARCS field contains an integer value specifying m, the number of arcs in the network.

  3. Node Descriptors: All node descriptor lines must appear before all arc descriptor lines. For minimum-cost flow instances, the node descriptor lines describe supply and demand nodes, but not transshipment nodes. That is, only nodes with nonzero node supply values appear. There is one node descriptor line for each such node, with the following format.
        n ID FLOW

    The lower-case character n signifies that this is a node descriptor line. The ID field gives a node identification number, an integer between 1 and n. The FLOW field gives the amount of supply at node ID.

  4. Arc Descriptors: There is one arc descriptor line for each arc in the network. For a minimum-cost flow instance, arc descriptor lines are of the following form.
        a SRC DST LOW CAP COST

    The lower-case character a signifies that this is an arc descriptor line. For a directed arc (v,w) the SRC field gives the identification number for the source vertex v, and the DST field gives the destination vertex w. Identification numbers are integers between 1 and n. The LOW field specifies the minimum abount of flow that can be sent along arc (v,w), and the CAP field gives the maximum amount of flow that can be sent along arc (v,w) in a feasible flow. The COST field contains the per-unit cost of flow sent along arc (v,w).

Input File Example :

The example network pictured here is followed by a corresponding DIMACS minimum-cost flow input file. Items listed in the lower-right of the graphic represent fields described above.

Minimum Cost Flow model graph

c This is a simple example file to demonstrate the DIMACS
c input file format for minimum cost flow problems. The solution
c vector is [2,2,2,0,4] with cost at 14.
c
c Problem line (nodes, links)
p min 4 5
c
c Node descriptor lines (supply+ or demand-)
n 1 4
n 4 -4
c
c Arc descriptor lines (from, to, minflow, maxflow, cost)
a 1 2 0 4 2
a 1 3 0 2 2
a 2 3 0 2 1
a 2 4 0 3 3
a 3 4 0 5 1
c
c End of file

lp_solve can read/write and solve these models via the xli_DIMACS XLI driver (see External Language Interfaces). It reads such a model in above format and solves it via linear programming. The xli can also generate a DIMACS formatted file.

For example:

lp_solve -rxli xli_DIMACS mincostflow.net

This gives as result:

Value of objective function: 14

Actual values of the variables:
C1                              2
C2                              2
C3                              2
C4                              0
C5                              4

Also from within the IDE, this XLI can be used. However, some entries must be added in LpSolveIDE.ini (in the folder where the IDE is installed).

In the [XLI] section the following must be added:

lib6=xli_DIMACS

And a new section for the DIMACS XLI must also be added:

[xli_DIMACS]
extension=.net
language=DIMACS

Then make sure that the xli_DIMACS.dll is available for the IDE. This must be done by placing this dll in the IDE folder or in the Windows system32 folder.

Solution :

The solution vector of above example is [2, 2, 2, 0, 4]
This must be interpreted as follows:
There are as many variables as there are arc descriptor lines in the input file and they appear in the same order. So:

C1 specifies how much flow there is for the first arc definition, in this case from 1 -> 2
C2 specifies how much flow there is for the second arc definition, in this case from 1 -> 3
C3 specifies how much flow there is for the third arc definition, in this case from 2 -> 3
C4 specifies how much flow there is for the fourth arc definition, in this case from 2 -> 4
C5 specifies how much flow there is for the fifth arc definition, in this case from 3 -> 4

This means there is a flow of 2 from node 1 to 2, a flow of 2 from node 1 to 3, a flow of 2 from node 2 to 3, a flow of 0 from node 2 to 4 and a flow of 4 from node 3 to 4.
The value of the objective is the cost of the flow: 2 * 2 + 2 * 2 + 2 * 1 + 0 * 3 + 4 * 1 = 14

Output :

The solution of the model can also be written in a DIMACS format:

  • comment lines
  • solution lines
  • flow assignments

For each network problem, the solution is an integer-valued flow assignment. The output file should list the solution and flow assignment for all arcs in the graph. As noted above, information is collected into lines, which begin with one-character designators. We describe each type of information line in turn.

  1. Comment Lines: Comment lines give human-readable information about the file and are ignored by programs. Comment lines can appear anywhere in the file. Each comment line begins with a lower-case character c.
        c This is an example of a comment line.
  2. Solution line. The solution line contains the flow value and has the following format:
        s VALUE

    The lower-case character s signifies that this is a solution line. The VALUE field contains the value of the objective.

  3. Flow assignments. There is one flow assignment line for each arc in the input network. These lines have the following format:
        f SRC DST FLOW
    The lower-case character f signifies that this is a flow assignment line. For arc (u,v), the SRC and DST fields give v and w, respectively. The FLOW field gives the amount of flow assigned to arc (u,v).

lp_solve can generate a solution file via the xli_DIMACS XLI driver (see External Language Interfaces).

For example:

lp_solve -rxli xli_DIMACS mincostflow.net -wxlisol xli_DIMACS mincostflow.sol

This generates the following solution contents:

c mincostflow.net
c
c Dimacs-format minimum cost flow result file
c generated by lp_solve
c
c Solution
s 14
c
c SRC DST FLOW
f 1 2 2
f 1 3 2
f 2 3 2
f 2 4 0
f 3 4 4
c
c End of file

lp_solve can also generate a solution file with only non-zero values.

For example:

lp_solve -rxli xli_DIMACS mincostflow.net -wxlisol xli_DIMACS mincostflow.sol -wxlisolopt "-nz"

This generates the following solution contents:

c mincostflow.net
c
c Dimacs-format minimum cost flow result file
c generated by lp_solve
c
c Solution
s 14
c
c Only non-zero flows are written
c SRC DST FLOW
f 1 2 2
f 1 3 2
f 2 3 2
f 3 4 4
c
c End of file

A testset of models can be found at http://elib.zib.de/pub/Packages/mp-testdata/mincost/
Also see the dimacs ftp site: ftp://dimacs.rutgers.edu/pub/netflow

See Also DIMACS maximum flow problems, DIMACS assignment problems

doc/is_int.htm0000644000175000017500000000545610553537304012305 0ustar renerene is_int

is_int

Gets the type of the variable. Integer or floating point.

unsigned char is_int(lprec *lp, int column);

Return Value

is_int returns TRUE (1) if the variable is set as integer, FALSE (0) otherwise.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be checked. It must be between 1 and the number of columns in the lp.

Remarks

The is_int function returns if a variable must be integer or not. Default a variable is not integer. From the moment there is at least one integer variable in the model, the Branch and Bound algorithm is used to make these variables integer. Note that solving times can be considerably larger when there are integer variables. See integer variables for a description about integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int integer;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  integer = is_int(lp, 1); /* will return 0 since the variable is not set as integer at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_int, is_binary, set_binary

doc/get_epsint.htm0000644000175000017500000000537710237176654013171 0ustar renerene get_epsint

get_epsint

Returns the tolerance that is used to determine whether a floating-point number is in fact an integer.

REAL get_epsint(lprec *lp);

Return Value

get_epsint returns the value of epsint.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_epsint function returns the tolerance that is used to determine whether a floating-point number is in fact an integer.
The default value for epsint is 1e-7

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL epsint;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  epsint = get_epsint(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epsint, set_infinite, is_infinite, get_infinite, set_epsb, get_epsb, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb

doc/lp-format.htm0000644000175000017500000002513410723124574012714 0ustar renerene LP file format

LP file format

The lp-format is lpsolves native format to read and write lp models.
Note that this format is not the same as the CPLEX LP format (see CPLEX lp files)
or the Xpress LP format (see Xpress lp files)
The lp-format input syntax is a set of algebraic expressions and "free", "int", "bin", "sec", "sos"
declarations in the following order:

<objective function>
<constraint>*
<declaration>*

where:

- <objective function> is a linear combination of optional variables and
  constants, ending with a semicolon, optionally preceded by "max: " or "min: "
  to indicate whether you want it to be minimized or maximized. The case
  is not important, "Max:" or "MAX:" will work as well. Maximization
  is the default. Alternatives are minimise, minimize, maximise, Maximize.
  The objective function is required, but can be empty.

- <constraint> is an optional constraint name followed by a colon plus
  a linear combination of variables and constants or (just one)
  constraint name followed by a colon (a range) or (just one) variable
  name without a colon (a bound), followed by a relational operator,
  followed again by a linear combination of variables and constants,
  ending with a semicolon. The relational operator can be any of the
  following: "<" "<=" "=" ">" ">=". There is no semantic difference
  between "<" and "<=" nor between ">" and ">=" (even for integer
  variables!).

- <declaration> is of one of the forms:
  To define variables as integer:
   "int"
   var [","] var [","] var ... ";"

  To define variables as binary:
   "bin"|"binary"
   var [","] var [","] var ... ";"

  To define variables as semi-cont:
   "sec"
   var [","] var [","] var ... ";"

  To define variables as free:
   "free"
   var [","] var [","] var ... ";"

  To define Special Ordered Sets (SOS):
   "sos"
   [sosdescr:] [","] var[:weight] [","] var[:weight] [","] var[:weight] ... "<[=]" sostype[:sosorder] ";" ...
  or:
   "sosx"
   [sosdescr:] var[:weight] [","] var[:weight] [","] var[:weight] ... ";" ...

- A var must start with a letter (either upper or lower case), and may
  contain any number of additional letters, numerals, or characters
  from this list: _[]{}/.&#$%~'@^

- Comments can be used with the /* */ syntax, just like in C.
  It can be put anywhere in the file and even over multiple lines.
  lp_solve 4.0.1.11 and newer also supports the C++ line comment //.

- Empty lines are also allowed.

EXAMPLES
      The simple problem:

      x1 >= 1
      x2 >= 1
      x1 + x2 >= 2
      minimize x1 + x2 (= maximize -(x1 + x2)), with x1 integer

      Can be written as follows in lp-format:

      -x1 -x2;
      /* or min: x1 + x2; */
      x1 >= 1;
      x2 >= 1;
      x1 + x2 >= 2;
      int x1;

The correct result for (x1, x2) is of course (1, 1).

If you want to give a name to a restriction then begin the line with the name and a colon.

For example:

      min: x1 + x2;
      x1 >= 1;
      x2 >= 1;
      myrow: x1 + x2 >= 2;
      int x1;

The objective function may also be empty, but it must be there:

      min: ;
      x1 >= 1;
      x2 >= 1;
      myrow: x1 + x2 >= 2;
      int x1;

Also constants may be put in the objective function:

      min: x1 + x2 + 3;
      x1 >= 1;
      x2 >= 1;
      myrow: x1 + x2 >= 2;
      int x1;

Or even the following is ok. The constants will be added to one constant value:

      min: 2 + x1 + 3 + x2 + 4;
      x1 >= 1;
      x2 >= 1;
      myrow: x1 + x2 >= 2;
      int x1;

This will lead to the same solution as without the constant(s),
but the objective value will be increased with this value.


Note that for bounds on variables, you should not put labels before them.
This is because lp_solve then makes this an extra restriction.
If you don't put a label before single variables then lp_solve doesn't have to create
an extra row for bounds on variables, resulting in better performance.

So it is better to write:

      x1 >= 1;

than

      r_x1: x1 >= 1;

Note that this is only for single variables, so

	  myrow: x1 + x2 >= 2;

performs as well as

	  x1 + x2 >= 2;

In addition, the variable can have a constant, without performance penalty.
For example:

      2 x1 >= 2;

is automatically translated to

      x1 >= 1;

by lp_solve, so this is not a restriction, but a (better performing) bound.
The moment there is more than one variable in a constraint, lp_solve can only
create a restriction (extra row) for this.


Sometimes there is a lower and upper bound on a variable. This can be written in several ways:

      x1 >= 1;
      x1 <= 3;

It doesn't matter if the lower bound comes first or not. They are also not required to be together.

Another way to write this is:

      1 <= x1 <= 3;

Or

      3 >= x1 >= 1;

These bounds on variables are handled by lp_solve in a special way so that no extra restrictions
(rows) are created, which will lead to better performance.


Also on restrictions there can be both a lower and upper value. They are called ranges.
For example:

      myrow: x1 + x2 >= 2;

Suppose that the same restriction should also be <= 6, then this could be written as:

      myrowmin: x1 + x2 >= 2;
      myrowmax: x1 + x2 <= 6;

However, then there are two rows in the model which makes it larger and harder to solve.
lp_solve can handle this in one row so that the model is smaller and it will solve more quickly.
This will only be done if the modeling is done in one of the following ways:

      myrow: x1 + x2 >= 2;
      myrow: <= 6;

Or

      myrow: x1 + x2 <= 6;
      myrow: >= 2;

Or

      myrow: 6 >= x1 + x2 >= 2;

Or

      myrow: 2 <= x1 + x2 <= 6;

Or

      6 >= x1 + x2 >= 2;

Or

      2 <= x1 + x2 <= 6;


Note that there must be a row label if the construction
label: op constant
is used. This requirement does not count if the min and max restriction is put on one line.
Also the range must come after the constraint definition.


Example with integer variables:

	min: -x1 -2 x2 +0.1 x3 +3 x4;
	r_1: +x1 +x2 <= 5;
	r_2: +2 x1 -x2 >= 0;
	r_3: -x1 +3 x2 >= 0;
	r_4: +x3 +x4 >= 0.5;
	x3 >= 1.1;

	int x3, x4;

See integer variables for a description about integer variables.

Example with binary variables:

	min: -x1 -2 x2 +0.1 x3 +3 x4;
	r_1: +x1 +x2 <= 5;
	r_2: +2 x1 -x2 >= 0;
	r_3: -x1 +3 x2 >= 0;
	r_4: +x3 +x4 >= 0.5;

	bin x3, x4;

See integer variables for a description about integer and binary variables.

Example with semi-continuous variables:

	max: x1 + 2x2 - 4x3 -3x4;
	x1 + x2 <= 5;
	2x1 - x2 >= 0;
	-x1 + 3x2 >= 0;
	x3 + x4 >= .5;
	x3 >= 1.1;
	x3 <= 10;

	sec x3, x4;

See semi-continuous variables for a description about semi-continuous variables.


Example with free variables:

        max: x1 + 2x2 - 4x3 -3x4;
        x1 + x2 <= 5;
        2x1 - x2 >= 0;
        -x1 + 3x2 >= 0;
        x3 + x4 >= .5;
        x3 >= 1.1;
        x3 <= 10;

        free x2, x4;

See free variables for a description about free variables.


Examples with Special Ordered Sets (SOS):

	min: -x1 -x2 -3 x3 -2 x4 -2 x5;
	c1: -x1 -x2 +x3 +x4 <= 30;
	c2: +x1 +x3 -3 x4 <= 30;
	x1 <= 40;
	x2 <= 1;
	x5 <= 1;

	sos
	SOS1: x1, x2, x3, x4 <= 2;
	SOS2: x2, x3, x4, x5 <= 3;


Alternative:

	min: -x1 -x2 -3 x3 -2 x4 -2 x5;
	c1: -x1 -x2 +x3 +x4 <= 30;
	c2: +x1 +x3 -3 x4 <= 30;
	x1 <= 40;
	x2 <= 1;
	x5 <= 1;

	sos2
	SOS1: x1, x2, x3, x4;
	SOS2: x2, x3, x4, x5;


With SOS weights:

  	min: -x1 -x2 -3 x3 -2 x4 -2 x5;
	c1: -x1 -x2 +x3 +x4 <= 30;
	c2: +x1 +x3 -3 x4 <= 30;
	x1 <= 40;
	x2 <= 1;
	x5 <= 1;

	sos
	SOS1: x1:5, x2:9, x3:12, x4:17 <= 2:3;
	SOS2: x2:9, x3:12, x4:17, x5:21 <= 2:3;

See Special Ordered Sets (SOS) for a description about Special Ordered Sets.


Peculiarities of the lp format:

Note that some strange effects can occur.
Exponents:
Consider the following lp: min: d1 + e1; -0.5 d1 + e1 <= 3; d1 + e1 >= 6; 3 d1 - 2 e1 <= 16; This works as expected. d1 and e1 are always seen as variables. Now consider this: min: d1 + e1; -0.5 d1 + e1 <= 3; d1 + e1 >= 6; 3d1 - 2e1 <= 16; You would expect that this is exactly the same model as before. And for variable d1, this is also the case. However, e1 in the last constraint is a problem. Here lp_solve doesn't recognise 2e1 as two times variable e1, but as the constant value 2.0e1 (20). It sees the e1 as an exponent! There is no problem when there is at least one space between 2 and e1. In that case lp_solve knows that it is two times variables e1 because there may not be any spaces in numbers.
Operators
Consider the following constraint: +3 x + 2 y <= 16; The + sign is optional. So above equation can also be written as: 3 x + 2 y <= 16; But also as: 3 x 2 y <= 16; This may look somewhat strange and can even lead to confusion. Consider the equation without the factor 2: 3 x y <= 16; This is still considered as: 3 x + y <= 16; And not as 3 x * y <= 16; as could be thought... Also, lp_solve allows adjacent operators. Consider the following constraint: +3 x - 2 y <= 16; This may also be written as: +3 x + -2 y <= 16; or +3 x +- 2 y <= 16; or +3 x - +2 y <= 16; And the constraint +3 x + 2 y <= 16; may also be written as: +3 x + +2 y <= 16; or +3 x + + 2 y <= 16; and even: +3 x - -2 y <= 16; Note that the lp-format does not allow parentheses () to make things clearer ... So the following is not allowed: +3 x - (-2) y <= 16; In fact, there is no limit on the number of operators that are placed next to each other, separated with as many or as few spaces as desired... For example - -- -- is seen as -, while ---- -- is seen as +.
doc/Euler3.jpg0000644000175000017500000030576511164464361012156 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?M1|̿ I_| k%|AmG 5FOxٵGU5gV߇4 gя/0<ɼFUI`JS oi?O SFG5M;B&rĻM)2CuZ8K\ %O0G`/8T(ᡖԌUxDa8߃ƏEWυ18c 8l[S1Ϊa!O **c3}Rg|.#FtυDhn~;x_gvOO6/ßGjV8mou7:{[oM%}?bOj{:%s}>umsI=?uueEs)na i~G\\!ObwF{W Gq^7x:!"| B";Ũ>*x ,=uY|z5)СXl濷9PC,?vxkg"4o7^g^:?h/=MW}ώ>>ڎ/zƁaZ|^ -mA|YA/RId>~_k\hW-|е}?Sc|>+o7tzi⎡oۋRé/|*>(xa˸36[Z8~e9Ź[,0UyfSy^d7[-_b|=7 8.Bx?vxkg"4o7^c_?WW 4q?>i>IӴ[V?"lOa׼\5 =u?Mm7/i|g ~쳦k*829 }K SG ;S/Rbs:UUhx<̩bc) (K b)`"}vxkg"4o7G. ,]FH:|?xfÏ7<1@VIӛEF:e5 Ŵ^kZMlnO_5O a]?5KO< WWuixLҵ &Pҵ;5(mk:9{;cx[0 ~M>|FLʆ&XZL&'FJ*pV3RQZ^m~UybhXxjRuIaքjP]QTVR*rʤM. ,]F% ѿ}/&&JUg>_O% ѿ(hϯ4Sn?_Naeg⦏'7uе6O [K]Os?Z &Nӯ<+~+m?>gH__ !Ꮙ~i4/3|@,Z["Uc.xDN9.`lnVWy.ṣWuSV9|9WT+is<."' NQNXі L,q.[Nyl*bW_O1':~F3 8N"TQ^U#/ .Y>ƨ% ??z.||X>6|kg/w/cOOҿg7t5}ju_ ?U[Ǻ΃e?^7zEϋiq|ǟ #$ױA&MGOOGOnx㏀<)f=?6Ӈng U|&mR͡Cejefv %',,,ʕ**5*CZq .\jWsUZX ฃ/1uㅄ'o,XΒt`, R+S_^>]}Q KP?V)kW>2[#"P) O W>|COC<+/0SCh~xŚM+?4-7 }gTMggj:ge\K(V .ў'4:caCQͰetqPJ&-ЫN_+<:"~m 8O%Lo`1V7UxT'$>9% ??|7Dg'SMic6{H8j<)ïf7\Ţok%6<;4:[Yȓ2j&~O_=_š|. o^"]B>+sj: kWtm?Jiڗ %]]iA=,o ׫J '^"YZ3+ҧ CJ8.|HEzkßf:(Tө^J>BiRcS%^jTjgCj^>]}WxT7Ŀ獴?mx?>|%ON4Oz~hi:eH~ק^^[\+|⟉:WOi'\?s~ۧ)ngxK/4#Oյ KOj:u^[[G,ɓ}GSE~b]ߵ>jYؿki,?g\ٟ=~YϴT9=nǶCj^>]}Wa{_?]8ߋb uo{|;5[Þ&7_[>gUҼI/^?x?5o  -[Z|o}]7÷lo RN/n a -xb̷::uQeTp0f] NuJaO͸ 2\D8b(M<7?SJ(bՕ8eCmIʊjn]_/ .Y>ƨ% ??rHڿJ&m 5/>M -j{k@Eց&<7)Դ2( jGSJ0} 2?~+|h~?,i>/u? ]}Q K>ğ>!w i=oZ\~*PW4V#SNuWMWG};M-Ě||a+/_[/oݧuٯ|s"W0m?}sjKrQ|r6oU bMV.G[30r~a^ _2JF# F7SU'>ae!B'1UNiWW)WaaySu*R^u(b!K?xow!O5Qc¥F9hN;g|Wux#~|D'~&i-8_ h_4%uּzm%tBmKAz֓tf57Κ,԰@澏 C*Ў'& ??w{Ÿ!.hC&7Wd OOgOy#]gm#)H'& ??w{Ÿ!.hC&7Wd OOgOy#]gm#)H'w> AG> |np\>TX1*K_ur`c{o  g~|ZymK}$-$AA/?S_qNMƸNἫ~.lV77XY9 P9M:TO(u9U\yY8k;Fsf\Eͱ8 42ʆLԖ#9cTR I974Z5^TnfU\2~Ъ#'^],]\mDp-i)_VɣWDQzYxf<qڈe܄T_rq_jχB@{?&F, ?ZRD$;dZ";?4l_2q%eYv fa L#,;V*s|<lOX_dOG fXf|QBtcjVO %^S5b,E:\V\<\~_W[:a]yY?h# r@k6o-_|?"%Rng sW;IQa_ F|K/7|Hρ46Ҿ x[}vėbŢ?nOI;_G~8|Qh ǖ9&t}H$nma>|5.~]:kgkj6i5=~e~:fw)_3z \MR:9t?|SK*xZ?b1(ѤZ47 ³X8cszir~ޥ5NRN3_ws|5O^7՗=x).m3&yK,Hcyz0fnO|hVl~rpd4qAb09;C)d|6o)|f?%4ydOq+ -ϞF%攴1rMz燿-S6p^. ۬5)ȏpX#mm nkH̸aH!1m CͫKU)fxXҡJd#R5*5F.u)N:pq18뉜_MPhRfYJRU0RHaj8œT.2?X]Qm,Sq{;Amk3;W`ؿ[uo$ޏCGSvVZU.Cs ƗZ~"K5Y%uw@.!inh6|^PĿP!v.0q 8ʗaWaZ|3΍|,:RRvH[UŜ#qUՖ+2:0xjì=,N:l-zs7g{ +2~!J彅o?E{" +(<Ul?%^~kO~=55⟄-|"R5-߄}RIIimuUa5ؽ~~_g\x3Q^4m|xJų T~+>!?._uALR$zmts1c~ڢqx'1‘_I ,p|G$>ψ8_2"+Qs^!q\sØ7z00vTb#^,W_=Y.q;$,Q[ IڕGFSZ5F\kJt'F9K/ /  I~34uz:nr%NJDҬw9⿃/x& s'[Zſ犾)|@lX1ׂ(ǚq/Ih[F͎kշ ܷypO3wŬ*G+#Q~>~Y뜝'O~8+/ c^8=PkĸOXis9s\6$˱y.gq6]93^TaR8ѧF0~w8(q.'ɨS|GVʥ,6*iRapYnQ FF,3JuSW_b_ #㿊nG PW?o|]jcνo%qiVLeĽ{ᯊtOKԣ<9/ß(?/|]H ̾?œ@ਟ~~h?I ڗ[O,Ƨ (7yq7Þh2?zѠl[8=rg933|GUOqF9BVJUo_^EbrX=zgّql*3[-`t<^A5S<+FJ8M9ƼPfqJtA}ON +w.YWz_ƟZ|"|>Xx|y퉯|N+Qշ_𽎃%B*~_Z?[O|:|S+7NxbF{x]u xTgFѼ%hx"?9 F/ٳ+7 ?f{ w8ʳ3fMCjg%>\kepbTh1Z28J:|0YSU8̱x1)O+36IΰL=9*u㣌NSྐྵOgW?ltwm={U>/.4w ,w4_?pfk[dm|v爣K-{.n/1>'|:*2>OW5o ׊4_⯇jzީwZ-챯[rZGq_+7 ?f{Þh2?p]/o } x3K8"p$cÞ1k ўj5Q 3/CuuO|^>Zf{[wᾹմ,,׆/o9&dR fA~s_?g=D4 q_ >9p \6_wb0ie|\Sx8L|\\jbj:_u|3?*|7P;*n?{nUj~+׬UEV%j$|H5ozTZVk_QKQ_|aIdߴ'_o M# 㯊_xF 1g|;Ru/~#xk{_Vo4~͟=Ye6߯8>]晦o9xln/2q] 9^t+ej,0m X?Ӳ Ap #Ϊ,g_c"~Mzkx=<ƴ' fA ٗ|3N=#JGoxwŖ٧t_< 6/xcB4?U^%E~Mg!g?ho_ZWuHW5O?-245i:{-\:umGWӢos_?g=?_Vo4~͟1[>p.ue9SF}⦡b]U0ԧP`_Rjʔy'ǹ~/-Y8|f;+WYVI.)aFq+ks(# ѝJUXiJi3Wh7ŻagOƛ/ gGSӾ]/O = |r?Ms 7g+4?ZT 1 0Xx/7B{|hk~?;=+,e~-|P𝏂<'_]YYub ;ZD0Iwk:md?4%3k )D>4M$㿉_ON~| /)RоsUơY,dx?9 F/ٛ_+'~fo{**_q9 Y\/Yq֎)?u:iVU%:|L~FXuIp]o.ESco8V#$iTsnϣ (93N2}|\Fs~׿O~#Ծ5k?o?Zg#}S''ASY4QxQE dž.Dz_} _ڣb,:k_}s7UiIcO?fW/Sw&4v*K.-x~ԢѴo?οVO3h:Y?3ݯ| DX |O~Y[mῄ)a?Z?|!t杯k~ Mx_ :x?m--beF|dgyĚ/z/lɼOi 9?o~0xk]s_??7=?οVO3k ^O1? O aq|OJ֧U CXj1ElzqƖ+岩q=HcxlG^֯xftg,] Sּa{-kmJ{/[dž5x$k_ǖ:o/^ZS|[qv h1>|C'>|2 kxN־*|B)M}kX7SO֧m7GKos_??7=?οVO3k; ѮMq7xiaxj ֏D-cFW_0R&[u14poQp3z3ub)CXa)ժ,LixBU| )K?l/?gZ} Ǎ|{u7 GGSm;Ǿ8wP^~*c^=<%vߴOt|b?e?MDž>" =ګAA ZZW'ƫG_@_Gľ3cukÝଟguџf_--Υ)~9XLYZ$p WW|+/2LcSq`qCjxa<akqSs*G;'QSU&7j': /1f?!ĿK)sv/3aS|sn|MkkKMEu^'eπ63"NJ>~?n_#cT?J5ZOÏ xW~8|F ^^SҾ ѼoeΣGp>Re|Z~R<_ړ7aǬiw.'+Hq{j7tZNgtl. #[DL%t =3O6M{ xm >0q/oq,m,{S\W_ҷx,V."`3 e'*_QiV3U׭Q9aBnThl?u3|%c"ߋZ5ZM[R~*Tzԭ~/k_i>6ex}>|]{A񗋵O~xco?zNĞuџfG9 F/ٛ}(qv3l-lT8+w\uŹ_S*ͰL.#uNX&^63QmSXW˸/eY1xl]:ogRN6ҡV,-_(? {sotG/?dO ,->{=^lLJ ;ḵYp% jXK)d+iRa`ai.Ǎ8_.87.%be,\A&9*T̪c+siND8}|^3eOG#S9?~Ý?ggbs?W?0G<rK_4}?IN|?+Z57O_o+O4أi;?f{}xKkS? %OWd#S9?M<+5vѝ?߳G=?V3hGL77?~3 _4}?IN|?+Z57O_o+O4أi;?f{}xKkS? %OWd#S9?M<+5vѝ?߳G=?V3hGL77?~3 _4}?IN|?+ihG2?^4jWIB0%_?\No uOğ?e햏x/Iu2h~= .uYk6ҋ}>L].>d źW1 Yjڧ{Wѵ}#\үw^*Kcxw5_xGKMWEhn\[_&dJ]G31KR(!"8j"*q~kVMg `)b~8 r3.#hV|SOxY GVrbaYa(O7 0߇lE<2,&q|Gq1 JqɌ+zmwR5eF 5hrzo>xS׍,?f~>?b x;~*{/j-߈~muoEO閆O i쬭>،ת|6־2i/-8FCsQ뵸^^s/KnH ~pAv[x?`)Ư#Budğ Ie*QHoKxxψ^fy/e5kW3ցV>9|fͤ^|?' iמq rvv'/? e φ_|c㟍ca=5>χi=Cm%3O𵭅j^uZmfѩcUD,~ UGx _9מMPbW"Ge/ܠ|o(R3\A<2ɣx#?^ejxʞ}. Y7EO _K *c,˖ю9^xss\ҩG3<>.l%Tg,XS59ºQ.xҊ^p<]q?e%Ā0~FrGCr}jź?/F^ G:ޫyk*gZA2!Q"yMͷ϶ʹN?->_xT|=\A;7ٷL𞟢xCH4>ͤI𿄴Fݝ}?$'w7s8##=1uF{e،P^ \7J+pOcZ'[mZzJ)T҇< ĹKxOq>Sf?5IԴ*6.,E?{:9g/5υcU6rjP>=#͵Ǘwo ?fh o#G{㜿ŏp|_1 FBPTQ%\:Ο述WK{3|vQvai~җaݳ 42YO/ke}q<Yx|Ma&żck*tͩ?׼G{gq7MU_Mjf?~ӕxW!7?X]w5wKp2~ྞe |]~QE(W|\KHO|?MqM2>4Լ boMi>6?ޝkco>y[A+7>+CFXDQZRjxz0֩:ӧӧ&ܖ\n/F3KT+jʦ&<5 ta֯Vuk֧JNrrkkI<) yel^-_S;CZm"vZ#M&IT&>#&WH7CO-cBՠ7qV>3u;; 7>ԯcRV5]S5+Z%x |Y=oΩaoNi)&,s.R\wM8V\\&e e. FqUj<3Rtj?鼡ԠJQŷ EB`_+?a7fO߃͏m6]O)_ADo}΋^x5O-5 }O|(3$~*{RoJK"Υ8J-/[Od׽8|"xz|>*!I_ ^W*uTJӓӴ~5?L|FLOڧ12|a?g/|#Q $Oc7Be~?FgI lmfFxG4W~?FgI IT&>#&Q9swy}?ux<_;S`KmQ5=;Zt(u;K? kct3 /y xFwjbx gV?"CBF?^44N>#GX?~5?L|FLOڧ12ͿÞ`>wO 5<7+<:QuxD<fk>NwE_VY_7jS 'SDk~ĘЙ^I/ ~t/c:ï^a-jk:fjׄg-k>ſ<[?k~ 'SDk~ĘЙU8Bk(]5ѧOTN;sWpj(WgR,.;iFIFQn3Rqih$~(5?L|FL9swy}|#Q $Oc7BesNx¾v[~OOoE Sc˳4mN?-1.|9 >Ӥj- iY<9?*qm+MY6پ$UXQtsiRJĺ”FʹeZik55 $Oc7Be~?FgI _8?<wٚ?u__ƿ'??zǂ _SeoQC gF" vO3M3Ὦu]9A*ZI}&? |go7$kz5xߊ 6~ѿt;SKOB4-Z &|uc?^3Լ6Z,-k{ SJtOFu xZ׆ |?'~x~,yMBJRv*qRRѵ' IF|#2^{S b)Tx t"49a9_ Tҫ.z F)E| 'SDk~ĘЙG$Oc7Bei9swy}?u@_?IT&>#&Q 'SDk~ĘЙG|a?a`?;g}E| 'SDk~ĘЙG$Oc7Be8?<wه|#Q rk "xoSmσWx#ZuŖFy4cF-,5k7?|7{qg¾=޳o^<Oڧ12nwW7_/3i <9Qǯx]oO>'/k~MoZᧁ 㷏`5-{_c:tshVs.y({F]<%Rma'*S[88VN4*1X^ 9F.QªhQ_)#g|~մ[C4_m'QtFF״ Ad;^/iڟ_iO#&Q9swy}?u@_?IT&>#&Q 'SDk~ĘЙG|a?a`?;g}_z|Z}{ |w G_?__~x3؟nÚo?ǧhgh}`_S!?l/{:K'B|1qez3yVN\gh/q$hOq1|Wp&NYPU>JNQ,TGy$ci5lֿCӯ&ߵ__ikҗuɧnq\@QE(|J7gOeob2F?|ILWAܸ8c֏*>+=$|7&v^whZƅAo3׌l4;R,-k{ SUѵ=3Yҵ xZ׉>@ߋ~xŞO5˽rOkM'Bši3Qɢycϋ^ &NTmMMR5nx|߄?.]yO?|/">45 ῍'<#AhGЫeل0r[O,Q*8Υ\$2uhGJQ^Sw'~&?ofG>,~ Ÿdk~![GG<+ⷁ%4?VjENwM6FIJ2$ '%$a+OVҔ' B#RZUitPJpFsRj5'J'"(0 ( O o\o7zM/O4_ i#g j~3u-3/}Gſ[? -#~_|!tTTpZiQ%Pc(I8LU\xb(5!(*tRJt1jTЩRX9S$nþ;YM?+e _;ÃO[m"xK%MJVWt}SN7Ǟ񷇾9|[OUx:Ɠbo ikψ mC{Zg>!_kIZ>xMG<[cž*w=G_oE $ht;SKմ-cBէώ<h,|gv6v7c_jk:fjׄg-k>ſ<[?k|X M5?dj.2zo7zNB`dZcy}eoƥ.^-'kW#ſ]H&wzihZƅOxY׌lo/xM,-k{ SJtOFu xZ׆ |?'~x~,SG}r\Iо1hZL,SX3׃,o/8~|SL/{SXԾ|Et}kſ[j xIդ'zRTKWi߯BuxuHҩJ< |b嫖MꮲI_] $ht;SKմ-cBէώ<h,|gv6v7c_jk:fjׄg-k>ſ<[?k~[BqTԣ%t_kf4<+aT^V.Y[iFIFQn3Rqi-¿wnw^ijnh}Úlnڿ>"hykw$W%Wn}/_sMQ^?Wg_3P1{y?eR2(;SG}r\Iо1hZL,SX3׃,o/8~|SL/{SXԾ|Et}kſ[j xEEJqY_t$(m(ԓiqUuj.-ʝJu#FRzoJ-%(1|čǃ,iZjd2+γkYx_~nN}hwz|u[Q3Z6/xWVz|x~(2|?[RZK4'N,WӴ >t // K𾓤|ū:#x_L񏃵?mVlP-6::ͦx_~״O~/4'FgFi:m*omZ5jkJ=eFrQnP*zZ<_)<^ENR筗WEjXFe:U 袊(e|9~ڿgOX}: OA>(h³wWL4پ[??W^w ?~'V~.fqf_.+LT<GQd7kkڷإ+;IӾ6iNiYkwh>|/?<__>}'H;Wt'?ŏռ Fjء[-GIlu'Qѵ_uM;^/iڟ_iONjtG.kMӄcK.jG :k*XlNK x#}3>[C4Z:Nwk6v_^ӵ? $4xCNiN:uW[Qc(J2JQZqZZii٭QURJkSg:UiUԥR*SNiJ$&M4QE2((d5oٟ |`{s{LV߾  ?wO6?h*٨Ͽ[q &~'? jfxx6?[!kpRa1? nq\@QE(|J7gOeobo%mtzíƺEώ|]'_7#cޓ߈z k |moqia$r=u?Z ~߷ ?_Ab2*ŷ> V?h[UmPtk0<* $Lj'?$K+yX ut0ըTnWph70Y"vMEaSZYՃu$Ҍ Ζ_Furvsn/ Po ʳUӍ7^ySEK Njs5E_G@ҿj?ٓA@π5_ ~_ ~7"Y~~*QӴRk?d_ mx}8|Yz·ڌ:cjczQEyO?bxz 7ÿxOŚ G' |qB{qiW|Ai/moĚ' Os_ ziG' |q\|=o 𯊼?^S;'؞$޷?oiM$:oG{kf ŸdhkGGU_xⷁ|K>'Z+$RMF"QUj*ZGF~a?gJqNJiukUu+uuT2s#۾M??7+gw/3__.???f|E>$|7.O n =參>-x2Sg9RI5K]7Gּ[Oź֯-G~/|!2>#۾M??7+gw/3__.???f|E SL<+cd,~&ҋI=6y.*3Eŷ)ԧRǧxwv~ _b{Yo`Qx~>M/kx#}3>[C4Z:Nwk6v_^ӵ? $4xCNiN:uW_?x(_5?m{V{i:w;Iӭ4-@:G'/~1jN'>s2)U*s|թ7%+$RKV엵uR'إVeF Rqxx{VqF>yN9v>iҧ9cQ8Ys fʆ+&-¿wnw^ijnh}Úlnڿ>"hykw$sJ ޅF&gJ*:S吩N9(NN3dZM4zQ]XQEW7G<O'3[^վ/ů^NNtM"_/u{;A}N!bIĿ :GߌZ? ,~ϟ@YԧI ť:sWJpm5{6iprR39F]X6og?>*x2?kםH5ߵb GCe|9~ڿgOX}: OA>(h³w&?`332v?_bQEu7G<O'3[^վ/ů^NNtM"_/u{;A}N!bIĿ :GߌZ? ,~Ϟ_7;Suo j:Nc:ލhiW}{N7xL|Qi:|Mi:]|\W;xFյzMC9vyxrEk|w߆,&xGzv½gL> xi۫)Jۃ\鮊Oi.jeR8jSJ0(y~2m%Fex6 T/eb9a+dKQYZCѼOgIGC6zhzŜ:ڶ5ņvcq=M,2t&M4IOTZ4BR(Nq&eE(-'Ei4M\(dQ@?~ɟj߳?W>?}e2?s߲gfkUφb~ ٯ=ս@_NFF}ܰWpOpヱY6?[!k7 9Ab5yU8?)|WOc7yG8[. (Oԏ~!~gPKKZ%ǃ/[\{ 2O4;O}^*ό&[-C߿ ?E.k |*gק/4?~_dž4fO.5k .mF{3NKx@oE??οUc=UuM*2gVUݗ5YJri]^|1ࡗWN zXДiVћ/cQӌEJs(8O/S K~'؟‹'&k7 O #$Abk}+oW<u7&~#. -B~#gG /#.VpjW(/ 狵k^# l6#z/Snn^x˗7ʯ?[oiC€o<nA GKY+¼_7?BI&-g+(߀<9 ?O4Fo_U?+߲.O#?|j+/` ̷$EεltYx;4^1sojƷ iM|iw'zҼ;-u㿂|u?xs7%>U|V~&|;gI?/g< Yx)%8Q E;1V +~| jf[8_O ?0g_J  {[_z>y~~/|i¯&:?O_5 ~ W|' A 7/~xZ| 3cǟ~Z6wUj<|Ft~E滔VrytJiJg ʱietaV9^2yt:InV/RrET0.e՚ះ/j_SCWů fy?|AO/bg®gy×n/)M?a:2{]S_?Ghtk5cQc*;]:}?Kmm|Y\jx@vOx:Jw~?G%?Bg XeAE}oH?I?  /T2WMah=Si4y\J*ԥ8K z4PjQ%8 ŦO>rv??|Z?`g _ٿd/'* 9};Rھ-|TNx3߲ag?w?D}` ̷$|ᏇGA. (W_X|m/!ixRҴ7?O f7 9};Rھ-|TNx3߲ag?w?DO^}w ~Gf ON]}K+w ,ψ\, j?ŗo a(Ny?_}Ծ ?_4/c3b+7_]>ڞ/$>0u=_P /YƷ7t$xsZISj |h'Ÿ]x+Lo;_>g`ga{ZPF2M5(vMJP\a05*J_,E/0pu)VN IաB9Bta40%Z6K<'|4x|cOAԴEMߌtE7t KAFx~׼i? ^Դ᧊<3 ׾ xNGWy×n/)M?a%$ޱoVC]k>?񎄞kR? u_OMSi gշO@ A:v Q]FM7RK^8׼9k8񞅭hKxþ.Iq|>;?xs^nJu>|Zou4->ź5t?д+ ;~/ſ G_uOOg[NXLgzSmW/Er6Ҋ^҄~4sCy^kaq\1r^/+ƝZ*e4pfcZTiҡF:^aRJ pdq/7 9};Rھ-|TNx3߲ag?w?DKφ~w|AO_?*i_'krv??|Z?`g _ٿd/'* 9};Rھ-|TNx3߲ag?w?D}>,'Q3-~ (%y×n/)M?afh]\~iB4ԢiI7)Bir2_f Re R3 W MWRiaqTtZ+S'NCUaSWO^ďx࿊>5?|;G/SӮk SI,.-F{;9ṶXeGla0R\5:XjJ3[{JwnFܠ;)l^ לL.UI{S8Qc^Q)b zPnKφ~w|AO_?*i_'k}c?iALy7|T.,.ln>61gxMҴ7.x+ a7ۿAKgjc<awOoW$? cذ>g̷̲; ,WP~K φ~w|AO_?*i_'k/6?^#յ]E:W<7jj^"Súl7_]~ hV|OSL y_÷(pwt_Yr]8/YA[' +5p8fx1RPbfqIG KhWTVgyڗk⦟lwvٞO,_ef ?؟"^|3ۼK hjcSO?;_~;o'/?~_OU {CNxΓ? xIӵxAl}^8u 'Yѵm>k SI,.-F{;9ṶXeGmZXI Ma4,[3ƖU)Byng `P]EN2ViVjφ~w|AO_?*i_'k4l4'Z|% ex×[[;TMoMyѼCO4[=Z%Y^Zj6ehIt,iNQjgz{,I(Ƣޥ4Oނzz5cÓ)ھu'U- JrJY; )nQ]QEQEvV2[1]_xBU 3s=]I;sweIkI|%?_xj+[moSS55F{QZ1r&uWY`s~PO'ouP@?jϮ ƷzR|R(e񗅵]BJ~7^> ~,|S O>M#?~wP ZG4go=CLln`_'n_ ~_ 7şh?hݎs){o6':|;EuS/%M*QөZijgZkDRUmFhMJzϙW%ʧRJ*QI7'vN?(g/k|g~Οu/c=3?x6'7xW,]xk^o?OCPox/Ozg}__ bӴ;f֚E^zvaC~t}'A~X>N5"n.-JJt殔jm4ӄNgNrxʸ:# )KQBPTΝ|=ztqXZ1t(Wx#}3>[C4Z:Nwk6v_^ӵ? $4xCNiN:uW_?x(_5?m{V{i:w;Iӭ4-@:G'/~1jN'>zogďj~ Oص7_+,S,5k7bl_7ȽXRiԓU(֊Pui&QMRntfd ҫW|fiGfQX"Q E': u*ҧCCutQElyEP^C_;i/?>6omwGc{_Y<ϵw; C+h|+g?|>e|9N(l} 3/N]ArO `=8j `9egA>Dѵmg:ޓy|^j^#\xZ78u _G?x?𞝧DY,/#x7^$A״?z71>#׈;^tFWXPuV渰4RNln'iTvկu\k?ڷxV|Gw4_\޹Mx_O_ꚶqwi-ZOy>}O2__x'Rtg':ZRv&+VWr(Ԩ0̰ԣל>;8,EI=14 CZrxjt2ӣZu: k:O5='N׼=Q={C,4gFմ,5M'Tӵliak4iM4zѦg8'Bp4(-FQi8-4IjES$(+{A>/6?^#յ]E:W<7jj^"Súl7_]~ hV|OSL ~MTI8Ө(Kq{NI-kSNOڧ֫Zui~x~Oz7%t=tkzNx{:gzYèi:΍i\XjNaqo}j67 ʹ*;r/>6og?>*x2?kםH5ߵb GC^uρ: xWmG~xsN 뚽ڗ5 jzƟ'+(%%j@w=soxËQQ(Ն>iTޮ kfhVrƕY$Q%,.*1Ҟ&Oקj[aQEz$Q@Q@4'\~!|=ѵo*/iךsWRƿa5mR][B}d6OCh~)ocY|G:v:g:6qai:ŽOg{g<76K _)߽7( LV߾  ?wO6?h*d5oٟ {_{w꿠'UaɽC?K?ӟ&ߵgv*Cӯ&ߵ__ij)|V}|/? ǃnq\@QE) _zg_ڪ^<5??~xWZcw`xo|o[S|w<+egƺŧ?k?^sx Cu#!og^?egⅾmrwF_xgi<>բ,j: :NxiIn-bj*t׍βH(FT84ӔeM)7 <$x^YUGC/t0Φ#(gP * F%R*3:JέOoÞ#_ x+_]=굒C>=fx`x].gK nn촟i6V}ޓi>o+8ԏ,qvd^IN .*EŷSNyף=*PMRE29}nMODך}:4OZ=՝͵孖jZO4WJÞ#_ x+_]=굒C>=fx`x].gK nn촟i6V}ޓi>oG _Eku-jz&!ѧx-x-gInm-lmVԴ M|AUtIKUpVhkçՊѝ)<+c\iԖ0׿*(((Þ#_ x+_]=굒C>=fx`x].gK nn촟i6V}ޓi>oG _Eku-jz&!ѧx-x-gInm-lmVԴ M|AUw˽&މ'iqs-1] [;OC z_/ /Ioq:ӔdӭJ)iJ8R+ޜ"Z1uyT5ZY(`1!J8Jv:N0OQƜpjt1 x UҥZމwSo,[[ouo\[jZFiuiwVVWDeF2$EEEiUZU(TF9ѭFsVXJJU)¥:攡8I8JQiA_q~>*/|boTz~~>+7?I ï[^ o xNMc_-^1)^u'E2%폨~Ŀ xO/m~1κV㏃)`uoQa\X}ytlҼ]j~&vg3KafΟOeƿV_ < 7_!ˬk,kg>@? _>ZA/l&[|9ԥbHzu(q5TiTN֝9I9FJ 9uYSJ'cG F.gdaU*RUNIRu: k:O5='N׼=Q={C,4gFմ,5M'Tӵliakj?xogXռM?"~j杮OyR5|FPռa+]ZUŏ W~.}Q%~3ֱɯx[>SC=uk>Շ(l5 '.-,,|?Ԧ1ғpO^Vi-Jm/ݖq0 Vc+ƕYeyF\'-ǩ|+O?NLW G?]3ۼujcԾ'd&Xۿ+K?_;?B2O?ϳ=-¿wnw^ijnh}Úlnڿ>"hykw$y?}KP'=KZigwOeZ> Ͼs+ ?  J HxkKn ?"Ju/5_-_~;վ3 6װ/0caCK oa22>~#wO_#z´a/weig?| 3y?}KP'=KZigwOeZ> f;(ϼw3/d3u\k?ڷxV|Gw4_\޹Mx_O_ꚶqwi-ZOy>}O2__x'A״?z71>#׈;^tFWXPuV渰4RNln'iTv/ǩ|+O?NLW G?]|W5Bm3ⷌkGWOmS\ӵ> jZƿO_/3k~ ZZ[^|J4OgnQt{t[ { qV3*C5T0幌c)(a3xTp؉4 *ߴT?)~( kXd׼- xCƺ j6  bZw>SipIמ3ۼujcԾ'd&Xۿ+K?_:Ii4OTXk4񥎥 J'y^gBQveai4M&O_:?|_ O?},|D|?/?WEGm'/CھG/i >>_">ho?g+?ɋ w3C}ٙ'ٞEyGm'/CھG/i >>_">ho?g+~#wO_#z´a/weig?| 3?ɋ w3fe̞fz|'z]'V} >7ǫ WD E ߀nt xƏxWt7ڧMGњZ=h/ǩ|+O?NLW G?]yŏxHsC?VpOgoz']K KnL?iZ?o s&Ogy"L.¤0S|Tu%uNirԇ4\RgS=qb0Gy~eZR9Ha/mJXB2FmB4WcmIcC .?nl_iOxzk|/'^7:~֞4ѿbO/ǩ|+O?NLW G?]v0$Q$M`qNRk $QBR{ΎPI18dg<.9fa5NJ5p1U 3+Vr#R*LN]^EyGm'/CھG/i >>_">ho?g+~#wO_#z´a/weig?| 3vbǟC}ٙ'ٞEyGm'/CھG/i >>_">ho?g+~#wO_#z´a/weig?| 3?ɋ w3fe̞fz3ۼujcԾ'd&Xۿ+K?_O_:?|_ O?},|D|?/?WGh&/1?; 2y}jjJjjVWxvn~A>}RV?ocn#/'&ºxZ-I9y,hz~{ٛ}-͖:I;_ُV4wO^ҿd+Uٺƚ7I],;)a8ج2\NXtc~j BIaŞr^]"rm[_%k{y⼱Sҵ; mKHۛ3W.5=6YRNNTZ*]BIդmE6JmћQ'J]:QvS՚Gb08FSX,ka7T tf4)ԫJ M ~EVǜQEQEw&k:eas[ _9|'ƆwWa Wu;5}" Ozߋ!iuu xMOúΏ[}gE{{x,o/帰NR5}6L˫MOM*[520-cCquq໋n氿+O:g֧N_<(ʌJiʔZQM2nF+VۼQGz'إVgNRqa 8 }iƝ:B]֛)ӧƖ]Ւ *tT؜uSseYf+ 9n,5=+SԴ_M5}2Sn.%ʭ(1d%(-8-]J-]4M4֨ҩBJ5΍j3*TRNN)ԧ4 IpRM& (^4~_woOI.|h;n?&un#|Ytl?x_ڇxJ |JV?hϿx;CGmucTأ-~-~#hͭ?;,t/gΫ-s߇_M]}/>㿄<}xh|wڃo(SUiN./^ӃKG%ӄkSaj6)u֝Zoߡ^Sލ h~)ocY|G:v:g:6qai:ŽOg{g<76K _1n/؏L7ov"hykw$W%Wn}/_sMQ^?Wg_3PosH@+ (>S1gQy{4x~/u9y8_=zg_-F[_xFѩ^]?VQ_)ɩ٩)))٩ɩ/ ǟG>+Š(e|9~ڿgOX}: OA>(h³wWL4پ[??W^w ?~'V~.fqf_.+LT=SSSSSSSSڥ>~YF\agR׵ F랔RN(U:Xϫ{J5gX#ϛWU§ձoiQqjOg*ЯK0xOMOOYOOYOOMO)挣VU)e Z+/=ջ@_&3ٿ|s<ko~5WQ,?/7a~_Mjf?ӵx6?ZNWKp2{ ɻ?iqQE~/ ?jkտ_:T`QEQEhޙl-|]\Kw56\_~'8.? wW~/׊)Υ8ԊM(N-)ӚSiٴN:92*p*ӫG,>/)Fs! Bn!R:uakPС^j~t}bK:,V[yca}g-ņjvږ7Zf]ZjzmՅսĹUhޙl-|]\Kw56\_~'8.? wW~/׊)[[5?w:>m[_%k{y⼱Sҵ; mKHۛ3W.5=6YRNNTZ*]BIդmE6JmћQ'J]:QvS՚Gb08FSX,ka7T tf4)ԫJ M ~EVǜQEQEw&k:eas[ _9|'ƆwWa Wu;5}" Ozߋ!iuu xMOúΏ[}gE{{x,o/帰NR5}6L˫MOM*&66~宝:Num,uHRO_5 [[X#3!)m_\WE־I:u"')Vsm?m2x+&F*nRsZ֔VgB4e9n*V(eU*tjajK5;;;RӮ,u >kKI#xxhfGDWVQVM&iN駪ikfx)Bq' 8N2ڔeM4iQE2B(OJ?Z4iSVU)2 :nhJ7\ʕJwWeB)ԇv oiF?q<s~{**T; *<.-SZbp8f dࣟNc_x3ͳ>"zďÚ~"xÐ|"5χ -"¯W/|Q]mG?~~ܿ (~t xDŽOmzmxZSimP׍5^  Bº2uO%Oʟ?ST^q](FMsqNtjiiEMaVӜn8yQҔqXJ9SP)b0աQq55qX*,f#>XY/`e?F~"-> x_ؚơg Ե 5] S.>iu^\WS~qc(~ѿ> _Cgރ_j?5S '⧇k[Y|')GԴk#^,o gO?C?g5π?<;xᾱk㶋uhMᔿ>8_7wx;^ _QEQEՔWjjJjj| ;/<:v?y#ϫ(<0?yi}?~?Sa_'?feAnO?]/>6og?>*x2?kםH5ߵb GC18陜Y@+ OGlDž|ߴh֑Ư/t~???ux> ::7x6!}KF9weekYljm'~>!Ysi:7X\\X:uwsms զ(5 ͮΜӪ8fR)TNQ0ZJ V44cQatN2)`5ht{\h~!k:xVӼ9_\޹CwƿjS\_ꚶqi|Ӯy>}3G}N__ZEQ4ӄR/ $Z,9a%ju0ixiV+П(exNEQZaEP߲gfkUφb~ ٯ=ս@;&ɫ~o\n/;O[ߴ Ua?gxMw[6?ZN_wu$kk;_׍_Ӂ[Ku? ǃnq\@QE()^|][I[K:G;W g >Myus3oM_DѮ40{H|7I}^7##߂ ڟo gZߴjڽa&Zk1 L.4C.:N|V~'~4_v|'5ǟ|Am?)$`GHoύ}[7H%f{e5"tMXQx/\S&?c3tWUb*FzꪝIBΛ5mSͨU"e)Ӛ8%pntI`qU#ZjSmR۞ҿ ƞ#QK RJ r.LKN4y/o&{{;K{[Y yI9]YEZwt[};^-n!lm!Km?~4.^8-mm`+xT0|Ur]Zc_XiwךfgujZuŎ[i}c}i3Z\$sZ\[M Ȋ&G&J5`(QTo[731+ 9WW*ITQ.iaqQ4ֺ~;V QElyEPEPX ӼSZnq ci [i rkkkqX3wҤ>-+⫕ K5;;;RӮ,u >kKI#xxhfGDWVQV&66~宝:Num,uHRO_5 [[X#3!)m_\WE־4);m ]oW8%ڌF40a >"mF9b6Ҏ2)(2ib Σj*}yjvwZv]\X}֗7֓=ݝG=լż̏t&M4IOTZ4BR(Nq&eE(-'Ei4M\(dQ@z?*i%O(SeVu-{^ДnO*h2XS3ҍjYy/UUplvTx\ZSJ+q8$~,WUx _ ŞGÞ*🊼9k7|C4-^Tѵ.Q.`U?蚦߾wP|~$i"8_Iźƿ/i0Y|P.O ^x3w?n~-|A}MVٟ?og}a]/;w?>&Ŋn1*kT,"vUqT|;]Y"'(GkT<|2Mq|]W/@#wk_#zo·a;3 eihy 3)yO_=7[fhwO w[1L_Q^yO_=7[fhwO wX.IN7i+|U~'Lj~ xS׋h:ׇ/|;4IƓmam=;gV$]U8th>]3~('A;ĺ<;_Ix[ռMk~,))u+o!7_wdfmnh*XN|ԓM(n6c)J2!iE9GީƮ*9v1g*N+ϗfJu+cpc>lfK4'5e|9~ڿgOX}: OA>(h³qyO_=7[fhwO w*\XZXO7iZ4A39k}GtF)bgc3oL?z_+<;y? k>Ǧ+N3?.W ?b ۼ_tjc~g'dy_x+KC]_z[1N߭f;eWx3w?n~-|A}MVٟ?og}a]/;w?>&/<;y? k>Ǧ+N3?.W ?bY@͡,̷՟{AS>>^#u>״=_C״=bm?Vѵ'PTuK GNya]^>7߈Zέ?^#մ|"=FW<7j)Z_Zh_4s|OLQ_S>6}Z#wk_#zo·a;3 eihy 3.OO=~vmZσއww^i:ZXm#AR;FI< O%խQ|*Ox3Śޭm[[g?L|eN[|O|"&6k}yO_=7[fhwO w6.p'Eݤ8bpUW& FXGJ2jcRBaZڐWQ^yO_=7[fhwO w-+⫕ K5;;;RӮ,u >kKI#xxhfGDWVQV&66~宝:Num,uHRO_5 [[X#3!)m_\WE־4);m ]oW8%ڌF40a >"mF9b6Ҏ2)(2ib Σj*}yjvwZv]\X}֗7֓=ݝG=լż̏t&M4IOTZ4BR(Nq&eE(-'Ei4M\(dQ@zMll? ];:u/7X66j/G-o ci 4^lkkkrx1$>.|U[e Z/6V7]^]iږuo}7Z_XZLwvVHC2$ jSrj6V ѓe:op~u~1 WWZQiTQ.Xⰲ4֚;Ѭe hGsX~ dO._~"/3hڿ|Isk>п|AχT--u0<|M%į iZofiKb>XM-ڮtY|-Q1Z|6/;\WY*c;GSV; #싡'x_U7_i!?+'E᛫ج{UcS[,SmsAٻoYM{IiN7W쪧xw2T11# }#\<5:s_0~_A\|Ÿ|=45QмAx;>6,Vx~6#蚞]KQ.u?xC?Z!EPYZC|1}IG:|=izhzŜ~k:N ņ:}o=[\,26M4ij駣M=ktTe(J3 JP[((4(iM;4:'\ѾBuo*xs7sWMO~"Ԧ5mRB-]}g C/>6og?>*x2?kםH5ߵb GC{AS>>^#u>״=_C״=bm?Vѵ'PTuK GNya]x\#VquM8_X7=nuj_ xSuWP&yC^jόVzoMW97wJs(”Q-\d9]853|4J1q]x0b1bע+8(( {AS>>^#u>״=_C״=bm?Vѵ'PTuK GNya]\GYյy [r|j7_+V^k|l7XF-o~-s|}oK|ZO#/;:g}YQuGIm5_5N׼/ vOxzxIʣ( ((+$z_o/Jww ^Zϊo/DO%GxSo-~x:,K$Թ*ASdm5tNirԂ\Rg7ꓩA\JI:sp8GVz\>{Jq]JRB'1%QZ!EPEPSOƟ?*T?*TiէeOJ//N`?yΝy(<0((SeOV?ZTeJ|*Υkۚ=)RFP u!݂}[QO8O"|ʽ >{J T{?iVzX'Km#Qow0jh 񞏨x¾{?/u {_/>Ǥh^д7ƻ;žN:~ 6tg<1C8*VR>i84)S%IOQEjpQ@x? xS04^"|#1|e փh)Ѿ"*׼;+^LԼ!xoqxMEw ^N}e|9~ڿgOX}: OA>(h³wc/FIJ2('EКiMhѭˍR ZIѭG J)ʝJU)ҜԧR J'$M&yiJ:ʔ*m2m(ѭ&۔-֣*OUiRT)ӣNu 0:US\.B*UsTpQS``d@ExEPEP)x_7?xLuoK41^:Nc:]W}{N d[|%-4'Nt ~HӴ >tc4 K𾓫b;i:c? r7G#x_SwtmVC6:k:k5ޝx_~״3Ğ='Fx:i:vmJrrUi5\*6K&v:JTe'(uiUpxQ,:5*j:Q#a)Μ%RPN$SЧNZ140ɟj߳?W>+fV_&3ٿ|s<ko~5cQ,?/7agou$kk;_׍!ioڃůٯO^5NJ_3?cMQcN/ˈ(#_PF(?lCŸ W3~?'iC(/0x3ߎ&Yx_y_ٿ>9xW\𧋼5 KGj&w___^}W;W<QExaEPEP^%Oʟ?S+*erUK^׷4%zSJ;2VCZp8E9?iz\*}[~ҭ 8N3(SeOV?ZTesFQ *{^zSuW(¬*S}[֣S8O;b=| }[º=^\NbJ(8B((S.^9KS/&iqmIm<}ZܾB%Otƾ#K/C@ʵc}}Yze֝iV~cq5qiygwnkuk*u*f|M*o}wM4Q?j:<1rSaNt[<]JmEWQQ@Q@o=OLӵ-:O,n&.-/,9ng9 &dI#uuVOۏ+U|3g[GíZo<+xG@4j^_E?QWƚxAkĖ:?5 Z=2NԴ{?Pdx絺8緸D$XcRU)V(Kx70xьJҋJruލd(w+w> x+W7&oާkzv?+^+5*j 0=CNV⨼=MCF'</>&xrv|%y?`e _ٿk/'-h@5S ~m[ğgKĚ|1Wo<9 /R<+)~)i?xs|B}Y=i~3uM&# ڥ7 }^KU~i`+؅OM4N7W?Qg,~i_?W_ \iAbhg qy3Ö?n߈//MCa.W^ _??h3(91*q{ [Ǟ~!Yi^W -4Km[>PqS)5UedQZO0mMѭ&GjU_'իtb84WէJ:q竘ԡ(\.T,bp7|Lۼ7 gjcKSP?;_~˟?;׈?~_OZ? ./>&xrv|%y?`e _ٿk/'-zɎ'Vy_~>&xrv|%y?`e _ٿk/'-<9c;MھT<Nx2OuߵnhxC?K91*2ZX~ ?53 ]x+7ۿg,~i_?W_ \iAbhg wQG&;pE[_}yK_d5oٟ {_{{wLV߾  _w_5h٨Ͽ[ 3 :mPص5ƿ4IAbv/x1&(eEWW,,u VY|YUPQEQEQETOʟ?,NozfKC.L%ŴZ%{kr5 >5m/ľaQK&&K|3i/gN_:NY*PJ$hu*NMG9e95E(<0((S[ǟiT3D$tȡۮ]Vk['־(KyM6ZoUm*Ս}g闗Zv][i֗7֓%ťݻ=լ=$̉$nܜjAզ'\eNk&T-cg`\L%[)biAԍJ*hbzGU*|קRZj.JQEzMlo*uᏛU.S/.KN /o&KK;w{[Y{{$IH]U}ccx~NNkqZu6:/sxz}G}?XĐfWm+h yxv&6跢{BovN1#*f#1MIG8h JOiMQ]'QEQEZ=2NԴ{?Pdx絺8緸D$X ws .|N[[3]GGk]jg>"Ƕkv<1⿇~5~+#?4?ٛ_>%~Կ_?F)l|{{|G-i7 lOHwƯ΋薷7񽆡ឣ;xF_ |S 7o\RU)V(Kx70xьJҋJruލd(}O*F~4ּkK,V}3~v*? G Sݽ?%&'t/?h4h~-4U*ogRiʕD%m.MI^3H9Sd`傯ZHl.j3 )44o' j\E:LT)b+&^}Úln-h|Te~ ï;O?ٿ_jۿk+?zyϰsM % ;ui7+ Cw؟|Qg18陞6e"bC(;BG}nizhZ&?<3=xM񏃵+RV5]S5+Z%x |Y=o(#8M)FJ>SM4kBl5juT*ԥ tM4&88-IŴSčr\SZIо1hZLrh^X3׃,o,tɾ),S/{SG~":Եkſ[ix^#ᾇ7CK[B4-Zxgcg}aڕao[jΕxK~ּI[ž,|7] ~+Zi:- IZM |Ze厙7?wڥoho_Zxu# [!wNTUnQ*vQ%jOүB:LviT|~Q_kX97Z'g|;tQEt@QE&3ٿ|s<ko~5ɟj߳?W>+fV_@?9O5r^2{?~_Mjf?ӵx6?ZNW_8cX~=?4l(Q?R H="]_.]^4I1 5?gڏ^Ouo-u>yMtOj'п9i_FsZA}?_g\5˿ i7ċ5ڶ[ X'}.\mktV?{CO[i?5'~o^tFXWjMCItm[OTuK {;QxnmQ/i ƕhs' Bm%'n]S4k #H;O:e0I/YE*iiFUX+6)'N}m(MF*S(NUT<%( ҎaU)GQsξ (<(V7]^]iږuo}7Z_XZLwvVHC2$ Ri4Ii4iQ(' )Bqn2ӌ$ӌii4zMlo*u:odö&PzohMBnܲ=9eVc sac)pI("' !)Wi)6+B(( V7]^]iږuo}7Z_XZLwvVHC2$67 :Qoxm,uH^Pd [[X#~ !)s /WZ~Z=2NԴ{?Pdx絺8緸D$XcRU)V(Kx70xьJҋJruލd(U&67 :Qoxm,uH^Pd [[X#~ !)s /WZ~U:i ڥ7B_ZIjY0rJ N5aqTTӳN7W?Qp(8Š(X_iwzyujZuսXMi}c}i2\Z^YۼsZsA"M ȒF*IM&iz4ѦEFR8JP$ Ÿ2N2N2Iiӹ:ō|=xGmMLJtx`әu>,&\jPAxI=3s0bx~gV~r6V[g}acyņjv:njVZf]]隕ՅżNiΙs}oxMf]VMw-N =#WSާui_xS~?xy*smє6ݣw NJj*^ح津1Ju34RSRy1e*t𐂩F4RY +h '<#oxPxG EoLei:cĺ^57GQ|ɩkkڷbKj[-;IӾ6iNwih>|/Nj!i>}'WwHt':>~-|e{AϟA'¿Co3@76wFwH|; Nռ+/ υuM.O,??#~!@n?_>kj:.&k_;ß> ?<׵Iƥ99*X_z`~ΥvnD*2T:8(h³wx#(_4σ5?m{Vl_ ~-Kei:w;IӮ{_-4:X4{ '/NXO>zϰsM % ;ui7+ Cw؟|Qgl]H'.&3Njm&M4QNS8^^}c9SN]r*ц#9Fpr!N:\US ( (  ?]jx8v>3u;; 7>ԯuK }ZTtmOLtk^3O<7߇-g@p4+4[N4ѭ թסRTR4'4Ӻd$8'O5˽rOkM'Bši3Qɢycϋ^ &NTmMMR5nx|߄?.]yďK.m Xеhc[?xzk> iR8ѨܔyԷG`Ɠ*k1SMI+fV_&3ٿ|s<ko~5WQ,?/7agou$kk;_׍!ioڃůٯO^5NJ_3?cMQcN/ˈ(#?~?Q{мa&ľ?|Ch|⏃]p_>_~$~%f???IQ?GI? F+dke}7SR>y}ON/=[QegU\zU}!%QtVʕ(U)s[+A5+m`b' X,*L φQK/Ps'((KZj ^%Oʟ?S+JerUK^׷4%zSJ;2VCZp8E9?iz\*}[~ҭ 8N3(SeOV?ZTesFQ *{^zSuW(¬*S}[֣S8O;b=| }[º=^\NbJ(8B(X_iwzyujZuսXMi}c}i2\Z^YۼsZsA"M ȒF*IM&iz4ѦEFR8JP$ Ÿ2N2N2Iiӹ76>9tַ|%[icB:<$pZ3eIaKxV|֋ͪՍ}g闗Zv][i֗7֓%ťݻ=լ=$̉$nÿ,l|[K:=hZm<;ˬ59d4MR #zO=ŤKw9xwIBR)ɻSaJOw IӖ2jqg87V(Uq1J4(SlF6RQJZp*RZoͨ3> 7~h0u-{¶>|v<'>㦠5g'O5 u{[>x )OKQQR 9+]өRiT(N:ydtqRjT+]ӫRjJ(#WWx߈b; ˠ:|_GڌZ5 k׭~&;׵xN/x[>xW}z/j>;Ŀˣ! O>bׅtuMNv𖤰h v}:}k߅6_#8]SAe? |ck_.gm~:'5??RNuχ  O?~!xżG|G|Kÿgm3> Tǂ|{KO=^Mx:_7 ۼ_tjc~g'dy_x+KC]_KxOů:| 3C} /K?®/X޹wⵦ|bд`gůXX|SY}_6Euk׋~ Z& *G_擛>2/ϻ<#wk_#zo·a;3 eihy 3)yO_=7[fhwO wxOů:| 3C} /K?®/XSk~¿~ 7/IgM½o_I+mOz{;_O>wkXwOXx.~y~\',[1馚e,Je%(N-JJQjI5V#_ o1Ԅ8:uiUS:UV)P qjTZJU' |[J|7~~O )|-ڏK_O> >!]hn—|+_^x3w?n~-|A}MVٟ?og}a]/;w?>&Oxo[ⷁw7_#_= A]CHO?4{_n5#_#*<[ >%c; Dⷁa}K_#_AtxO^m?HO?5}#_#W[x(aiJZ'eW$Ԓ(ƼRnPQJ**؜nX~_ox'ø?P4IAbvCӯ&ߵ__ij+g 'Ɯ_Q_'A_(gY/=[QegU@ EP^t-iZ\oD4˽o]/8&a}GiL6KC*Ս}g闗Zv][i֗7֓%ťݻ=լ=$̉$n*Ҕh){)v&*1U!ќjHz dpL%_.Jqh(A˓fURx5:|D+qX&"76>9tַ|%[icB:<$pZ3eIaKxV|֋ͩӨ&p]S%85[3,$_ ^.M5OM;=~z Ȣ+C(+WD?vƏs[_9Q{y峾Sҵ; 7W5+k3W.J\)J1\d$('E4Ѧi֌ҕZ*ӭFJ5ԅZUiNTҫNJtS Rԣ$LﵽLt˟x>Kxk5ǂ."kn/?wYZ;Oxž+Z&wS4{ʎ[ouo-W\\麾[]iuwjVVW:މk:eό<m[ _%Y5wWZCa5ܷu;,^{Ozէ<_wuuOT$nTiUnQiFi6ܥ&h֖U~ߒxR*Y*%:tqiζ?FJ*qsԠaEJcR *x V8l+Š(( ][;k=o|Ghm緺+ OJ..t_Hԭ_L5+K yzoD52-,quq໋![O:zFy=֧N/֮~r6V[g}acyņjv:njVZf]]隕Յżԧ'%VQ]BoԲnmӨFRr'V_GRR_V5b0FxU% tN: tUCCeQ]iΙs}oxMf]VMw-N =#WSާui_xS~?jԍHg YNMi6Ir(ԧ)Ӝe,1::N:l6&<( 89Bt _^l.* ] )QEhrQ@jާNX~k*;Couo=ռw7\XjzVaqsFmujeޙZ]X]\[˕E)F2de$(fz4֍=њRVZuԩFJ)ʝZUiNJu RJPZdIM2k{xFkcO [7w-ukj/ ]ۤ7EkÞ#VZYZ蚚M>yG-y-dVѵk-7_5-'NjÖ1X Ku} 뤲exg|' )=Iu$w>M&Pu'ž<%*.4jI.ѣZM+-)ՓIi6zK0lNGan,^ ?PaQKΜExEPG:?h~_7LtmN+G Xo/ _i|?Wuz_iƍi<W|' ~ ?k;7USĞw/?3<#嶱O+v]O΅/O x>;3S7 7Ķ2ox,\!)K c)JTbmIݑɘFScasB)RF1MRm$mdgďK.m Xеh@C|]o|?ßvčs'{M&ĿiOcGlt/-t;=s?}ZF/K}&TNSo!Hc^N,>?i6N9tַ|%[icB:<$pZ3eIaKxV|֋ͪՍ}g闗Zv][i֗7֓%ťݻ=լ=$̉$nܚMՂdGwN[nFgBUVZU(K8,9tַ|%[icB:<$pZ3eIaKxV|֋ͪUM8N.)^KUPjqS Zuir OvWQEQEkzu;mcG- ռVX_EqaZΛ֙Wzfiuauqo.U.2JQqd՚iZ4kFiJZi֣RjB**uiU%:u)ԃSHM)BqjQRM&wމk:eό<m[ _%Y5wWZCa5ܷu;,^{Ozէ<_wuuO][;k=o|Ghm緺+ OJ..t_Hԭ_L5+K yzd2=O69..LoR[]*X>_Hn5OŞ񽞋:3)*sVM&nS*TeVO1Ž*,F )_2тJh00Rl8ʸ(O((5}-լVw֯kz&OxFh'h'KY'մmZM KIjZ#V1x_xB,o^ 3=x_m]Iχ|EmieI,-4kIo%"1筗֟RwXTEv#V1x_xB,o^ 3=x_m]Iχ|EmieI,-4kIo%֔Fy}ڔZ%dROuWM7ˊtk(S=g:*-*Rd81((+Þ#VZYZ蚚M>yG-y-dVѵk-7_5-'N`QS8FqpR}ɭZfhօzjЩ*UKiJ2Mqq[i#V1x_xB,o^ 3=x_m]Iχ|EmieI,-4kIo%IdzϬOYS({h-`H-n|;+kK-'ƚMޡaiZO|%,a9RUFNԪڝG-M?J 851qRymE}^:`ik,EWAQ@5T*xⷈ?~?A?RJ׵I5Om| :7*x!5<=/ _|GwӬmwY_S G Gy?4OxN|$ 5leo~nkO xWUti >K j(P/ |ܶ璽k ؜69ӥnn^yG7̯: ?]jx8v>3u;; 7>ԯuK }ZTtmOLtk^3O<7߇-gSčr\SZIо1hZLrh^X3׃,o,tɾ),S/{SG~":Եkſ[ix]X~ ?53 ]x+7ۿ)_|I]|AWo/o?'%m Y |} mu/M<*u Vfvu18QaOuTh%Z 굨7Rn)Мyեfxe4,8J)Ֆ^EJj' B*iVZ5SxK+|7χq|8]3Ş׬ST~8Q E44_ ikן<9c;MھT<Nx2OuߵnhxC?KeT1Gi(2e'IJN2JIÉa0cp0VjBPԥVZuJ ԧNΎ"Juԝ*ωwA_? ~*jg?'k<sºWo< G%X~ ?53 ]x+7ۿpSG0aº}Q^y3Ö?n߈//MCa.W^ _??h3yo⦡cw?~w+efwC؟~\}AO)ɇ[C k'# f>nX~G_ox'ø?P4IAbvCӯ&ߵ__ij+g 'Ɯ_Q_'A_(gY= D%A}M+q[5ݝ3Njgnl./WTaӡ,Mz(tm#TRb%ܚI]]%w*UkN4өVN%RrNONNNNDz&}QL((c}}Yze֝iV~cq5qiygwnkuk4)kwkN/[ڶi2!}߆mZ&wS4{ʎ[ouo-W\\麾[]iuwjVVWVJmF-f8]9RIY.Y:Rjc+8K)U0ή_5VppsWSІ6eZr[4gLak䷋<&\]\x.+Ho&SqOuoS)5TF[IQ|Ni&4IM9FqjS2\XrVZjEX|^RaQ:sHSNF.z(9B(9; _Kukމ!ѧ 4}b gImo-lmVuR|AZ3g (Y5vihWN Z8ԣ$g'Ÿ8i?Xc|--/ɖY<3ܧPZ%ԐZwV֖ZO4+BIִK\]osw+[;W5SIѼCO4hŴ%[\Yj6eIҵ[-_r+Sin!}tL τg{ X$ [IewXZi:֓ xKxWZk}g}jfji47ti{X{Y䵒{[[k;-[Fլ@Դi:VeJrR,ݣZ+hzzx\UX {¹JX|Dc[/?8S QⰩť^)g{ X$ [IewXZi:֓ xK)ԍHF(iFKxn殚oQm5)ԧ.z5ZuTZTQk/8FqbQEg0QEV&nmW[2xsOUүͽ'OIGgwO^~Il7>Ũ׿~ [}d9ҵ[qwvq^]z~߅u [ƜMƅVjU_QWjn,DbUXZIUCХW3S:jJy[RHUժFr:yv:R<75娢<<:૚?< &>-}žS6GAMWXg߀f-?|@|Aߎs|Fx^tE 5ExO:v_xWV|)Y޳iw`1E~`~ÿ i w ; h }cº?h Kzĭ 6ھ%Z7~jv0U';xPӾ i/΃@S;'؞$޷?oiM$:oG{kf ŸdhkGGU_xⷁ|K9w'~&?ofG>,~ Ÿdk~![GG<+ⷁ%4?WNc '<7[S|;Yq=/ƑxW(I֢'okJ*$vQ&jE*UZVQ_O҇2g9ө79RqZUjJzqlj3 }Z?8߉4OA+x6Կ?AgN>#X{ G?+fV_@?9O5r^2{?~_Mjf?ӵx6?ZNW_8cX~=?4l(Q?R C?/ ;ze֝iP~cq5SZ^YۼsZsA"M ȒF?:@oE??οU&M4iiOFJ)Bp'(-82M8-&iN3vok/7co xwYhl˯Z$6Kkv'>!Ss:FKxk5ǂ."kn/?wYZ;Oxž+Z&wS4{ʎ[ouo-W\\麾[]iuwjVVWRZMFW/u MgRɻ]NRI*pZU}2iKJ}Zteb%AJs T)ӆ/ :f4)ӥV M ?Ewމk:eό<m[ _%Y5wWZCa5ܷu;,^{Ozէ<_wuuOR5"N2%e:sI7 M&i3RNq`:Uؚ.R Fr$ Ӝ*B|=zu41t+ЦQEQExj[Xo_LMM&FSM4kBl5juT*ԥ tM4&88-IŴOr+Sin!}tL τyG-y-dVѵk-7_5-'NjÖ:E|7-֡M~Qڵ5XMɠAm<;具4Vk-oF: 뚾04j7%%'Fj:s{{hV֬#9zu-bhQafX:qʚpTqúp3enJ3px|3X*EWAQ@Q@O|M;Qdk'_{Ohk k4SO+zo b}Qӯ+='sjZ'伻'SK5 ~&WSb}Nl+Ũ׿~ [}d9ҵ[qwvq^]z~߅u [XN5"xiR$FIpRippհCՇ+iJRJ*:UV8Vף9QNREUQ@u>7'tFoºٓ>{}h~mWNqQʭlYƞIԭ:y~aRZvkQEo7ONX~zG~+x_',x NgTom_-C[=Vk_~ ּc:>o+5?ѿ;<?~ ïiD xU[ZX_QEyO?bxz 7ÿxOŚ G' |qB{qiW|Ai/|/_j:'">4KG$Կ'<#0]ϧ蚵uƿ!?xLjO ˽r›'Bši0hGOycϋ^ YNm2TmMcRuMnG|ߋ~.27Zm5QޥTjEm+g 'Ɯ_Q_'Gw_7~2)_?G~"xBqaEKr>k?z=s]ƇX17I|5::ukPWyy_و5 f???IQ?GI? F+dke}7SR>y}N:51r[S~Ӛ3EHB0}l-|gk]\Ei r_~ 5{? wV}ׅ4l M'Z|[/ qu:hv(o-ԓ|Mⰵu-ƥ:FN J-c%(2J( ( |3oOڍ߅u'|,5]*bxD]vwd^~]oĞj*gԋզjQde%(N-JJQjI5[ Z<*I¤% TҫJgJ ԧ:8=hT:kSJsxgZ{]o/>O+U؞*>gק^W[߉5Z ve]o=>O WJ6؞*>y'A>רizW['^mW[K{)mOJl'OywOk~7Mo(NPUNʭUWjI%׊MJ5"ZIEUCO WJ6؞*>y'A>רizW['^mW[K{)mOJl'OywOk~7Mo>&nmW[2xsOUүͽ'OIGgwO^~Io PE^N֕UI)&^IBMԊTJW 0eǸs˧RnrV4:e:::*f}9՞;WS 1o{jVkkmTմMZM\^êWKyi:iE>&-̜i Ƥ#RRNϺiJ-l$M4ppհx\D=z:Ҕ^NSRV::u`R FL*(OL\υ+ iʺmS<+kxl]{O訩N5`+ٸӳ%8J/8Q}$:p*QqjBQTԥ^b(ՋWRrRI49}nMODך}:4OZ=՝͵孖jZO4WJÞ#_ x+_]=굒C>=fx`x].gK nn촟i6V}ޓi>oG _Eku-jz&!ѧx-x-gInm-lmVԴ M|AUtIKUpVhkçՊѝ)<+c\iԖ0׿*+ؿ?kcχf|+ix~&>#uSмUΧxc6z?tϘ(0wWYd~?j?/?gϿkڏx={> |?Z"sO;/ ^{\?O)׈~r7~"|Pw |M]5XxOÖ6@ ~so&^&"VJr(J7eWNz7S՛婈 EZ)+*SF_58kǕ(?g~ZW??;'~__w*mlh|L^x3w?n~-|A}MVٟ?og}a]/;w?>&ŏ _?f;e|Ho]떟:- IE=j{|Zeϊsi:okïnxu_<[^Cwo#C]k?|qAgc?^3Լ6Tխ5M+Y5=Uּ%? k^Ğ-y [/<;y? k>Ǧ+N3?.W ?b>6 'kz'oFn|1kp.ž(Gc/S$Z|)w._XдZxWK^RԥV 5i4k(Tms s0xPX)SpZZ\r(c)ajt*VjR:oLV߾  wo6h*?d5oٟ {|aysߠ'UaWɽC?KӞ~~-~͟?i_׍!ioڃſٷRv*/x1&(eEWW,,u VY|YUPQEVyG-y-dVѵk-7_5-'NjÖ1X Ku} 뤲exg|' )=Iu$w>M&Pu'ž0IRܣ'jU_NTKWi^u 8ҩJ<6/ \ro Nw Nj+(( xWZk}g}jfji47ti{X{Y䵒{[[k;-[Fլ@Դi:Ve?Xc|--/ɖY<3ܧPZ%ԐZwV֖ZO4+BIִK\]osw+[;W5SIѼCO4hŴ%[\Yj6eIҵ[,*Soid[FO؟OWΊcܞR#z}iU)zjO-.ZNxWi?Xc|--/ɖY<3ܧPZ%ԐZwV֖ZO4+BIִK\]iNjG7ݩEJ2[Ku$_5t|-lgFn1N9sѯFzӯBҥ*XyJ3(9( ve]o=>O WJ6؞*>y'A>רizW['Z5"5xuie&FIJRZMoV#>Jn0 Bp:ҩүB)Ύ#Z((ΥR.^mW[K{)mOJl'OywOk~7Mo>#!&^G _Eku-jz&!ѧx-x-gInm-lmVԴ M|AUT(Ѫ5:%nME(mJVUaB~Οv3 F8rah0fe9ESJU`k`UsKq5[QEQ@Q@4l4'Z|% ex×[[;TMoMyѼCO4[=Z%Y^Zj6ehIt, <9;ebޫY$3>g gG{X$ [KoxvIei:֓/Kp):dV]S[*|Qڪ4WOU)GVL\rɿUX);./5}Զw֩ޚOxFi4{൞KY'մmZR57IVX'N J2WMu&iIͯBJʕjR%{de8(( (Þ#_ x+_]=굒C>=fx`x].gK nn촟i6V}ޓi>o**SH'iFKiEO QqmTSz5J+zTQi()Eq?_xj+[moSS55F)K=DЯw xsMguoiG4~Zfaz}SEQE&3ٿ|s<le Q_&3ٿ|s<ko~5WQ,?/7agou$kl|AN_wu$kk;_׍_ӃR ad<wӋ+DH+տ_:U~,,u((+Þ#VZYZ蚚M>yG-y-dVѵk-7_5-'N`QS8FqpR}ɭZfhօzjЩ*UKiJ2Mqq[i#V1x_xB,o^ 3=x_m]Iχ|EmieI,-4kIo%IdzϬOYS({h-`H-n|;+kK-'ƚMޡaiZO|%,a9RUFNԪڝG-M?J 851qRymE}^:`ik,EWAQ@Q@oDio>mk$6wVZYii> tVW^&Ku}yj/ ַcx:ݼi.Jhi$͏?=?þ,\qug؟mӵ/ fOy~}XjUV"ά9[JP% JUiU)ҭB)¶Ύ"Juԝ*((+猦,eOshWإowG7}~TfRuMZ?;8**SX*Jӌ8IZP^ZL8*ʾT%eӫJzT5*85hRznTS9J/7>Ũ׿~ [}d9ҵ[qwvq^]z~߅u [嫩ω>ۧj6_~̞!d@towwxzi߅uxo[oV\]bxD]~ d^iz]o~$ *5]%Y%vQxܡR)դUZT;18j832rR)Ԟ]94V9UW8ש:uO/*TSyj(<((b)OzdϬOY-K`H-m-Eۛ-'ƚMwZO[,rWZKk}g}j47ti }cG Y䵒{[;k[-[Fլ-_ti:e]4l4'Z|% s'Vr_kJkeQ/;U]~ qiq#J(`1ڊח X97'u|;#[)CxwP}.顏PӞibE[3^. _ft Q`SFm68'3RKiFI8MmzpaJJJқR(6EUQ@w˽&މ'iqs-1] [;OC z_/ /IoN5c+82JP_4gW[IJ2W(JQ}X+/=ջ@_NFF}ܰWOpioڃůٯO^5_Mjf?ӵx8?)|WOc7yG8[. (Oԏkoxo }nj*^jQwk |=Iex@7͚K.%?o#\%>/xI/_SX ]\wFxVѭ RI.!ӠloWhU>{g]K*~ۛ|vWsy$2k0kSkk,}é8ק,W*p%<=6TWQ[QWQ@ES\jYj$ҏS.5==3ZTVM'UH@[^Gvk:VMhS8F\&n4R$ԣ()BqjPRRIؚJaV2M!(NVZU#:UV9aBEԣZJS%&'ص:oº_!Ko}g7V`..&j>_iڻRH |)'Z+$RMF"QUj*ZGF~a?gJqNJiukUu+uuT2s2RdR+5u%(ROFMmZrR)9RҫN7(IźuΥm7 NHt(_E2z|3oOڍ߅u'|,5]*bxD]vwd^~]oĞ'0k?_@'m7<)k^7ߏυ>2f࿏?e߈fuoCUm#|PŨ׿~ [}d9ҵ[qwvq^]z~߅u [~*|75s6i>,|/3go<%gf9 Դψ:o7!|}oh:毡ڶ4;Qƽ6qxrYƳ? OhJ~7Chr[NX5TQ9R,WʬVRjx*V#?gONq7N+5Φ.jt}"kaOT<&"똿z+(E53Y- Z?47W k m"Oyp]j~_ KSj~t}bK:,V[yca}g-ņjvږ7Zf]ZjzmՅսĿ_?x(_5?m{V{i:w;Iӭ4-@:G'/~1jN'>s2'Rr&VSrQն*bQޭ%)UӧԅuBZqN:qPf5 t1f5d5,6'%++ǿ hOx|Q[P<CS隿?"]-A^/?nľY||0#MyQpRf8ԓN U?*jns^&Sͪէ0ZS.ja)S,cpN.a[T0LELEL-+f'?g/>6qgA'Fqkx\&]Ƴk>'Q/`QסյHƛPQKs/S7 Ssf5i*NNJ-J3PB,T0!%*ѫ*qFIJeRpi=U}kzf[x??e~,hn.<quq-EqSW,7]W^+Υ8ԊM(N-)ӚSiٴN:92*p*ӫG,>/)Fs! Bn!R:uakPС^kz&NG-k䳢ouo=ռW7rXjzVaqmisujeզX][KT%xⷈA-5<=heGwk>,Ӭn?gGQd7kkڷإ+;IӾ6iNiYkwh>|/?<__>}'H;Wt'?ŏT7 k)uM+^ϚJIN]10xoisQR*SupظACHtԚaT~{Yd~ο,%&G8Ocm[J׿d/W]е=?Z5ٻnM嶣jV~jrMiM ՝][KH:<ln~U|?w_oZ acb sN(rIJq0A6 ɻ?iqQE~QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE|?w_5hA>;O[`qCQ3$߅OgÍ:|y|1 erÏEhHx%:aΆ>5=F #.hN;gx:>3+θ;Fg>!ܻeTyO0U A{ -7QR]JөRe"00n)ͰuF7C  cFakcxgb*EUQMST?0?fCJғ# sFc+:(_FiukkW82Ta??dh~ј:Eu_g]+uIaq?qe|a??dh¾+gZ(u=aLq8|/6'FH:|90?7QGKGK0JYx| |аWÓ6a%t?GF6J֊)Ĵ}dxnlwx/¾јIZ_+lCSџ엧+wKS^69̯+0͒?u¾јIZ(G_3.kzWKx٤lTW ~љI+JO'䮿(3__Lon6sOE|Tq0?fw?a??dh3}4=odoEqe|ד6Oß3;Z?0?fw?QRGU6{%aTOwa90͓u# sFa'sE/?յ{%aL.&}?6z̯/Oß3;Z?0?fw?QM//&+v'-+/# sFa'sGF6N֊)Ĵ}dxOw^Oa??dh~ј:E7g:$Odx/q?mt_w6Oß3;Z?0?fw?QK%F{$o?ߕofOw?a90͓u# sFa'sEZ>g_Le.&vz̯'DWß3+Z?0?fw?QI}>{%կ mui<_ ]L8ҍۦo+O |<19yw[+o3wՆKFl|8Rx)զtq!sĹi0a+w JXeI>H# ;sIXdoc/set_epslevel.htm0000644000175000017500000000642710337663240013510 0ustar renerene set_epslevel

set_epslevel

This is a simplified way of specifying multiple eps thresholds that are "logically" consistent.

unsigned char set_epslevel(lprec *lp, int epslevel);

Return Value

Returns TRUE if level accepted and FALSE if an incalid epsilon level was provided.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epslevel

Can by any of the following values:

EPS_TIGHT (0) Very tight epsilon values (default)
EPS_MEDIUM (1) Medium epsilon values
EPS_LOOSE (2) Loose epsilon values
EPS_BAGGY (3) Very loose epsilon values

Remarks

This is a simplified way of specifying multiple eps thresholds that are "logically" consistent.
It sets the following values: set_epsel, set_epsb, set_epsd, set_epspivot, set_epsint, set_mip_gap
The default is EPS_TIGHT.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epslevel(lp, EPS_MEDIUM);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epsel, set_epsb, set_epsd, set_epspivot, set_epsint, set_mip_gap

doc/put_abortfunc.htm0000644000175000017500000000613210311061220013640 0ustar renerene put_abortfunc

put_abortfunc

Sets an abort routine.

void put_abortfunc(lprec *lp, lphandle_intfunc newctrlc, void *ctrlchandle);

Return Value

put_abortfunc has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

newctrlc

The abort routine.

typedef int (__WINAPI lphandle_intfunc)(lprec *lp, void *userhandle);

Note the __WINAPI attribute. This is important under Windows. It ensures __stdcall calling convention which is required.

ctrlchandle

A parameter that will be provided to the abort routine.

Remarks

The put_abortfunc function sets an abort routine.
When set, the abort routine is called regularly. The user can do whatever he wants in this routine. For example check if the user pressed abort. The return value of this routine must be FALSE (0) or TRUE (1). If TRUE (1), then lp_solve aborts the solver and returns with an appropriate code. The abort routine can be cleared by specifying NULL as abort routine.
The default is no abort routine (NULL).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int __WINAPI abortfunction(lprec *lp, void *userhandle)
{
 int doabort = FALSE;

 /* do something */

 return(doabort);
}

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  put_abortfunc(lp, abortfunction, NULL);

  solve(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, put_logfunc

doc/R.htm0000644000175000017500000003075011170701364011207 0ustar renerene Using lpsolve from R

Using lpsolve from R

R?

R is a language and environment for statistical computing and graphics. It is a GNU project which is similar to the S language and environment which was developed at Bell Laboratories (formerly AT&T, now Lucent Technologies) by John Chambers and colleagues. R can be considered as a different implementation of S. There are some important differences, but much code written for S runs unaltered under R.

R provides a wide variety of statistical (linear and nonlinear modelling, classical statistical tests, time-series analysis, classification, clustering, ...) and graphical techniques, and is highly extensible. The S language is often the vehicle of choice for research in statistical methodology, and R provides an Open Source route to participation in that activity.

One of R's strengths is the ease with which well-designed publication-quality plots can be produced, including mathematical symbols and formulae where needed. Great care has been taken over the defaults for the minor design choices in graphics, but the user retains full control.

R is available as Free Software under the terms of the Free Software Foundation's GNU General Public License in source code form. It compiles and runs on a wide variety of UNIX platforms and similar systems (including FreeBSD and Linux), Windows and MacOS.

The R environment

R is an integrated suite of software facilities for data manipulation, calculation and graphical display. It includes

  • an effective data handling and storage facility,
  • a suite of operators for calculations on arrays, in particular matrices,
  • a large, coherent, integrated collection of intermediate tools for data analysis,
  • graphical facilities for data analysis and display either on-screen or on hardcopy, and
  • a well-developed, simple and effective programming language which includes conditionals, loops, user-defined recursive functions and input and output facilities.

The term "environment" is intended to characterize it as a fully planned and coherent system, rather than an incremental accretion of very specific and inflexible tools, as is frequently the case with other data analysis software.

R, like S, is designed around a true computer language, and it allows users to add additional functionality by defining new functions. Much of the system is itself written in the R dialect of S, which makes it easy for users to follow the algorithmic choices made. For computationally-intensive tasks, C, C++ and Fortran code can be linked and called at run time. Advanced users can write C code to manipulate R objects directly.

Many users think of R as a statistics system. We prefer to think of it of an environment within which statistical techniques are implemented. R can be extended (easily) via packages. There are about eight packages supplied with the R distribution and many more are available through the CRAN family of Internet sites covering a very wide range of modern statistics.

We will not discuss the specifics of R here but instead refer the reader to the R website. Also see An Introduction to R

R and lpsolve

lpsolve is callable from R via an extension or module. As such, it looks like lpsolve is fully integrated with R. Matrices can directly be transferred between R and lpsolve in both directions. The complete interface is written in C so it has maximum performance.

There are currently two R packages based on lp_solve. Both packages are available from CRAN.

The lpSolve R package is the first implementation of an interface of lpsolve to R. It provides high-level functions for solving general linear/integer problems, assignment problems and transportation problems. The following link contains the version of the driver: lpSolve: Interface to Lp_solve v. 5.5 to solve linear/integer programs. It does not contain the lpsolve API. Only the higher level calls. Documentation for this interface can be found on: Interface to Lp_solve v. 5.5 to solve linear/integer programs
This driver is written and maintained by Sam Buttrey.

The lpSolveAPI R package is a second implementation of an interface of lpsolve to R. It provides an R API mirroring the lp_solve C API and hence provides a great deal more functionality but has a steeper learning curve. The R interface to lpsolve contains its own documentation. See An R interface to the lp_solve library for the driver.
This driver is written and maintained by Kjell Konis.

Installing the lpsolve driver in R

How to install the driver depends on the environment.

Windows

In the RGui menu, there is a menu item 'Packages'. From there a package can be installed from a CRAN mirror or from a local zip file.

R command line

Packages can also be installed from the R command line. This is a more general approach that will work under all environments.
Installing the package takes a single command:

The lpSolve R package:

  > install.packages("lpSolve")
and to install the lpSolveAPI package use the command:
  > install.packages("lpSolveAPI")
Note

The > shown before each R command is the R prompt. Only the text after > must be entered.

Loading the lpsolve driver in R

Installing the package is not enough. It must also loaded in the R memory space before it can be used. This can be done with the following command:
  > library(lpSolveAPI)
Or
  > library("lpSolveAPI", character.only=TRUE)

Getting Help

Documentation is provided for each function in the lpSolve package using R's built-in help system. For example, the command

  > ?add.constraint
will display the documentation for the add.constraint function.

Building and Solving Linear Programs Using the lpSolve R Package

This implementation provides the functions lp, lp.assign, lp.object, lp.transport and print.lp. These functions allow a linear program (and transport and assignment problems) to be defined and solved using a single command.

For more information enter:

  > ?lp
  > ?lp.assign
  > ?lp.object
  > ?lp.transport
  > ?print.lp

See also Interface to Lp_solve v. 5.5 to solve linear/integer programs

Building and Solving Linear Programs Using the lpSolveAPI R Package

This implementation provides an API for building and solving linear programs that mimics the lp_solve C API. This approach allows much greater flexibility but also has a few caveats. The most important is that the lpSolve linear program model objects created by make.lp and read.lp are not actually R objects but external pointers to lp_solve 'lprec' structures. R does not know how to deal with these structures. In particular, R cannot duplicate them. Thus one must never assign an existing lpSolve linear program model object in R code.

To load the library, enter:

  > library(lpSolveAPI)

Consider the following example. First we create an empty model x.

  > x <- make.lp(2, 2)
Then we assign x to y.
  > y <- x
Next we set some columns in x.
  > set.column(x, 1, c(1, 2))
  > set.column(x, 2, c(3, 4))

And finally, take a look at y.

  > y
  Model name:
              C1    C2
  Minimize     0     0
  R1           1     3  free  0
  R2           2     4  free  0
  Type      Real  Real
  upbo       Inf   Inf
  lowbo        0     0
The changes we made in x appear in y as well. Although x and y are two distinct objects in R, they both refer to the same lp_solve 'lprec' structure.

The safest way to use the lpSolve API is inside an R function - do not return the lpSolve linear program model object.

Learning by Example
  > lprec <- make.lp(0, 4)
  > set.objfn(lprec, c(1, 3, 6.24, 0.1))
  > add.constraint(lprec, c(0, 78.26, 0, 2.9), ">=", 92.3)
  > add.constraint(lprec, c(0.24, 0, 11.31, 0), "<=", 14.8)
  > add.constraint(lprec, c(12.68, 0, 0.08, 0.9), ">=", 4)
  > set.bounds(lprec, lower = c(28.6, 18), columns = c(1, 4))
  > set.bounds(lprec, upper = 48.98, columns = 4)
  > RowNames <- c("THISROW", "THATROW", "LASTROW")
  > ColNames <- c("COLONE", "COLTWO", "COLTHREE", "COLFOUR")
  > dimnames(lprec) <- list(RowNames, ColNames)
Lets take a look at what we have done so far.
  > lprec  # or equivalently print(lprec)
  Model name:
              COLONE    COLTWO  COLTHREE   COLFOUR
  Minimize         1         3      6.24       0.1
  THISROW          0     78.26         0       2.9  >=  92.3
  THATROW       0.24         0     11.31         0  <=  14.8
  LASTROW      12.68         0      0.08       0.9  >=     4
  Type          Real      Real      Real      Real
  upbo           Inf       Inf       Inf     48.98
  lowbo         28.6         0         0        18
Now lets solve the model.
  > solve(lprec)
  [1] 0

  > get.objective(lprec)
  [1] 31.78276

  > get.variables(lprec)
  [1] 28.60000  0.00000  0.00000 31.82759

  > get.constraints(lprec)
  [1]  92.3000   6.8640 391.2928

Note that there are some commands that return an answer. For the accessor functions (generally named get.*) the output should be clear. For other functions (e.g., solve), the interpretation of the returned value is described in the documentation. Since solve is generic in R, use the command

  > ?solve.lpExtPtr
to view the appropriate documentation. The assignment functions (generally named set.*) also have a return value - often a logical value indicating whether the command was successful - that is returned invisibly. Invisible values can be assigned but are not echoed to the console. For example,
  > status <- add.constraint(lprec, c(12.68, 0, 0.08, 0.9), ">=", 4)
  > status
  [1] TRUE
indicates that the operation was successful. Invisible values can also be used in flow control.
Cleaning up

To free up resources and memory, the R command rm() must be used.
For example:

  > rm(lprec)

See also Using lpsolve from MATLAB, Using lpsolve from O-Matrix, Using lpsolve from Sysquake, Using lpsolve from Octave, Using lpsolve from FreeMat, Using lpsolve from Euler, Using lpsolve from Python, Using lpsolve from Sage, Using lpsolve from PHP, Using lpsolve from Scilab

doc/is_presolve.htm0000644000175000017500000001642110447454052013344 0ustar renerene is_presolve

is_presolve

Returns if presolve level specified in testmask is active.

unsigned char is_presolve(lprec *lp, int testmask);

Return Value

is_presolve returns TRUE or FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

testmask

PRESOLVE_NONE (0) No presolve at all
PRESOLVE_ROWS (1) Presolve rows
PRESOLVE_COLS (2) Presolve columns
PRESOLVE_LINDEP (4) Eliminate linearly dependent rows
PRESOLVE_SOS (32) Convert constraints to SOSes (only SOS1 handled)
PRESOLVE_REDUCEMIP (64) If the phase 1 solution process finds that a constraint is redundant then this constraint is deleted. This is no longer active since it is very rare that this is effective, and also that it adds code complications and delayed presolve effects that are not captured properly.
PRESOLVE_KNAPSACK (128) Simplification of knapsack-type constraints through addition of an extra variable, which also helps bound the OF
PRESOLVE_ELIMEQ2 (256) Direct substitution of one variable in 2-element equality constraints; this requires changes to the constraint matrix
PRESOLVE_IMPLIEDFREE (512) Identify implied free variables (releasing their explicit bounds)
PRESOLVE_REDUCEGCD (1024) Reduce (tighten) coefficients in integer models based on GCD argument
PRESOLVE_PROBEFIX (2048) Attempt to fix binary variables at one of their bounds
PRESOLVE_PROBEREDUCE (4096) Attempt to reduce coefficients in binary models
PRESOLVE_ROWDOMINATE (8192) Idenfify and delete qualifying constraints that are dominated by others, also fixes variables at a bound
PRESOLVE_COLDOMINATE (16384) Deletes variables (mainly binary), that are dominated by others (only one can be non-zero)
PRESOLVE_MERGEROWS (32768) Merges neighboring >= or <= constraints when the vectors are otherwise relatively identical into a single ranged constraint
PRESOLVE_IMPLIEDSLK (65536) Converts qualifying equalities to inequalities by converting a column singleton variable to slack. The routine also detects implicit duplicate slacks from inequality constraints, fixes and removes the redundant variable.This latter removal also tends to reduce the risk of degeneracy.The combined function of this option can have a dramatic simplifying effect on some models
PRESOLVE_COLFIXDUAL (131072) Variable fixing and removal based on considering signs of the associated dual constraint
PRESOLVE_BOUNDS (262144) Does bound tightening based on full-row constraint information. This can assist in tightening the OF bound, eliminate variables and constraints. At the end of presolve, it is checked if any variables can be deemed free, thereby reducing any chance that degeneracy is introduced via this presolve option.
PRESOLVE_DUALS (524288) Calculate duals
PRESOLVE_SENSDUALS (1048576) Calculate sensitivity if there are integer variables

Remarks

The is_presolve function returns a flag if the presolve level specified in testmask is active. Presolve looks at the model and tries to simplify it so that solving times are shorter. For example a constraint on only one variable is converted to a bound on this variable (and the constraint is deleted). Note that the model dimensions can change because of this, so be careful with this. Both rows and columns can be deleted by the presolve.
The default is not (FALSE) doing a presolve.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int presolve;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  presolve = is_presolve(lp, PRESOLVE_ROWS | PRESOLVE_COLS); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_presolve, get_presolve, get_presolveloops

doc/set_infinite.htm0000644000175000017500000000571510237176662013503 0ustar renerene set_infinite

set_infinite

Specifies the practical value for "infinite".

void set_infinite(lprec *lp, REAL infinite);

Return Value

set_infinite has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

infinite

The value that must be used for "infinite".

Remarks

The set_infinite function specifies the practical value for "infinite". This value is used for very big numbers. For example the upper bound of a variable without an upper bound.
The default is 1e30

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_infinite(lp, 1.0e100); /* sets infinite to 1e100 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_infinite, is_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap

doc/lp_solve_5.5.0.12.chw0000644000175000017500000010056311034243741013567 0ustar renereneITSF` |{ "|{ "`8`T s.!"T Uncompressed MSCompressed{7FC28940-9D31-11D0LZXC Cd;)X44 $/'absolute valuesadd_column add_columnexadd_constraint'add_constraintex4add_lag_con Aadd_SOS NBasis Factorization Packages[Calling the lpsolve API from your applicationhChanges from version 4 to version 5.1uChanges from version 5.1 to version 5.5column_in_lp copy_lp CPLEX lp filesdefault_basis del_columndel_constraintdelete_lpDIMACS maximum flow problemsDIMACS minimum assignment problemsDIMACS minimum cost flow problemsDownloaddualize_lpExternal Language Interfaces+Formulation of an lp model in lpsolve8free variablesEfree_lpRFrequently Asked Questions_get_anti_degenlget_basisy%get_basiscrashget_bb_depthlimitget_bb_floorfirstget_bb_ruleget_bounds_tighterget_break_at_valueget_col_nameget_columnget_columnexget_constr_typeget_constr_valueget_constraintsget_dual_solution "get_epsb!/get_epsd"<get_epsel#Iget_epsint$Vget_epsperturb%cget_epspivot&pget_improve'}get_infinite(get_lambda)get_lowbo*get_lp_index+get_lp_name,get_Lrows-get_mat.get_max_level/get_maxpivot0get_mip_gap1get_nameindex2 get_Ncolumns3get_negrange4&get_nonzeros53get_Norig_columns6@get_Norig_rows7Mget_Nrows8Z!get_obj_bound9gget_objective:tget_orig_index;get_origcol_nameget_origrow_name<get_pivoting=get_presolve>get_presolveloops?get_primal_solution@get_print_solAget_ptr_constraintsget_ptr_dual_solution get_ptr_lambda)get_ptr_primal_solution@get_ptr_sensitivity_objBget_ptr_sensitivity_objexB*get_ptr_sensitivity_rhs 7get_ptr_variablesCDget_rhDQget_rh_rangeE^get_rowFkget_row_name<xget_rowexFget_scalelimitGget_scalingHget_sensitivity_objBget_sensitivity_objexBget_sensitivity_rhs get_simplextypeIget_solutioncountJget_solutionlimitKget_statusLget_statustextM8Z$get_timeoutNget_total_iterO!get_total_nodesP.get_upboQ;get_var_branchRHget_var_dualresult Uget_var_primalresult@bget_var_prioritySoget_variablesC|get_verboseTget_working_objectiveUGNU LESSER GENERAL PUBLIC LICENSEGNU MathProgguess_basisVhas_BFPWhas_XLIXInfeasible modelsinteger variablesIntroductionis_add_rowmodeY is_anti_degenZis_binary[%is_break_at_first\2is_constr_type]?is_debug^Lis_feasible_Yis_infiniteafis_intbsis_integerscalingcis_lag_tracedis_maximeis_nativeBFPfis_nativeXLIgis_negativehis_obj_in_basisiis_piv_modej#is_piv_rulekis_presolvelis_scalemodemis_scaletypenis_semicontois_SOS_varp)is_traceq6is_unbounded`Cis_use_namesrPlag_solves]LINDO lp filesjLinear programming basicswLinear Programming FAQlp file formatlp_solve API referencelp_solve commandlp_solve Yahoo grouplp_solve_versiontlpsolve distributed filesLPSolve IDEmake_lpumps bas file formatmps file formatMPS_writefileexvPresolve print_constraintsw-print_debugdumpx:print_dualsyGprint_lpzTprint_objective{aprint_scales|nprint_solution}{print_str~print_tableauput_abortfuncj*%put_bb_branchfuncput_bb_nodefuncput_logfuncput_msgfuncQuick startratio'sread_basisread_freemps read_freeMPS read_lp$ read_LP1 read_mps> read_MPSK read_paramsX read_XLIe reset_basisr reset_params resize_lp scaling semi-continuous variables sensitivity set_add_rowmode set_anti_degen set_basis set_basiscrash set_basisvar set_bb_depthlimit set_bb_floorfirst set_bb_rule set_BFP( set_binary5 set_boundsB set_bounds_tighterO set_break_at_first\ set_break_at_valuei set_col_namev set_column j 'set_columnex set_constr_type set_debug set_epsb set_epsd set_epsel set_epsint set_epslevel set_epsperturb set_epspivot set_improve set_infinite set_int, set_lag_trace9 set_lowboF set_lp_nameS set_mat` set_maximm set_maxpivotz set_minim set_mip_gap set_negrange set_obj set_obj_bound set_obj_fn set_obj_fnex set_obj_in_basis set_outputfile set_outputstream set_pivoting set_preferdual set_presolve# set_print_sol0 set_rh= set_rh_rangeJ set_rh_vecW set_rowd set_row_nameq set_rowex~ j&!set_scalelimit set_scaling set_semicont set_sense set_simplextype set_solutionlimit set_timeout set_trace set_unbounded set_upbo set_use_names set_var_branch set_var_weights' set_verbose4 set_XLIA solveN special ordered sets[ str_add_columnh str_add_constraintu str_add_lag_con  str_set_obj_fn str_set_rh_vec time_elapsed unscale Usefull links Using lpsolve from AMPL Using lpsolve from Java Using lpsolve from MATLAB Using lpsolve from Octave Using lpsolve from O-MatrixUsing lpsolve from PythonUsing lpsolve from RUsing lpsolve from Scilab+~ j write_basis8write_freempsvEwrite_freeMPSvRwrite_lp_write_LPlwrite_lpexywrite_mpsvwrite_MPSvwrite_paramswrite_XLIXpress lp filesZimplar_branch set_var_weights' set_verbose4 set_XLIA solveN special ordered sets[ str_add_columnh str_add_constraintu str_add_lag_con  str_set_obj_fn str_set_rh_vec time_elapsed unscale Usefull links Using lpsolve from AMPL Using lpsolve from Java Using lpsolve from MATLAB Using lpsolve from Octave Using lpsolve from O-MatrixUsing lpsolve from PythonUsing lpsolve from RUsing lpsolve from Scilab+~ jZget_basiscrashget_obj_bound9get_timeoutNis_piv_rulekput_bb_branchfuncset_columnexset_scalelimitwrite_basis $bFVOf/'ITSPT  j].!"TPMGL^/ /$HHTitleMapR! /$OBJINSTJ4/$WWAssociativeLinks//$WWAssociativeLinks/PROPERTY:/$WWKeywordLinks//$WWKeywordLinks/BTREE^L/$WWKeywordLinks/DATA T/$WWKeywordLinks/MAP>J/$WWKeywordLinks/PROPERTY* ::DataSpace/NameList4<(::DataSpace/Storage/MSCompressed/Content,::DataSpace/Storage/MSCompressed/ControlData)::DataSpace/Storage/MSCompressed/SpanInfo/::DataSpace/Storage/MSCompressed/Transform/Listp&_::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/i::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/ResetTablealp_solve_5.5.0.12mm doc/set_print_sol.htm0000644000175000017500000000527210246357710013700 0ustar renerene set_print_sol

set_print_sol

Sets a flag if all intermediate valid solutions must be printed while solving.

void set_print_sol(lprec *lp, int print_sol);

Return Value

set_print_sol has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

print_sol

FALSE (0) No printing
TRUE (1) Print all values
AUTOMATIC (2) Print only non-zero values

Remarks

The set_print_sol function sets a flag if all intermediate valid solutions must be printed while solving. Can give you useful solutions even if the total run time is too long. This function is mend for debugging purposes. The default is not to print (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_print_sol(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_print_sol

doc/get_lowbo.htm0000644000175000017500000000573211127442414012771 0ustar renerene get_lowbo

get_lowbo

Gets the lower bound of a variable.

REAL get_lowbo(lprec *lp, int column);

Return Value

get_lowbo returns the lower bound on the specified variable. If no bound was set, it returns 0, the default lower bound.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable. It must be between 1 and the number of columns in the lp.

Remarks

The get_lowbo function returns the lower bound on the variable identified by column.
Setting a bound on a variable is the way to go instead of adding an extra constraint (row) to the model. Setting a bound doesn't increase the model size that means that the model stays smaller and will be solved faster.
Note that the default lower bound of each variable is 0. So variables will never take negative values if no negative lower bound is set.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL a;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  a = get_lowbo(lp, 1); /* will return 0 since no lower bound was set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_lowbo, set_upbo, get_upbo, set_bounds, set_unbounded, is_unbounded, is_negative

doc/Octave1.jpg0000644000175000017500000016436510252703004012303 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?ml/8Gþ1 5:O4Osÿt^?j+w/O5-Q>+Vܚ楪h׭x_7Ö1_ e`yx7I v` .42kV\΍M\k.}{Iӵ/_l.n44}fH4NxQ4FR6vz_[u_|!|T eix-51?:\Z=Ik/6vfMbK}ᱼm3G,Uo9'?:O 0^R< /%2aOkY,r7 縬)d_Y㡉Nu)WteW ! X~3xvܫb`2O `ja*9Hpp. R >&o_zQ?  !C6@#?9 rAğW c>@ $`@9 Ir?9STo?40}-+Z{kKTխw%eo}%5ރGxM;i?-ߊ~,bU@O<ޅeZj7Z-ޯmUխ5]2}:kRߣߍWf!q2g q-<ƃ2l|dIb3Z|УV15N>!=x}Ĺ_ SsN$<9C xna jV*e7Up[% ѿ<5Dw7~:xǎ|+Sω Ko g`|aMcnsVy._ǨOx.|3Edx{O»Oş7# ans !?f?F?ؼ6SԞ%U \>1T̨A+k)bSZ_cӫ:x<>#8ƅÇqT\(SXpqzU1pQi?kN* 4'hVRc.g|.#FtυDhn}b|Io>7_& ’PxZ:I>>ze~zឫ~><<&.Zĺ:"xoK5?ɨ[8,>;7Uxɉ" \CfUӭG(w:VPS*WF~ sLuV8\sQ:NYSxJuN:x 0 8UUFjC% ѿ<5Dw7B/>7xv^V9?Kmk~g ׼Ay⎏s>ږO/U/^+B򗁾xt|4G~!\o/ cž)?4cRejڇ~ꗿdu]ҧV<¾sf.*`C:] CKW>$u/##$A?H?Y϶lf/GRм;zោ~"M˭ ᮻK4|oW@On>DV+:nZ6p0sk9F2qòᆩ,*xڎqkg ]Xxi/vDIJ fɴyqh Xh׋N7RYOZQΣg|.#FtυDhn}b|Io>7_& ’PxZ:I>>z% ѿ<5Dw76;֣7@pʾ_Pcz]o+}%3]Y _K>g?Zj?pV7_>% ѿ<5Dw76;֣7@pʾ_Pcz]o+}%3^®Y#蝾Q K?Xh,>gV7ts^>]}Q K?Xh,z/z}> _{}5 K?xow!O5_2c?ٸOOOcAXޟ_u}Ϧxow!O5G/ .Y>ƫ_,tyc7 @?ƨ% ??|֏,tf?=?>KQcz]/yO>% ??|7Dg'|֏'ǧc1oOO:_|7Dg'|,DU/?Z<X_,}F?1u]>k|,DTCjeOG?Z?p ޟ?.]}W̾XhOGnc~y{V7tsw8aNzt<|#۸)H榋#g?o½=w"_ª{Կo=DOGG.3S6O24y?o:=?~_솰jtK>& ??w{Ÿ!.hC&7Wd OOgOy#]gm#)H'& ??w{Ÿ!.hC&7Wd OOgOy#]gm#)H'& ??w{Ÿ!.hC&7Wd OOgOy#V^6^S/&wiX׵ SH xwK{'|sxo =v7Ecb..HOM/y%g_p73 T@>?>)_h]h$%QqH !EP m/?5sF_Os߿lky3|%C*ɪj.qM|^K9a8BYNhJJ49T?f xO¹Vw|O,n>i`\. F1i(ƾ])N8/i):^n W8ymi15;0?hث(" #Þ}S~%ׯkx@-oW ?KO8G/x*=#Zώ#Uz&7ڌ^G+ãĮWGI}?JOj>% ]M yc(YXdB92~xͼ ~q$ laG"!'tO-BƎ ~6^-Yqak2ꔲg(1kKjQoZUa(ЧӖxc٥UZi4pZfJCGzS{*ʷ=Oً$~qH"OoBA A #W?|Ϣ麮;RiZUs|8!|Sƛ[K}^h|`oBVƩǡxS}?Jկ: 'x>>;xw xL𦫨hZΕ؋;l_\@.ln'̶#~rQ7 s2?J/L_-W׾OO>a}=5O ^]W[3LN.\%(<<)sEUa3lj7W 쾳RT)SץBq>3԰qؚ1L Z:/TpK[/ĺ4+էΔT RNU":|ߎ_gdΑo>hzbɩ{RM0^ZXx}?째Q{y. Wd?ڕcx%7Sb8+IU.~Ǟ9Ҽ="7%O j_MoXūϢZ3KgC'b+x'hx'~#SO  c,_{ò.Ժ/|sP? Zյ2`wg3ǀ\G8_ 3\x>20o5 ]CQPc <Mx'eg&k %?dzM:ɹҬ?~g>o=q)X^y? xG,FOK 8xׇ`kf(XxR[RՔ3(S}5OZ19`1y^)^CN# ib~xeğTdsßNO.tsφ?h}R\@Ezx.j6m汪_ i Xj:>duJ XO,S߄? 1|Hys=ïͼ8xw_Xǝ64C<b3L$O[5f;PO.mO\lN'kYΨ`)`xG]B eѝ&uNY#KnKW>ѿN > 7>ϋxV~4߅z=)u+mY/ZK?~c?_:'ÿ'?_xP4 j |S%|ağ;=Jе(࿻@-S|/`Vۋk__h4yK%kY__fA~GgS:˳Zy7yK4CH0!xaRme+1x\ Us 7|*/8e]jo3ȳy3*9t0> G)>A,*xJQF\Noٓc~ԿW&g;|_"Ѿ|Xƿ 񖫤:ᆛ瀴oN5M;O+G~z՚x]Ⱦ_3E?N*M'74{ïψx}«YkU-?d1OG<>MXk񦹣:֯U|Լ#]7ƺ凉|e|{ bVD,o6MVv&: 5|OQ>$ai>ڏ:/6hF;T;|=?ßEi'q=oĞ>"!࿈GmxiFu~O | 8MD4|KͪxcǺ^|Qx~$Ͽ+x|7e^>Z}4OS+xGgJ:γjzm&}q-ݿ(Þh2?eh83+Bxss}W[/|&f O_BxMOKWOZwߋ>9|VG5+__ +^6 =sVеKGď,NUmbx= u}7SIoi+s?ֽ6 ռ5~Q>Yf]_ +  fk?í# jWK>|kXxQx7''nizM"^l$nn#=Ye6ߪFLևI> \e'z\^2МqTlMi3tUhKW>nzʜ!?Tg)k _3xRN"cO#9){jν|1i7??GzѠlG9 F/ٳo GO[~og7BO1=?-oG# <+#fA~s_?g=?a>y(5 y?xD4_o#c ?o_+7 ?f{Þh2? GO[~oa 8 y3OO3YI8DN2P{0d OEfԃuO1~>}i?οVO3jn oǜ11!?o Y9_qq܏+7#~ÝଟguџfO&Gn^pǗLzi>Ə7]/VoG?vQοVO3h:Y?3ݣ&Gn^pǗLzi>Ə7]/VoG?vQοVO3h:Y?3ݣ&Gn^pǗLzi>Ə7]/VoG?vQοVO3h:Y?3ݣ&Gn^pǗLzi>Ə7]/VoG?vQοVO3h:Y?3ݣ&Gn^pǗLzi>Ə7]/VoG?vQοVO3h:Y?3ݣ&Gn^pǗLzi>Ə7]/VoG?vQοVO3h:Y?3ݣ&Gn^pǗLzi>Ə7]/VoG?vQοVO3h:Y?3ݣ&Gn^pǗLzi>Ə7]/ ̠UCo<{=j/FrߕMo#=o:}GŶ}[vѝ?߳G=k ~I_#%\|&o~`ߧ-?y~Whjo'_Կs?Qvѝ?߳G=0G<rׄ4i̓ӗ~~Wjo'_真ƿRV3hG9 Fv~(?׼/ӗAxKF19ϗOFrߕ?y~Wk/i;?f{Ý?ggboo z{9g4i̓ӗ~~Wjo'_真ƿRV3hG9 Fv~(?׼/ӗAxKF19ϗOFrߕ?y~Wk/i;?f{Ý?ggboo z{9g4i̓ӗ~~Wjo'_真ƿRV3hG9 Fv~(?׼/ӗAxKF19ϗ(5AeOaKڣ=,걂>x3⏇^Ծ(? R_/{>CF5I}ee4:ƯFwV_2?୞Ok_?4ǟ_ !~3M_-?|Gm|;>Þ%kZZN?h7NP,t6_3 TK|*#qyOy&KG3j.Ib1!9G<iO1*|VQӎ*.#S뒪ahFpM9' e~meax|'wcѩS8̳x,gJQ?kVZU{:?!>4kvx4uawD޸x?ZjG|M[1?T*t},߲sBwu*ovmOM.~̶:֝s~4񍶟ZH^OOPxq[$rɢ~#ަmuRkYM; }6??]ucouayNQ_E_ڋ?oX[OW(KkBԼ?_io⧅Ye ,8cacU-]B W[g_Ekj?h xw[NW[_Ե j ԵˏXޥ>F&ҷ.d&x$KU{#ȯ/x8ï>oD+(f.d4s7ocf8U ] xk6)f/ V??9~ p/>}$kpe Y,G/ex9UO7úaVT1U18:4s T oC>T?fx'Ś?SG.-GLW\ijohۂq45D9A\|za@$dzLjVѼK/`|xZ4ox]7~OxA爵OhZW jzdž[ZM]ִ _a?hoG> 6+#X܏A希15s[*T -9bIRcw$gj9_ׅ!iڃş٫׿i++g ' ɺ?gEjRoڃIM`5fA̞u/~ߵbi/߇G|1YqڏOXE~&xoKDLhoh|*gP`|`>5<#5h^*uٳs_of?q8?jo|A@e|o񵟎~B+uoZOKƿ~ W]KWvXgOH摡koy&qhڭ6m^KQ_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_x= eI,?2?g_xؿ_#u@_ؿ_#uG= eI,?2?g_xkchA?5ſC&o@@HY+ ubf1IS?(x#?^ɥPy{ÖĞ]3VD4IAbnCӳ?HlW]M>+_ 'nq\@{W? c_K~?}S~Һ_|Od|9|a?|Mf_n~4oo+ž5*ԏ>~?S?hڋ6mO:_?Ɵt v|T>!XC?jm_ }_qOozm;ztn\'W'PQEQEQE/O _~%іz$O xKӟ¶~O^4ku{jZ)]_kyi>KҴkb^ ((((iS¿ iBڇ/5SV֝qi>*~| ci6>?|\*ԼM}yz7Q@Q@Q@Q@xkmSJm{KeVp7lt}WA,u;( ( ( ++_ۛ!_} ĿUZXO/o&n@k ,_#~oŨagz[W?_oui_c&h?^+ׄbC?g ޱ=~?hoi@?G%O~^: =_kk-u[ڷ_?g;?ŐiZOֺ=惨 KͤYs|UT_ß7Ÿ_=k߱?6Wjnu53nxEy៍ i߳hojK![egtW>'ž)=ȿ7'Pws?iwjZ|4!o;ht{/_k^ZKg)Y} ]lU<]7Rqf' TeuKFYBIT wr U<:O^\<11I9U9ԫJ15)Q"t*(ƕzßJof֊WßJof֊Wx_'?VN:w_'?VN:iowZXqo9lJN~-~k; 9AbxxwӃR adcMQcN/ˈ( ?l8$u?l8$u>((((((((((((((((((((((/izQEQEQEßJof֊WßJof֊WW_Nm_n5G~?ƿ< Mÿy`zOs$omԇʿ4IAb;_וw}8?)|WN/?4l(@[ ~8B[S>0|MG#? x_ؚ>-g > _#F}4}3P++Q?R>?l8$uX%?D (- 7#?? #'?5}6 ~)_^ ~2xR4ۭgQoJZHGԬ?.+m=.uEtvoz!;rc< _bi`Xh{LF&:4ạRoHAJI9;(v} e|)9.a\K'2xŗ_tm;AӮUk>:׉ltk[iAOx>1f,MZbW/'Q?R> )M?य़_I?~Tz'~%?O;q (a#A$'}Je?~Tzo7|[b'S#g8[ ybwOPռK&Vn+c]q} XۥΡMԬn'YTv'C^uد]v5oɾ%ե{[X~k_x–6sj5]BmG: ǾŒ|Y-8,N4rҴNVJF˛5G?g/ig^<ʦ7N*CmԵkk?kXx槮]x]iq[:ֱTխ5'žaio鷚okv5 KA״7Yom֥J ЯN֣8ԥZHӫJRHINgL.2fYeN]e 0 y᱘v X&3 Sb)ӭB9ҫT(8Š((((((((((((((((((((((>Sl0&W>Sl0&W_$9wks| 꿌O$:Nm_ACoo;4~sWxsg?=+ :mPص5ƿ4IAbvoYv2q1&(e_=>/i |~Wo|3=gu+o| wg|s|zw ?9x~-h/?cO?`_ǀe_iL+஫Akӿ;ҵ>|8$\?%|:^%_Ὴi~1R?R?Ov>'7aK߆~:jgᧈO⦻mgahIß1^N$gٴC5VچiZ揯ŝvRu7Mt&?<7;|w[OW\15Em`~%46~Jm..4/Swi ?zʼ)Vq jjN\>"\*ujJpKu2ړ' BNX4\j8[0x?2z^ਨSIa8 .u^Ti3С 3ɿ"o ў3O(x'P,_^ՠ?J.o xI4g(Sh[A}#kf"* |W@{BMYµEU>+oOow_7|KV?W_Nm_n5'~?ƿ< Mÿy`zOu$kk;_׍!ioڃůٯO^5_8cX~8wӋ+DH+?~Tzk?~Tzo7|[b'S#g8+?((( yH>2;%4wZ~c>Ogoy"8/?[}9|+_A=-w7xr|u|/Z|2YUV\VZ+VuqxX!ʝ<Yx+T_UxK`rqC 0yn] hr.Wb)eʿ\ ؟7?|%Դ>Mk^΋ t/Z^iږyZ-w@O |n KR|6&Vz5bN:n2M3X83nl0x!1YVuZ,,̰UC+b(VRki( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (>s)M??_V*s)M??_V* 1o1o< Mÿ닿3[zOu$kk;_׍!ioڃůٯO^5KadcMQcN/ˈ( XQgg_SXQgg_So@_L (((((/d_I|%g>Ꚅ~k9+Kc ź/ K Gº|_Q> onK]ci|8-fּ /_lkEӵ-:K/MwZ_p~O$O-w?KT' Yo/] aǜ/P\? &"\hg(8~LD%K&j\Q_<˟߆8|':|Y)mk9anV[;Rӯ4kT|%5s1x\~b)bPМjѯFTԧR-PZiʧpyymSl0&WϊToĿZO2;~2֞Wo xㆍY>ΰ|ooş~/_|a; HRֵo߲W_ ǃ|o ᷇O&_Oԏ>~?S?hڋ6mO:_?Ɵt v|T>!XC?jm_ }_qOozm;ztn_r;?_4z\2~<7?[oԴ7k^΋ ՟߱ڵY:ngZ @|/CX⽮7Ta*Jy^cR/XQT8U ϟoK>|(܉e3o )Ԧ`R8CBW֝Gfj|o k)08+J > /__ŏ~x X;xNVg}:t/G?pW[`s|31T m(bhKZrR%(U8ƭ**HJ+Mxׂî+x2,Æxs ^y攕,fEFV,F`ZY bpxQEv.QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE|Rdـ4U|Rdـ4Ub#d)[[gUb#d)[[Px&=f;qw>yr6?ZN_wu$kk;_׍w}8+._Ɯ_Q_'A_7&+;3_7&+;+ɻOOQ?G8/AǟQ_AgAEPEPEPEPEPEPEP߲G;῎I }$񿅯'Z7tXn|%կ-Qu=/ľ4/Z qw⟆'V<{'³|b_Xj^|5|W/t6I񶓫O_hׇnm =6Zu5ck?~;dwa/gğ/X'Oji֚ƕ=]72i>-zσQax[^϶[ dOx1ƦaØx쳙{ZU]72qC̩ҨV418_?>; W3:x^Ia*pab\Ҟ2Y^'˙gX8 Ixt. ߆ըϣx? <[s|%׷wwOB:^'+w/Ӛ?˰ٮSJ+Ÿԧ4pJjTӕNe$'>#qƾu!pa.|#~Oգּ-HNXk{tWIt_5; znjW7xoFg4}3"TUν;Pmƞ*VTka~B]pBYknP6]*#0<)JQkcrmiD*JggE~W0??_$I'%M& ๕l[k/ᠿ5_skoaqu8o<-⛽JRgw_Y.uqY] ]~~V ~'t*м+MGznj|3x[fWuOh7i jW>Q?R> )M?य़_I?~Tz'~%?O;q (a#A$'}Je?~Tzo7|[b'S#g8+?(((((((((?># _x75h xE%ӯ)mn!+?Uu]>G bBh:hڕ0??_$I'%M& ๕l[k/ᠿ5_skoaqu8o<-⛽JRgwv;_/? $25x]ƻo [i6چK twDV&|E|=ʸ,.27MӫN'*QJj5(Wڔj3j-ow_c8c2:/tү|&cӫm/ zjj*ӁEW~vQEQEQEQEQEQEQEQEQEQEQEQEQEQE~`~Z=G ~o}@{?_|,િƿ|'Q s~ M W<+[?ϋ1|ߧßJof֊WW?NmonoW?NmonoAoo֖'<]%w4Yӯ&ߵ__ikN~-~k/Ɯ_Q_'A_7&+;3_7&+;+ɻOOQ?G8/AǟQ_AgAEPEPEPEPEPEPEPEPEPEPt_[Zռ5o jnh揮ykZ.MmiZ[[i7Cuk4SĎg ~ښ'㶡k֓+$Vz>B~Km?Jij?>g==^>cֶt_[Zռ5o jnh揮ykZ.MmiZ[[i7Cuk4SĎ{pl&9v%U9Ћvc()I1pnTF iO3wDmkaO%,+<}¶ihE΅x)RgyQdu+SN/ W` TWO ~ښ'㶡k֓+$Vz>B~Km?Jij?>g==^>c_9yOe8l%ĬNӴk'W M$Sm*ҝJ)ULj^xgfIS%Le:^u֝H8JG”BB0]~Ӟ4Ox/)5|?/~~>%O#{?ه#mxskz}+ź?-~ joK,Ɋ(/nSO/G PqEWQEQEQEQEQEQEQEQEQEQEQEQEWynwVi>?|>gGдG៉zNjuP_+,e,,'*rVL&.o9tSpFsR >j4Ĝ깆9*2.+ȪUO<=NֲW*S)2eɦOپiqo9lIN~-~k; :mPص5ƻ~+g 'nq\@QE(.-/4-vT`KOY=<+ÒcTeqRndiK USl0&W>Sl0&W_$9wks| 꿌_$9wks| ?}'pθJg_Mjf?ӵx6?ZN]NJ_3?ᓋ7yG8[. (O9ͥ~ $m6 s_%h2|1Wx'~ gRrӴgx/-?Oԏy1_v~=޾o?¯ڗ??fڃ]ީ?V⯇^*>+~>cg!?#m_z F]G_&>kkY_9cLWGO|wϼVwſ*_}2>p0_? (΃΂(((((((((((((((?#?c/"'w^+WI~宕.tIYxGײťƅ  +O3 (g95gV8j ¹'S >T$J5+Q*ӄH/I_3O I⯋ɳ"O=L*\Cڔ}W0I¥9¦1ez1E_F,*_E?dOiм;WW]+]VeK ]//dpOdu2ά9)9uIX(I/iJvSM Q IE_\ǘ_ecx7Xz.4ȩՌ#e}W0J4s܎j̗R'S1(((((((((7iEX,|,MVK+Oxs?SwU᧍ԵE~ xWGO>s:|o*Si:xWKo|MC?sqg7|6Ӽ'I^?O<,Ɋ(/ ,Ɋ(/nSO/G PqEWQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWYдٛ.s[@e'u l7᧊X7~K ?ҴW]}x^Ώ7¯掊NsjYITNz`y4Ќ麴&җ:uiN1B*ЅH)?(e1F&qfkԡ>)Bpg5!xTI\^_/08VX-_мWh)𶵤>%tþ"5+=cB-bGHִ]_NOtWOu+i`jYl#̚~^%ռ+[i:_<;ͦŪ iyXwM4mkZ)[k_oxB|SmkI/|K|EjVzƅZŜ:h5Ο:so}V7Y լ*;}p{s.*p?g?k%7MT\*F"SߥϢ_.<5<˅OqV8+[J+Ua20ϲ:Lz`F+.1QE}QEQEQEQEQEQEQE|Rdـ4U|Rdـ4Ub#d)uj?_$9wks| }'?9+83VE6?ZN_wu$kk;_׍w}8?)|WN??4l(Q?R y1_v~=޿y1_v~=޿>[Mتz}=< (:: ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( C^uد]v5oɾ%ե{[X~k_x–6sj5]BmG: ǾŒ hs86\ daw M 41tJmZS^*<=?2Jy Tԣ(Q2\Ҍ*G?:3̲ug<2Ntb08>3,c85 z kZO|3]'M;-R4-B,tkEtWIt{7Rxnf QZ$7]?OmCV/]ZWH5w^=)cn:U.f~ |?ӡ |{+)|Y/|-;5 z kZO|3]'M;-R4-B,tkEtWIt{7Rxnf Q8)cpMa23\sR$8;Eqbcԍ:҇.!}|B q,*g\TbxY+8Я*8,Z4̎j0*R*2f_b0((((((7iEX7iEX+GɿS'7 ΫGɿS'7 7M7{K.Ïg??ioڃůٯO^5_Mjf?ӵxwӃR adcMQcN/ˈ+go}/,/:v/Ŗ:]χ5OԎo9cLWGO|wٯPS K~G ؟‹!k7 O ##?bk}WW?o<_9cLWGO|wϼVwſ*_}2>p0_? (΃΂((((((((((((((((((uWw+t? [Ŀoui^"5߀x+𥍺\WPQN{/'d)š+#͸W6gY.%᱘gfCBM:L]$᫨RiVקJ?,|};̒uy5(.sL4 qN,Y*S:;1'` B^֓_ Iu@Ԭ _е8u#Zu}:k?Uu]>MԬn'YTv֯RWSx?_e_ZZv ?>)c1?CV|tq_ώ xEVlYmn!+mCJմBG b]ah::mχ#d}{l37BORg_gb%R"49*U CxG/%:8gL*կӍLM0hם|*ְ*fm\V5eC袊 8 ( ( ( ( (>s)M??_V*s)M??_V* 1:M{:o?+9 !+&N?~k4I/wZhw9dOHN~-~k; :mPص5ƻ~+g 'nq\@ۿ | ")Zeď"^?ou=c#Q|Go5J]x'4 |2 ?s𭟊Yg63?FӠV_>,<g1[.xz|uxgFNuxK-oJoof,֊N/&+;;X)hgOMEuFxG ׿?Ww/&+;+ɻOOQ?G8/AǟQ_AgAEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP_L)'y,oռw6V¸.bk ƊKh/m+Z\]Xh_+ O xM|?~W^Kf|=3|SU(֦פU+P*uԌէ)Bqqmg|gx`,e"M5S i2/F3,u(p4qXZӌ'Ï|\G'|wǭx[:,fkq Q[jVjך>kv5 KA״7Yom ?%zfUWMyax[X Ͷ|CҴk[{ >aio鷚onuMTԒnlG5~\oEuFq/_ř~2g*3S<,(ҏP((((zԾ)?T~;MuĿJeUG^5?@~ kHh_9_f|X?>Sl0&Wo$?ۣWs_/CVN9>Wi~?:+9VolQ*kSktV:jFTӔ83>3E0|K\K2qi`q4q~i#Ofx:q m8-juiKU~XqDŽ>.|#~㿇>;cּ-IZQiek{ +Vҵ k_5; wÚ톥n6_oGzG=[oki*+&hĿOҾ!Z}ՆBn73'6П?j?h:π$i7:.鷚VwZ<hLJ)WB&hW:v{ljW`#ฃ Ai;FS;wWRjq\up**u^4G؊q7i'xEN.?n&AB0x<R^ʕ<;a'e^SQE~Q@Q@Q@|9`M?h+}_|9`M?h+}@IY7 sdO꿌_$9wks| }'>i~uſWxsc<U=' 9Ab5x6?ZN]NJ_3?ᓋ7yG8[. (OԂo9cLWGO|wfo9cLWGO|wϼVwſ*_}2>p0_? (΃΂(((((((((((((((((((((oOH>%4wZ~c>Ogoy"8/?[}9|+_A=-w7Wn[cv31UpXXbhK*q%(U8ʕZR*9/ׂS^x2,O^y攝\;YV,Z"hR`Z1~6azQ> onK]ci|8-fּ /_lkEӵ-:K/MwZCWO$O-w?KT' Yo/] eڏo>wZKMH,Sk6o^axBe^Z-杩iך_|5kt T ~X.%RR始EzrRkмSJt+_oKV܉fMf)Ԧ2 eeR8CB((QGfj `T)l+˾+ ( (>s)M??_V*s)M??_V* 1o1o< Mÿy`zOu$kk;_׍!ioڃůٯO^5_8cX~8wӋ~5Wk֟ [?~K/vu/ +^5]H摡^[ֺijuyWO~ҟw9Po߳߂,/_hV~Wl5/Cu}:;tF"DHߴwG$N]S¿|iG4Wf?gW?W|>އ'Nf9G/&+;_ UFx^-x'_P|>xj|U_o^>'~>-u\Ũ>Ҽsmqk}3K~l? ?hNz/%3|Shcix^է4kaN|֒\ZMomb3̋SKॆS:Л 'ZtiWZ/XQowAාx8<|6|+9a)a4eO.9Urbs%7&ꦒE8 iFG8 iF_?-qC^Gj~?@_5O͢i^Dۣi^Dۣ%?kŸ]??E |[ï_e4Zѯl4Zѯl5O.Z>?-MSh2-?׿6~?-?׿6~?ofOgyWÍ?k?h{tÍ?k?h{tķ xS qVDxuT<+ ƟKO5͟O=?ƟKO5͟O=?[)ٿ8+SYE:m_O%f'O%f'-qC^A,"?6C/q{3gnq{3gn8 vo ojE8 iFG8 iFGKׅ?7j~?@_5O͢i^Dۣi^Dۣ%?kŸ]??E |[ï_e4Zѯl4Zѯl5O.Z>?-MSh2-?׿6~?-?׿6~?ofOgyWÍ?k?h{tÍ?k?h{tķ xS qVDxuT<+ ƟKO5͟O=?ƟKO5͟O=?[)ٿ8+SYE:m_O%f'O%f'-qC^A,"?6C/q{3gnq{3gn8 vo ojE8 iFG8 iFGKׅ?7j~?@_5O͢i^Dۣi^Dۣ%?kŸ]??E |[ï_e4Zѯl4Zѯl5O.Z>?-MSh2-?׿6~?-?׿6~?ofOgyWÍ?k?h{tÍ?k?h{tķ xS qVDxuT<+ ƟKO5͟O=?ƟKO5͟O=?[)ٿ8+SYE:m_O%f'O%f'-qC^A,"?6oOH>%4wZ~c>Ogoy"8/?[}9|+_A=-w74Zѯl4Zѯln[F; *3xԥR7WWȜg EiN2VJ'Nr~5BxS=~8&>&yGpupxgZ\+B E Хcphcrm >;c0+\ ؟7?|%Դ>Mk^΋ t/Z^iږyZ-w@O7HOW* ~~ /KJS~^ڏ'/?mK];Ouؿ੿ole~F.=U1r֌W ,U 5xµ5 R*NtcR)ƵO'!%8~Un`(֖;fSWbQ1fL631f+vEűS2(iοQo[7"3Ͽ诀?oMȣ:Fl_T>Sl0&W>ǿ?f|BUx◇xO1L~ҿϊ/ +~!3cWׇ5XZѴGڭ,?O_'?VN:w_'?VN:iowZXqo9lJN~-~k; :mPص5ƻ+g 'nq\@QE(Wg_g/E;%)υ>+_<G&{z/f>YݞNaw:7E|Ag{|^&.ѵ ;*_Eu| G|Gտi٧N);?v9ᧂ/0~^*' _~6GxѴXG?1~05 |f^>5^8?F~ 5χ|5oS>FӼ%O|O~.x? [i7C[_o}+Kӵo^?/k9??i?d/s5AZ֫ k]?_UٟoB]/?h g/|=c=G|M9l|lf~˺LJm?',?$i2=^ᗄ<'׃th,9x_þΛxDto((~~/~[o~o^eÿOM'¿)|:scx'o So>:^xN=/ |ywO~o'>/|:~7Z'7j 4Ƽ+ WG&.1gj~~)xk-O4N?P>cSYiU2G+O_ٿ_)2 W#e[5@Q@Q@WR-/kƿ>x2YZƟ{oh^56Oƾ?h %|=񮛭J%oⷅ)t|97VZgGks iWŸٓ1O\{=V,_>࿈/|7ght :?> x -x#J?+&OW;s>",D|Eo/R['w_1|?|u/|%~/%~+:|+ws?S @0/g>ٟ?>&~ ;/?OeEW5;((+n'~)]xk>GRxƿZw%_|5WC +xN?iZM ߌO_|0Ś?'d?mxK Ğu;k:O ߏW >3XX||9ߍ,$/yA|D~: ǯx'w?d%-'\w?VHY7 sdA_HY7 sdA_ɦOٿib~uſWxsc<U=' :mPص5/F|G*o>"~ |(W@k|jď,hU-2|8[JxsĿ|yv׺xW~&_Mjf?ӵ  7c/:s_$ coC!$')w¿!mw}8?)|WN/?4lZO_ ~1|;_—u?+g?|/k>'i mkAៅ~}SN5mTA!BjG?|-gj>"AKˆ|]G_|;xZU~Nßl7] dd5+E } ߴ*K ~@Z_f$wWf/?o?/A|Xh|LxZnxK?,qmxg{;죬xZǿ \^h|9់?b t6p5O~&o'= >7[jSS:Y>)|5X4[_H>6j[/wzmDh?࡟>>|3-xZ_B k(?('+,|3O/wgW1_&~ 𷈼[㿇ڇ?ٟ4y _'>Ӿ!Nw| w/c ~W^9 w_'xz~ G _S4.~5旤¦nk'QL\~ݚ'Fe;>?am3ot:ZW _/d(7 ?=ik[|Cnx2 h+/ك:7c/'7߳)<'Þ ׇ j YA4/6vzi4Z|8C?< AjTe_S:gfx)45]o[7%Χ,[vsG4k?''~ך s?fT;Wc:,ğߎ_ h 7_.Ǐt=~xs]m=w~Һ_5msᖳ/q_ĿIߴxA|sxjT^~Ӗp?Ý|:)~ڏ,|Qm?^?+/v+ /8{ '|v~-;Y} _;SQZs u_s~Wj_m~ƞ/w-?d(F3f|Nm0?|A>=7/|Y/_-w__fk#KŞ.; |?꺅^x|)ko[OXeNo[I 㯇zω~|M"|_^& X? |8|Ykm㋋`य़w xwؗ >*Xe~?|=OrK-5xxoWj?~߶ۇ٧5^ /ঃ)? -#Vҿm5 M?5٥2բxJ|/n|'x_o|POZYxF>+x[[/ك #*?<ǯW:ZxZw~&¾.?< AjTe_S:gfx)45]o[7%Χ,[vsG4k|}w'_{ w/ 3+(O~eω~ X~1~?v/sOXѴh?Oaox;wσ c/o> 奭7`x?Y w\m )v.lou( ( ?i_> |txG=;=ow6/_~OaSQ>^+ _?[ |6m?/imm>xXukYxچ@ߋus~"\#x"ώ|EYo(((>:~_hE~"|@6~_mx6g_ ~&o:ό>O| EOh^?:e]SN𝆓|`ks/eQ'g^=ӯ ?x;z6 O¾ӭxg>gg6gkizuEQ@Q@Q@ |Rf;~ x%g,S OC>)O/]@aO^_ }^CH>x_Oaٟ-E i  O?Ne R K/&_#}EQEQEQE|?>_? @'fG:ߏ'ϊ~YsO> |S'cx^0o ߈>tž𖷣U4 i:>φ[jڻx:^&~6|:C;*_|xG7ϋ_~#go}Es|_ w'i+:G|3H|?ivz^ivvvZXAmQ/AEQEWY[O? >%Q|-=cD<9xOχu #G}COе]3XGڴB(.b (E|Sƿg|?[lOr'|?] *QRώ.jںǝ;ѼgsV|2m>o ~&|ag9:}EQEQE2[O#Oh_ RP,?ޯ_MC].YYkhe/Jp#h)|m>Q䣗գ9ty~ҵEZ:xJZ69IRmI/958 j~(@:o:CL|:EbOU}$KIe"옮7S6':?M;Q'?5notQO"'|@3tdtq{tI9ws&N~k~(a? {}3tdtq{t sW?':?N|:E/_?B'$ 8wOLWO7G_?:?rw$&Ά( +|_p. ?1]?osGɿ߷7: Ot uW?ES 5;&'ͳ'Njiro$&΂( _p!<Tp&+'lt sW?':?N|:E/a?B%vHp옮7S7I97?rg$&Ά)POSH옮7S6':?M;RãS_9B(a? {}\úbz8G?rw$&Ά?'5nt4QGE0?O=p&+'ltI8t?nãIÿMoۛQC?>_N \úb9L|C DIMACS maximum flow problems

DIMACS maximum flow problems

DIMACS (Center for Discrete Mathematics and Theoretical Computer Science (see http://dimacs.rutgers.edu/)) has formulated some 'challenges' for some specific problem instances (see http://dimacs.rutgers.edu/Challenges/). One of these challenges is network flows and matching - the first DIMACS implementation challenge.

One of these network flows are maximum flow problems:

The maximum flow problem is structured on a network. Here the arc capacities, or upper bounds, are the only relevant parameters. The problem is to find the maximum flow possible from some given source node to a given sink node. All arc costs are zero. Since the goal of the optimization is to minimize cost, the maximum flow possible is delivered to the sink node. Applications of this problem include finding the maximum flow of orders through a job shop, the maximum flow of water through a storm sewer system, and the maximum flow of product through a product distribution system, among others.

Network Structure

  • A network is a directed graph with n nodes and m arcs.
  • Nodes are identified by integers 1...n.
  • Graphs do not have to be symmetric: if an arc (v,w) is in the graph, the reverse arc (w,v) does not have to be in the graph.
  • Parallel arcs are not allowed.
  • Self-loops are not allowed.
  • Arc capacities are 32-bit signed integers.
  • The source and the sink are distinct.
  • The sink may be unreachable from the source.

The following information makes up a DIMACS maximum flow input file:

  • comment lines
  • problem line
  • node descriptors
  • arc descriptors

As noted above, information is collected into lines, which begin with one-character designators. We describe each type of information line in turn.

  1. Comment Lines: Comment lines give human-readable information about the file and are ignored by programs. Comment lines can appear anywhere in the file. Each comment line begins with a lower-case character c.
        c This is an example of a comment line.
  2. Problem Line: There is one problem line per input file. The problem line must appear before any node or arc descriptor lines. For maximum flow network instances the problem line has the following format:
        p max NODES ARCS

    The lower-case character p signifies that this is a problem line. The three-character problem designator max identifies the file as containing specification information for a maximum flow problem. The NODES field contains an integer value specifying n, the number of nodes in the network. The ARCS field contains an integer value specifying m, the number of arcs in the network.

  3. Node Descriptors: All node descriptor lines must appear before all arc descriptor lines. Node descriptors are of the form:
        n ID WHICH

    where ID is the node id and WHICH is s for the source and t for the sink. Two node descriptors, one for the source and one for the sink, must appear between the problem line and the arc descriptor lines.

  4. Arc Descriptors: There is one arc descriptor line for each arc in the network. For a maximum flow instance, arc descriptor lines are of the following form.
        a SRC DST CAP

    The lower-case character a signifies that this is an arc descriptor line. For a directed arc (v,w) the SRC field gives the identification number for the source vertex v, and the DST field gives the destination vertex w. Identification numbers are integers between 1 and n. The CAP field gives the arc capacity.

Input File Example :

The example network pictured here is followed by a corresponding DIMACS maximum flow input file.

Maximum Flow model graph

c This is a simple example file to demonstrate the DIMACS
c input file format for maximum flow problems. The solution
c vector is [5,10,5,0,5,5,10,5] with cost at 15.
c Problem line (nodes, links)
p max 6 8
c source
n 1 s
c sink
n 6 t
c Arc descriptor lines (from, to, capacity)
a 1 2 5
a 1 3 15
a 2 4 5
a 2 5 5
a 3 4 5
a 3 5 5
a 4 6 15
a 5 6 5
c
c End of file

lp_solve can read/write and solve these models via the xli_DIMACS XLI driver (see External Language Interfaces). It reads such a model in above format and solves it via linear programming. The xli can also generate a DIMACS formatted file.

For example:

lp_solve -rxli xli_DIMACS maxflow.net

This gives as result:

Value of objective function: 45

Actual values of the variables:
C1                              5
C2                             10
C3                              5
C4                              0
C5                              5
C6                              5
C7                             10
C8                              5

Also from within the IDE, this XLI can be used. However, some entries must be added in LpSolveIDE.ini (in the folder where the IDE is installed).

In the [XLI] section the following must be added:

lib6=xli_DIMACS

And a new section for the DIMACS XLI must also be added:

[xli_DIMACS]
extension=.net
language=DIMACS

Then make sure that the xli_DIMACS.dll is available for the IDE. This must be done by placing this dll in the IDE folder or in the Windows system32 folder.

Solution :

The solution vector of above example is [5, 10, 5, 0, 5, 5, 10, 5]
This must be interpreted as follows:
There are as many variables as there are arc descriptor lines in the input file and they appear in the same order. So:

C1 specifies how much flow there is for the first arc definition, in this case from A -> B
C2 specifies how much flow there is for the second arc definition, in this case from A -> C
...

This means there is a flow of 5 from node A to B, a flow of 10 from node A to C, ...
The value of the objective of lp_solve doesn't give you much information. It is the sum of all variables used.

Output :

The solution of the model can also be written in a DIMACS format:

  • comment lines
  • solution lines
  • flow assignments

For each network problem, the solution is an integer-valued flow assignment. The output file should list the solution and flow assignment for all arcs in the graph. As noted above, information is collected into lines, which begin with one-character designators. We describe each type of information line in turn.

  1. Comment Lines: Comment lines give human-readable information about the file and are ignored by programs. Comment lines can appear anywhere in the file. Each comment line begins with a lower-case character c.
        c This is an example of a comment line.
  2. Solution line. The solution line contains the flow value and has the following format:
        s VALUE

    The lower-case character s signifies that this is a solution line. The VALUE field contains the value of the objective.

  3. Flow assignments. There is one flow assignment line for each arc in the input network. These lines have the following format:
        f SRC DST FLOW
    The lower-case character f signifies that this is a flow assignment line. For arc (u,v), the SRC and DST fields give v and w, respectively. The FLOW field gives the amount of flow assigned to arc (u,v).

lp_solve can generate a solution file via the xli_DIMACS XLI driver (see External Language Interfaces).

For example:

lp_solve -rxli xli_DIMACS maxflow.net -wxlisol xli_DIMACS maxflow.sol

This generates the following solution contents:

c maxflow.net
c
c Dimacs-format maximum flow result file
c generated by lp_solve
c
c Solution
s 15
c
c SRC DST FLOW
f 1 2 5
f 1 3 10
f 2 4 5
f 2 5 0
f 3 4 5
f 3 5 5
f 4 6 10
f 5 6 5
c
c End of file

lp_solve can also generate a solution file with only non-zero values.

For example:

lp_solve -rxli xli_DIMACS maxflow.net -wxlisol xli_DIMACS maxflow.sol -wxlisolopt "-nz"

This generates the following solution contents:

c maxflow.net
c
c Dimacs-format maximum flow result file
c generated by lp_solve
c
c Solution
s 15
c
c Only non-zero flows are written
c SRC DST FLOW
f 1 2 5
f 1 3 10
f 2 4 5
f 3 4 5
f 3 5 5
f 4 6 10
f 5 6 5
c
c End of file

A testset of models can be found at the dimacs ftp site: ftp://dimacs.rutgers.edu/pub/netflow

See Also DIMACS minimum cost flow problems, DIMACS assignment problems

doc/print_objective.htm0000644000175000017500000000545210237176420014177 0ustar renerene print_objective

print_objective

Prints the objective value of the lp.

void print_objective(lprec *lp);

Return Value

print_objective has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The print_objective function prints the objective value of the lp. This can only be done after a successful solve.
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_objective(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_objective, print_lp, print_solution, print_constraints, print_duals, print_scales, print_tableau, print_str, set_outputstream, set_outputfile, print_debugdump

doc/MATLAB.htm0000644000175000017500000035160611244025346011755 0ustar renerene Using lpsolve from MATLAB

Using lpsolve from MATLAB

MATLAB?

MATLAB is a high-performance language for technical computing. It integrates computation, visualization, and programming in an easy-to-use environment where problems and solutions are expressed in familiar mathematical notation. Typical uses include

  • Math and computation
  • Algorithm development
  • Data acquisition
  • Modeling, simulation, and prototyping
  • Data analysis, exploration, and visualization
  • Scientific and engineering graphics
  • Application development, including graphical user interface building

MATLAB is an interactive system whose basic data element is an array that does not require dimensioning. This allows you to solve many technical computing problems, especially those with matrix and vector formulations, in a fraction of the time it would take to write a program in a scalar non-interactive language such as C or Fortran.

The name MATLAB stands for matrix laboratory. MATLAB was originally written to provide easy access to matrix software developed by the LINPACK and EISPACK projects. Today, MATLAB engines incorporate the LAPACK and BLAS libraries, embedding the state of the art in software for matrix computation.

MATLAB has evolved over a period of years with input from many users. In university environments, it is the standard instructional tool for introductory and advanced courses in mathematics, engineering, and science. In industry, MATLAB is the tool of choice for high-productivity research, development, and analysis.

MATLAB features a family of add-on application-specific solutions called toolboxes. Very important to most users of MATLAB, toolboxes allow you to learn and apply specialized technology. Toolboxes are comprehensive collections of MATLAB functions (M-files) that extend the MATLAB environment to solve particular classes of problems. Areas in which toolboxes are available include signal processing, control systems, neural networks, fuzzy logic, wavelets, simulation, and many others.

We will not discuss the specifics of MATLAB here but instead refer the reader to the MATLAB website and documentation.

MATLAB and lpsolve

lpsolve is callable from MATLAB via an external interface or MEX-function. As such, it looks like lpsolve is fully integrated with MATLAB. Matrices can directly be transferred between MATLAB and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for MATLAB (especially for matrix support). So you have full control to the complete lpsolve functionality via the mxlpsolve MATLAB driver. If you find that this involves too much work to solve an lp model then you can also work via higher-level M-files that can make things a lot easier. See further in this article.

MATLAB is ideally suited to handle linear programming problems. These are problems in which you have a quantity, depending linearly on several variables, that you want to maximize or minimize subject to several constraints that are expressed as linear inequalities in the same variables.If the number of variables and the number of constraints are small, then there are numerous mathematical techniques for solving a linear programming problem. Indeed these techniques are often taught in high school or university level courses in finite mathematics.But sometimes these numbers are high, or even if low, the constants in the linear inequalities or the object expression for the quantity to be optimized may be numerically complicated in which case a software package like MATLAB is required to effect a solution.

Installation

To make this possible, a driver program is needed: mxlpsolve (mxlpsolve.dll or mxlpsolve.mexw32 or mxlpsolve.mexw64 under Windows). This driver must be put in a directory known to MATLAB (specified via File, Set Path or via the MATLAB path command) and MATLAB can call the mxlpsolve solver.
Note that under Windows, the original extension was .dll. Newer versions of MATLAB require extension .mexw32. You can just rename the .dll to .mexw32 for that.

This driver calls lpsolve via the lpsolve shared library (lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux) (archive lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). This has the advantage that the mxlpsolve driver doesn't have to be recompiled when an update of lpsolve is provided. The shared library must be somewhere in the Windows path.

So note the difference between the MATLAB lpsolve driver that is called mxlpsolve and the lpsolve library that implements the API that is called lpsolve55.

There are also some MATLAB script files (.m) as a quick start.

To test if everything is installed correctly, enter mxlpsolve in the MATLAB command window. If it gives the following, then everything is ok:

mxlpsolve MATLAB Interface version 5.5.0.6
using lpsolve version 5.5.0.15

Usage: [ret1, ret2, ...] = mxlpsolve('functionname', arg1, arg2, ...)

However, if you get the following:

mxlpsolve driver not found !!!
Check if mxlpsolve.dll (or mxlpsolve.mexw32 or mxlpsolve.mexw64) is on your system and in a directory known to MATLAB.
Press enter to see the paths where MATLAB looks for the driver.

Then MATLAB can find the mxlpsolve.m file, but not the mxlpsolve.dll, mxlpsolve.mexw32 or mxlpsolve.mexw64 file. This dll should be in the same directory as the .m file.
Note that under Windows, the original extension was .dll. Newer versions of MATLAB require extension .mexw32. You can just rename the .dll to .mexw32 for that.

If you get the following:

??? Undefined function or variable 'mxlpsolve'.

Then MATLAB cannot find the mxlpsolve.* files. Enter path in the command line to see the MATLAB search path for its files. You can modify this path via File, Set Path. Specify the path where the mxlpsolve.* files are located on your system.

If you get the following (Windows):

??? Failed to initialise lpsolve library. Error

in == > ...\mxlpsolve.dll

Or (Unix/Linux):

liblpsolve55.so: cannot open shared object file: No such file or directory.

Then MATLAB can find the mxlpsolve driver program, but the driver program cannot find the lpsolve library that contains the lpsolve implementation. This library is called lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux.
Under Windows, the lpsolve55.dll file must be in a directory that in the PATH environment variable. This path can be shown via the following command in MATLAB: !PATH
It is common to place this in the WINDOWS\system32 folder.

Under Unix/Linux, the liblpsolve55.so shared library must be either in the directories /lib or /usr/lib or in a directory specified by the LD_LIBRARY_PATH environment variable.

Note that it may also be necessary to restart MATLAB after having put the files in the specified directory. It was noted that MATLAB sometimes doesn't see the newly added files in folders until it is restarted.

All this is developed and tested with MATLAB version 6.0.0.88 Release 12.

Solve an lp model from MATLAB via mxlpsolve

In the following text, >> before the MATLAB commands is the MATLAB prompt. Only the text after >> must be entered.

To call an lpsolve function, the following syntax must be used:

>> [ret1, ret2, ...] = mxlpsolve('functionname', arg1, arg2, ...)

The return values are optional and depend on the function called. functionname must always be enclosed between single quotes to make it alphanumerical and it is case sensitive. The number and type of arguments depend on the function called. Some functions even have a variable number of arguments and a different behaviour occurs depending on the type of the argument. functionname can be (almost) any of the lpsolve API routines (see lp_solve API reference) plus some extra MATLAB specific functions. Most of the lpsolve API routines use or return an lprec structure. To make things more robust in MATLAB, this structure is replaced by a handle or the model name. The lprec structures are maintained internally by the lpsolve driver. The handle is an incrementing number starting from 0. Starting from driver version 5.5.0.2 on, it is also possible to use the model name instead of the handle. This can of course only be done if a name is given to the model. This is done via lpsolve routine set_lp_name or by specifying the model name in routine read_lp. See Using model name instead of handle.

Almost all callable functions can be found in the lp_solve API reference. Some are exactly as described in the reference guide, others have a slightly different syntax to make maximum use of the MATLAB functionality. For example make_lp is used identical as described. But get_variables is slightly different. In the API reference, this function has two arguments. The first the lp handle and the second the resulting variables and this array must already be dimensioned. When lpsolve is used from MATLAB, nothing must be dimensioned in advance. The mxlpsolve driver takes care of dimensioning all return variables and they are always returned as return value of the call to mxlpsolve. Never as argument to the routine. This can be a single value as for get_objective (although MATLAB stores this in a 1x1 matrix) or a matrix or vector as in get_variables. In this case, get_variables returns a 4x1 matrix (vector) with the result of the 4 variables of the lp model.

Note that you can get an overview of the available functionnames and their arguments by entering the following in MATLAB:

>> help mxlpsolve

An example

(Note that you can execute this example by entering command per command as shown below or by just entering example1. This will execute example1.m. You can see its contents by entering type example1.m)

>> lp=mxlpsolve('make_lp', 0, 4);
>> mxlpsolve('set_verbose', lp, 3);
>> mxlpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
>> mxlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
>> mxlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
>> mxlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);
>> mxlpsolve('set_lowbo', lp, 1, 28.6);
>> mxlpsolve('set_lowbo', lp, 4, 18);
>> mxlpsolve('set_upbo', lp, 4, 48.98);
>> mxlpsolve('set_col_name', lp, 1, 'COLONE');
>> mxlpsolve('set_col_name', lp, 2, 'COLTWO');
>> mxlpsolve('set_col_name', lp, 3, 'COLTHREE');
>> mxlpsolve('set_col_name', lp, 4, 'COLFOUR');
>> mxlpsolve('set_row_name', lp, 1, 'THISROW');
>> mxlpsolve('set_row_name', lp, 2, 'THATROW');
>> mxlpsolve('set_row_name', lp, 3, 'LASTROW');
>> mxlpsolve('write_lp', lp, 'a.lp');
>> mxlpsolve('get_mat', lp, 1, 2)

ans =

   78.2600

>> mxlpsolve('solve', lp)

ans =

     0

>> mxlpsolve('get_objective', lp)

ans =

   31.7828

>> mxlpsolve('get_variables', lp)

ans =

   28.6000
         0
         0
   31.8276

>> mxlpsolve('get_constraints', lp)

ans =

   92.3000
    6.8640
  391.2928

Note that there are some commands that return an answer. To see the answer, the command was not terminated with a semicolon (;). If the semicolon is put at the end of a command, the answer is not shown. However it is also possible to write the answer in a variable. For example:

>> obj=mxlpsolve('get_objective', lp)

obj =

   31.7828

Or without echoing on screen:

>> obj=mxlpsolve('get_objective', lp);

The last command will only write the result in variable obj without showing anything on screen. get_variables and get_constraints return a vector with the result. This can also be put in a variable:

>> x=mxlpsolve('get_variables', lp);
>> b=mxlpsolve('get_constraints', lp);

It is always possible to show the contents of a variable by just giving it as command:

>> x

x =
  28.6000
        0
        0
  31.8276

Don't forget to free the handle and its associated memory when you are done:

>> mxlpsolve('delete_lp', lp);

Using model name instead of handle

From driver version 5.5.0.2 on, it is possible to use the model name instead of the handle. From the moment the model has a name, you can use this name instead of the handle. This is best shown by an example. Above example would look like this:
>> lp=mxlpsolve('make_lp', 0, 4);
>> mxlpsolve('set_lp_name', lp, 'mymodel');
>> mxlpsolve('set_verbose', 'mymodel', 3);
>> mxlpsolve('set_obj_fn', 'mymodel', [1, 3, 6.24, 0.1]);
>> mxlpsolve('add_constraint', 'mymodel', [0, 78.26, 0, 2.9], 2, 92.3);
>> mxlpsolve('add_constraint', 'mymodel', [0.24, 0, 11.31, 0], 1, 14.8);
>> mxlpsolve('add_constraint', 'mymodel', [12.68, 0, 0.08, 0.9], 2, 4);
>> mxlpsolve('set_lowbo', 'mymodel', 1, 28.6);
>> mxlpsolve('set_lowbo', 'mymodel', 4, 18);
>> mxlpsolve('set_upbo', 'mymodel', 4, 48.98);
>> mxlpsolve('set_col_name', 'mymodel', 1, 'COLONE');
>> mxlpsolve('set_col_name', 'mymodel', 2, 'COLTWO');
>> mxlpsolve('set_col_name', 'mymodel', 3, 'COLTHREE');
>> mxlpsolve('set_col_name', 'mymodel', 4, 'COLFOUR');
>> mxlpsolve('set_row_name', 'mymodel', 1, 'THISROW');
>> mxlpsolve('set_row_name', 'mymodel', 2, 'THATROW');
>> mxlpsolve('set_row_name', 'mymodel', 3, 'LASTROW');
>> mxlpsolve('write_lp', 'mymodel', 'a.lp');
>> mxlpsolve('get_mat', 'mymodel', 1, 2)

ans =

   78.2600

>> mxlpsolve('solve', 'mymodel')

ans =

     0

>> mxlpsolve('get_objective', 'mymodel')

ans =

   31.7828

>> mxlpsolve('get_variables', 'mymodel')

ans =

   28.6000
         0
         0
   31.8276

>> mxlpsolve('get_constraints', 'mymodel')

ans =

   92.3000
    6.8640
  391.2928

So everywhere a handle is needed, you can also use the model name. You can even mix the two methods. There is also a specific MATLAB routine to get the handle from the model name: get_handle.
For example:

>> mxlpsolve('get_handle', 'mymodel')
0

Don't forget to free the handle and its associated memory when you are done:

>> mxlpsolve('delete_lp', 'mymodel')

In the next part of this documentation, the handle is used. But if you name the model, the name could thus also be used.

Matrices

In MATLAB, all numerical data is stored in matrices; even a scalar variable. MATLAB also supports complex numbers (a + b * i with i=SQRT(-1)). mxlpsolve can only work with real numbers. MATLAB also supports sparse matrices. Sparse matrices are matrices where only the non-zero elements are provided and stored. This results in both less storage and faster calculation if there are a sufficient number of zero values in the matrix and there usually are. The mxlpsolve driver supports both dense and sparse matrices and their use is totally transparent to the user. Everywhere a matrix can be provided, it can be dense or sparse. In the above example all matrices were dense. For example:
>> mxlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);

In sparse matrix notation, this can be written:

>> mxlpsolve('add_constraint', lp, sparse([0.24, 0, 11.31, 0]), 1, 14.8);

Most of the time, variables are used to provide the data:

>> mxlpsolve('add_constraint', lp, a1, 1, 14.8);

Where a1 is a matrix variable that can be dense or sparse.

The mxlpsolve driver sees all provided matrices as sparse matrices. mxlpsolve also uses sparse matrices internally and data can be provided sparse via the ex routines. For example add_constraintex. The mxlpsolve driver always uses the ex routines to provide the data to lpsolve. Even if you call from MATLAB the routine names that would require a dense matrix (for example add_constraint), the mxlpsolve driver will always call the sparse version of the routine (for example add_constraintex). This results in the most performing behaviour. Note that if a dense matrix is provided, the dimension must exactly match the dimension that is expected by mxlpsolve. Matrices with too few or too much elements gives an 'invalid vector.' error. Sparse matrices can off course provide less elements (the non provided elements are seen as zero). However if too many elements are provided or an element with a too large index, again an 'invalid vector.' error is raised.

Most of the time, mxlpsolve needs vectors (rows or columns). In all situations, it doesn't matter if the vectors are row or column vectors. The driver accepts them both. For example:

>> mxlpsolve('add_constraint', lp, [0.24; 0; 11.31; 0], 1, 14.8);

Which is a column vector, but it is also accepted.

An important final note. Several lp_solve API routines accept a vector where the first element (element 0) is not used. Other lp_solve API calls do use the first element. In the MATLAB interface, there is never an unused element in the matrices. So if the lp_solve API specifies that the first element is not used, then this element is not in the MATLAB matrix.

Sets

All numerical data is stored in matrices. Alphanumerical data, however, is more difficult to store in matrices. Matrices require that each element has the same size (length) and that is difficult and unpractical for alphanumerical data. In a limited number of lpsolve routines, alphanumerical data is required or returned and in some also multiple elements. An example is set_col_name. For this, MATLAB sets are used. To specify a set of alphanumerical elements, the following notation is used: { 'element1', 'element2', ... }. Note the { and } symbols instead of [ and ] that are used with matrices.

Maximum usage of matrices/sets with mxlpsolve

Because MATLAB is all about matrices, all lpsolve API routines that need a column or row number to get/set information for that column/row are extended in the mxlpsolve MATLAB driver to also work with matrices. For example set_int in the API can only set the integer status for one column. If the status for several integer variables must be set, then set_int must be called multiple times. The mxlpsolve MATLAB driver however also allows specifying a vector to set the integer status of all variables at once. The API call is: return = mxlpsolve('set_int', lp, column, must_be_int). The matrix version of this call is: return = mxlpsolve('set_int', lp, [must_be_int]). The API call to return the integer status of a variable is: return = mxlpsolve('is_int', lp, column). The matrix version of this call is: [is_int] = mxlpsolve('is_int', lp)
Also note the get_mat and set_mat routines. In MATLAB these are extended to return/set the complete constraint matrix. See following example.

Above example can thus also be done as follows:
(Note that you can execute this example by entering command per command as shown below or by just entering example2. This will execute example2.m. You can see its contents by entering type example2.m)

>> lp=mxlpsolve('make_lp', 0, 4);
>> mxlpsolve('set_verbose', lp, 3);
>> mxlpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
>> mxlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
>> mxlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
>> mxlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);
>> mxlpsolve('set_lowbo', lp, [28.6, 0, 0, 18]);
>> mxlpsolve('set_upbo', lp, [Inf, Inf, Inf, 48.98]);
>> mxlpsolve('set_col_name', lp, {'COLONE', 'COLTWO', 'COLTHREE', 'COLFOUR'});
>> mxlpsolve('set_row_name', lp, {'THISROW', 'THATROW', 'LASTROW'});
>> mxlpsolve('write_lp', lp, 'a.lp');
>> mxlpsolve('get_mat', lp)

ans =

         0   78.2600         0    2.9000
    0.2400         0   11.3100         0
   12.6800         0    0.0800    0.9000

>> mxlpsolve('solve', lp)

ans =

     0

>> mxlpsolve('get_objective', lp)

ans =

   31.7828

>> mxlpsolve('get_variables', lp)

ans =

   28.6000
         0
         0
   31.8276

>> mxlpsolve('get_constraints', lp)

ans =

   92.3000
    6.8640
  391.2928

Note the usage of Inf in set_upbo. This stands for 'infinity'. Meaning an infinite upper bound. It is also possible to use -Inf to express minus infinity. This can for example be used to create a free variable.

Starting from driver version 5.5.0.3 in, get_mat can also return the matrix in sparse format. By default the function returns it in dense format for backwards compatibility. However if a 3rd argument is provided that is non-zero, the returned matrix is sparse:

>> mxlpsolve('get_mat', lp, 1)

ans =

   (2,1)       0.2400
   (3,1)      12.6800
   (1,2)      78.2600
   (2,3)      11.3100
   (3,3)       0.0800
   (1,4)       2.9000
   (3,4)       0.9000

To show the full power of the matrices, let's now do some matrix calculations to check the solution. It works further on above example:

>> A=mxlpsolve('get_mat', lp);
>> X=mxlpsolve('get_variables', lp);
>> B = A * X

B =
   92.3000
    6.8640
  391.2928

So what we have done here is calculate the values of the constraints (RHS) by multiplying the constraint matrix with the solution vector. Now take a look at the values of the constraints that lpsolve has found:

>> mxlpsolve('get_constraints', lp)

ans =

   92.3000
    6.8640
  391.2928

Exactly the same as the calculated B vector, as expected.

Also the value of the objective can be calculated in a same way:

>> C=mxlpsolve('get_obj_fn', lp);
>> X=mxlpsolve('get_variables', lp);
>> obj = C * X

obj =

   31.7828

So what we have done here is calculate the value of the objective by multiplying the objective vector with the solution vector. Now take a look at the value of the objective that lpsolve has found:

>> mxlpsolve('get_objective', lp)

ans =

   31.7828

Again exactly the same as the calculated obj value, as expected.

Using string constants

From driver version 5.5.0.15 on, it is possible to use string constants everywhere an lp_solve constant is needed or returned. This is best shown by an example. In the above code we had:
>> lp=mxlpsolve('make_lp', 0, 4);
>> mxlpsolve('set_verbose', lp, 3);
>> mxlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
>> mxlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
>> mxlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);

Note the 3rd parameter on set_verbose and the 4th on add_constraint. These are lp_solve constants. One could define all the possible constants in MATLAB and then use them in the calls, but that has several disadvantages. First there stays the possibility to provide a constant that is not intended for that particular call. Another issue is that calls that return a constant are still returning it numerical.

Both issues can now be handled by string constants. The above code can be done as following with string constants:

>> lp=mxlpsolve('make_lp', 0, 4);
>> mxlpsolve('set_verbose', lp, 'IMPORTANT');
>> mxlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 'GE', 92.3);
>> mxlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 'LE', 14.8);
>> mxlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 'GE', 4);

This is not only more readable, there is much lesser chance that mistakes are being made. The calling routine knows which constants are possible and only allows these. So unknown constants or constants that are intended for other calls are not accepted. For example:

>> mxlpsolve('set_verbose', lp, 'blabla');
??? BLABLA: Unknown.

>> mxlpsolve('set_verbose', lp, 'GE');
??? GE: Not allowed here.

Note the difference between the two error messages. The first says that the constant is not known, the second that the constant cannot be used at that place.

Constants are case insensitive. Internally they are always translated to upper case. Also when returned they will always be in upper case.

The constant names are the ones as specified in the documentation of each API routine. There are only 3 exceptions, extensions actually. 'LE', 'GE' and 'EQ' in add_constraint and is_constr_type can also be '<', '<=', '>', '>=', '='. When returned however, 'GE', 'LE', 'EQ' will be used.

Also in the matrix version of calls, string constants are possible. For example:

>> mxlpsolve('set_constr_type', lp, {'LE', 'EQ', 'GE'});

Some constants can be a combination of multiple constants. For example set_scaling:

>> mxlpsolve('set_scaling', lp, 3+128);

With the string version of constants this can be done as following:

>> mxlpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_INTEGERS');

| is the OR operator used to combine multiple constants. There may optinally be spaces before and after the |.

Not all OR combinations are legal. For example in set_scaling, a choice must be made between SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC or SCALE_CURTISREID. They may not be combined with each other. This is also tested:

>> mxlpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_RANGE');
??? SCALE_RANGE cannot be combined with SCALE_MEAN

Everywhere constants must be provided, numeric or string values may be provided. The routine automatically interpretes them.

Returning constants is a different story. The user must let lp_solve know how to return it. Numerical or as string. The default is numerical:

>> mxlpsolve('get_scaling', lp)

ans =

   131

To let lp_solve return a constant as string, a call to a new function must be made: return_constants

>> mxlpsolve('return_constants', 1);

From now on, all returned constants are returned as string:

>> mxlpsolve('get_scaling', lp)

ans =

SCALE_MEAN|SCALE_INTEGERS

Also when an array of constants is returned, they are returned as string when return_constants is set:

>> mxlpsolve('get_constr_type', lp)

ans =

    'LE'    'EQ'    'GE'

This for all routines until return_constants is again called with 0:

>> mxlpsolve('return_constants', 0);

The (new) current setting of return_constants is always returned by the call. Even when set:

>> mxlpsolve('return_constants', 1)

ans =

     1

To get the value without setting it, don't provide the second argument:

>> mxlpsolve('return_constants')

ans =

     1

In the next part of this documentation, return_constants is the default, 0, so all constants are returned numerical and provided constants are also numerical. This to keep the documentation as compatible as possible with older versions. But don't let you hold that back to use string constants in your code.

M-files

MATLAB can execute a sequence of statements stored in diskfiles. Such files are called "M-files" because they must have the file type of ".m" as the last part of their filename (extension). Much of your work with MATLAB will be in creating and refining M-files. M-files are usually created using your local editor.

M-files can be compared with batch files or scripts. You can put MATLAB commands in them and execute them at any time. The M-file is executed like any other command, by entering its name (without the .m extension).

The mxlpsolve MATLAB distribution contains some example M-files to demonstrate this.

To see the contents of such a file, enter the command 'type filename'. You can also edit these files with your favourite text editor (or notepad).

example1.m

Contains the commands as shown in the first example of this article.

example2.m

Contains the commands as shown in the second example of this article.

example3.m

Contains the commands of a practical example. See further in this article.

example4.m

Contains the commands of a practical example. See further in this article.

example5.m

Contains the commands of a practical example. See further in this article.

example6.m

Contains the commands of a practical example. See further in this article.

lp_solve.m

This script uses the API to create a higher-level function called lp_solve. This function accepts as arguments some matrices and options to create and solve an lp model. See the beginning of the file or type help lp_solve or just lp_solve to see its usage:

 >> help lp_solve
 LP_SOLVE  Solves mixed integer linear programming problems.

   SYNOPSIS: [obj,x,duals] = lp_solve(f,a,b,e,vlb,vub,xint,scalemode,keep)

      solves the MILP problem

              max v = f'*x
                a*x <> b
                  vlb <= x <= vub
                  x(int) are integer

   ARGUMENTS: The first four arguments are required:

            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) = -1  ==> Less Than
                      e(i) =  0  ==> Equals
                      e(i) =  1  ==> Greater Than
          vlb: n vector of lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
         keep: Flag for keeping the lp problem after it's been solved.
               If omitted, the lp will be deleted when solved.

   OUTPUT: A nonempty output is returned if a solution is found:

          obj: Optimal value of the objective function.
            x: Optimal value of the decision variables.
        duals: solution of the dual problem.

Example of usage. To create and solve following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

>> [obj, x]=lp_solve([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])

obj =

     3


x =

     1
     2

lp_maker.m

This script is analog to the lp_solve script and also uses the API to create a higher-level function called lp_maker. This function accepts as arguments some matrices and options to create an lp model. Note that this scripts only creates a model and returns a handle. See the beginning of the file or type help lp_maker or just lp_maker to see its usage:

 >> help lp_maker

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: Autoscale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Example of usage. To create following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

>> lp=lp_maker([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])

lp =

     0

To solve the model and get the solution:

>> mxlpsolve('solve', lp)

ans =

     0

>> mxlpsolve('get_objective', lp)

ans =

     3

>> mxlpsolve('get_variables', lp)

ans =

     1
     2

Don't forget to free the handle and its associated memory when you are done:

>> mxlpsolve('delete_lp', lp);

lpdemo.m

Contains several examples to build and solve lp models.

ex.m

Contains several examples to build and solve lp models. Also solves the lp_examples from the lp_solve distribution.

A practical example

We shall illustrate the method of linear programming by means of a simple example, giving a combination graphical/numerical solution, and then solve both a slightly as well as a substantially more complicated problem.

Suppose a farmer has 75 acres on which to plant two crops: wheat and barley. To produce these crops, it costs the farmer (for seed, fertilizer, etc.) $120 per acre for the wheat and $210 per acre for the barley.The farmer has $15000 available for expenses. But after the harvest, the farmer must store the crops while awaiting favourable market conditions. The farmer has storage space for 4000 bushels.Each acre yields an average of 110 bushels of wheat or 30 bushels of barley. If the net profit per bushel of wheat (after all expenses have been subtracted) is $1.30 and for barley is $2.00, how should the farmer plant the 75 acres to maximize profit?

We begin by formulating the problem mathematically. First we express the objective, that is the profit, and the constraints algebraically, then we graph them, and lastly we arrive at the solution by graphical inspection and a minor arithmetic calculation.

Let x denote the number of acres allotted to wheat and y the number of acres allotted to barley. Then the expression to be maximized, that is the profit, is clearly

P = (110)(1.30)x + (30)(2.00)y = 143x + 60y.

There are three constraint inequalities, specified by the limits on expenses, storage and acreage. They are respectively:

120x + 210y <= 15000
110x + 30y <= 4000
x + y <= 75

Strictly speaking there are two more constraint inequalities forced by the fact that the farmer cannot plant a negative number of acres, namely:

x >= 0,y >= 0.

Next we graph the regions specified by the constraints. The last two say that we only need to consider the first quadrant in the x-y plane. Here's a graph delineating the triangular region in the first quadrant determined by the first inequality.

>> X = 0:125;
>> Y1 = (15000 - 120.*X)./210;
>> area(X, Y1)

Source

Now let's put in the other two constraint inequalities.

>> Y2 = max((4000 - 110.*X)./30, 0);
>> Y3 = max(75 - X, 0);
>> Ytop = min([Y1; Y2; Y3]);
>> area(X, Ytop)
>> axis([0 40 0 75])

Source

The blue area is the solution space that holds valid solutions. This means that any point in this area fulfils the constraints.

Now let's superimpose on top of this picture a contour plot of the objective function P.

>> hold on
>> [U V] = meshgrid(0:40, 0:75);
>> contour(U, V, 143.*U + 60.*V);
>> hold off

Source

The lines give a picture of the objective function. All solutions that intersect with the blue area are valid solutions, meaning that this result also fulfils the set constraints. The more the lines go to the right, the higher the objective value is. The optimal solution or best objective is a line that is still in the blue area, but with an as large as possible value.

It seems apparent that the maximum value of P will occur on the level curve (that is, level line) that passes through the vertex of the polygon that lies near (22,53).
It is the intersection of x + y = 75 and 110*x + 30*y = 4000
This is a corner point of the diagram. This is not a coincidence. The simplex algorithm, which is used by lp_solve, starts from a theorem that the optimal solution is such a corner point.
In fact we can compute the result:

>> x = [1 1; 110 30] \ [75; 4000]

x =

   21.8750
   53.1250

The acreage that results in the maximum profit is 21.875 for wheat and 53.125 for barley. In that case the profit is:

>> format bank
>> P = [143 60] * x

P =
       6315.63

That is, $6315.63.

Note that these command are in script example3.m

Now, lp_solve comes into the picture to solve this linear programming problem more generally. After that we will use it to solve two more complicated problems involving more variables and constraints.

For this example, we use the higher-level script lp_maker to build the model and then some lp_solve API calls to retrieve the solution. Here is again the usage of lp_maker:

>> help lp_maker

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: Autoscale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Now let's formulate this model with lp_solve:

>> f = [143 60];
>> A = [120 210; 110 30; 1 1];
>> b = [15000; 4000; 75];
>> lp = lp_maker(f, A, b, [-1; -1; -1], [], [], [], 1, 0);
>> solvestat = mxlpsolve('solve', lp)

solvestat =

             0

>> format bank
>> obj = mxlpsolve('get_objective', lp)

obj =

       6315.63

>> format short
>> x = mxlpsolve('get_variables', lp)

x =

   21.8750
   53.1250

>> mxlpsolve('delete_lp', lp);

Note that these command are in script example4.m

With the higher-level script lp_maker, we provide all data to lp_solve. lp_solve returns a handle (lp) to the created model. Then the API call 'solve' is used to calculate the optimal solution of the model. The value of the objective function is retrieved via the API call 'get_objective' and the values of the variables are retrieved via the API call 'get_variables'. At last, the model is removed from memory via a call to 'delete_lp'. Don't forget this to free all memory allocated by lp_solve.

The solution is the same answer we obtained before. Note that the non-negativity constraints are accounted implicitly because variables are by default non-negative in lp_solve.

Well, we could have done this problem by hand (as shown in the introduction) because it is very small and it can be graphically presented.
Now suppose that the farmer is dealing with a third crop, say corn, and that the corresponding data is:

cost per acre$150.75
yield per acre125 bushels
profit per bushel$1.56

With three variables it is already a lot more difficult to show this model graphically. Adding more variables makes it even impossible because we can't imagine anymore how to represent this. We only have a practical understanding of 3 dimentions, but beyound that it is all very theorethical.

If we denote the number of acres allotted to corn by z, then the objective function becomes:

P = (110)(1.30)x + (30)(2.00)y+ (125)(1.56) = 143x + 60y + 195z

And the constraint inequalities are:

120x + 210y + 150.75z <= 15000
110x + 30y + 125z <= 4000
x + y + z <= 75
x >= 0,y >= 0, z >= 0

The problem is solved with lp_solve as follows:

>> f = [143 60 195];
>> A = [120 210 150.75; 110 30 125; 1 1 1];
>> b = [15000; 4000; 75];
>> lp = lp_maker(f, A, b, [-1; -1; -1], [], [], [], 1, 0);
>> solvestat = mxlpsolve('solve', lp)

solvestat =

     0

>> format bank
>> obj = mxlpsolve('get_objective', lp)

obj =

       6986.84

>> format short
>> x = mxlpsolve('get_variables', lp)

x =

         0
   56.5789
   18.4211

>> mxlpsolve('delete_lp', lp);

Note that these command are in script example5.m

So the farmer should ditch the wheat and plant 56.5789 acres of barley and 18.4211 acres of corn.

There is no practical limit on the number of variables and constraints that MATLAB can handle. Certainly none that the relatively unsophisticated user will encounter.Indeed, in many true applications of the technique of linear programming, one needs to deal with many variables and constraints.The solution of such a problem by hand is not feasible, and software like MATLAB is crucial to success.For example, in the farming problem with which we have been working, one could have more crops than two or three. Think agribusiness instead of family farmer.And one could have constraints that arise from other things beside expenses, storage and acreage limitations. For example:

  • Availability of seed.This might lead to constraint inequalities like xj < k.
  • Personal preferences. Thus the farmer's spouse might have a preference for one variety over another and insist on a corresponding planting, or something similar with a collection of crops; thus constraint inequalities like xi < xj or x1 + x2 > x3.
  • Government subsidies. It may take a moment's reflection on the reader's part, but this could lead to inequalities like xj > k.

Below is a sequence of commands that solves exactly such a problem. You should be able to recognize the objective expression and the constraints from the data that is entered. But as an aid, you might answer the following questions:

  • How many crops are under consideration?
  • What are the corresponding expenses? How much is available for expenses?
  • What are the yields in each case? What is the storage capacity?
  • How many acres are available?
  • What crops are constrained by seed limitations? To what extent?
  • What about preferences?
  • What are the minimum acreages for each crop?
>> f = [110*1.3 30*2.0 125*1.56 75*1.8 95*.95 100*2.25 50*1.35];
>> A = [120 210 150.75 115 186 140 85;
        110 30 125 75 95 100 50;
        1 1 1 1 1 1 1;
        1 -1 0 0 0 0 0;
        0 0 1 0 -2 0 0;
        0 0 0 -1 0 -1 1];

>> b = [55000;40000;400;0;0;0];
>> lp = lp_maker(f, A, b, [-1; -1; -1; -1; -1; -1], [10 10 10 10 20 20 20], [100 Inf 50 Inf Inf 250 Inf], [], 1, 0);
>> solvestat = mxlpsolve('solve', lp)

solvestat =

     0

>> format bank
>> obj = mxlpsolve('get_objective', lp)

obj =

      75398.04

>> format short
>> x = mxlpsolve('get_variables', lp)

x =

   10.0000
   10.0000
   40.0000
   45.6522
   20.0000
  250.0000
   20.0000

>> mxlpsolve('delete_lp', lp);

Note that these command are in script example6.m

Note that we have used in this formulation the vlb and vub arguments of lp_maker. This to set lower and upper bounds on variables. This could have been done via extra constraints, but it is more performant to set bounds on variables. Also note that Inf is used for variables that have no upper limit. This stands for Infinity.

Note that despite the complexity of the problem, lp_solve solves it almost instantaneously. It seems the farmer should bet the farm on crop number 6.We strongly suggest you alter the expense and/or the storage limit in the problem and see what effect that has on the answer.

Another, more theoretical, example

Suppose we want to solve the following linear program using MATLAB:

max 4x1 + 2x2 + x3
s. t. 2x1 + x2 <= 1
x1 + 2x3 <= 2
x1 + x2 + x3 = 1
x1 >= 0
x1 <= 1
x2 >= 0
x2 <= 1
x3 >= 0
x3 <= 2

Convert the LP into MATLAB format we get:

f = [4 2 1]
A = [2 1 0; 1 0 2; 1 1 1]
b = [1; 2; 1]

Note that constraints on single variables are not put in the constraint matrix. lp_solve can set bounds on individual variables and this is more performant than creating additional constraints. These bounds are:

l = [ 0 0 0]
u = [ 1 1 2]

Now lets enter this in MATLAB:

>> f = [4 2 1];
>> A = [2 1 0; 1 0 2; 1 1 1];
>> b = [1; 2; 1];
>> l = [ 0 0 0];
>> u = [ 1 1 2];

Now solve the linear program using MATLAB: Type the commands

>> lp = lp_maker(f, A, b, [-1; -1; -1], l, u, [], 1, 0);
>> solvestat = mxlpsolve('solve', lp)

solvestat =

     0

>> obj = mxlpsolve('get_objective', lp)

obj =

    2.5000

>> x = mxlpsolve('get_variables', lp)

x =

    0.5000
         0
    0.5000

>> mxlpsolve('delete_lp', lp)

What to do when some of the variables are missing ?
For example, suppose there are no lower bounds on the variables. In this case define l to be the empty set using the MATLAB command:

>> l = [];

This has the same effect as before, because lp_solve has as default lower bound for variables 0.

But what if you want that variables may also become negative?
Then you can use -Inf as lower bounds:

>> l = [-Inf -Inf -Inf];

Solve this and you get a different result:

>> lp = lp_maker(f, A, b, [-1; -1; -1], l, u, [], 1, 0);
>> solvestat = mxlpsolve('solve', lp)

solvestat =

     0

>> obj = mxlpsolve('get_objective', lp)

obj =

    2.6667

>> x = mxlpsolve('get_variables', lp)

x =

    0.6667
   -0.3333
    0.6667

>> mxlpsolve('delete_lp', lp)

Overview of API routines

Note again that the MATLAB command 'help mxlpsolve' gives an overview of all functions that can be called via mxlpsolve with their arguments and return values.

Note that everwhere where lp is used as argument that this can be a handle (lp_handle) or the models name.

  • add_column, add_columnex
    • return = mxlpsolve('add_column', lp, [column])
    • return = mxlpsolve('add_columnex', lp, [column])
    • Both have the same interface from add_column but act as add_columnex
  • add_constraint, add_constraintex
    • return = mxlpsolve('add_constraint', lp, [row], constr_type, rh)
    • return = mxlpsolve('add_constraintex', lp, [row], constr_type, rh)
    • Both have the same interface from add_constraint but act as add_constraintex
  • add_SOS
    • return = mxlpsolve('add_SOS', lp, name, sostype, priority, [sosvars], [weights])
    • The count argument in the API documentation is not needed in MATLAB since the number of elements is derived from the size of the sosvars and weights matrices. These must have the same size.
  • column_in_lp
    • return = mxlpsolve('column_in_lp', lp, [column])
    • No special considerations.
  • copy_lp
    • lp_handle = mxlpsolve('copy_lp', lp)
    • No special considerations.
  • default_basis
    • mxlpsolve('default_basis', lp)
    • No special considerations.
  • del_column
    • return = mxlpsolve('del_column', lp, column)
    • No special considerations.
  • del_constraint
    • return = mxlpsolve('del_constraint', lp, del_row)
    • No special considerations.
  • delete_lp
    • mxlpsolve('delete_lp', lp)
    • No special considerations.
  • free_lp
    • mxlpsolve('free_lp', lp)
    • lp is not changed as in the lpsolve API since it is a read_only input parameter. So it acts the same as delete_lp.
  • get_anti_degen
    • return = mxlpsolve('get_anti_degen', lp)
    • No special considerations.
  • get_basis
    • [bascolumn] = mxlpsolve('get_basis', lp {, nonbasic})
    • The bascolumn argument in the API documentation is here the return value. The nonbasic argument is optional in MATLAB. If not provided, then 0 is used.
  • get_basiscrash
    • return = mxlpsolve('get_basiscrash', lp)
    • No special considerations.
  • get_bb_depthlimit
    • return = mxlpsolve('get_bb_depthlimit', lp)
    • No special considerations.
  • get_bb_floorfirst
    • return = mxlpsolve('get_bb_floorfirst', lp)
    • No special considerations.
  • get_bb_rule
    • return = mxlpsolve('get_bb_rule', lp)
    • No special considerations.
  • get_bounds_tighter
    • return = mxlpsolve('get_bounds_tighter', lp)
    • No special considerations.
  • get_break_at_value
    • return = mxlpsolve('get_break_at_value', lp)
    • No special considerations.
  • get_col_name
    • name = mxlpsolve('get_col_name', lp, column)
    • [names] = mxlpsolve('get_col_name', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_column get_columnex
    • [column, return] = mxlpsolve('get_column', lp, col_nr)
    • [column, return] = mxlpsolve('get_columnex', lp, col_nr)
    • The column argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_constr_type
    • return = mxlpsolve('get_constr_type', lp, row)
    • [constr_type] = mxlpsolve('get_constr_type', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_constr_value
    • return = mxlpsolve('get_constr_value', lp, row {, primsolution})
    • The primsolution argument is optional. If not provided, then the solution of last solve is used.
  • get_constraints
    • [constr, return] = mxlpsolve('get_constraints', lp)
    • The constr argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_dual_solution
    • [duals, return] = mxlpsolve('get_dual_solution', lp)
    • The duals argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In MATLAB, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_epsb
    • return = mxlpsolve('get_epsb', lp)
    • No special considerations.
  • get_epsd
    • return = mxlpsolve('get_epsd', lp)
    • No special considerations.
  • get_epsel
    • return = mxlpsolve('get_epsel', lp)
    • No special considerations.
  • get_epsint
    • return = mxlpsolve('get_epsint', lp)
    • No special considerations.
  • get_epsperturb
    • return = mxlpsolve('get_epsperturb', lp)
    • No special considerations.
  • get_epspivot
    • return = mxlpsolve('get_epspivot', lp)
    • No special considerations.
  • get_improve
    • return = mxlpsolve('get_improve', lp)
    • No special considerations.
  • get_infinite
    • return = mxlpsolve('get_infinite', lp)
    • No special considerations.
  • get_lowbo
    • return = mxlpsolve('get_lowbo', lp, column)
    • [return] = mxlpsolve('get_lowbo', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_lp_index
    • return = mxlpsolve('get_lp_index', lp, orig_index)
    • No special considerations.
  • get_lp_name
    • name = mxlpsolve('get_lp_name', lp)
    • No special considerations.
  • get_mat
    • value = mxlpsolve('get_mat', lp, row, col)
    • [matrix, return] = mxlpsolve('get_mat', lp[, sparse])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix in the first return value. If sparse is different from zero then the returned matrix is a sparse matrix. The return code of the call is the second return value.
  • get_max_level
    • return = mxlpsolve('get_max_level', lp)
    • No special considerations.
  • get_maxpivot
    • return = mxlpsolve('get_maxpivot', lp)
    • No special considerations.
  • get_mip_gap
    • return = mxlpsolve('get_mip_gap', lp, absolute)
    • No special considerations.
  • get_nameindex
    • return = mxlpsolve('get_nameindex', lp, name, isrow)
    • No special considerations.
  • get_Ncolumns
    • return = mxlpsolve('get_Ncolumns', lp)
    • No special considerations.
  • get_negrange
    • return = mxlpsolve('get_negrange', lp)
    • No special considerations.
  • get_nonzeros
    • return = mxlpsolve('get_nonzeros', lp)
    • No special considerations.
  • get_Norig_columns
    • return = mxlpsolve('get_Norig_columns', lp)
    • No special considerations.
  • get_Norig_rows
    • return = mxlpsolve('get_Norig_rows', lp)
    • No special considerations.
  • get_Nrows
    • return = mxlpsolve('get_Nrows', lp)
    • No special considerations.
  • get_obj_bound
    • return = mxlpsolve('get_obj_bound', lp)
    • No special considerations.
  • get_objective
    • return = mxlpsolve('get_objective', lp)
    • No special considerations.
  • get_orig_index
    • return = mxlpsolve('get_orig_index', lp, lp_index)
    • No special considerations.
  • get_origcol_name
    • name = mxlpsolve('get_origcol_name', lp, column)
    • [names] = mxlpsolve('get_origcol_name', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_origrow_name
    • name = mxlpsolve('get_origrow_name', lp, row)
    • [names] = mxlpsolve('get_origrow_name', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_pivoting
    • return = mxlpsolve('get_pivoting', lp)
    • No special considerations.
  • get_presolve
    • return = mxlpsolve('get_presolve', lp)
    • No special considerations.
  • get_presolveloops
    • return = mxlpsolve('get_presolveloops', lp)
    • No special considerations.
  • get_primal_solution
    • [pv, return] = mxlpsolve('get_primal_solution', lp)
    • The pv argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_print_sol
    • return = mxlpsolve('get_print_sol', lp)
    • No special considerations.
  • get_ptr_constraints
    • Not implemented.
  • get_ptr_dualsolution
    • Not implemented.
  • get_ptr_primal_solution
    • Not implemented.
  • get_ptr_sensitivity_obj, get_ptr_sensitivity_objex
    • Not implemented.
  • get_ptr_sensitivity_rhs
    • Not implemented.
  • get_ptr_variables
    • Not implemented.
  • get_rh
    • return = mxlpsolve('get_rh', lp, row)
    • [rh] = mxlpsolve('get_rh', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_rh_range
    • return = mxlpsolve('get_rh_range', lp, row)
    • [rh_ranges] = mxlpsolve('get_rh_range', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_row get_rowex
    • [row, return] = mxlpsolve('get_row', lp, row_nr)
    • [row, return] = mxlpsolve('get_rowex', lp, row_nr)
    • The row argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In MATLAB, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_row_name
    • name = mxlpsolve('get_row_name', lp, row)
    • [names] = mxlpsolve('get_row_name', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_scalelimit
    • return = mxlpsolve('get_scalelimit', lp)
    • No special considerations.
  • get_scaling
    • return = mxlpsolve('get_scaling', lp)
    • No special considerations.
  • get_sensitivity_obj, get_sensitivity_objex
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = mxlpsolve('get_sensitivity_obj', lp)
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = mxlpsolve('get_sensitivity_objex', lp)
    • The objfrom, objtill, objfromvalue, objtillvalue arguments in the API documentation are here the return values. Note that MATLAB allows the return of fewer variables. For example if only objfrom and objtill are needed then the call can be [objfrom, objtill] = mxlpsolve('get_sensitivity_obj', lp). The unrequested values are even not calculated.
    • Since the API routine doesn't calculate the objtillvalue value at this time, MATLAB always returns a zero vector for this.
    • The return code of the call is the last value.
    • get_sensitivity_obj and get_sensitivity_objex are both implemented, but have the same functionality.
  • get_sensitivity_rhs, get_sensitivity_rhsex
    • [duals, dualsfrom, dualstill, return] = mxlpsolve('get_sensitivity_rhs', lp)
    • [duals, dualsfrom, dualstill, return] = mxlpsolve('get_sensitivity_rhsex', lp)
    • The duals, dualsfrom, dualstill arguments in the API documentation are here the return values. Note that MATLAB allows the return of fewer variables. For example if only duals is needed then the call can be [duals] = mxlpsolve('get_sensitivity_rhs', lp). The unrequested values are even not calculated.
    • The return code of the call is the last value.
    • get_sensitivity_rhs and get_sensitivity_rhsex are both implemented, but have the same functionality.
  • get_simplextype
    • return = mxlpsolve('get_simplextype', lp)
    • No special considerations.
  • get_solutioncount
    • return = mxlpsolve('get_solutioncount', lp)
    • No special considerations.
  • get_solutionlimit
    • return = mxlpsolve('get_solutionlimit', lp)
    • No special considerations.
  • get_status
    • return = mxlpsolve('get_status', lp)
    • No special considerations.
  • get_statustext
    • return = mxlpsolve('get_statustext', lp, statuscode)
    • No special considerations.
  • get_timeout
    • return = mxlpsolve('get_timeout', lp)
    • No special considerations.
  • get_total_iter
    • return = mxlpsolve('get_total_iter', lp)
    • No special considerations.
  • get_total_nodes
    • return = mxlpsolve('get_total_nodes', lp)
    • No special considerations.
  • get_upbo
    • return = mxlpsolve('get_upbo', lp, column)
    • [upbo] = mxlpsolve('get_upbo', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_var_branch
    • return = mxlpsolve('get_var_branch', lp, column)
    • [var_branch] = mxlpsolve('get_var_branch', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_var_dualresult
    • return = mxlpsolve('get_var_dualresult', lp, index)
    • No special considerations.
  • get_var_primalresult
    • return = mxlpsolve('get_var_primalresult', lp, index)
    • No special considerations.
  • get_var_priority
    • return = mxlpsolve('get_var_priority', lp, column)
    • [var_priority] = mxlpsolve('get_var_priority', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • get_variables
    • [var, return] = mxlpsolve('get_variables', lp)
    • The var argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_verbose
    • return = mxlpsolve('get_verbose', lp)
    • No special considerations.
  • get_working_objective
    • return = mxlpsolve('get_working_objective', lp)
    • No special considerations.
  • guess_basis
    • [basisvector, return] = mxlpsolve('guess_basis', lp, [guessvector])
    • In the API, element 0 of guessvector is not used and values start from element 1. In Matlab, there is no unused element in the matrix.
    • In the API, element 0 of basisvector is not used and values start from element 1. In Matlab, there is no unused element in the matrix.
  • has_BFP
    • return = mxlpsolve('has_BFP', lp)
    • No special considerations.
  • has_XLI
    • return = mxlpsolve('has_XLI', lp)
    • No special considerations.
  • is_add_rowmode
    • return = mxlpsolve('is_add_rowmode', lp)
    • No special considerations.
  • is_anti_degen
    • return = mxlpsolve('is_anti_degen', lp, testmask)
    • No special considerations.
  • is_binary
    • return = mxlpsolve('is_binary', lp, column)
    • [binary] = mxlpsolve('is_binary', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • is_break_at_first
    • return = mxlpsolve('is_break_at_first', lp)
    • No special considerations.
  • is_constr_type
    • return = mxlpsolve('is_constr_type', lp, row, mask)
    • No special considerations.
  • is_debug
    • return = mxlpsolve('is_debug', lp)
    • No special considerations.
  • is_feasible
    • return = mxlpsolve('is_feasible', lp, [values] {, threshold})
    • The threshold argument is optional. When not provided, the value of get_epsint will be taken.
  • is_free is_unbounded
    • return = mxlpsolve('is_free', lp, column)
    • return = mxlpsolve('is_unbounded', lp, column)
    • [free] = mxlpsolve('is_free', lp)
    • [free] = mxlpsolve('is_unbounded', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • is_infinite
    • return = mxlpsolve('is_infinite', lp, value)
    • No special considerations.
  • is_int
    • return = mxlpsolve('is_int', lp, column)
    • [int] = mxlpsolve('is_int', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • is_integerscaling
    • return = mxlpsolve('is_integerscaling', lp)
    • No special considerations.
  • is_maxim
    • return = mxlpsolve('is_maxim', lp)
    • No special considerations.
  • is_nativeBFP
    • return = mxlpsolve('is_nativeBFP', lp)
    • No special considerations.
  • is_nativeXLI
    • return = mxlpsolve('is_nativeXLI', lp)
    • No special considerations.
  • is_negative
    • return = mxlpsolve('is_negative', lp, column)
    • [negative] = mxlpsolve('is_negative', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • is_piv_mode
    • return = mxlpsolve('is_piv_mode', lp, testmask)
    • No special considerations.
  • is_piv_rule
    • return = mxlpsolve('is_piv_rule', lp, rule)
    • No special considerations.
  • is_presolve
    • return = mxlpsolve('is_presolve', lp, testmask)
    • No special considerations.
  • is_scalemode
    • return = mxlpsolve('is_scalemode', lp, testmask)
    • No special considerations.
  • is_scaletype
    • return = mxlpsolve('is_scaletype', lp, scaletype)
    • No special considerations.
  • is_semicont
    • return = mxlpsolve('is_semicont', lp, column)
    • [semicont] = mxlpsolve('is_semicont', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • is_SOS_var
    • return = mxlpsolve('is_SOS_var', lp, column)
    • [SOS_var] = mxlpsolve('is_SOS_var', lp)
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a MATLAB matrix.
  • is_trace
    • return = mxlpsolve('is_trace', lp)
    • No special considerations.
  • is_use_names
    • return = mxlpsolve('is_use_names', lp, isrow)
    • No special considerations.
  • lp_solve_version
    • versionstring = mxlpsolve('lp_solve_version')
    • The mxlpsolve API routine returns the version information in 4 provided argument variables while the MATLAB version returns the information as a string in the format major.minor.release.build
  • make_lp
    • lp_handle = mxlpsolve('make_lp', rows, columns)
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
  • print_constraints
    • mxlpsolve('print_constraints', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
    • The same information can also be obtained via mxlpsolve('get_constraints', lp). This shows the result on screen.
  • print_debugdump
    • return = mxlpsolve('print_debugdump', lp, filename)
    • No special considerations.
  • print_duals
    • mxlpsolve('print_duals', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
    • The same information can be obtained via mxlpsolve('get_dual_solution', lp). This shows the result on screen.
  • print_lp
    • mxlpsolve('print_lp', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
  • print_objective
    • mxlpsolve('print_objective', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
    • The same information can be obtained via mxlpsolve('get_objective', lp). This shows the result on screen.
  • print_scales
    • mxlpsolve('print_scales', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
  • print_solution
    • mxlpsolve('print_solution', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
    • The same information can also be obtained via mxlpsolve('get_variables', lp). This shows the result on screen.
  • print_str
    • mxlpsolve('print_str', lp, str)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
  • print_tableau
    • mxlpsolve('print_tableau', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under MATLAB (Windows) this means that the output is not shown.
  • put_abortfunc
    • Not implemented.
  • put_logfunc
    • Not implemented.
    • However, the mxlpsolve driver sets a log function to redirect the output of lpsolve from stdout (which is not visible in Windows MATLAB) to the command window of MATLAB. As such, all reported output can be seen in MATLAB. How much output is seen is controlled by the verbose level that can be defined by set_verbose or can be specified in the read_ routines.
  • put_msgfunc
    • Not implemented.
  • read_basis
    • [ret, info] = mxlpsolve('read_basis', lp, filename)
    • No special considerations.
  • read_freemps, read_freeMPS
    • lp_handle = mxlpsolve('read_freemps', filename {, options})
    • lp_handle = mxlpsolve('read_freeMPS', filename {, options})
    • In the lpsolve API, read_freemps needs a FILE handle. In MATLAB it needs the filename and thus acts the same as read_freeMPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_lp, read_LP
    • lp_handle = mxlpsolve('read_lp', filename {, verbose {, lp_name}})
    • lp_handle = mxlpsolve('read_LP', filename {, verbose {, lp_name}})
    • In the lpsolve API, read_lp needs a FILE handle. In MATLAB it needs the filename and thus acts the same as read_LP.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not provided then NORMAL is used.
    • lp_name is optional. If not provided then no name is given to the model ('').
  • read_mps, read_MPS
    • lp_handle = mxlpsolve('read_mps', filename {, options})
    • lp_handle = mxlpsolve('read_MPS', filename {, options})
    • In the lpsolve API, read_mps needs a FILE handle. In MATLAB it needs the filename and thus acts the same as read_MPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_params
    • return = mxlpsolve('read_params', lp, filename {, options })
    • options is optional.
  • read_XLI
    • lp_handle = mxlpsolve('read_XLI', xliname, modelname {, dataname {, options {, verbose}}}
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • dataname is optional. When not provided, '' (NULL) is taken. '' is taken as NULL.
    • options is optional. When not provided, '' is taken.
    • verbose is optional. If not specified, then NORMAL is used.
  • reset_basis
  • set_basisvar
    • mxlpsolve('set_basisvar', lp, basisPos, enteringCol)
    • No special considerations.
  • set_add_rowmode
    • return = mxlpsolve('set_add_rowmode', lp, turnon)
    • No special considerations.
  • set_anti_degen
    • mxlpsolve('set_anti_degen', lp, anti_degen)
    • No special considerations.
  • set_basis
    • return = mxlpsolve('set_basis', lp, [bascolumn], nonbasic)
    • In the API, element 0 of bascolumn is not used and values start from element 1. In MATLAB, there is no unused element in the matrix.
  • set_basiscrash
    • mxlpsolve('set_basiscrash', lp, mode)
    • No special considerations.
  • set_bb_depthlimit
    • mxlpsolve('set_bb_depthlimit', lp, bb_maxlevel)
    • No special considerations.
  • set_bb_floorfirst
    • mxlpsolve('set_bb_floorfirst', lp, bb_floorfirst)
    • No special considerations.
  • set_bb_rule
    • mxlpsolve('set_bb_rule', lp, bb_rule)
    • No special considerations.
  • set_BFP
    • return = mxlpsolve('set_BFP', lp, filename)
    • No special considerations.
  • set_binary
    • return = mxlpsolve('set_binary', lp, column, must_be_bin)
    • return = mxlpsolve('set_binary', lp, [must_be_bin])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds
    • return = mxlpsolve('set_bounds', lp, column, lower, upper)
    • return = mxlpsolve('set_bounds', lp, [lower], [upper])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds_tighter
    • mxlpsolve('set_bounds_tighter', lp, tighten)
    • No special considerations.
  • set_break_at_first
    • mxlpsolve('set_break_at_first', lp, break_at_first)
    • No special considerations.
  • set_break_at_value
    • mxlpsolve('set_break_at_value', lp, break_at_value)
    • No special considerations.
  • set_col_name
    • return = mxlpsolve('set_col_name', lp, column, name)
    • return = mxlpsolve('set_col_name', lp, [names])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_column, set_columnex
    • return = mxlpsolve('set_column', lp, col_no, [column])
    • return = mxlpsolve('set_columnex', lp, col_no, [column])
    • Both have the same interface from set_column but act as set_columnex
  • set_constr_type
    • return = mxlpsolve('set_constr_type', lp, row, con_type)
    • return = mxlpsolve('set_constr_type', lp, [con_type])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_debug
    • mxlpsolve('set_debug', lp, debug)
    • No special considerations.
  • set_epsb
    • mxlpsolve('set_epsb', lp, epsb)
    • No special considerations.
  • set_epsd
    • mxlpsolve('set_epsd', lp, epsd)
    • No special considerations.
  • set_epsel
    • mxlpsolve('set_epsel', lp, epsel)
    • No special considerations.
  • set_epsint
    • mxlpsolve('set_epsint', lp, epsint)
    • No special considerations.
  • set_epslevel
    • mxlpsolve('set_epslevel', lp, epslevel)
    • No special considerations.
  • set_epsperturb
    • mxlpsolve('set_epsperturb', lp, epsperturb)
    • No special considerations.
  • set_epspivot
    • mxlpsolve('set_epspivot', lp, epspivot)
    • No special considerations.
  • set_free set_unbounded
    • return = mxlpsolve('set_free', lp, column)
    • return = mxlpsolve('set_unbounded', lp, column)
    • No special considerations.
  • set_improve
    • mxlpsolve('set_improve', lp, improve)
    • No special considerations.
  • set_infinite
    • mxlpsolve('set_infinite', lp, infinite)
    • No special considerations.
  • set_int
    • return = mxlpsolve('set_int', lp, column, must_be_int)
    • return = mxlpsolve('set_int', lp, [must_be_int])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lowbo
    • return = mxlpsolve('set_lowbo', lp, column, value)
    • return = mxlpsolve('set_lowbo', lp, [values])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lp_name
    • return = mxlpsolve('set_lp_name', lp, name)
    • In MATLAB, when you name a model, this name can be used everywhere where lp is specified. This to access the model via the name instead of via a handle.
  • set_mat
    • return = mxlpsolve('set_mat', lp, row, column, value)
    • return = mxlpsolve('set_mat', lp, [matrix])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows to set the whole matrix (all rows/columns) at once. This is the most performant way to provide the constraint matrix. Consider using a MATLAB sparse matrix for maximum performance and least memory usage. The matrix must be two-dimentional.
  • set_maxim
    • mxlpsolve('set_maxim', lp)
    • No special considerations.
  • set_maxpivot
    • mxlpsolve('set_maxpivot', max_num_inv)
    • No special considerations.
  • set_minim
    • mxlpsolve('set_minim', lp)
    • No special considerations.
  • set_mip_gap
    • mxlpsolve('set_mip_gap', lp, absolute, mip_gap)
    • No special considerations.
  • set_negrange
    • mxlpsolve('set_negrange', negrange)
    • No special considerations.
  • set_obj
    • return = mxlpsolve('set_obj', lp, column, value)
    • return = mxlpsolve('set_obj', lp, [values])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables. It is then the same as set_obj_fn
  • set_obj_bound
    • mxlpsolve('set_obj_bound', lp, obj_bound)
    • No special considerations.
  • set_obj_fn, set_obj_fnex
    • return = mxlpsolve('set_obj_fn', lp, [row])
    • return = mxlpsolve('set_obj_fnex', lp, [row])
    • Both have the same interface from set_obj_fn but act as set_obj_fnex
    • In the API, element 0 is not used and values start from element 1. In MATLAB, there is no unused element in the matrix.
  • set_outputfile
    • return = mxlpsolve('set_outputfile', lp, filename)
    • In the API description it says that setting filename to NULL results in writing output back to stdout. In MATLAB under Windows, output to stdout it not shown. However it results in closing the file. Use '' to have the effect of NULL.
  • set_outputstream
    • Not implemented.
  • set_pivoting
    • mxlpsolve('set_pivoting', lp, pivoting)
    • No special considerations.
  • set_preferdual
    • mxlpsolve('set_preferdual', lp, dodual)
    • No special considerations.
  • set_presolve
    • mxlpsolve('set_presolve', lp, do_presolve {, maxloops})
    • The maxloops argument is optional in MATLAB. If not provided, then infinite is used.
  • set_print_sol
    • mxlpsolve('set_print_sol', lp, print_sol)
    • No special considerations.
  • set_rh
    • return = mxlpsolve('set_rh', lp, row, value)
    • return = mxlpsolve('set_rh', lp, [values])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows. Note that in this case, the value of row 0 is not specified in the matrix.
  • set_rh_range
    • return = mxlpsolve('set_rh_range', lp, row, deltavalue)
    • return = mxlpsolve('set_rh_range', lp, [deltavalues])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_rh_vec
    • mxlpsolve('set_rh_vec', lp, [rh])
    • In the API, element 0 is not used and values start from element 1. In MATLAB, there is no unused element in the matrix.
  • set_row, set_rowex
    • return = mxlpsolve('set_row', lp, row_no, [row])
    • return = mxlpsolve('set_rowex', lp, row_no, [row])
    • Both have the same interface from set_row but act as set_rowex
    • In the API, element 0 is not used and values start from element 1. In MATLAB, there is no unused element in the matrix.
  • set_row_name
    • return = mxlpsolve('set_row_name', lp, row, name)
    • return = mxlpsolve('set_row_name', lp, [names])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_scalelimit
    • mxlpsolve('set_scalelimit', lp, scalelimit)
    • No special considerations.
  • set_scaling
    • mxlpsolve('set_scaling', lp, scalemode)
    • No special considerations.
  • set_semicont
    • return = mxlpsolve('set_semicont', lp, column, must_be_sc)
    • return = mxlpsolve('set_semicont', lp, [must_be_sc])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_sense
    • mxlpsolve('set_sense', lp, maximize)
    • No special considerations.
  • set_simplextype
    • mxlpsolve('set_simplextype', lp, simplextype)
    • No special considerations.
  • set_solutionlimit
    • mxlpsolve('set_solutionlimit', lp, simplextype)
    • No special considerations.
  • set_timeout
    • mxlpsolve('set_timeout', lp, sectimeout)
    • No special considerations.
  • set_trace
    • mxlpsolve('set_trace', lp, trace)
    • No special considerations.
  • set_upbo
    • return = mxlpsolve('set_upbo', lp, column, value)
    • return = mxlpsolve('set_upbo', lp, [values])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_use_names
    • mxlpsolve('set_use_names', lp, isrow, use_names)
    • No special considerations.
  • set_var_branch
    • return = mxlpsolve('set_var_branch', lp, column, branch_mode)
    • return = mxlpsolve('set_var_branch', lp, [branch_mode])
    • In MATLAB, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_weights
    • return = mxlpsolve('set_var_weights', lp, [weights])
    • No special considerations.
  • set_verbose
    • mxlpsolve('set_verbose', lp, verbose)
    • No special considerations.
  • set_XLI
    • return = mxlpsolve('set_XLI', lp, filename)
    • No special considerations.
  • solve
    • result = mxlpsolve('solve', lp)
    • No special considerations.
  • str_add_column
    • Not implemented.
  • str_add_constraint
    • Not implemented.
  • str_set_obj_fn
    • Not implemented.
  • str_set_rh_vec
    • Not implemented.
  • time_elapsed
    • return = mxlpsolve('time_elapsed', lp)
    • No special considerations.
  • unscale
    • mxlpsolve('unscale', lp)
    • No special considerations.
  • write_basis
    • mxlpsolve('write_basis', lp, filename)
    • No special considerations.
  • write_freemps, write_freeMPS
    • return = mxlpsolve('write_freemps', lp, filename)
    • return = mxlpsolve('write_freeMPS', lp, filename)
    • In the lpsolve API, write_freeMPS needs a FILE handle. In MATLAB it needs the filename and thus acts the same as write_freemps.
  • write_lp, write_LP
    • return = mxlpsolve('write_lp', lp, filename)
    • return = mxlpsolve('write_LP', lp, filename)
    • In the lpsolve API, write_LP needs a FILE handle. In MATLAB it needs the filename and thus acts the same as write_lp.
  • write_mps, write_MPS
    • return = mxlpsolve('write_mps', lp, filename)
    • return = mxlpsolve('write_MPS', lp, filename)
    • In the lpsolve API, write_MPS needs a FILE handle. In MATLAB it needs the filename and thus acts the same as write_mps.
    • No special considerations.
  • write_XLI
    • return = mxlpsolve('write_XLI', lp, filename {, options {, results}})
    • No special considerations.

Extra MATLAB routines

These routines are not part of the lpsolve API, but are added for backwards compatibility. Most of them exist in the lpsolve API with another name.

  • [names] = mxlpsolve('get_col_names', lp)
    • The same as get_col_name. Implemented for backwards compatibility.
  • [constr_type] = mxlpsolve('get_constr_types', lp)
    • The same as get_constr_type. Implemented for backwards compatibility.
  • [int] = mxlpsolve('get_int', lp)
    • The same as is_int. Implemented for backwards compatibility.
  • return = mxlpsolve('get_no_cols', lp)
    • The same as get_Ncolumns. Implemented for backwards compatibility.
  • return = mxlpsolve('get_no_rows', lp)
    • The same as get_Nrows. Implemented for backwards compatibility.
  • name = mxlpsolve('get_objective_name', lp)
    • The same as get_row_name with row=0. Implemented for backwards compatibility.
  • [row_vec, return] = mxlpsolve('get_obj_fn', lp)
    [row_vec, return] = mxlpsolve('get_obj_fun', lp)
    • The same as get_row with row 0. Implemented for backwards compatibility.
  • name = mxlpsolve('get_problem_name', lp)
    • The same as get_lp_name. Implemented for backwards compatibility.
  • [costs] = mxlpsolve('get_reduced_costs', lp)
    • The same as get_dual_solution. Implemented for backwards compatibility.
  • [names] = mxlpsolve('get_row_names', lp)
    • The same as get_row_name. Implemented for backwards compatibility.
  • [obj, x, duals, return] = mxlpsolve('get_solution', lp)
    • Returns the value of the objective function, the values of the variables and the duals. Implemented for backwards compatibility.
    • The return code of the call is the last value.
  • value = mxlpsolve('mat_elm', lp)
    • The same as get_mat. Implemented for backwards compatibility.
  • [handle_vec] = mxlpsolve('print_handle')
    • Returns a vector with open handles. Can be handy to see which handles aren't closed yet with delete_lp or free_lp.
  • lp_handle = mxlpsolve('read_lp_file', filename {, verbose {, lp_name}})
    • The same as read_LP. Implemented for backwards compatibility.
  • lp_handle = mxlpsolve('get_handle', lp_name)
    • Get the handle for this model from the models name. If an unknown model name is given (or already deleted), -1 is returned.
  • return_constants = mxlpsolve('return_constants'[, return_constants])
    • Returns the setting of return_constants and optionally sets its value.

Compile the mxlpsolve driver

Windows

Under Windows, the mxlpsolve MATLAB driver is a dll: mxlpsolve.dll or mxlpsolve.mexw32 or mxlpsolve.mexw64
This dll is an interface to the lpsolve55.dll lpsolve dll that contains the implementation of lp_solve. lpsolve55.dll is distributed with the lp_solve package (archive lp_solve_5.5.0.15_dev.zip). The mxlpsolve MATLAB driver dll is just a wrapper between MATLAB and lp_solve to translate the input/output to/from MATLAB and the lp_solve library.
Note that under Windows, the original extension was .dll. Newer versions of MATLAB require extension .mexw32. You can just rename the .dll to .mexw32 for that.
See also External Interfaces/API, MATLAB

Also the library lp_explicit.lib is needed. The lp_explicit.lib file is a wrapper library between the lp_solve dll and the compiled application. This wrapper is needed because the lp_solve dll uses __stdcall calling convention. There seems to be a problem in MATLAB to call __stdcall functions directly (unexpected crashes). The lp_explicit library uses __cdecl calling convention and this then calls the lp_solve dll which uses __stdcall calling convention. Looks a bit complex, but it works without any problem.

There appears to be another way to compile MATLAB mex files with gcc for Windows. This is not tested. See Compiling Matlab mex files with gcc for Windows.

Unix/Linux

Under Unix/Linux, the mxlpsolve MATLAB driver is a shared library. The resulting file has a platform-dependent extension, as shown in the table below:

    sol2, SunOS 5.x - .mexsol
    hpux            - .mexhpux
    hp700           - .mexhp7
    ibm_rs          - .mexrs6
    sgi             - .mexsg
    alpha           - .mexaxp
    glnx86          - .mexglx
    Mac OS X        - .mexmac

This shared library is an interface to the lpsolve55.so lpsolve shared library that contains the implementation of lp_solve. lpsolve55.so is distributed with the lp_solve package (archive lp_solve_5.5.0.15_dev.tar.gz). The mxlpsolve MATLAB driver library is just a wrapper between MATLAB and lp_solve to translate the input/output to/from MATLAB and the lp_solve library.

All platforms

The mxlpsolve MATLAB driver is written in C. To compile this code, the MATLAB compiler is needed (mex). This compiler must be called from MATLAB. MATLAB may also need to be configured to find the C compiler. For this, enter the following in the MATLAB command windows and follow the instructions: mex -setup

To make the compilation process easier, a makefile can be used: Makefile.m
Enter 'help Makefile' from the MATLAB command window to see a list of options.
It may be necessary to edit this file first to change the path where lp_solve is installed. Change at the beginning lpsolvepath.
To make for release, just enter Makefile and everything is build.
This compiles three source files: lpsolve.c, matlab.c and hash.c
The optional arguments to Makefile are used for development. The first argument allows specifying a filename so that only this file is build. For example hash.c should only be compiled once while developing. So specifying 'lpsolve.c' as first argument will only compile this file and then link everything. This makes the build process a bit faster. The second argument is by default 0. When set to 1, then extra argument checking is done and while executing, some debug information is printed. Should only be used for debugging purposes. When released, this parameter should be 0. The third argument is by default 1. When set to 0, the makefile will not ask to press enter to start building.

See also Using lpsolve from O-Matrix, Using lpsolve from Sysquake, Using lpsolve from Scilab, Using lpsolve from Octave, Using lpsolve from FreeMat, Using lpsolve from Euler, Using lpsolve from Python, Using lpsolve from Sage, Using lpsolve from PHP, Using lpsolve from R

doc/set_epsel.htm0000644000175000017500000000672710237176662013012 0ustar renerene set_epsel

set_epsel

Specifies the value that is used as a tolerance for rounding values to zero.

void set_epsel(lprec *lp, REAL epsel);

Return Value

set_epsel has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

epsel

The value that is used as a tolerance for rounding values to zero.

Remarks

The set_epsel function specifies the value that is used as a tolerance for rounding values to zero.
Floating-point calculations always result in loss of precision and rounding errors. Therefore a very small value (example 1e-99) could be the result of such errors and should be considered as 0 for the algorithm. epsel specifies the tolerance to determine if a value should be considered as 0. If abs(value) is less than this epsel value, it is considered as 0.
epsel is used on all other places where epsint, epsb, epsd, epspivot, epsperturb are not used. The default epsel value is 1e-12

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_epsel(lp, 1.0e-11); /* sets epsel to 1e-11 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_epsel, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsb, get_epsb, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap

doc/time_elapsed.htm0000644000175000017500000000453610237176666013462 0ustar renerene time_elapsed

time_elapsed

Gets the time elapsed since start of solve.

REAL time_elapsed(lprec *lp);

Return Value

time_elapsed returns the number of seconds after solve and lag_solve has started.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The time_elapsed function returns the time in seconds since solve and lag_solve has started.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  long timeelapsed;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  timeelapsed = time_elapsed(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_timeout, set_timeout, solve, lag_solve

doc/.DS_Store0000644000175000017500000011600411203100717011744 0ustar renereneBud1``  0 ;t_lowb get_lowbo.htmIlocblobe is_debug.htmIlocblobprint_solution.htmIlocblob5 set_mat.htmIlocblobeput_bb_nodefunc.htmIlocblobZput_logfunc.htmIlocblobput_msgfunc.htmIlocblob Python.htmIlocblobZI  @ @ @ @3 set_maxim.htmIlocblobZset_maxpivot.htmIlocblob set_minim.htmIlocblobset_mip_gap.htmIlocblobZ set_negrange.htmIlocblob set_obj_bound.htmIlocblob set_obj_fn.htmIlocblobZ yset_obj_in_basis.htmIlocblob yset_output.htmIlocblob yset_pivoting.htmIlocblobZ set_preferdual.htmIlocblob set_presolve.htmIlocblob set_print_sol.htmIlocblobZ!1 set_rh.htmIlocblob!1set_rh_range.htmIlocblob!1set_rh_vec.htmIlocblobZ! set_row.htmIlocblob!set_row_name.htmIlocblob!set_scalelimit.htmIlocblobZ!set_scaling.htmIlocblob!set_semicont.htmIlocblob! set_sense.htmIlocblobZ"Eset_simplextype.htmIlocblob"Eset_solutionlimit.htmIlocblob"Eset_timeout.htmIlocblobZ" set_trace.htmIlocblob"set_unbounded.htmIlocblob" set_upbo.htmIlocblobZ"set_use_names.htmIlocblob"set_var_branch.htmIlocblob"set_var_weights.htmIlocblobZ#Yset_verbose.htmIlocblob#Y set_XLI.htmIlocblob#Ysimpletree.cssIlocblobZ#simpletreemenu.jsIlocblob# solve.htmIlocblob#SOS.htmIlocblobZ$!SpecialOrderedSetsOfTypeOne_filesIlocblob$!SpecialOrderedSetsOfTypeTwo_filesIlocblob$ Sysquake.htmIlocblobZ$mtime_elapsed.htmIlocblob$m unscale.htmIlocblob$mWin32IlocblobZ$write_basis.htmIlocblob$ write_lp.htmIlocblob$ write_mps.htmIlocblobZ%%write_params.htmIlocblob%% write_XLI.htmIlocblob%%XLI.htmIlocblobZ%Xpress-format.htmIlocblob% Zimpl.htmIlocblob%Fa.batIlocblobZ! absolute.htmIlocblob!add_column.htmIlocblob!add_constraint.htmIlocblobZ}add_lag_con.htmIlocblob} add_SOS.htmIlocblob}AMPL.htmIlocblobZarvIlocblobBAK.sqIlocblobBAK2.sqIlocblobZ5BAK3.sqIlocblob5bas-format.htmIlocblob5BFP.htmIlocblobZ Build.htmIlocblob BuildLog.htmIlocblob changes5.htmIlocblobZ changes55.htmIlocblob closed.gifIlocblobcolumn_in_lp.htmIlocblobZI contents.htmIlocblobI copy_lp.htmIlocblobICPLEX-format.htmIlocblobZdefault_basis.htmIlocblobdel_column.htmIlocblobdel_constraint.htmIlocblobZ delete_lp.htmIlocblobdimacs_asn.gifIlocblobDIMACS_asn.htmIlocblobZ]dimacs_maxf.gifIlocblob]DIMACS_maxf.htmIlocblob]dimacs_mcf.gifIlocblobZDIMACS_mcf.htmIlocblobdistribIlocblob distrib.batIlocblobZdistribution.htmIlocblob download.htmIlocblobdualize_lp.htmIlocblobZq Euler.htmIlocblobq Euler1.jpgIlocblobq Euler2.jpgIlocblobZ Euler3.jpgIlocblobFAQ.htmIlocblobfold.gifIlocblobZ) formulate.htmIlocblob)free.htmIlocblob) free_lp.htmIlocblobZ FreeMat.htmIlocblobgen.batIlocblobget_anti_degen.htmIlocblobZ get_basis.htmIlocblobget_basiscrash.htmIlocblobget_bb_depthlimit.htmIlocblobZ=get_bb_floorfirst.htmIlocblob=get_bb_rule.htmIlocblob=get_bounds_tighter.htmIlocblobZget_break_at_value.htmIlocblobget_col_name.htmIlocblobget_column.htmIlocblobZget_constr_type.htmIlocblobget_constr_value.htmIlocblobget_constraints.htmIlocblobZQ get_epsb.htmIlocblobQ get_epsd.htmIlocblobQ get_epsel.htmIlocblobZget_epsint.htmIlocblobget_epsperturb.htmIlocblobget_epspivot.htmIlocblobZ get_improve.htmIlocblob get_infinite.htmIlocblob get_lambda.htmIlocblobZe>get_lp_index.htmIlocblobeget_lp_name.htmIlocblobZ get_Lrows.htmIlocblob get_mat.htmIlocblobget_max_level.htmIlocblobZ get_maxpivot.htmIlocblob get_mip_gap.htmIlocblob get_nameindex.htmIlocblobZ yget_Ncolumns.htmIlocblob yget_negrange.htmIlocblob yget_nonzeros.htmIlocblobZ get_Norig_columns.htmIlocblob get_Norig_rows.htmIlocblob get_Nrows.htmIlocblobZ 1get_obj_bound.htmIlocblob 1get_objective.htmIlocblob 1get_orig_index.htmIlocblobZ get_pivoting.htmIlocblob get_presolve.htmIlocblob get_presolveloops.htmIlocblobZ get_primal_solution.htmIlocblob get_print_sol.htmIlocblob get_rh.htmIlocblobZ Eget_rh_range.htmIlocblob E get_row.htmIlocblob Eget_row_name.htmIlocblobZ get_scalelimit.htmIlocblob get_scaling.htmIlocblob get_sensitivity_obj.htmIlocblobZ get_sensitivity_rhs.htmIlocblob get_simplextype.htmIlocblob get_solutioncount.htmIlocblobZ Yget_solutionlimit.htmIlocblob Yget_status.htmIlocblob Yget_statustext.htmIlocblobZ get_timeout.htmIlocblob get_total_iter.htmIlocblob get_total_nodes.htmIlocblobZ  get_upbo.htmIlocblob get_var_branch.htmIlocblob get_var_priority.htmIlocblobZ mget_variables.htmIlocblob mget_verbose.htmIlocblob mget_working_objective.htmIlocblobZ guess_basis.htmIlocblob has_BFP.htmIlocblob has_XLI.htmIlocblobZ%HTMLHelp.vcprojIlocblob%'HTMLHelp.vcproj.penohomevista.peno.userIlocblob%$HTMLHelp.vcproj.PENOHOMEXP.peno.userIlocblobZIDEIlocblobIDE.htmIlocblob index.htmIlocblobZ index.htmlIlocblobInfeasible.htmIlocblob integer.htmIlocblobZ9 Intro.htmIlocblob9is_add_rowmode.htmIlocblob9is_anti_degen.htmIlocblobZ is_binary.htmIlocblobis_break_at_first.htmIlocblobis_constr_type.htmIlocblobZda.htmIlocblobZeDis_feasible.htmIlocblobis_infinite.htmIlocblobZM is_int.htmIlocblobMis_integerscaling.htmIlocblobMis_lag_trace.htmIlocblobZ is_maxim.htmIlocblobis_nativeBFP.htmIlocblobis_nativeXLI.htmIlocblobZis_negative.htmIlocblobis_obj_in_basis.htmIlocblobis_piv_mode.htmIlocblobZais_piv_rule.htmIlocblobais_presolve.htmIlocblobais_scalemode.htmIlocblobZis_scaletype.htmIlocblobis_semicont.htmIlocblobis_SOS_var.htmIlocblobZ is_trace.htmIlocblobis_unbounded.htmIlocblobis_use_names.htmIlocblobZuJavaIlocblobuJava.htmIlocblobu lag_solve.htmIlocblobZLGPL.htmIlocblobLINDO-format.htmIlocblob links.htmIlocblobZ-list.gifIlocblob- lp-format.htmIlocblob- lp_solve.hhcIlocblobZ lp_solve.hhkIlocblob lp_solve.hhpIlocblob lp_solve.htmIlocblobZlp_solve_5.5.0.12.chwIlocbloblp_solve_5.5.0.13.chwIlocbloblp_solve_5.5.0.14.chmIlocblobZAlp_solve_5.5.0.14.chwIlocblobAlp_solve_5.5_doc.tar.gzIlocblobAlp_solve_version.htmIlocblobZlp_solveAPIreference.htmIlocblob LPBasics.htmIlocblob make_lp.htmIlocblobZman.ncbIlocblobman.slnIlocblobman.suoIlocblobZU MathProg.htmIlocblobU MATLAB.htmIlocblobU MATLAB1.jpgIlocblobZ MATLAB2.jpgIlocblob MATLAB3.jpgIlocblobmps-format.htmIlocblobZ O-Matrix.htmIlocblob O-Matrix1.jpgIlocblob O-Matrix2.jpgIlocblobZi O-Matrix3.jpgIlocblobi Octave.htmIlocblobi Octave1.jpgIlocblobZ Octave2.jpgIlocblob Octave3.jpgIlocblobopen.gifIlocblobZ!pe.cfgIlocblob!PHP.htmIlocblob! Presolve.htmIlocblobZ}print_constraints.htmIlocblob}print_debugdump.htmIlocblob}print_duals.htmIlocblobZ print_lp.htmIlocblobprint_objective.htmIlocblobprint_scales.htmIlocblobZ5da.htmIlocblobZe< print_str.htmIlocblob5print_tableau.htmIlocblobZput_abortfunc.htmIlocblobput_bb_branchfunc.htmIlocblobput_bb_nodefunc.htmIlocblobZput_logfunc.htmIlocblobput_msgfunc.htmIlocblob Python.htmIlocblobZIquickstart.htmIlocblobIR.htmIlocblobI ratio.htmIlocblobZread_basis.htmIlocblob read_lp.htmIlocblob read_mps.htmIlocblobZread_params.htmIlocblob read_XLI.htmIlocblobreset_basis.htmIlocblobZ]reset_params.htmIlocblob] resize_lp.htmIlocblob]Sage.htmIlocblobZ scaling.htmIlocblob Scilab.htmIlocblob Scilab1.jpgIlocblobZ Scilab2.jpgIlocblob Scilab3.jpgIlocblob search.htmIlocblobZq semi-cont.htmIlocblobqSemi-ContinuousVariables_filesIlocblobqsensitivity.htmIlocblobZset_add_rowmode.htmIlocblobset_anti_degen.htmIlocblob set_basis.htmIlocblobZ)set_basiscrash.htmIlocblob)set_basisvar.htmIlocblob)set_bb_depthlimit.htmIlocblobZset_bb_floorfirst.htmIlocblobset_bb_rule.htmIlocblob set_BFP.htmIlocblobZset_binary.htmIlocblobset_bounds.htmIlocblobset_bounds_tighter.htmIlocblobZ=set_break_at_first.htmIlocblob=set_break_at_value.htmIlocblob=set_col_name.htmIlocblobZset_column.htmIlocblobset_constr_type.htmIlocblob set_debug.htmIlocblobZ set_epsb.htmIlocblob set_epsd.htmIlocblob set_epsel.htmIlocblobZQset_epsint.htmIlocblobQset_epslevel.htmIlocblobQset_epsperturb.htmIlocblobZset_epspivot.htmIlocblobset_improve.htmIlocblobset_infinite.htmIlocblobZ set_int.htmIlocblob set_lag_trace.htmIlocblob set_lowbo.htmIlocblobZeset_lp_name.htmIlocblobeprint_debugdump.htmIlocblob}print_duals.htmIlocblobZ print_lp.htmIlocblobprint_objective.htmIlocblobprint_scales.htmIlocblobZ5da.htmIlocblobZe` E  0 @ P DSDB `hp @ @locblob Scilab1.jpgIlocblobZ Scilab2.jpgIlocblob Scilab3.jpgIlocblob search.htmIlocblobZq semi-cont.htmIlocblobqSemi-ContinuousVariables_filesIlocblobqsensitivity.htmIlocblobZset_add_rowmode.htmIlocblobset_anti_degen.htmIlocblob set_basis.htmIlocblobZ)set_basiscrash.htmIlocblob)set_basisvar.htmIlocblob)doc/Scilab2.jpg0000644000175000017500000014212710252627532012263 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?\>)㯊|[OZW7|OIm \5/xH qwuknZX#ZZ2G]:g!^IJE|BۛB7I$(<~ ؘ<I\|7©}IbCaT~J//|i|)њ/k dž=%?h$-NG/>_W-Rqujx9˨ѭO-Ԗ QPSѧux9檦3[ .rc08 oueYwa/Y]tgPo\|9o<-m>E kLLj؍W't:1c o?|HFm  Fh<)¯gOuo# zljk@>& _$گMj %%n?Lo|/]xw?~" k:foE_?߉CT:3^ևhvYP_Ts JsU*xs9fo2 NSfTᯈwWĭƏ_ ڪM;H}o:W^?|Iy|5Ei,$˳a3fw=2ܷrܫcjT瘏2(۶GRJT劤?e9e)L3Y^XeY1qx% ZueiiӦ7(K3w'z?1ׯ?xsI#jxSӡ~&_7N+QA5eC$kk~NoWB- :~,|WԶ_?e_MnKW߈|'? 7 h}-4Zg'K 5[6~u/݋!3.$u=Yq3Vccs|cx|'|4˰Qj̮;K(N[K.χd2x|7p8 bF_~_,nyV<˱5(؜-*h0*~[cG&:O?o62ir@xbi~ɾ>?F_{/ ?)R\ZAo)~ lZjV0 W4 [¿a{P~%#sSM]e36?ox{Hx?]&YQԖ?5 >erɱT0yd\K[+K- ' SOj֥ Y5Lͪ`k cXnRab5aa +(U|nmRG[22#.?l2?1ףw'z/i | Z|+K EcźG^#՗<57])˩b%+ϲWrR`3 .&aV3 _ _ -X^WG ӝl.{a"K^KuJ$8*ԫJZOLuu/sh59HlH})vG,&Y>0>#o-{~ ?Sksq!4}o7?ƏaZmS-o>^^H^4eocby>ό7//$me?2׿Mb}o7?Ə1_ST62׿Mk?o&>7G~Chke Gk?o&L7Xcsq!4{ Wo52#䍿L7G&ZOO9ߐ=+j_oF&ZO-{~'~Cho?/}L|ayy#o-{~o pҹRĐ2xCk#sq!4ƴ?0`qq^>B誯5$O.S_nB7鵭Zkk~gWwOZe}?->]ٱ ~??G%]cGt}_޿޿?_j,6[>_ݛ_ߓt_~O?t}Ge}?->]ٱ ~??G%]cGt}_޿޿?_j,6[>_ݛ_ߓt_~O?t}Ge}?->]Oj__oV>xF`f.es ÞM/W4[O6oSI]YuBD?@[)ouwd3'w$b ߰IO#>ޮY7c/O@A9"kWIpef'qo't5؎+mXs&˫>](Ny&Iխ7c2VW4+Oྵ@-]uo |G߃&oi K+ZIvnd&/.mJy}O=?L<9>(ћ `y sm $,#d\M{l߇Z+\{GNya$ҩԟ]bp*^̛%_yg^Th`pxE*O3uႡ"\5qPgF"^#?7뙭O)<^'[i`O 6@9#kOsO_ړKUoo*}q<߱߁,:jzOA}]J77Wl|*}߃:ׇ|/#ucj:x'^/e v+o#L)ifd# M`Nf>-h;?i Ҵym'.nmGɪI}NPխa;(y4(c9۹g,lp|I񛉳 }'.%,\rS$޲ӥ*ÈS :\lx|/OC]t xfT*?i:4=ĺ>mJHߦ'ҧpoxŞp<<-e Y|o p?0K%գZxYxψ&A_RY<>kUĹvQFY, 3խ)eGfWj[?!⟊9E@.4l|5<[#\S~ 7\|y:{sYx]1|=|k,'_D #Y| fKt˩YO4>x zcI6N~.xFRfShxv~O iZ?omK/o5jzcx_DniibY_pJeUQ"БĐNPmA*_/ѷ7s/ aØ)0X5<#nqx,f8,D%^g(G~_G S=*;̣)s>!G2ҍ<0Zx\®SR9~'*.%*Fkzu.t-R C%敥7z֩{im\_6Rj?.%6Mi0Kr#&9'_& ZmNw>#_|Y/ AWsxSCgKO#Sľy+xKY47Ksm_o Ɵ® :G背o2(n2-ꬣ(˨ᱸeĘgB|%w:m8N1QpN/þ湧dO渺2QbkT e5(Մ+A:9G=(J򊬛?OZ\pKS/"n4xoY_=Ck.rZRo-70ӏ_OId<4{È>.G'wXgY']A}/~+> _']kvxR/n$ui:#NZo L>+|Եx>񥧇|Sgi^{]o%4Z;MB úvzeλ+ƿ݉GUxq,4fbJuLMaQ*1[JO`62 q~ }&3.q+7_."uƎ W2U3q#eMp#߅?g}C\9ǯ|$w@ Z 1~~񎗡kzǂv_|tVu;OIkY?>ݤi>6h4\x\C[{}{oxYeÜQ< b)`jpsSa18,9^yܰE qtxl&*q`)P:|r?xB,O[i}_~| MGxQucaY΁>'DvG!p|v#ah߳?;~gz?٪O)]cT!xjÞ u_k)ZMWG!^&X^ ~þ8χ|k/|_i(|/S࿈<3 Oմxw^~ ZޅWvw:~YMm4r7]V01Ŕgf3<I2RXy Of5)O*˿՜8,?nV{S[2)@Ykh <~¤s,C1ҭ5w?dž~|_S=sDeDljO Ccg_9#K5!?O '^ύm xSZW/tL]|I׏|C1xw\4k+ ~Me&7_ٚᾩT?nO |f~η_|q گë8uo+o/M <5C[xgW ~þ3nrK#]g#xDOO >%yu][VY# ƿ7eoګLlMg!c;]o xO<᛿]c_oKoyZ {?/Omoq>_ ߄-pbgb1՝N5q\YsGw5u0_*UT<'J kiac2uB R:x|(R5%%Z+suTW6"=<' ?/𿇼%C4k^9xQ:|cį]o״t/Kcuݯdo lu ?jo7@>'Ix]+'sxk>4FwxHM /jZOwC!iM>C[{}{9sk`c.Î1Y  NoK\"2ޮq3 &? VLTqpXbNl=+/;} f|9CT04u8Cr.r~[G(pN PQTpʅL=\]QS*Կ ~~_7M>~#KCuoO@<ῄgvOk~ P|R.D|g6NXO;7&= M'o=|/owau^'|=k{x=AּS{Mwjk(&QFC[{}E78q}8W?YGS0uipsV*סF+=qqT1us\~of5l~gcjb'Z*":*ϣGO%1\ 5iKСe^WXe,9=)aGiɰE&E~˯3tN{W7~Zko/~?5 FTx7pdutO6}mocoNWt_N?M:Wp5O>? ߄|d?-_ UL>?/I?_Z,?:Wp4d^}=Zk/~!~^%GTAso/}něAyʽzGN?MSE/8?Wo_qL>?/I?_Z,?:Wp4d^}=Zk/~!~^%GTAso/}něAyʽzGN?MSE/8?Wo_qL>?/I?_Z,?:Wp4d^}=Zk/~!~^%GTAso/}něAyʽzGN?MSE/8?Wo_qL>?/I?_Z,?:Wp5q?$B!ny<{qQ>? ߄㩭~Lr~5C|~(!M~*qJGkz_C//!K}:^z+?/{|5P=¯r4=¯r4_F_ DQ~_$ Nkc=a?_wW9?_wW9?_F_ DQ~_7!×;W_?G5k{?d-?_h{?d-?_h}7E~>?N<^܇^_Ʊ0?/!p!p*ee7J~_8{r9zӿ_{|4cXxƿA]UFA]UFїx)_s$ NeM>J<y5?hi 8BQopx[VM_מ mb][ĺ=C^>Sv?|E ?PoyTxĚNJoFu^h:t-C\[V]VK3zC k*#GC k*#_(}.~'S3b\&<<(3P0-X.//T+҄0pӯWUN*o88/QKJ' , >T^`Vߞqu*Iօjq(ЧTJo?'g#>$xž8֠eϏ~e[׵(?'{-myL:ܶQ^_Np >|&ү~+|gMg(ǎ|U7 @/~Ѽ/ω)ҴY<i)xM75f!p!p=؎1i'e9, ƏӖcqc_0ӟ0TlfW8S]><#/>]I|=.J[$nOQ'7ŏlj{;{??|GLwO ľ1+;Jg;U/+}SSեU{c_wW9Fzcr >q! N2k>?G̓`8U0*}+/_yV+Ze/c0xGTpqI/W5KLZ,LCGT1X|lc_O#' F_Nu%'vg5OگƽCm>:k>.jz' k6Z|3G O\צs[v-EXi~%A>4~%e?­Kд:ÿك㇃<5|?okizoh:U>gpY:t~xsH77?kr ? W~_#FAy5C (r  H2|7S_,Ȱ?C7N,>"ʍ*C< M8-\W &7qv/]9fT,3FeS.jUԫ)2lDjlٷg<1w⏌_<_? ']%Ğ#3މu k67<:7,<# ?he.8?h g8'hI/زlykggGO'ֿ2?d_77~u^FKKU+ 7PtOi$z5-V Ec O$W?D^/Ÿ\ϊ{xmǹk C<0GyUX4ձqT 4BZ$Y8~ |<xG=T<ҷu'`V d~ :1R5R)}17YE؟c[Q_ۇ"_ }Li/?ҿ>A/?|?Wo@<&?O {u]oixcwm?]-ۼ>mį'+Z5ڻJuX|5m/ +Im~< ~mo6tZKWvz_NXON%®#+mJ.Һ 5c)BxSQYϭTg/ڟO࿌_e_a ǏJ|3~&xO? ?ƿbsw,=??x7gbVax?oW7y|[NB⏅E x[þ x߄4(|CsǤx_▃|EO7֚?B ɕu9@tٵ/MҵOC\$4^lt=VLMDi hυ~j:|i:OgMg^5>$zq+^D^:Ҵ-; ~/xǍլ5o__s_o4xu/G|Uli2_۴-WSӯ8_߱_A:kcjhoK_ڿbk'??C<훿C"tH?OJ*q$榩^nj24eo^JPm5R֖M=V;so>+}ORN'_&!<' @7ğ Կ xg~'xOᇊ|MiyELxwSXM_+Y8McNfCoMs6zU7Zog,w +WOiT'\I5F%^d;NRNmY%x]?m?WniU5} Cq3gqFrxH[?]+^Ug?/1j5=km4Jx_=e|s3ǟ})x~-3gg/ jz׋e|8h?5[?~7ּ7>Cɴ^xBI|U)I JP:^exB״Zu*Sjz;yk|Ckj} __ 챯xg߃_N+s%?hh_w/Ľ^;Oqh^ᯍx{߲M8ГN]?O/Gf?OP3G>!|*3? |lt/o湣|fŞ;k᛽#?4Oߋ[ "!KIn ZGt˿xTljtO,B8RNpNR^I'(׽}̼HgFQmx&8/L_db4ك ?qR#?> HJ_>/xs{gzx]sN񧌴] 65xj_8ϠC|g|K|E3 +N/bK^l^Szto_uu㇊?h,^_U.?bۓ>燾Gv{4.~+|C?g/x~|ExIT[x3*|ےԚJm8N]ak?vW_g\"|OjOVO1Edso7exӎx3 9ZLug?x?f߱gd؏⾹o 7Z\Z6]ϣc4DO:WL0V0nʅw/m;yxZm|!áN'֭gZ|[Ig>~=>&[|~MO~_|JOF_k7xto|Fiy{;#|F4>9|Rѿg hJ/??#?~wC{{WKOտh=Zf~>|uso_?9|ȲҼQK>|-77s jwv^" |\t?;WxZյL4_j׈4[Fᯍ:Ҿh|SԹo~a?X!_c] |Ca Kg|-'? [+#~_l]KO0Ҕ*99$&;y Unߥ#^(<ࢊ(((((((((((((((((((((?w[;3}%C֏Oß8o87z&6Ԟ||F >xHZ| w~ǫ[^,njY߲_g~7~_| 3R}GZx? k+|J+ xI~Z~i:~/|/}4IAb;_וeaT9֫,g ޜ->ӽO9u%N0u?(G_}m+v>~vៀ9|}<^bL΃w~#Ni>%ע/?(u;#2HIFn5QGi.VՒiW1>k~`?w~^/|KWkvo6-E+W3Mg%YiN/<g_G_E)dtg)Nx򔛔.Vޭk+ $PKDD}{WOF;CG~z_t?e3 ;/"Mt+m6]{ʦML_ rլ-Et<㯵xN]/~x?L߂~%>9| Ko^xGޣox{V_oEimS-E9deÒ-rng-tkKieww{KG6 m xJWդ!υ;pVZ[zUs/~ī~kt <_T;M~>z^5/ӨisɦK{ :!BTV\+­IJ I)r٩Eâm));m~?Q^QEQEQEQEQEWſh#%᯶4'(o)\xszEOA?_Wo|GGMc?}{߆_w__׏k/_'Ak ?gUkj7oSo (> ~|E>6y\^ 񧊴 \ Y'O/K 3 su𾱣xs$xEO5K|GmZ߄o|_ok7_?xEx9|;7ŶV=coFiox-0e|Uk |I5 >оk| W?xWĶ/5?8<)jĿ)?~@ox3g5_X>_|/[ ??m?Px7ŚG?G0-:>5(<>@W ⨾:K4|} m~=_4*~')>#h9?cr A|+?'VmxV3G'izτ?e x~+hx>?񎏯Bӵox;>)|xs^5+N4zŸ~+|-K㯉+ȼ ͹4/>1|xg7Ꮁ➝[xnOTWgߌ>3վ|`a߄;|7t~xIgߍ^?f|vxğ'|omGXz7Ŵ wE?>7i)|X5=c_t+#Iٟğ @~5Kx[|Mio~#5ڏ5_|@>e'~_~|CYok߂@=__=~!мAy[Z7g;IA?7υڎh|cem;GOK> <>)4af_?; 3N5#߂"|c࿋P_@ ?П?i=)w -W&_?#sO~ |%2m/xg_|K34ӼYx  J>+~?[9;x~/|fyh~ 7@X )xφ|2x3X?"'i,-?H_O?5+L,>]OO{h gN_|3G?xgKg:g|+RX^6'm7 [Ӿ.x~+?7:)iߠ(((((((((((((((((((((((_ ?iaW[?=B~I_ES?}.Y$=' :mPص5ƿ4IAbvoRx adcMQcN/ˈ(# N?X_NSi@O#}gW$O?T> 0~ؿtP?@||Ge"?O7W⯂7/> f_?7Qous~Ѿ1-|K>8|`HXxេf‹oGGa?M)'_['Au~Ox{?i+xƟ?|Mxz_ŚG YQ״NT|Rdـ4Tç_?usG:w eH? g_w5:w eH? g_w4ç_?us_@ç_?usG:w eH? g_w5:w eH? g_w4ç_?us_@ç_?usG:w eH? g_w5:w eH? g_w4ç_?us_@ç_?usG:w eH? g_w5:w eH? g_w4ç_?us_@ç_?usG:w eH? g_w5:w eH? g_w4ç_?us_@ç_?usG:w eH? g_w5:w eH? g_w4ç_?us_@ç_?usG:w eH? g_w5:w eH? g_w4ç_?us_@ç_?usG:w eH? g_w5:w eH? g_w4ç_?us_@ç_?usG:w eH? g_w5:w eH? g_w4ç_?us_@ç_?usG:w eH? g_w5:w eH? g_w4ç_?us_@w k~|[ oxTwO W]KW੺=xEt^ik7rj7vXruP)GOZ+ _EPEP_'oυO;?wAgqJ/qqrg4IAb;_ו!i jfʻ+g 'nq\@QE(Q@~`~Zo=; ~@{_i?,િ7ƿ|X f Ľ mm:k^c|C'ZtkQ/k[~@W~ž!(ǟ< O|$<+:|B _X|4>9o/ƚ=dwßR|P#j/:_ 6[A@~~u?[xƟkhxg◂Y.|y~?=мwxd<=zs_uw~6go8i犓Q& h^.jVWQ//ȹun͓VYUP'`dF,j~ ?^~ӼI~[^JgA>ФOO#[oi75caOpT{~4k:^tGÞ_ Ѭf/i mk<:<ZW]O7GE:jAig8-G w'!Cu/+/ |?ڿ~? KoXY/`e?F~"-> x_ؚơg Ե 5] S.>iu^\#נ|-Ow/_>%@?7E[/?߇}Cú'i ??[G 2ͲP\_ G44GMoI!k^ _KOOx[#|xV}:CcizG쇯i?7o h_~3x×>  {ў=nUEqNHc,ܢd?9?_iIcTxp׼M|9R;DT^WuK^}~\WQQѬn|; xOŞ|34O,|,Mq __d'9@~);.i_Gu-G_#nom~;տ)>E~TQEQEQEW|~>~* }xSG3k& f?&_;~v_-ӿikt ^:ѼAzկ-Gq&gNxN%5 8.m 1x+ɥ~=W? ?jgcNbmbKS|Yy_)Ӽ+/|dž쥺((((((((((((((?# b?# b((?zgUbVasOP7W{?hǟb4IAbvCӯ&ߵ__ikYpN??4l(Q?R gόCA>,/g_4&7_kPx~_n.uCӠ~&[A+_Uk<5.~8~I_M:5W.⯏Gi_H/3n|g8.|Fпh/6d|_<~|8~|cW"⧍ |'>%/*G|A~'x{֩ OZZ*u|5 lntmF+odտ)>E~U~žg t'ǟI> x{_/SW>k6:ע|Ui[|'&OךŭΩKO뺬W&!b((((((Kzvٻ||Af_'Z Þ15G~*tk&Oi> ~Ŀ|+o :x~;S^>3 6~[|2՗O?;5yEEm?;~*R5Go{^xWzv3H/xƞ6-] ?x}:þwWkrܢhg#f\-_M ~W/9ً iG:ΕS^/e0(((((((((((7iEX7iEX((+Ov_)+^Z>?9q6Xī=' :mPص5ƿ4IAbvpi_8cX~8wӋ+DH(+?oJo?0_U'1|S੿?ix7 x?MuĿJeN#/EG ?5$ 4/Y^l>,xg(TQEQEQEQEQEQEQEQEzߋxBS_|/_2woG<;axz #_j}OP.+ۘ%`i~ux~*mx{sg> е{;=SFt]GKmmn`)W]tQػ;_uOoVkO_?[)o_7^-|[[ύcw|8k??A?%Gx3_?h/T|q|49>xXݏ<377z/@ާxRGï?qwG|;o,=}@Q@Q@Q@Q@Q@Q@Q@Q@Q@|9`M?h+}_|9`M?h+}@Q@Q@)+:?zP>!G\\T ߴO~ ;/I#ž6C{n>0i c t!~?~xTj6h')MfZ+sM'B?टu9q?:OAz~ |K_O *J|1hZƉۍ3[f(>~5R{Aϟ?SOo3Nv<76wz W|; N|Ui:υs)M??_V*s)M??_V* ( ( 1|S+}0]Wu_/o4 3%?C֋|@}6Y%=' :mPص5ƿ4IAbvpRa1? ~ ɻ?iqQE~ĿGOM񿊾8|2 %&'?~x4I%q|zwo|(+_O~oᇊ/~&u_@~?ٳ^/=#_u| xWZ5Gg߅|m[|io|o|#R> )MfZ+տ)>E~TQEQEQEQEQEQEQEQEQEQEQExOŞ*3 Ax1𞳨s^W5mc&ψt{=_A6Z:^km}csJu%W |3xGÏrxGix<;/o 6t-GVg¿xY>-7ik{KCWgX4os⧈4/ǃV}GG>'k>!kvυ~TtZ-QEQEQEQEQEQEQEQEßJof֊WßJof֊WQEQEW[?=B1|S+}0]Wџ)h\ ~sqPq)?ioڃůٯO^5_Mjf?ӵxwӃR adcMQcN/ˈ( (>xs7# GO,|SZ?|'uoG;տ)>E~TQEQEQEQEQEQEQEQEQEQEQEQEhONe'?Td&YyxX߲::^mu[~%> 'o[3'%MMލh'ÿ7KShM[#o3G.ς]j x~]W|9H"nbs_/~ 5o_~?ϟcB׵> w"zE~TQEQEQEQEQEQEQEQEQEQEQEQEWKᙿlYK/+w~WO[$^<<%^P]axG_~'Sfg4Q@E~ ?૚?gMu_kG#_j P &_xKJxgv#;zιZ\>o =xZ((((((>Sl0&W>Sl0&W((_ ?iaW[?=B>?IOEc?|7ꃉOIN~-~k; :mPص5ƻ+g 'nq\@QE(Q@'1/ß੿?~ ii¿W;x+| +sïJxe">2?')MfZ+ (((((((((((((!w_5z> x?iOy_~%j<*~ >:k W4xzΝ? ¾#ӭx>!o4{yghΗyujuյ+=o?MCůecOOm<97$ i;3'<9k<7n>xBGO EPEPEPEPEPEP)GOZ+ _)GOZ+ _EPEP_/o4 ΫOv_Fp1ψ?Aħ_Mjf?ӵx6?ZN]NJ_3?ᓏ7yG8[. (OԂ@ah ~)WR@O#^>[_7 >Ŀ_?2Ko/~O/ok㿍w:|@Es;-cD5g|9L|?g~;\^>ᶃLn!G?0=5K!x3Xo~nN?>?=[RgWU_uWjğc/G7V : u9h%>0G~,l xsuo؃᷋5O|i࿅~ԼU}Mx{.^xHд=.YQӴm*kӬb(((((((((((((i_)d|M@|hEW׼/ O˪/4^"VZ|s[?j|?Wk:6㿆>;ӭln|M◆mE~ xWF =/Y ƞ |U^f']SӿcX>3x| x/!ҿn ( ( ( ( (>s)M??_V*s)M??_V* ( ( 1|S+}/aΫOvP~_EUq?忇3=' :mPص5ƿ4IAbvpRa1? ^ ɻ?iqQE~QE`z7hڪ~)T߇e?o<|:ᧈ+o"_C?z+_xVٟ  @?*( ( ( ( ( ( ( ( ( ( ( ( ( ( ]6 I` ;^#X>?:*uxK+u_ ^K;[~kvZş/M[,d6h W>߇>S~479տ)>E~UW~ž!(ǟ< O|$<+:|B _X|4>9o/ƚ=dwßR|P#j/;_>*I> x_ٯW>h׭|׼Uii[|Y~~?x&?\7=7IZ&Mdb(((((((((((((((?ο*j?Iw_ao?d|`MjxU,Y7. o)JxĚgyx=/K`Ь>((((?# b?# b((?zgUbVasOP7W{?h|9ꇉIN~-~k; :mPص5ƻ~+g 'nq\@QE(|o؋/[o3?'eo|S|eWѭ| kom<m[OY\]GÐhZ4:=͜z]?g_?7<>?mc'g0W>!|p5¾A㏶j5^No'ekt<@Q@Q@Q@|9`M?h+}_|9`M?h+}@Q@Q@)~gCi>*ogž+Ѵohڦi U=;A|U?OsOxe-ŇGY6cĞ#4x} &xVW_?x@?r(((>Sl0&W>Sl0&W((_ ?iaW[?=B~?I_ES?|7ꃉOIN~-~k; :mPص5ƻ~+g 'nq\@QE(|K~˟k'/G߁?o3(|yo_xHCo[տ)>E~TQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW|'㿁|k[/7Ruo[wG:7_G4?PtOG?u=>Y(RTa߆ߴφW;_w]?w|%=gVm_ZWG?;ox^ӼYi4gA?Ef?૚?OOŻ̿W+5xcG[^.7>&><"Ghg> N5TQEQEßJof֊WßJof֊WQEQEW[?=B1S+}|/]5AgqJy}C֏~sqPq)ioڃůٯO^5_Mjf?ӵxwӃR adcMQcN/ˈ( (5/z7-/?w?d?_|,iD|e_H(Pᦅ +Þ-gŏ;տ)>E~TQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWU؟-ؿh_#Z-?m~6ڟ~Э;Gx~?~%?[} k/0jz7bB)/l3D<9m犼G/|_Y<]j/U滤xÞ/xSWBo+?e__g8 j 8?<>×ƅj?|DxLj?:";3u{-s(>Sl0&W>Sl0&W((o_ +a_s_/o6k^Z>?9|oqp3ӯ&ߵ_gvCӟ&ߵo?^U_8cX~8wӋ+DH(o~^*#gm`#5*x[QO/M# 4ڧ~\|WGuuпiO)'/~~~N|6Sºo~<ҺuZ״?Y]h6v_Mlڍ|=|g_ه>e^~k~|=_;;xϋvw?gWO-Sxs_#?O_fb}g)^o_L???tG 7>WWY[O? >%Q|-=cD<9xOχu #G}COе]3XGڴB(.bz+( 'K| +D|E O$e A OF~?|Y _7oï i#7~п|Ej 5/ :п-CO5x?|k]5;ؿ(&̂-Dx~LҬ?w[_4GïxC?d؟}7K-}¤+o3 $ Խ?-'Ygt/|qRixHYটS/lO2??ٞ4yٟO`Exc/XfJ2| oCm:?)s_? 'Okhd  EWj_ | SoƽCBG߇%-<  YBƃPxwCOSүu#ZeW z++?d4S 3o_&؟a ׇ< O# G?쯵_R?&j++e/i=P_4 wu?S $c[P~?iE[mI#ڿ:o_q/o>0xsM] />R=cH?|Soƿڴ-CL#oeoi=*(7/'_A A@xsO'W O/I ?L?țlO඾-u~ؿ~- kxN|=W^4 uᗂ~<wy2q|AҮ&㯎O~o_ i'$^K~.п|;i ??Ň>զjWAs/%$QbYK?`L5}E~P~ߴ//S Ilxst؃ =S?>%/⧅tXy??y0$cEPEP_/oL;#_)+^Z>?:?城Aīg# jf5x6?ZN]NJ_3?ᓋ7yG8[. (OԂ(5|St>M7㯇U_G AA/GIO?x?PgO|5g 'Ov_/PEPEP?^U kx'?[G?B/`_ξ.m? | ~ Oc׃mϋ ?~"|iiOz((^|lw@~_W |^-)|+G~"O?5߀> k#]u|7SZE?xᶟ|:agʐ(?~We]B/|A!0~zF|'`]ſ/-kVn5τ@>WKѾkh_oEQE~Կ7G' ]xoVO Mh|w'+ ՟fxHok 8 S1٠h-9i_ ?i/PJo?/?~ /j +''мgj_ψߧPEP_%]7C?g{~Ӻg\|.l~>/i>ψ࢞>e|)Ac>%С4of ?g6߳ߵ'E~P? i~ʿ?foؿ?e e_u¾4'7C_k? |a&h>&$Ľ;ž?5~((gG>x |@~___VZj>f?ڻ|u[eXt11C??iڏ?J/z=?<8j// >$^x/[|z? _/g(>~'ߎwu?=EQElaψf5y;oo5SF?d'd~#k|$_㯀<7~Ķf4k/}E~AiOmV<=]x"~?kWǶ?rGmj Ӿ~?K/_OK_~>/[O2o_v  (?0?> Ex.?\W$p=ggqmMw?-; xǨ'RԾ0x-Ÿ-iWO?{b|9~~?> -i|Fg_cQEWj,<#+?=wg_"͞#>9⹼Qτ߄Ϯh@?hүoe(Iy,F~jXb\u}_Jp*Bn^_{"JPxy8ԔouS8W7Neks[wn~ a<|Ӌg ~e۱7!# g|Ao¯vu"‡??+Oy4Wx*gG!# "‡??+T'l}E| g|Ao¯vt?+_[B/(Oy4Wx*gG!# "‡??+T'l}E| g|Ao¯vt?+_[B/(Oy4Wx*gG!# "‡??+T'l}E| g|Ao¯vt?+_[B/(Oy4Wx*gG!# "‡??+T'l}E| g|Ao¯vt?+_[B/(Oy4Wx*gG!# "‡??+T'l}E| g|Ao¯vt?+_[B/(Oy4Wx*gG!# "‡??+T'l}E| g|Ao¯vt?+_[B/(Oy4Wx*gG!# "‡??+T'l}E| g|Ao¯vt?+_[B/(Oy4Wx*gG!# "‡??+T'l}E| g|Ao¯vt?+_[B/(Oy4Wx*gG!# "‡??+T'l}E| g|Ao¯vt?+_[B/(Oy4Wx*gG!# "‡??+T'l}E| g|Ao¯vt?+_[B/(Oy4Wx*gG!# "‡??+T'l}E| g|Ao¯vt?+_[B/(Oy4Wx*gG!# "‡??+T'l}E| g|Ao¯vt?+_[B/(Oy4Wx*gG!# "‡??+T'l}_n|Gr'?3V W;:&৶CLɧɭ4 Aywx-Q h美uKooei Im_2x'bRP-&m/$젭6$N_(,g9m8~gw? ϊF| UkW-?7ouڟxž}fsg]\&yss$ !zT[[{=!4ƙuto?&& 5oWHxk'x_<+̥\UQB|+9> ўKI^|<_٘WHeo?>"vuwH|/c_EyoWĚOj?+σgz$3Q3# 7GŽa?;:4HǢޯ4 Wޯ4~č}&??hQUE1XWo^;?&Wޱ2 č}&??hQU"vwwE'6wM 53_i?Lo? Aσ>h"7FwLC-/E{oWĚOjg2?hQ[y C>?z+8~ _i?+߃gz$25# 7Gž~W_Cս/dQ_EyoVĚ_ZO- <"vuwH|/c_E{oWĚOjOޱ2 Č&_- <_׋;:?z>?+9u6y2e"7Fy($g2?hQU "vuwyԇ5WIf> ўKO$g3D>AnmUC>kcQ_~ \?i?촟3cehLtG[m"o2"M+߃gz$2WIf3# ţGV/'g_qH<KXWq^gz$3RWIe$g2?hQUF^G1!cR?EWIf"7FwM'C5?O>uV_/'g_qH|cǢޯ4 WIf3# 7GŽag_H|c_EyoWĚOj?+σgz$3P_I4FA] |_?ο//yWW"7FwM'C53_i?Lo?;:;z>֗"7FwM'C53_i?L2Z>ym>?;:?|CN?+σgz$3Q^|;&- ֗"7FwM'C5c_躎^$n֩+mkJF_>Eٜç{k}SɚLYZYNlLi~ȭ|PlE7*-C"vuwyv~X4[=P|wC^uCr&Mb?!41_fn5MRv at )Z{Kfc<#o>?fu-k}8rk?'[7_aA Y?gKϱ;$ߋ6LkO ~S|mwi6> +jp^x k,R[۟ݼ=x!xr,58xù~#Ɯ 5q9'6ޖ`gs|92KW K TWZL2.$^Ӏy|q]b#+K ;Jf^ qZJ+JnhӔ!VO+d(((((((((((((((((((((((((((doc/is_obj_in_basis.htm0000644000175000017500000000554710621636452014135 0ustar renerene is_obj_in_basis

is_obj_in_basis

Returns if the objective is in the matrix or not.

unsigned char is_obj_in_basis(lprec *lp);

Return Value

is_obj_in_basis returns if the objective is in the matrix or not.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_obj_in_basis function returns if the objective is in the matrix or not.
The default is that the objective is in the matrix (TRUE).

By default, the objective function is stored as the top row in the constraint matrix When this function is called with obj_in_basis = FALSE then it is moved out into separate storage. When out of the basis, the computation of reduced costs is somewhat slower. In the late versions of v5.5, there is now the option to calculate reduced cost in the textbook way, i.e. completely independently of the basis.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char obj_in_basis;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  obj_in_basis = is_obj_in_basis(lp); /* Will return 1 (TRUE) */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_obj_in_basis

doc/is_nativeBFP.htm0000644000175000017500000000445310237176660013330 0ustar renerene is_nativeBFP

is_nativeBFP

Returns if the native (build-in) basis factorization package (BFP) is used, or an external package.

unsigned char is_nativeBFP(lprec *lp);

Return Value

is_nativeBFP returns TRUE if the native (build-in) BFP is used, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_nativeBFP function checks if an external BFP is set or not. See Basis Factorization Packages for a complete description on BFPs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char nativeBFP;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  nativeBFP = is_nativeBFP(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, has_BFP, set_BFP

doc/index.htm0000644000175000017500000000315311236130432012105 0ustar renerene lp_solve reference guide (5.5.0.15) <body> <a href="contents.htm">contents</a> </body> doc/add_SOS.htm0000644000175000017500000000633310237176652012273 0ustar renerene add_SOS

add_SOS

Add a SOS (Special Ordered Sets) constraint.

int add_SOS(lprec *lp, char *name, int sostype, int priority, int count, int *sosvars, REAL *weights);

Return Value

add_SOS returns the list index of the new SOS if the operation was successful. A return value of 0 indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

name

The name of the SOS constraint.

sostype

The type of the SOS constraint. Must be >= 1

priority

Priority of the SOS constraint in the SOS set.

count

The number of variables in the SOS list.

sosvars

An array specifying the count variables (their column numbers).

weights

An array specifying the count variable weights. May also be NULL. In that case, lp_solve will weight the variables in the order they are specified.

Remarks

The add_SOS function adds an SOS constraint.
See Special Ordered Sets for a description about SOS variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int vars[2];
  double weights[2];

  /* Create a new LP model */
  lp = make_lp(0, 4);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  vars[0] = 2; vars[1] = 3;
  weights[0] = 1.0; weights[1] = 2.0;
  add_SOS(lp, "SOS", 1, 1, sizeof(vars)/sizeof(*vars), vars, weights);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_SOS_var

doc/set_use_names.htm0000644000175000017500000000574610242162616013647 0ustar renerene set_use_names

set_use_names

Sets if variable or constraint names are used.

void set_use_names(lprec *lp, unsigned char isrow, unsigned char use_names);

Return Value

set_use_names has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

isrow

Set to FALSE (0) if column information is needed and TRUE (1) if row information is needed.

use_names

If FALSE (0), then names are not used, else they are.

Remarks

When a model is read from file or created via the API, variables and constraints can be named. These names are used to report information or to save the model in a given format. However, sometimes it is required to ignore these names and to use the internal names of lp_solve. This is for example the case when the names do not comply to the syntax rules of the format that will be used to write the model to.
Names are used by default.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_use_names(lp, FALSE, FALSE); /* specify that variable names are ignored */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_use_names, set_col_name, get_col_name, set_row_name, get_row_name

doc/is_trace.htm0000644000175000017500000000427710237176660012614 0ustar renerene is_trace

is_trace

Returns a flag if pivot selection must be printed while solving.

unsigned char is_trace(lprec *lp);

Return Value

is_trace returns TRUE or FALSE. Print or do not print.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The is_trace function returns a flag if pivot selection must be printed while solving. This function is mend for debugging purposes. The default is not to print (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char trace;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  trace = is_trace(lp); /* Will return FALSE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_trace

doc/FreeMat.htm0000644000175000017500000033565411244025772012350 0ustar renerene Using lpsolve from FreeMat

Using lpsolve from FreeMat

FreeMat?

FreeMat is a free environment for rapid engineering and scientific prototyping and data processing. It is similar to commercial systems such as MATLAB from Mathworks, and IDL from Research Systems, but is Open Source. FreeMat is available under the GPL license.

In addition to supporting many MATLAB functions and some IDL functionality, it features a codeless interface to external C, C++, and Fortran code, further parallel distributed algorithm development (via MPI), and has plotting and 3D visualization capabilities.

We will not discuss the specifics of FreeMat here but instead refer the reader to the FreeMat website, documentation, FreeMat Google Discussions and the FreeMat primer overthere.

FreeMat and lpsolve

lpsolve is callable from FreeMat via an external interface or Import. As such, it looks like lpsolve is fully integrated with FreeMat. Matrices can directly be transferred between FreeMat and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for FreeMat (especially for matrix support). So you have full control to the complete lpsolve functionality via the fmlpsolve FreeMat driver. If you find that this involves too much work to solve an lp model then you can also work via higher-level script files that can make things a lot easier. See further in this article.

FreeMat is ideally suited to handle linear programming problems. These are problems in which you have a quantity, depending linearly on several variables, that you want to maximize or minimize subject to several constraints that are expressed as linear inequalities in the same variables.If the number of variables and the number of constraints are small, then there are numerous mathematical techniques for solving a linear programming problem. Indeed these techniques are often taught in high school or university level courses in finite mathematics.But sometimes these numbers are high, or even if low, the constants in the linear inequalities or the object expression for the quantity to be optimized may be numerically complicated in which case a software package like FreeMat is required to effect a solution.

Installation

To make this possible, a driver program is needed: fmlpsolve (fmlpsolve.dll under Windows, fmlpsolve.so under Unix/Linux). This driver must be put in a directory known to FreeMat and FreeMat can call the fmlpsolve solver.

This driver calls lpsolve via the lpsolve shared library (lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux) (archive lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). This has the advantage that the fmlpsolve driver doesn't have to be recompiled when an update of lpsolve is provided. The shared library must be somewhere in the Windows/Unix/Linux path.

So note the difference between the FreeMat lpsolve driver that is called fmlpsolve and the lpsolve library that implements the API that is called lpsolve55.

There are also some FreeMat script files (.m) as a quick start.

To test if everything is installed correctly, enter fmlpsolve in the FreeMat command window. If it gives the following, then everything is ok:

fmlpsolve FreeMat Interface version 5.5.0.6
using lpsolve version 5.5.0.15

Usage: ret = fmlpsolve(functionname, arg1, arg2, ...)

If you get the following (Windows):

In base(base) on line 0
In docli(built in) on line 0
In Eval(fmlpsolve) on line 2
In Z:/lp_solve_5.5/extra/FreeMat/fmlpsolve(fmlpsolve) on line 195
Error: Unable to find file fmlpsolve.dll on the current path!

Or (Unix/Linux):

In base(base) on line 0
In docli(built in) on line 0
In Eval(fmlpsolve) on line 2
In fmlpsolve(fmlpsolve) on line 195
Error: Unable to find file fmlpsolve.so on the current path!

Then FreeMat can find the fmlpsolve.m file, but not the fmlpsolve.so/fmlpsolve.dll file. This library should be in the same directory as the .m file.

Error: Undefined function or variable fmlpsolve.

Then FreeMat cannot find the fmlpsolve.* files. Use the Path tool (Tools, Path tool) to add the path where the fmlpsolve.m script file is located and put the library fmlpsolve.dll/fmlpsolve.so in the appropriate directory. Under Windows, c:\windows\system32 is a common location and under Unix/Linux, /lib or /usr/lib is common.

If you get the following (Windows):

In base(base) on line 0
In docli(built in) on line 0
In Eval(fmlpsolve) on line 2
In Z:/lp_solve_5.5/extra/FreeMat/fmlpsolve(fmlpsolve) on line 195
Error: Unable to open module: Z:/lp_solve_5.5/extra/FreeMat/fmlpsolve.dll

Or (Unix/Linux):

In base(base) on line 0
In docli(built in) on line 0
In Eval(fmlpsolve) on line 2
In fmlpsolve(fmlpsolve) on line 195
Error: Unable to open module: /lp_solve/lp_solve_5.5/extra/FreeMat/fmlpsolve.so, operating system reported error: liblpsolve55.so: cannot open shared object file: No such file or directory

Then FreeMat can find the fmlpsolve driver program, but the driver program cannot find the lpsolve library that contains the lpsolve implementation. This library is called lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux.
Under Windows, the lpsolve55.dll file must be in a directory that in the PATH environment variable. This path can be shown via the following command at a command prompt: PATH
It is common to place this in the WINDOWS\system32 folder.

Under Unix/Linux, the liblpsolve55.so shared library must be either in the directories /lib or /usr/lib or in a directory specified by the LD_LIBRARY_PATH environment variable.

Note that it may also be necessary to restart FreeMat after having put the files in the specified directory.

Also note that there is an fmlpsolve.dll/fmlpsolve.so library and an fmlpsolve.m script file. Both are needed. In theory it is possible to call the library directly from FreeMat without the script, but this is strongly unadvised and not supported.

All this is developed and tested with FreeMat version 3.6.

Solve an lp model from FreeMat via fmlpsolve

In the following text, --> before the FreeMat commands is the FreeMat prompt. Only the text after --> must be entered.

To call an lpsolve function, the following syntax must be used:

--> [ret1, ret2, ...] = fmlpsolve('functionname', arg1, arg2, ...)

The return values are optional and depend on the function called. functionname must always be enclosed between single quotes to make it alphanumerical and it is case sensitive. The number and type of arguments depend on the function called. Some functions even have a variable number of arguments and a different behaviour occurs depending on the type of the argument. functionname can be (almost) any of the lpsolve API routines (see lp_solve API reference) plus some extra FreeMat specific functions. Most of the lpsolve API routines use or return an lprec structure. To make things more robust in FreeMat, this structure is replaced by a handle or the model name. The lprec structures are maintained internally by the lpsolve driver. The handle is an incrementing number starting from 0. Starting from driver version 5.5.0.2, it is also possible to use the model name instead of the handle. This can of course only be done if a name is given to the model. This is done via lpsolve routine set_lp_name or by specifying the model name in routine read_lp. See Using model name instead of handle.

Almost all callable functions can be found in the lp_solve API reference. Some are exactly as described in the reference guide, others have a slightly different syntax to make maximum use of the FreeMat functionality. For example make_lp is used identical as described. But get_variables is slightly different. In the API reference, this function has two arguments. The first the lp handle and the second the resulting variables and this array must already be dimensioned. When lpsolve is used from FreeMat, nothing must be dimensioned in advance. The fmlpsolve driver takes care of dimensioning all return variables and they are always returned as return value of the call to fmlpsolve. Never as argument to the routine. This can be a single value as for get_objective (although FreeMat stores this in a 1x1 matrix) or a matrix or vector as in get_variables. In this case, get_variables returns a 4x1 matrix (vector) with the result of the 4 variables of the lp model.

Note that you can get an overview of the available functionnames and their arguments by entering the following in FreeMat:

--> help fmlpsolve

An example

(Note that you can execute this example by entering command per command as shown below or by just entering example1. This will execute example1.m. You can see its contents by entering type example1.m)

--> lp=fmlpsolve('make_lp', 0, 4);
--> fmlpsolve('set_verbose', lp, 3);
--> fmlpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
--> fmlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
--> fmlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
--> fmlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);
--> fmlpsolve('set_lowbo', lp, 1, 28.6);
--> fmlpsolve('set_lowbo', lp, 4, 18);
--> fmlpsolve('set_upbo', lp, 4, 48.98);
--> fmlpsolve('set_col_name', lp, 1, 'COLONE');
--> fmlpsolve('set_col_name', lp, 2, 'COLTWO');
--> fmlpsolve('set_col_name', lp, 3, 'COLTHREE');
--> fmlpsolve('set_col_name', lp, 4, 'COLFOUR');
--> fmlpsolve('set_row_name', lp, 1, 'THISROW');
--> fmlpsolve('set_row_name', lp, 2, 'THATROW');
--> fmlpsolve('set_row_name', lp, 3, 'LASTROW');
--> fmlpsolve('write_lp', lp, 'a.lp');
--> fmlpsolve('get_mat', lp, 1, 2)

ans =

   78.2600

--> fmlpsolve('solve', lp)

ans =

 0

--> fmlpsolve('get_objective', lp)

ans =

   31.7828

--> fmlpsolve('get_variables', lp)

ans =

   28.6000
         0
         0
   31.8276

--> fmlpsolve('get_constraints', lp)

ans =

   1.0e+02 *

    0.9230
    0.0686
    3.9129

Note that there are some commands that return an answer. To see the answer, the command was not terminated with a semicolon (;). If the semicolon is put at the end of a command, the answer is not shown. However it is also possible to write the answer in a variable. For example:

--> obj=fmlpsolve('get_objective', lp)

obj =

   31.7828

Or without echoing on screen:

--> obj=fmlpsolve('get_objective', lp);

The last command will only write the result in variable obj without showing anything on screen. get_variables and get_constraints return a vector with the result. This can also be put in a variable:

--> x=fmlpsolve('get_variables', lp);
--> b=fmlpsolve('get_constraints', lp);

It is always possible to show the contents of a variable by just giving it as command:

--> x

x =
  28.6000
        0
        0
  31.8276

Don't forget to free the handle and its associated memory when you are done:

--> fmlpsolve('delete_lp', lp);

Using model name instead of handle

From driver version 5.5.0.2, it is possible to use the model name instead of the handle. From the moment the model has a name, you can use this name instead of the handle. This is best shown by an example. Above example would look like this:
--> lp=fmlpsolve('make_lp', 0, 4);
--> fmlpsolve('set_lp_name', lp, 'mymodel');
--> fmlpsolve('set_verbose', 'mymodel', 3);
--> fmlpsolve('set_obj_fn', 'mymodel', [1, 3, 6.24, 0.1]);
--> fmlpsolve('add_constraint', 'mymodel', [0, 78.26, 0, 2.9], 2, 92.3);
--> fmlpsolve('add_constraint', 'mymodel', [0.24, 0, 11.31, 0], 1, 14.8);
--> fmlpsolve('add_constraint', 'mymodel', [12.68, 0, 0.08, 0.9], 2, 4);
--> fmlpsolve('set_lowbo', 'mymodel', 1, 28.6);
--> fmlpsolve('set_lowbo', 'mymodel', 4, 18);
--> fmlpsolve('set_upbo', 'mymodel', 4, 48.98);
--> fmlpsolve('set_col_name', 'mymodel', 1, 'COLONE');
--> fmlpsolve('set_col_name', 'mymodel', 2, 'COLTWO');
--> fmlpsolve('set_col_name', 'mymodel', 3, 'COLTHREE');
--> fmlpsolve('set_col_name', 'mymodel', 4, 'COLFOUR');
--> fmlpsolve('set_row_name', 'mymodel', 1, 'THISROW');
--> fmlpsolve('set_row_name', 'mymodel', 2, 'THATROW');
--> fmlpsolve('set_row_name', 'mymodel', 3, 'LASTROW');
--> fmlpsolve('write_lp', 'mymodel', 'a.lp');
--> fmlpsolve('get_mat', 'mymodel', 1, 2)

ans =

   78.2600

--> fmlpsolve('solve', 'mymodel')

ans =

 0

--> fmlpsolve('get_objective', 'mymodel')

ans =

   31.7828

--> fmlpsolve('get_variables', 'mymodel')

ans =

   28.6000
         0
         0
   31.8276

--> fmlpsolve('get_constraints', 'mymodel')

ans =

   1.0e+02 *

    0.9230
    0.0686
    3.9129

So everywhere a handle is needed, you can also use the model name. You can even mix the two methods. There is also a specific FreeMat routine to get the handle from the model name: get_handle.
For example:

--> fmlpsolve('get_handle', 'mymodel')

ans =

 0

Don't forget to free the handle and its associated memory when you are done:

--> fmlpsolve('delete_lp', 'mymodel');

In the next part of this documentation, the handle is used. But if you name the model, the name could thus also be used.

Matrices

In FreeMat, all numerical data is stored in matrices; even a scalar variable. FreeMat also supports complex numbers (a + b * i with i=SQRT(-1)). fmlpsolve can only work with real numbers. FreeMat also supports sparse matrices. Sparse matrices are matrices where only the non-zero elements are provided and stored. This results in both less storage and faster calculation if there are a sufficient number of zero values in the matrix and there usually are. The fmlpsolve driver supports both dense and sparse matrices and their use is totally transparent to the user. Everywhere a matrix can be provided, it can be dense or sparse. In the above example all matrices were dense. For example:
--> fmlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);

In sparse matrix notation, this can be written:

--> fmlpsolve('add_constraint', lp, sparse([0.24, 0, 11.31, 0]), 1, 14.8);

Most of the time, variables are used to provide the data:

--> fmlpsolve('add_constraint', lp, a1, 1, 14.8);

Where a1 is a matrix variable that can be dense or sparse.

The fmlpsolve driver sees all provided matrices as sparse matrices. fmlpsolve also uses sparse matrices internally and data can be provided sparse via the ex routines. For example add_constraintex. The fmlpsolve driver always uses the ex routines to provide the data to lpsolve. Even if you call from FreeMat the routine names that would require a dense matrix (for example add_constraint), the fmlpsolve driver will always call the sparse version of the routine (for example add_constraintex). This results in the most performing behaviour. Note that if a dense matrix is provided, the dimension must exactly match the dimension that is expected by fmlpsolve. Matrices with too few or too much elements gives an 'invalid vector.' error. Sparse matrices can off course provide less elements (the non provided elements are seen as zero). However if too many elements are provided or an element with a too large index, again an 'invalid vector.' error is raised.

Most of the time, fmlpsolve needs vectors (rows or columns). In all situations, it doesn't matter if the vectors are row or column vectors. The driver accepts them both. For example:

--> fmlpsolve('add_constraint', lp, [0.24; 0; 11.31; 0], 1, 14.8);

Which is a column vector, but it is also accepted.

An important final note. Several lp_solve API routines accept a vector where the first element (element 0) is not used. Other lp_solve API calls do use the first element. In the FreeMat interface, there is never an unused element in the matrices. So if the lp_solve API specifies that the first element is not used, then this element is not in the FreeMat matrix.

Maximum usage of matrices/sets with fmlpsolve

Because FreeMat is all about matrices, all lpsolve API routines that need a column or row number to get/set information for that column/row are extended in the fmlpsolve FreeMat driver to also work with matrices. For example set_int in the API can only set the integer status for one column. If the status for several integer variables must be set, then set_int must be called multiple times. The fmlpsolve FreeMat driver however also allows specifying a vector to set the integer status of all variables at once. The API call is: return = fmlpsolve('set_int', lp, column, must_be_int). The matrix version of this call is: return = fmlpsolve('set_int', lp, [must_be_int]). The API call to return the integer status of a variable is: return = fmlpsolve('is_int', lp, column). The matrix version of this call is: [is_int] = fmlpsolve('is_int', lp)
Also note the get_mat and set_mat routines. In FreeMat these are extended to return/set the complete constraint matrix. See following example.

Above example can thus also be done as follows:
(Note that you can execute this example by entering command per command as shown below or by just entering example2. This will execute example2.m. You can see its contents by entering type example2.m)

--> lp=fmlpsolve('make_lp', 0, 4);
--> fmlpsolve('set_verbose', lp, 3);
--> fmlpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
--> fmlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
--> fmlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
--> fmlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);
--> fmlpsolve('set_lowbo', lp, [28.6, 0, 0, 18]);
--> fmlpsolve('set_upbo', lp, [1.0e30, 1.0e30, 1.0e30, 48.98]);
--> fmlpsolve('set_col_name', lp, 1, 'COLONE');
--> fmlpsolve('set_col_name', lp, 2, 'COLTWO');
--> fmlpsolve('set_col_name', lp, 3, 'COLTHREE');
--> fmlpsolve('set_col_name', lp, 4, 'COLFOUR');
--> fmlpsolve('set_row_name', lp, 1, 'THISROW');
--> fmlpsolve('set_row_name', lp, 2, 'THATROW');
--> fmlpsolve('set_row_name', lp, 3, 'LASTROW');
--> fmlpsolve('write_lp', lp, 'a.lp');
--> fmlpsolve('get_mat', lp)

ans =

         0   78.2600         0    2.9000
    0.2400         0   11.3100         0
   12.6800         0    0.0800    0.9000

--> fmlpsolve('solve', lp)

ans =

 0

--> fmlpsolve('get_objective', lp)

ans =

   31.7828

--> fmlpsolve('get_variables', lp)

ans =

   28.6000
         0
         0
   31.8276

--> fmlpsolve('get_constraints', lp)

ans =

   1.0e+02 *

    0.9230
    0.0686
    3.9129

Note the usage of 1.0e30 in set_upbo. This stands for 'infinity'. Meaning an infinite upper bound. It is also possible to use -1.0e30 to express minus infinity. This can for example be used to create a free variable.

Starting from driver version 5.5.0.3, get_mat can also return the matrix in sparse format. By default the function returns it in dense format for backwards compatibility. However if a 3rd argument is provided that is non-zero, the returned matrix is sparse:

--> fmlpsolve('get_mat', lp, 1)

ans =
 Matrix is sparse with 7 nonzeros

To show the full power of the matrices, let's now do some matrix calculations to check the solution. It works further on above example:

--> A=fmlpsolve('get_mat', lp);
--> X=fmlpsolve('get_variables', lp);
--> B = A * X

B =

   1.0e+02 *

    0.9230
    0.0686
    3.9129

So what we have done here is calculate the values of the constraints (RHS) by multiplying the constraint matrix with the solution vector. Now take a look at the values of the constraints that lpsolve has found:

--> fmlpsolve('get_constraints', lp)

ans =

   1.0e+02 *

    0.9230
    0.0686
    3.9129

Exactly the same as the calculated B vector, as expected.

Also the value of the objective can be calculated in a same way:

--> C=fmlpsolve('get_obj_fn', lp);
--> X=fmlpsolve('get_variables', lp);
--> obj = C * X

obj =

   31.7828

So what we have done here is calculate the value of the objective by multiplying the objective vector with the solution vector. Now take a look at the value of the objective that lpsolve has found:

--> fmlpsolve('get_objective', lp)

ans =

   31.7828

Again exactly the same as the calculated obj value, as expected.

Using string constants

From driver version 5.5.0.15 on, it is possible to use string constants everywhere an lp_solve constant is needed or returned. This is best shown by an example. In the above code we had:
--> lp=fmlpsolve('make_lp', 0, 4);
--> fmlpsolve('set_verbose', lp, 3);
--> fmlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
--> fmlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
--> fmlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);

Note the 3rd parameter on set_verbose and the 4th on add_constraint. These are lp_solve constants. One could define all the possible constants in FreeMat and then use them in the calls, but that has several disadvantages. First there stays the possibility to provide a constant that is not intended for that particular call. Another issue is that calls that return a constant are still returning it numerical.

Both issues can now be handled by string constants. The above code can be done as following with string constants:

--> lp=fmlpsolve('make_lp', 0, 4);
--> fmlpsolve('set_verbose', lp, 'IMPORTANT');
--> fmlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 'GE', 92.3);
--> fmlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 'LE', 14.8);
--> fmlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 'GE', 4);

This is not only more readable, there is much lesser chance that mistakes are being made. The calling routine knows which constants are possible and only allows these. So unknown constants or constants that are intended for other calls are not accepted. For example:

--> fmlpsolve('set_verbose', lp, 'blabla');
BLABLA: Unknown.

--> fmlpsolve('set_verbose', lp, 'GE');
GE: Not allowed here.

Note the difference between the two error messages. The first says that the constant is not known, the second that the constant cannot be used at that place.

Constants are case insensitive. Internally they are always translated to upper case. Also when returned they will always be in upper case.

The constant names are the ones as specified in the documentation of each API routine. There are only 3 exceptions, extensions actually. 'LE', 'GE' and 'EQ' in add_constraint and is_constr_type can also be '<', '<=', '>', '>=', '='. When returned however, 'GE', 'LE', 'EQ' will be used.

Some constants can be a combination of multiple constants. For example set_scaling:

--> fmlpsolve('set_scaling', lp, 3+128);

With the string version of constants this can be done as following:

--> fmlpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_INTEGERS');

| is the OR operator used to combine multiple constants. There may optinally be spaces before and after the |.

Not all OR combinations are legal. For example in set_scaling, a choice must be made between SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC or SCALE_CURTISREID. They may not be combined with each other. This is also tested:

--> fmlpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_RANGE');
SCALE_RANGE cannot be combined with SCALE_MEAN

Everywhere constants must be provided, numeric or string values may be provided. The routine automatically interpretes them.

Returning constants is a different story. The user must let lp_solve know how to return it. Numerical or as string. The default is numerical:

--> fmlpsolve('get_scaling', lp)

ans =

 131

To let lp_solve return a constant as string, a call to a new function must be made: return_constants

--> fmlpsolve('return_constants', 1);

From now on, all returned constants are returned as string:

--> fmlpsolve('get_scaling', lp)

ans =

 SCALE_MEAN|SCALE_INTEGERS

This for all routines until return_constants is again called with 0:

--> fmlpsolve('return_constants', 0);

The (new) current setting of return_constants is always returned by the call. Even when set:

--> fmlpsolve('return_constants', 1)

ans =

 1

To get the value without setting it, don't provide the second argument:

--> fmlpsolve('return_constants')

ans =

 1

In the next part of this documentation, return_constants is the default, 0, so all constants are returned numerical and provided constants are also numerical. This to keep the documentation as compatible as possible with older versions. But don't let you hold that back to use string constants in your code.

Script files

FreeMat can execute a sequence of statements stored in diskfiles. Such files are called "Script files". They must have the file type of ".m" as the last part of their filename (extension). Much of your work with FreeMat will be in creating and refining script files. Script files are usually created using your local editor.

Script files can be compared with batch files or scripts. You can put FreeMat commands in them and execute them at any time. The Script file is executed like any other command, by entering its name (without the .m extension).

The fmlpsolve FreeMat distribution contains some example Script files to demonstrate this.

You can edit these files with your favourite text editor (or notepad).

example1.m

Contains the commands as shown in the first example of this article.

example2.m

Contains the commands as shown in the second example of this article.

example3.m

Contains the commands of a practical example. See further in this article.

example4.m

Contains the commands of a practical example. See further in this article.

example5.m

Contains the commands of a practical example. See further in this article.

example6.m

Contains the commands of a practical example. See further in this article.

lp_solve.m

This script uses the API to create a higher-level function called lp_solve. This function accepts as arguments some matrices and options to create and solve an lp model. See the beginning of the file or type help lp_solve or just lp_solve to see its usage:

 --> help lp_solve
 LP_SOLVE  Solves mixed integer linear programming problems.

   SYNOPSIS: [obj,x,duals] = lp_solve(f,a,b,e,vlb,vub,xint,scalemode,keep)

      solves the MILP problem

              max v = f'*x
                a*x <> b
                  vlb <= x <= vub
                  x(int) are integer

   ARGUMENTS: The first four arguments are required:

            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) = -1  ==> Less Than
                      e(i) =  0  ==> Equals
                      e(i) =  1  ==> Greater Than
          vlb: n vector of lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
         keep: Flag for keeping the lp problem after it's been solved.
               If omitted, the lp will be deleted when solved.

   OUTPUT: A nonempty output is returned if a solution is found:

          obj: Optimal value of the objective function.
            x: Optimal value of the decision variables.
        duals: solution of the dual problem.

Example of usage. To create and solve following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

--> [obj, x]=lp_solve([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])
obj =

 3

x =

 1
 2

lp_maker.m

This script is analog to the lp_solve script and also uses the API to create a higher-level function called lp_maker. This function accepts as arguments some matrices and options to create an lp model. Note that this scripts only creates a model and returns a handle. See the beginning of the file or type help lp_maker or just lp_maker to see its usage:

 --> help lp_maker

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: Autoscale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Example of usage. To create following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

--> lp=lp_maker([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])

lp =

 0

To solve the model and get the solution:

--> fmlpsolve('solve', lp)

ans =

 0

--> fmlpsolve('get_objective', lp)

ans =

 3

--> fmlpsolve('get_variables', lp)

ans =

 1
 2

Don't forget to free the handle and its associated memory when you are done:

--> fmlpsolve('delete_lp', lp);

lpdemo.m

Contains several examples to build and solve lp models.

ex.m

Contains several examples to build and solve lp models. Also solves the lp_examples from the lp_solve distribution.

A practical example

We shall illustrate the method of linear programming by means of a simple example, giving a combination graphical/numerical solution, and then solve both a slightly as well as a substantially more complicated problem.

Suppose a farmer has 75 acres on which to plant two crops: wheat and barley. To produce these crops, it costs the farmer (for seed, fertilizer, etc.) $120 per acre for the wheat and $210 per acre for the barley.The farmer has $15000 available for expenses. But after the harvest, the farmer must store the crops while awaiting favourable market conditions. The farmer has storage space for 4000 bushels.Each acre yields an average of 110 bushels of wheat or 30 bushels of barley. If the net profit per bushel of wheat (after all expenses have been subtracted) is $1.30 and for barley is $2.00, how should the farmer plant the 75 acres to maximize profit?

We begin by formulating the problem mathematically. First we express the objective, that is the profit, and the constraints algebraically, then we graph them, and lastly we arrive at the solution by graphical inspection and a minor arithmetic calculation.

Let x denote the number of acres allotted to wheat and y the number of acres allotted to barley. Then the expression to be maximized, that is the profit, is clearly

P = (110)(1.30)x + (30)(2.00)y = 143x + 60y.

There are three constraint inequalities, specified by the limits on expenses, storage and acreage. They are respectively:

120x + 210y <= 15000
110x + 30y <= 4000
x + y <= 75

Strictly speaking there are two more constraint inequalities forced by the fact that the farmer cannot plant a negative number of acres, namely:

x >= 0,y >= 0.

Next we graph the regions specified by the constraints. The last two say that we only need to consider the first quadrant in the x-y plane. Here's a graph delineating the triangular region in the first quadrant determined by the first inequality.

Source

Now let's put in the other two constraint inequalities.

Source

The black area is the solution space that holds valid solutions. This means that any point in this area fulfils the constraints.

Now let's superimpose on top of this picture a contour plot of the objective function P.

Source

The lines give a picture of the objective function. All solutions that intersect with the black area are valid solutions, meaning that this result also fulfils the set constraints. The more the lines go to the right, the higher the objective value is. The optimal solution or best objective is a line that is still in the black area, but with an as large as possible value.

It seems apparent that the maximum value of P will occur on the level curve (that is, level line) that passes through the vertex of the polygon that lies near (22,53).
It is the intersection of x + y = 75 and 110*x + 30*y = 4000
This is a corner point of the diagram. This is not a coincidence. The simplex algorithm, which is used by lp_solve, starts from a theorem that the optimal solution is such a corner point.
In fact we can compute the result:

--> x = [1 1; 110 30] \ [75; 4000]

x =

   21.8750
   53.1250

The acreage that results in the maximum profit is 21.875 for wheat and 53.125 for barley. In that case the profit is:

--> P = [143 60] * x

P =

 6.3156e+03

That is, $6315.63.

Note that these command are in script example3.m

Now, lp_solve comes into the picture to solve this linear programming problem more generally. After that we will use it to solve two more complicated problems involving more variables and constraints.

For this example, we use the higher-level script lp_maker to build the model and then some lp_solve API calls to retrieve the solution. Here is again the usage of lp_maker:

--> help lp_maker

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: Autoscale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Now let's formulate this model with lp_solve:

--> f = [143 60];
--> A = [120 210; 110 30; 1 1];
--> b = [15000; 4000; 75];
--> lp = lp_maker(f, A, b, [-1; -1; -1], [], [], [], 1, 0);
--> solvestat = fmlpsolve('solve', lp)

solvestat =

 0

--> obj = fmlpsolve('get_objective', lp)

obj =

 6.3156e+03

--> x = fmlpsolve('get_variables', lp)

x =

   21.8750
   53.1250

--> fmlpsolve('delete_lp', lp);

Note that these command are in script example4.m

With the higher-level script lp_maker, we provide all data to lp_solve. lp_solve returns a handle (lp) to the created model. Then the API call 'solve' is used to calculate the optimal solution of the model. The value of the objective function is retrieved via the API call 'get_objective' and the values of the variables are retrieved via the API call 'get_variables'. At last, the model is removed from memory via a call to 'delete_lp'. Don't forget this to free all memory allocated by lp_solve.

The solution is the same answer we obtained before. Note that the non-negativity constraints are accounted implicitly because variables are by default non-negative in lp_solve.

Well, we could have done this problem by hand (as shown in the introduction) because it is very small and it can be graphically presented.
Now suppose that the farmer is dealing with a third crop, say corn, and that the corresponding data is:

cost per acre$150.75
yield per acre125 bushels
profit per bushel$1.56

With three variables it is already a lot more difficult to show this model graphically. Adding more variables makes it even impossible because we can't imagine anymore how to represent this. We only have a practical understanding of 3 dimentions, but beyound that it is all very theorethical.

If we denote the number of acres allotted to corn by z, then the objective function becomes:

P = (110)(1.30)x + (30)(2.00)y+ (125)(1.56) = 143x + 60y + 195z

And the constraint inequalities are:

120x + 210y + 150.75z <= 15000
110x + 30y + 125z <= 4000
x + y + z <= 75
x >= 0,y >= 0, z >= 0

The problem is solved with lp_solve as follows:

--> f = [143 60 195];
--> A = [120 210 150.75; 110 30 125; 1 1 1];
--> b = [15000; 4000; 75];
--> lp = lp_maker(f, A, b, [-1; -1; -1], [], [], [], 1, 0);
--> solvestat = fmlpsolve('solve', lp)

solvestat =

 0

--> obj = fmlpsolve('get_objective', lp)

obj =

 6.9868e+03

--> x = fmlpsolve('get_variables', lp)

x =

         0
   56.5789
   18.4211

--> fmlpsolve('delete_lp', lp);

Note that these command are in script example5.m

So the farmer should ditch the wheat and plant 56.5789 acres of barley and 18.4211 acres of corn.

There is no practical limit on the number of variables and constraints that FreeMat can handle. Certainly none that the relatively unsophisticated user will encounter.Indeed, in many true applications of the technique of linear programming, one needs to deal with many variables and constraints.The solution of such a problem by hand is not feasible, and software like FreeMat is crucial to success.For example, in the farming problem with which we have been working, one could have more crops than two or three. Think agribusiness instead of family farmer.And one could have constraints that arise from other things beside expenses, storage and acreage limitations. For example:

  • Availability of seed.This might lead to constraint inequalities like xj < k.
  • Personal preferences. Thus the farmer's spouse might have a preference for one variety over another and insist on a corresponding planting, or something similar with a collection of crops; thus constraint inequalities like xi < xj or x1 + x2 > x3.
  • Government subsidies. It may take a moment's reflection on the reader's part, but this could lead to inequalities like xj > k.

Below is a sequence of commands that solves exactly such a problem. You should be able to recognize the objective expression and the constraints from the data that is entered. But as an aid, you might answer the following questions:

  • How many crops are under consideration?
  • What are the corresponding expenses? How much is available for expenses?
  • What are the yields in each case? What is the storage capacity?
  • How many acres are available?
  • What crops are constrained by seed limitations? To what extent?
  • What about preferences?
  • What are the minimum acreages for each crop?
--> f = [110*1.3 30*2.0 125*1.56 75*1.8 95*.95 100*2.25 50*1.35];
--> A = [120 210 150.75 115 186 140 85;
        110 30 125 75 95 100 50;
        1 1 1 1 1 1 1;
        1 -1 0 0 0 0 0;
        0 0 1 0 -2 0 0;
        0 0 0 -1 0 -1 1];

--> b = [55000;40000;400;0;0;0];
--> lp = lp_maker(f, A, b, [-1; -1; -1; -1; -1; -1], [10 10 10 10 20 20 20], [100 1.0e30 50 1.0e30 1.0e30 250 1.0e30], [], 1, 0);
--> solvestat = fmlpsolve('solve', lp)

solvestat =

 0

--> obj = fmlpsolve('get_objective', lp)

obj =

 7.5398e+04

--> x = fmlpsolve('get_variables', lp)

x =

   1.0e+02 *

    0.1000
    0.1000
    0.4000
    0.4565
    0.2000
    2.5000
    0.2000

--> fmlpsolve('delete_lp', lp);

Note that these command are in script example6.m

Note that we have used in this formulation the vlb and vub arguments of lp_maker. This to set lower and upper bounds on variables. This could have been done via extra constraints, but it is more performant to set bounds on variables. Also note that 1.0e30 is used for variables that have no upper limit. This stands for Infinity.

Note that despite the complexity of the problem, lp_solve solves it almost instantaneously. It seems the farmer should bet the farm on crop number 6.We strongly suggest you alter the expense and/or the storage limit in the problem and see what effect that has on the answer.

Another, more theoretical, example

Suppose we want to solve the following linear program using FreeMat:

max 4x1 + 2x2 + x3
s. t. 2x1 + x2 <= 1
x1 + 2x3 <= 2
x1 + x2 + x3 = 1
x1 >= 0
x1 <= 1
x2 >= 0
x2 <= 1
x3 >= 0
x3 <= 2

Convert the LP into FreeMat format we get:

f = [4 2 1]
A = [2 1 0; 1 0 2; 1 1 1]
b = [1; 2; 1]

Note that constraints on single variables are not put in the constraint matrix. lp_solve can set bounds on individual variables and this is more performant than creating additional constraints. These bounds are:

l = [ 0 0 0]
u = [ 1 1 2]

Now lets enter this in FreeMat:

--> f = [4 2 1];
--> A = [2 1 0; 1 0 2; 1 1 1];
--> b = [1; 2; 1];
--> l = [ 0 0 0];
--> u = [ 1 1 2];

Now solve the linear program using FreeMat: Type the commands

--> lp = lp_maker(f, A, b, [-1; -1; -1], l, u, [], 1, 0);
--> solvestat = fmlpsolve('solve', lp)

solvestat =

 0

--> obj = fmlpsolve('get_objective', lp)

obj =

    2.5000

--> x = fmlpsolve('get_variables', lp)

x =

    0.5000
         0
    0.5000

--> fmlpsolve('delete_lp', lp);

What to do when some of the variables are missing ?
For example, suppose there are no lower bounds on the variables. In this case define l to be the empty set using the FreeMat command:

--> l = [];

This has the same effect as before, because lp_solve has as default lower bound for variables 0.

But what if you want that variables may also become negative?
Then you can use -1.0e30 as lower bounds:

--> l = [-1.0e30 -1.0e30 -1.0e30];

Solve this and you get a different result:

--> lp = lp_maker(f, A, b, [-1; -1; -1], l, u, [], 1, 0);
--> solvestat = fmlpsolve('solve', lp)

solvestat =

 0

--> obj = fmlpsolve('get_objective', lp)

obj =

    2.6667

--> x = fmlpsolve('get_variables', lp)

x =

    0.6667
   -0.3333
    0.6667

--> fmlpsolve('delete_lp', lp);

Overview of API routines

Note again that the FreeMat command 'help fmlpsolve' gives an overview of all functions that can be called via fmlpsolve with their arguments and return values.

Note that everwhere where lp is used as argument that this can be a handle (lp_handle) or the models name.

  • add_column, add_columnex
    • return = fmlpsolve('add_column', lp, [column])
    • return = fmlpsolve('add_columnex', lp, [column])
    • Both have the same interface from add_column but act as add_columnex
  • add_constraint, add_constraintex
    • return = fmlpsolve('add_constraint', lp, [row], constr_type, rh)
    • return = fmlpsolve('add_constraintex', lp, [row], constr_type, rh)
    • Both have the same interface from add_constraint but act as add_constraintex
  • add_SOS
    • return = fmlpsolve('add_SOS', lp, name, sostype, priority, [sosvars], [weights])
    • The count argument in the API documentation is not needed in FreeMat since the number of elements is derived from the size of the sosvars and weights matrices. These must have the same size.
  • column_in_lp
    • return = fmlpsolve('column_in_lp', lp, [column])
    • No special considerations.
  • copy_lp
    • lp_handle = fmlpsolve('copy_lp', lp)
    • No special considerations.
  • default_basis
    • fmlpsolve('default_basis', lp)
    • No special considerations.
  • del_column
    • return = fmlpsolve('del_column', lp, column)
    • No special considerations.
  • del_constraint
    • return = fmlpsolve('del_constraint', lp, del_row)
    • No special considerations.
  • delete_lp
    • fmlpsolve('delete_lp', lp)
    • No special considerations.
  • free_lp
    • fmlpsolve('free_lp', lp)
    • lp is not changed as in the lpsolve API since it is a read_only input parameter. So it acts the same as delete_lp.
  • get_anti_degen
    • return = fmlpsolve('get_anti_degen', lp)
    • No special considerations.
  • get_basis
    • [bascolumn] = fmlpsolve('get_basis', lp {, nonbasic})
    • The bascolumn argument in the API documentation is here the return value. The nonbasic argument is optional in FreeMat. If not provided, then 0 is used.
  • get_basiscrash
    • return = fmlpsolve('get_basiscrash', lp)
    • No special considerations.
  • get_bb_depthlimit
    • return = fmlpsolve('get_bb_depthlimit', lp)
    • No special considerations.
  • get_bb_floorfirst
    • return = fmlpsolve('get_bb_floorfirst', lp)
    • No special considerations.
  • get_bb_rule
    • return = fmlpsolve('get_bb_rule', lp)
    • No special considerations.
  • get_bounds_tighter
    • return = fmlpsolve('get_bounds_tighter', lp)
    • No special considerations.
  • get_break_at_value
    • return = fmlpsolve('get_break_at_value', lp)
    • No special considerations.
  • get_col_name
    • name = fmlpsolve('get_col_name', lp, column)
    • column must be provided and is as such not optional. As such no array of names can be returned. This because FreeMat has no possibility to return sets via the import interface.
  • get_column get_columnex
    • [column, return] = fmlpsolve('get_column', lp, col_nr)
    • [column, return] = fmlpsolve('get_columnex', lp, col_nr)
    • The column argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_constr_type
    • return = fmlpsolve('get_constr_type', lp, row)
    • [constr_type] = fmlpsolve('get_constr_type', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • get_constr_value
    • return = fmlpsolve('get_constr_value', lp, row {, primsolution})
    • The primsolution argument is optional. If not provided, then the solution of last solve is used.
  • get_constraints
    • [constr, return] = fmlpsolve('get_constraints', lp)
    • The constr argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_dual_solution
    • [duals, return] = fmlpsolve('get_dual_solution', lp)
    • The duals argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In FreeMat, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_epsb
    • return = fmlpsolve('get_epsb', lp)
    • No special considerations.
  • get_epsd
    • return = fmlpsolve('get_epsd', lp)
    • No special considerations.
  • get_epsel
    • return = fmlpsolve('get_epsel', lp)
    • No special considerations.
  • get_epsint
    • return = fmlpsolve('get_epsint', lp)
    • No special considerations.
  • get_epsperturb
    • return = fmlpsolve('get_epsperturb', lp)
    • No special considerations.
  • get_epspivot
    • return = fmlpsolve('get_epspivot', lp)
    • No special considerations.
  • get_improve
    • return = fmlpsolve('get_improve', lp)
    • No special considerations.
  • get_infinite
    • return = fmlpsolve('get_infinite', lp)
    • No special considerations.
  • get_lowbo
    • return = fmlpsolve('get_lowbo', lp, column)
    • [return] = fmlpsolve('get_lowbo', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • get_lp_index
    • return = fmlpsolve('get_lp_index', lp, orig_index)
    • No special considerations.
  • get_lp_name
    • name = fmlpsolve('get_lp_name', lp)
    • No special considerations.
  • get_mat
    • value = fmlpsolve('get_mat', lp, row, col)
    • [matrix, return] = fmlpsolve('get_mat', lp[, sparse])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix in the first return value. If sparse is different from zero then the returned matrix is a sparse matrix. The return code of the call is the second return value.
  • get_max_level
    • return = fmlpsolve('get_max_level', lp)
    • No special considerations.
  • get_maxpivot
    • return = fmlpsolve('get_maxpivot', lp)
    • No special considerations.
  • get_mip_gap
    • return = fmlpsolve('get_mip_gap', lp, absolute)
    • No special considerations.
  • get_nameindex
    • return = fmlpsolve('get_nameindex', lp, name, isrow)
    • No special considerations.
  • get_Ncolumns
    • return = fmlpsolve('get_Ncolumns', lp)
    • No special considerations.
  • get_negrange
    • return = fmlpsolve('get_negrange', lp)
    • No special considerations.
  • get_nonzeros
    • return = fmlpsolve('get_nonzeros', lp)
    • No special considerations.
  • get_Norig_columns
    • return = fmlpsolve('get_Norig_columns', lp)
    • No special considerations.
  • get_Norig_rows
    • return = fmlpsolve('get_Norig_rows', lp)
    • No special considerations.
  • get_Nrows
    • return = fmlpsolve('get_Nrows', lp)
    • No special considerations.
  • get_obj_bound
    • return = fmlpsolve('get_obj_bound', lp)
    • No special considerations.
  • get_objective
    • return = fmlpsolve('get_objective', lp)
    • No special considerations.
  • get_orig_index
    • return = fmlpsolve('get_orig_index', lp, lp_index)
    • No special considerations.
  • get_origcol_name
    • name = fmlpsolve('get_origcol_name', lp, column)
    • column must be provided and is as such not optional. As such no array of names can be returned. This because FreeMat has no possibility to return sets via the import interface.
  • get_origrow_name
    • name = fmlpsolve('get_origrow_name', lp, row)
    • row must be provided and is as such not optional. As such no array of names can be returned. This because FreeMat has no possibility to return sets via the import interface.
  • get_pivoting
    • return = fmlpsolve('get_pivoting', lp)
    • No special considerations.
  • get_presolve
    • return = fmlpsolve('get_presolve', lp)
    • No special considerations.
  • get_presolveloops
    • return = fmlpsolve('get_presolveloops', lp)
    • No special considerations.
  • get_primal_solution
    • [pv, return] = fmlpsolve('get_primal_solution', lp)
    • The pv argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_print_sol
    • return = fmlpsolve('get_print_sol', lp)
    • No special considerations.
  • get_ptr_constraints
    • Not implemented.
  • get_ptr_dualsolution
    • Not implemented.
  • get_ptr_primal_solution
    • Not implemented.
  • get_ptr_sensitivity_obj, get_ptr_sensitivity_objex
    • Not implemented.
  • get_ptr_sensitivity_rhs
    • Not implemented.
  • get_ptr_variables
    • Not implemented.
  • get_rh
    • return = fmlpsolve('get_rh', lp, row)
    • [rh] = fmlpsolve('get_rh', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • get_rh_range
    • return = fmlpsolve('get_rh_range', lp, row)
    • [rh_ranges] = fmlpsolve('get_rh_range', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • get_row get_rowex
    • [row, return] = fmlpsolve('get_row', lp, row_nr)
    • [row, return] = fmlpsolve('get_rowex', lp, row_nr)
    • The row argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In FreeMat, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_row_name
    • name = fmlpsolve('get_row_name', lp, row)
    • row must be provided and is as such not optional. As such no array of names can be returned. This because FreeMat has no possibility to return sets via the import interface.
  • get_scalelimit
    • return = fmlpsolve('get_scalelimit', lp)
    • No special considerations.
  • get_scaling
    • return = fmlpsolve('get_scaling', lp)
    • No special considerations.
  • get_sensitivity_obj, get_sensitivity_objex
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = fmlpsolve('get_sensitivity_obj', lp)
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = fmlpsolve('get_sensitivity_objex', lp)
    • The objfrom, objtill, objfromvalue, objtillvalue arguments in the API documentation are here the return values. Note that FreeMat allows the return of fewer variables. For example if only objfrom and objtill are needed then the call can be [objfrom, objtill] = fmlpsolve('get_sensitivity_obj', lp). The unrequested values are even not calculated.
    • Since the API routine doesn't calculate the objtillvalue value at this time, FreeMat always returns a zero vector for this.
    • The return code of the call is the last value.
    • get_sensitivity_obj and get_sensitivity_objex are both implemented, but have the same functionality.
  • get_sensitivity_rhs, get_sensitivity_rhsex
    • [duals, dualsfrom, dualstill, return] = fmlpsolve('get_sensitivity_rhs', lp)
    • [duals, dualsfrom, dualstill, return] = fmlpsolve('get_sensitivity_rhsex', lp)
    • The duals, dualsfrom, dualstill arguments in the API documentation are here the return values. Note that FreeMat allows the return of fewer variables. For example if only duals is needed then the call can be [duals] = fmlpsolve('get_sensitivity_rhs', lp). The unrequested values are even not calculated.
    • The return code of the call is the last value.
    • get_sensitivity_rhs and get_sensitivity_rhsex are both implemented, but have the same functionality.
  • get_simplextype
    • return = fmlpsolve('get_simplextype', lp)
    • No special considerations.
  • get_solutioncount
    • return = fmlpsolve('get_solutioncount', lp)
    • No special considerations.
  • get_solutionlimit
    • return = fmlpsolve('get_solutionlimit', lp)
    • No special considerations.
  • get_status
    • return = fmlpsolve('get_status', lp)
    • No special considerations.
  • get_statustext
    • return = fmlpsolve('get_statustext', lp, statuscode)
    • No special considerations.
  • get_timeout
    • return = fmlpsolve('get_timeout', lp)
    • No special considerations.
  • get_total_iter
    • return = fmlpsolve('get_total_iter', lp)
    • No special considerations.
  • get_total_nodes
    • return = fmlpsolve('get_total_nodes', lp)
    • No special considerations.
  • get_upbo
    • return = fmlpsolve('get_upbo', lp, column)
    • [upbo] = fmlpsolve('get_upbo', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • get_var_branch
    • return = fmlpsolve('get_var_branch', lp, column)
    • [var_branch] = fmlpsolve('get_var_branch', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • get_var_dualresult
    • return = fmlpsolve('get_var_dualresult', lp, index)
    • No special considerations.
  • get_var_primalresult
    • return = fmlpsolve('get_var_primalresult', lp, index)
    • No special considerations.
  • get_var_priority
    • return = fmlpsolve('get_var_priority', lp, column)
    • [var_priority] = fmlpsolve('get_var_priority', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • get_variables
    • [var, return] = fmlpsolve('get_variables', lp)
    • The var argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_verbose
    • return = fmlpsolve('get_verbose', lp)
    • No special considerations.
  • get_working_objective
    • return = fmlpsolve('get_working_objective', lp)
    • No special considerations.
  • guess_basis
    • [basisvector, return] = fmlpsolve('guess_basis', lp, [guessvector])
    • In the API, element 0 of guessvector is not used and values start from element 1. In FreeMat, there is no unused element in the matrix.
    • In the API, element 0 of basisvector is not used and values start from element 1. In FreeMat, there is no unused element in the matrix.
  • has_BFP
    • return = fmlpsolve('has_BFP', lp)
    • No special considerations.
  • has_XLI
    • return = fmlpsolve('has_XLI', lp)
    • No special considerations.
  • is_add_rowmode
    • return = fmlpsolve('is_add_rowmode', lp)
    • No special considerations.
  • is_anti_degen
    • return = fmlpsolve('is_anti_degen', lp, testmask)
    • No special considerations.
  • is_binary
    • return = fmlpsolve('is_binary', lp, column)
    • [binary] = fmlpsolve('is_binary', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • is_break_at_first
    • return = fmlpsolve('is_break_at_first', lp)
    • No special considerations.
  • is_constr_type
    • return = fmlpsolve('is_constr_type', lp, row, mask)
    • No special considerations.
  • is_debug
    • return = fmlpsolve('is_debug', lp)
    • No special considerations.
  • is_feasible
    • return = fmlpsolve('is_feasible', lp, [values] {, threshold})
    • The threshold argument is optional. When not provided, the value of get_epsint will be taken.
  • is_free is_unbounded
    • return = fmlpsolve('is_free', lp, column)
    • return = fmlpsolve('is_unbounded', lp, column)
    • [free] = fmlpsolve('is_free', lp)
    • [free] = fmlpsolve('is_unbounded', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • is_infinite
    • return = fmlpsolve('is_infinite', lp, value)
    • No special considerations.
  • is_int
    • return = fmlpsolve('is_int', lp, column)
    • [int] = fmlpsolve('is_int', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • is_integerscaling
    • return = fmlpsolve('is_integerscaling', lp)
    • No special considerations.
  • is_maxim
    • return = fmlpsolve('is_maxim', lp)
    • No special considerations.
  • is_nativeBFP
    • return = fmlpsolve('is_nativeBFP', lp)
    • No special considerations.
  • is_nativeXLI
    • return = fmlpsolve('is_nativeXLI', lp)
    • No special considerations.
  • is_negative
    • return = fmlpsolve('is_negative', lp, column)
    • [negative] = fmlpsolve('is_negative', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • is_piv_mode
    • return = fmlpsolve('is_piv_mode', lp, testmask)
    • No special considerations.
  • is_piv_rule
    • return = fmlpsolve('is_piv_rule', lp, rule)
    • No special considerations.
  • is_presolve
    • return = fmlpsolve('is_presolve', lp, testmask)
    • No special considerations.
  • is_scalemode
    • return = fmlpsolve('is_scalemode', lp, testmask)
    • No special considerations.
  • is_scaletype
    • return = fmlpsolve('is_scaletype', lp, scaletype)
    • No special considerations.
  • is_semicont
    • return = fmlpsolve('is_semicont', lp, column)
    • [semicont] = fmlpsolve('is_semicont', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • is_SOS_var
    • return = fmlpsolve('is_SOS_var', lp, column)
    • [SOS_var] = fmlpsolve('is_SOS_var', lp)
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a FreeMat matrix.
  • is_trace
    • return = fmlpsolve('is_trace', lp)
    • No special considerations.
  • is_use_names
    • return = fmlpsolve('is_use_names', lp, isrow)
    • No special considerations.
  • lp_solve_version
    • versionstring = fmlpsolve('lp_solve_version')
    • The fmlpsolve API routine returns the version information in 4 provided argument variables while the FreeMat version returns the information as a string in the format major.minor.release.build
  • make_lp
    • lp_handle = fmlpsolve('make_lp', rows, columns)
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
  • print_constraints
    • fmlpsolve('print_constraints', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under FreeMat (Windows) this means that the output is not shown.
    • The same information can also be obtained via fmlpsolve('get_constraints', lp). This shows the result on screen.
  • print_debugdump
    • return = fmlpsolve('print_debugdump', lp, filename)
    • No special considerations.
  • print_duals
    • fmlpsolve('print_duals', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under FreeMat (Windows) this means that the output is not shown.
    • The same information can be obtained via fmlpsolve('get_dual_solution', lp). This shows the result on screen.
  • print_lp
    • fmlpsolve('print_lp', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under FreeMat (Windows) this means that the output is not shown.
  • print_objective
    • fmlpsolve('print_objective', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under FreeMat (Windows) this means that the output is not shown.
    • The same information can be obtained via fmlpsolve('get_objective', lp). This shows the result on screen.
  • print_scales
    • fmlpsolve('print_scales', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under FreeMat (Windows) this means that the output is not shown.
  • print_solution
    • fmlpsolve('print_solution', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under FreeMat (Windows) this means that the output is not shown.
    • The same information can also be obtained via fmlpsolve('get_variables', lp). This shows the result on screen.
  • print_str
    • fmlpsolve('print_str', lp, str)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under FreeMat (Windows) this means that the output is not shown.
  • print_tableau
    • fmlpsolve('print_tableau', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under FreeMat (Windows) this means that the output is not shown.
  • put_abortfunc
    • Not implemented.
  • put_logfunc
    • Not implemented.
    • However, the fmlpsolve driver sets a log function to redirect the output of lpsolve from stdout (which is not visible in Windows FreeMat) to the command window of FreeMat. As such, all reported output can be seen in FreeMat. How much output is seen is controlled by the verbose level that can be defined by set_verbose or can be specified in the read_ routines.
  • put_msgfunc
    • Not implemented.
  • read_basis
    • [ret, info] = fmlpsolve('read_basis', lp, filename)
    • No special considerations.
  • read_freemps, read_freeMPS
    • lp_handle = fmlpsolve('read_freemps', filename {, options})
    • lp_handle = fmlpsolve('read_freeMPS', filename {, options})
    • In the lpsolve API, read_freemps needs a FILE handle. In FreeMat it needs the filename and thus acts the same as read_freeMPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_lp, read_LP
    • lp_handle = fmlpsolve('read_lp', filename {, verbose {, lp_name}})
    • lp_handle = fmlpsolve('read_LP', filename {, verbose {, lp_name}})
    • In the lpsolve API, read_lp needs a FILE handle. In FreeMat it needs the filename and thus acts the same as read_LP.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not provided then NORMAL is used.
    • lp_name is optional. If not provided then no name is given to the model ('').
  • read_mps, read_MPS
    • lp_handle = fmlpsolve('read_mps', filename {, options})
    • lp_handle = fmlpsolve('read_MPS', filename {, options})
    • In the lpsolve API, read_mps needs a FILE handle. In FreeMat it needs the filename and thus acts the same as read_MPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_params
    • return = fmlpsolve('read_params', lp, filename {, options })
    • options is optional.
  • read_XLI
    • lp_handle = fmlpsolve('read_XLI', xliname, modelname {, dataname {, options {, verbose}}}
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • dataname is optional. When not provided, '' (NULL) is taken. '' is taken as NULL.
    • options is optional. When not provided, '' is taken.
    • verbose is optional. If not specified, then NORMAL is used.
  • reset_basis
  • set_basisvar
    • fmlpsolve('set_basisvar', lp, basisPos, enteringCol)
    • No special considerations.
  • set_add_rowmode
    • return = fmlpsolve('set_add_rowmode', lp, turnon)
    • No special considerations.
  • set_anti_degen
    • fmlpsolve('set_anti_degen', lp, anti_degen)
    • No special considerations.
  • set_basis
    • return = fmlpsolve('set_basis', lp, [bascolumn], nonbasic)
    • In the API, element 0 of bascolumn is not used and values start from element 1. In FreeMat, there is no unused element in the matrix.
  • set_basiscrash
    • fmlpsolve('set_basiscrash', lp, mode)
    • No special considerations.
  • set_bb_depthlimit
    • fmlpsolve('set_bb_depthlimit', lp, bb_maxlevel)
    • No special considerations.
  • set_bb_floorfirst
    • fmlpsolve('set_bb_floorfirst', lp, bb_floorfirst)
    • No special considerations.
  • set_bb_rule
    • fmlpsolve('set_bb_rule', lp, bb_rule)
    • No special considerations.
  • set_BFP
    • return = fmlpsolve('set_BFP', lp, filename)
    • No special considerations.
  • set_binary
    • return = fmlpsolve('set_binary', lp, column, must_be_bin)
    • return = fmlpsolve('set_binary', lp, [must_be_bin])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds
    • return = fmlpsolve('set_bounds', lp, column, lower, upper)
    • return = fmlpsolve('set_bounds', lp, [lower], [upper])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds_tighter
    • fmlpsolve('set_bounds_tighter', lp, tighten)
    • No special considerations.
  • set_break_at_first
    • fmlpsolve('set_break_at_first', lp, break_at_first)
    • No special considerations.
  • set_break_at_value
    • fmlpsolve('set_break_at_value', lp, break_at_value)
    • No special considerations.
  • set_col_name
    • return = fmlpsolve('set_col_name', lp, column, name)
    • column must be provided and is as such not optional. As such no array of names can be provided. This because FreeMat has no possibility to provide sets via the import interface.
  • set_column, set_columnex
    • return = fmlpsolve('set_column', lp, col_no, [column])
    • return = fmlpsolve('set_columnex', lp, col_no, [column])
    • Both have the same interface from set_column but act as set_columnex
  • set_constr_type
    • return = fmlpsolve('set_constr_type', lp, row, con_type)
    • return = fmlpsolve('set_constr_type', lp, [con_type])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_debug
    • fmlpsolve('set_debug', lp, debug)
    • No special considerations.
  • set_epsb
    • fmlpsolve('set_epsb', lp, epsb)
    • No special considerations.
  • set_epsd
    • fmlpsolve('set_epsd', lp, epsd)
    • No special considerations.
  • set_epsel
    • fmlpsolve('set_epsel', lp, epsel)
    • No special considerations.
  • set_epsint
    • fmlpsolve('set_epsint', lp, epsint)
    • No special considerations.
  • set_epslevel
    • fmlpsolve('set_epslevel', lp, epslevel)
    • No special considerations.
  • set_epsperturb
    • fmlpsolve('set_epsperturb', lp, epsperturb)
    • No special considerations.
  • set_epspivot
    • fmlpsolve('set_epspivot', lp, epspivot)
    • No special considerations.
  • set_free set_unbounded
    • return = fmlpsolve('set_free', lp, column)
    • return = fmlpsolve('set_unbounded', lp, column)
    • No special considerations.
  • set_improve
    • fmlpsolve('set_improve', lp, improve)
    • No special considerations.
  • set_infinite
    • fmlpsolve('set_infinite', lp, infinite)
    • No special considerations.
  • set_int
    • return = fmlpsolve('set_int', lp, column, must_be_int)
    • return = fmlpsolve('set_int', lp, [must_be_int])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lowbo
    • return = fmlpsolve('set_lowbo', lp, column, value)
    • return = fmlpsolve('set_lowbo', lp, [values])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lp_name
    • return = fmlpsolve('set_lp_name', lp, name)
    • In FreeMat, when you name a model, this name can be used everywhere where lp is specified. This to access the model via the name instead of via a handle.
  • set_mat
    • return = fmlpsolve('set_mat', lp, row, column, value)
    • return = fmlpsolve('set_mat', lp, [matrix])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows to set the whole matrix (all rows/columns) at once. This is the most performant way to provide the constraint matrix. Consider using a FreeMat sparse matrix for maximum performance and least memory usage. The matrix must be two-dimentional.
  • set_maxim
    • fmlpsolve('set_maxim', lp)
    • No special considerations.
  • set_maxpivot
    • fmlpsolve('set_maxpivot', max_num_inv)
    • No special considerations.
  • set_minim
    • fmlpsolve('set_minim', lp)
    • No special considerations.
  • set_mip_gap
    • fmlpsolve('set_mip_gap', lp, absolute, mip_gap)
    • No special considerations.
  • set_negrange
    • fmlpsolve('set_negrange', negrange)
    • No special considerations.
  • set_obj
    • return = fmlpsolve('set_obj', lp, column, value)
    • return = fmlpsolve('set_obj', lp, [values])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables. It is then the same as set_obj_fn
  • set_obj_bound
    • fmlpsolve('set_obj_bound', lp, obj_bound)
    • No special considerations.
  • set_obj_fn, set_obj_fnex
    • return = fmlpsolve('set_obj_fn', lp, [row])
    • return = fmlpsolve('set_obj_fnex', lp, [row])
    • Both have the same interface from set_obj_fn but act as set_obj_fnex
    • In the API, element 0 is not used and values start from element 1. In FreeMat, there is no unused element in the matrix.
  • set_outputfile
    • return = fmlpsolve('set_outputfile', lp, filename)
    • In the API description it says that setting filename to NULL results in writing output back to stdout. In FreeMat under Windows, output to stdout it not shown. However it results in closing the file. Use '' to have the effect of NULL.
  • set_outputstream
    • Not implemented.
  • set_pivoting
    • fmlpsolve('set_pivoting', lp, pivoting)
    • No special considerations.
  • set_preferdual
    • fmlpsolve('set_preferdual', lp, dodual)
    • No special considerations.
  • set_presolve
    • fmlpsolve('set_presolve', lp, do_presolve {, maxloops})
    • The maxloops argument is optional in FreeMat. If not provided, then infinite is used.
  • set_print_sol
    • fmlpsolve('set_print_sol', lp, print_sol)
    • No special considerations.
  • set_rh
    • return = fmlpsolve('set_rh', lp, row, value)
    • return = fmlpsolve('set_rh', lp, [values])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows. Note that in this case, the value of row 0 is not specified in the matrix.
  • set_rh_range
    • return = fmlpsolve('set_rh_range', lp, row, deltavalue)
    • return = fmlpsolve('set_rh_range', lp, [deltavalues])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_rh_vec
    • fmlpsolve('set_rh_vec', lp, [rh])
    • In the API, element 0 is not used and values start from element 1. In FreeMat, there is no unused element in the matrix.
  • set_row, set_rowex
    • return = fmlpsolve('set_row', lp, row_no, [row])
    • return = fmlpsolve('set_rowex', lp, row_no, [row])
    • Both have the same interface from set_row but act as set_rowex
    • In the API, element 0 is not used and values start from element 1. In FreeMat, there is no unused element in the matrix.
  • set_row_name
    • return = fmlpsolve('set_row_name', lp, row, name)
    • row must be provided and is as such not optional. As such no array of names can be provided. This because FreeMat has no possibility to provide sets via the import interface.
  • set_scalelimit
    • fmlpsolve('set_scalelimit', lp, scalelimit)
    • No special considerations.
  • set_scaling
    • fmlpsolve('set_scaling', lp, scalemode)
    • No special considerations.
  • set_semicont
    • return = fmlpsolve('set_semicont', lp, column, must_be_sc)
    • return = fmlpsolve('set_semicont', lp, [must_be_sc])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_sense
    • fmlpsolve('set_sense', lp, maximize)
    • No special considerations.
  • set_simplextype
    • fmlpsolve('set_simplextype', lp, simplextype)
    • No special considerations.
  • set_solutionlimit
    • fmlpsolve('set_solutionlimit', lp, simplextype)
    • No special considerations.
  • set_timeout
    • fmlpsolve('set_timeout', lp, sectimeout)
    • No special considerations.
  • set_trace
    • fmlpsolve('set_trace', lp, trace)
    • No special considerations.
  • set_upbo
    • return = fmlpsolve('set_upbo', lp, column, value)
    • return = fmlpsolve('set_upbo', lp, [values])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_use_names
    • fmlpsolve('set_use_names', lp, isrow, use_names)
    • No special considerations.
  • set_var_branch
    • return = fmlpsolve('set_var_branch', lp, column, branch_mode)
    • return = fmlpsolve('set_var_branch', lp, [branch_mode])
    • In FreeMat, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_weights
    • return = fmlpsolve('set_var_weights', lp, [weights])
    • No special considerations.
  • set_verbose
    • fmlpsolve('set_verbose', lp, verbose)
    • No special considerations.
  • set_XLI
    • return = fmlpsolve('set_XLI', lp, filename)
    • No special considerations.
  • solve
    • result = fmlpsolve('solve', lp)
    • No special considerations.
  • str_add_column
    • Not implemented.
  • str_add_constraint
    • Not implemented.
  • str_set_obj_fn
    • Not implemented.
  • str_set_rh_vec
    • Not implemented.
  • time_elapsed
    • return = fmlpsolve('time_elapsed', lp)
    • No special considerations.
  • unscale
    • fmlpsolve('unscale', lp)
    • No special considerations.
  • write_basis
    • fmlpsolve('write_basis', lp, filename)
    • No special considerations.
  • write_freemps, write_freeMPS
    • return = fmlpsolve('write_freemps', lp, filename)
    • return = fmlpsolve('write_freeMPS', lp, filename)
    • In the lpsolve API, write_freeMPS needs a FILE handle. In FreeMat it needs the filename and thus acts the same as write_freemps.
  • write_lp, write_LP
    • return = fmlpsolve('write_lp', lp, filename)
    • return = fmlpsolve('write_LP', lp, filename)
    • In the lpsolve API, write_LP needs a FILE handle. In FreeMat it needs the filename and thus acts the same as write_lp.
  • write_mps, write_MPS
    • return = fmlpsolve('write_mps', lp, filename)
    • return = fmlpsolve('write_MPS', lp, filename)
    • In the lpsolve API, write_MPS needs a FILE handle. In FreeMat it needs the filename and thus acts the same as write_mps.
    • No special considerations.
  • write_XLI
    • return = fmlpsolve('write_XLI', lp, filename {, options {, results}})
    • No special considerations.

Extra FreeMat routines

These routines are not part of the lpsolve API, but are added for backwards compatibility. Most of them exist in the lpsolve API with another name.

  • [constr_type] = fmlpsolve('get_constr_types', lp)
    • The same as get_constr_type. Implemented for backwards compatibility.
  • [int] = fmlpsolve('get_int', lp)
    • The same as is_int. Implemented for backwards compatibility.
  • return = fmlpsolve('get_no_cols', lp)
    • The same as get_Ncolumns. Implemented for backwards compatibility.
  • return = fmlpsolve('get_no_rows', lp)
    • The same as get_Nrows. Implemented for backwards compatibility.
  • name = fmlpsolve('get_objective_name', lp)
    • The same as get_row_name with row=0. Implemented for backwards compatibility.
  • [row_vec, return] = fmlpsolve('get_obj_fn', lp)
    [row_vec, return] = fmlpsolve('get_obj_fun', lp)
    • The same as get_row with row 0. Implemented for backwards compatibility.
  • name = fmlpsolve('get_problem_name', lp)
    • The same as get_lp_name. Implemented for backwards compatibility.
  • [costs] = fmlpsolve('get_reduced_costs', lp)
    • The same as get_dual_solution. Implemented for backwards compatibility.
  • [obj, x, duals, return] = fmlpsolve('get_solution', lp)
    • Returns the value of the objective function, the values of the variables and the duals. Implemented for backwards compatibility.
    • The return code of the call is the last value.
  • value = fmlpsolve('mat_elm', lp)
    • The same as get_mat. Implemented for backwards compatibility.
  • [handle_vec] = fmlpsolve('print_handle')
    • Returns a vector with open handles. Can be handy to see which handles aren't closed yet with delete_lp or free_lp.
  • lp_handle = fmlpsolve('read_lp_file', filename {, verbose {, lp_name}})
    • The same as read_LP. Implemented for backwards compatibility.
  • lp_handle = fmlpsolve('get_handle', lp_name)
    • Get the handle for this model from the models name. If an unknown model name is given (or already deleted), -1 is returned.
  • return_constants = fmlpsolve('return_constants'[, return_constants])
    • Returns the setting of return_constants and optionally sets its value.

Compile the fmlpsolve driver

Under Windows, the fmlpsolve FreeMat driver is a dll: fmlpsolve.dll
Under Unix/Linux, the fmlpsolve FreeMat driver is a shared library.: fmlpsolve.so
This driver is an interface to the lpsolve library lpsolve55.dll/liblpsolve55.so that contains the implementation of lp_solve. lpsolve55.dll/liblpsolve55.so is distributed with the lp_solve package (archive lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). The fmlpsolve FreeMat driver is just a wrapper between FreeMat and lp_solve to translate the input/output to/from FreeMat and the lp_solve library.

Compilation

The fmlpsolve FreeMat driver is written in C. To compile this code, under Windows the Microsoft visual C compiler is needed and under Unix/Linux the standard cc compiler.
The needed commands are in a batch file/script.
Under Windows it is called cvc.bat, under Unix/Linux ccc.
In a command prompt/shell, go to the lpsolve FreeMat directory and enter cvc.bat/sh ccc and the compilation is done. The result is fmlpsolve.dll/fmlpsolve.so.

See also Using lpsolve from MATLAB, Using lpsolve from O-Matrix, Using lpsolve from Sysquake, Using lpsolve from Scilab, Using lpsolve from Octave, Using lpsolve from Euler, Using lpsolve from Python, Using lpsolve from Sage, Using lpsolve from PHP, Using lpsolve from R

doc/is_scalemode.htm0000644000175000017500000001472410246722024013437 0ustar renerene is_scalemode

is_scalemode

Returns if scaling mode specified in testmask is active.

unsigned char is_scalemode(lprec *lp, int testmask);

Return Value

is_scalemode returns if scaling mode specified in testmask is active.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

testmask

SCALE_EXTREME (1) Scale to convergence using largest absolute value
SCALE_RANGE (2) Scale based on the simple numerical range
SCALE_MEAN (3) Numerical range-based scaling
SCALE_GEOMETRIC (4) Geometric scaling
SCALE_CURTISREID (7) Curtis-reid scaling

Additionally, the value can be OR-ed with any combination of one of the following values:

SCALE_QUADRATIC (8)  
SCALE_LOGARITHMIC (16) Scale to convergence using logarithmic mean of all values
SCALE_USERWEIGHT (31) User can specify scalars
SCALE_POWER2 (32) also do Power scaling
SCALE_EQUILIBRATE (64) Make sure that no scaled number is above 1
SCALE_INTEGERS (128) also scaling integer variables
SCALE_DYNUPDATE (256) dynamic update
SCALE_ROWSONLY (512) scale only rows
SCALE_COLSONLY (1024) scale only columns

Remarks

The is_scalemode function returns if scaling mode specified in testmask. This can influence numerical stability considerably. It is advisable to always use some sort of scaling.
set_scaling must be called before solve is called.
SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC, SCALE_CURTISREID are the possible scaling algorithms. SCALE_QUADRATIC, SCALE_LOGARITHMIC, SCALE_USERWEIGHT, SCALE_POWER2, SCALE_EQUILIBRATE, SCALE_INTEGERS are possible additional scaling parameters.
SCALE_POWER2 results in creating a scalar of power 2. May improve stability.
SCALE_INTEGERS results also in scaling Integer columns. Default they are not scaled.
SCALE_DYNUPDATE is new from version 5.1.1.0
It has always been so that scaling is done only once on the original model. If a solve is done again (most probably after changing some data in the model), the scaling factors aren't computed again. The scalars of the original model are used. This is not always good, especially if the data has changed considerably. One way to solve this was/is call unscale before a next solve. In that case, scale factors are recomputed.
From version 5.1.1.0 on, there is another way to make sure that scaling factors are recomputed and this is by settings SCALE_DYNUPDATE. In that case, the scaling factors are recomputed also when a restart is done. Note that they are then always recalculated with each solve, even when no change was made to the model, or a change that doesn't influence the scaling factors like changing the RHS (Right Hand Side) values or the bounds/ranges. This can influence performance. It is up to you to decide if scaling factors must be recomputed or not for a new solve, but by default it still isn't so. It is possible to set/unset this flag at each next solve and it is even allowed to choose a new scaling algorithm between each solve. Note that the scaling done by the SCALE_DYNUPDATE is incremental and the resulting scalarsare typically different from scalars recomputed from scratch.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int scalemode;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  scalemode = is_scalemode(lp, SCALE_MEAN);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_scaling, get_scaling, set_scalelimit, get_scalelimit, is_integerscaling, is_scaletype

doc/Scilab.htm0000644000175000017500000036030711244025441012204 0ustar renerene Using lpsolve from Scilab

Using lpsolve from Scilab

Scilab?

Developed at INRIA, Scilab has been developed for system control and signal processing applications. It is freely distributed in source code format.

Scilab is made of three distinct parts: an interpreter, libraries of functions (Scilab procedures) and libraries of Fortran and C routines. These routines (which, strictly speaking, do not belong to Scilab but are interactively called by the interpreter) are of independent interest and most of them are available through Netlib. A few of them have been slightly modified for better compatibility with Scilab's interpreter. A key feature of the Scilab syntax is its ability to handle matrices: basic matrix manipulations such as concatenation, extraction or transpose are immediately performed as well as basic operations such as addition or multiplication. Scilab also aims at handling more complex objects than numerical matrices. For instance, control people may want to manipulate rational or polynomial transfer matrices. This is done in Scilab by manipulating lists and typed lists which allows a natural symbolic representation of complicated mathematical objects such as transfer functions, linear systems or graphs.

Polynomials, polynomials matrices and transfer matrices are also defined and the syntax used for manipulating these matrices is identical to that used for manipulating constant vectors and matrices.

Scilab provides a variety of powerful primitives for the analysis of non-linear systems. Integration of explicit and implicit dynamic systems can be accomplished numerically. The scicos toolbox allows the graphic definition and simulation of complex interconnected hybrid systems.

Scilab has an open programming environment where the creation of functions and libraries of functions is completely in the hands of the user. Functions are recognized as data objects in Scilab and, thus, can be manipulated or created as other data objects. For example, functions can be defined inside Scilab and passed as input or output arguments of other functions.

In addition Scilab supports a character string data type which, in particular, allows the on-line creation of functions. Matrices of character strings are also manipulated with the same syntax as ordinary matrices.

Finally, Scilab is easily interfaced with Fortran or C subprograms. This allows use of standardized packages and libraries in the interpreted environment of Scilab.

The general philosophy of Scilab is to provide the following sort of computing environment:

  • To have data types which are varied and flexible with a syntax which is natural and easy to use.
  • To provide a reasonable set of primitives which serve as a basis for a wide variety of calculations.
  • To have an open programming environment where new primitives are easily added. A useful tool distributed with Scilab is intersci which is a tool for building interface programs to add new primitives i.e. to add new modules of Fortran or C code into Scilab.
  • To support library development through ``toolboxes'' of functions devoted to specific applications (linear control, signal processing, network analysis, non-linear control, etc.)

We will not discuss the specifics of Scilab here but instead refer the reader to the Scilab website and documentation.

Scilab and lpsolve

lpsolve is callable from Scilab via an external interface. As such, it looks like lpsolve is fully integrated with Scilab. Matrices can directly be transferred between Scilab and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for Scilab (especially for matrix support). So you have full control to the complete lpsolve functionality via the sclpsolve Scilab driver. If you find that this involves too much work to solve an lp model then you can also work via higher-level scripts that can make things a lot easier. See further in this article.

Quickstart

Compile and build sclpsolve:
----------------------------
  1. Get the needed sources and libraries: Archive lp_solve_5.5.0.15_scilab_source.tar.gz contains the sources to build sclpsolve. Uncompress it to a directory, for example d:\lp_solve. Make sure that the folder structure is kept. It will create a directory structure lp_solve_5.5\extra\scilab\lpsolve in that folder. Archive lp_solve_5.5.0.15_dev.zip (Windows) or lp_solve_5.5.0.15_dev.tar.gz (Unix) contains needed libraries and include files to link the sources with. Uncompress it to the same folder as for the sources, appended with lp_solve_5.5. In this example that would be d:\lp_solve\lp_solve_5.5 You have now all needed files in place. In your chosen directory (in this example d:\lp_solve) there will only be a directory lp_solve_5.5 In this directory, you have a directory extra and some files ending with .h and .lib The extra directory contains a scilab directory which contains a directory lpsolve with some files and directories. Under Windows, the lpsolve library lpsolve55.lib must be available in the lpsolve55 directory. However older version of scilab (<=3.0) require that this file is called lpsolve55.ilib In that case copy lpsolve55.lib to lpsolve55.ilib
  2. Under Windows, the Microsoft Visual C/C++ compiler must be installed and the environment variables must be active so that when a command prompt is opened, the cl and nmake commands can be executed. This can be done also by opening a command prompt and execute the batch file VCVARS32.BAT (somewhere on your system) and then starting scilab from that same command prompt. Under Unix/Linux, the standard c compiler is used so no special things must be done.
  3. Start Scilab
  4. Check under Scilab that the current directory is the lpsolve directory. Use the Scilab pwd command to show the current directory. With the chdir command, you can change the current directory. This current directory must be lp_solve_5.5/extra/scilab/lpsolve example: chdir('d:/lp_solve/lp_solve_5.5/extra/scilab/lpsolve')
  5. To compile and build sclpsolve, enter the following command in Scilab: -->exec builder.sce This should be done once to build the sclpsolve driver and to produce the file loader.sce.
Load the sclpsolve driver in the Scilab memory space: -----------------------------------------------------
  1. Under Windows, make sure that the lpsolve55.dll file is somewhere in the path Under Unix/Linux, make sure that the liblpsolve55.so shared library is in /usr/lib or /lib so that Unix can find it. They are in archives lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz and were installed in the lp_solve_5.5 directory of step 1 of the previous procedure.
  2. It is required that the sclpsolve driver is first build. That must be done only once. So if you haven't taken the steps yet to build the sclpsolve driver, then do this first as described previously in 'Compile and build sclpsolve'
  3. Start Scilab
  4. Check under Scilab that the current directory is the lpsolve directory. Use the Scilab pwd command to show the current directory. With the chdir command, you can change the current directory. This current directory must be lp_solve_5.5/extra/scilab/lpsolve example: chdir('/lp_solve/lp_solve_5.5/extra/scilab/lpsolve')
  5. Enter the following command in Scilab: -->exec loader.sce

Installation

To make this possible, a driver program is needed: sclpsolve (sclpsolve.dll under Windows, sclpsolve.a under Unix/Linux). This driver must be put in a directory known to Scilab and Scilab can call the sclpsolve solver.

This driver calls lpsolve via the lpsolve shared library (lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux) (in archive lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). This has the advantage that the sclpsolve driver doesn't have to be recompiled when an update of lpsolve is provided. For Windows, the lpsolve55.dll file must be somewhere in the path. For Unix, the lpsolve shared library (liblpsolve55.so) must be in the /usr/lib or /lib directory.

So note the difference between the Scilab lpsolve driver that is called sclpsolve and the lpsolve library that implements the API that is called lpsolve55.

There are also some Scilab script files (*.sce, *.sci) as a quick start.

The first thing that must be done, each time Scilab is restarted and you want to use lpsolve is load the sclpsolve driver into the Scilab workspace. This can be done via the script loader.sce. The following command must be used to load the driver:

exec loader.sce

It is assumed here that the current directory is the Scilab lpsolve directory (lp_solve_5.5/extra/scilab/lpsolve), but this is not a requirement. You can also provide the full path to the script files. The current directory can be shown via the pwd command in Scilab:

pwd

That is basically all you need to do. From now on, you can use the library. This until Scilab is restarted. Then this command must be given again to reload the library.

To make things easier, you can edit the file scilab.star with your favourite editor (or notepad/vi) in the Scilab directory and add above line at the end of this file. That will automatically load the lpsolve driver in memory when Scilab is started. So it will appear as if the sclpsolve command is then always available.

If you get an error similar to below, then probably the lpsolve library can not be found:

link failed for dll c:\lp_solve\lp_solve_5.5\extra\scilab\lpsolve\libs\sclpsolve.dll
addinter(liblpmex,'lpmex_gateway','sclpsolve')
                                               !--error   236
link: the shared archive was not loaded

Under Windows, the lpsolve55.dll file must be in one of the directories specified by the PATH environment variable. This path can be seen in Scilab via the command getenv("PATH"). It is common to place dlls in the WINDOWS\system32 folder.

Under Unix/Linux, the liblpsolve55.so file must be in the directory /usr/lib or /lib.

To test if everything is installed correctly, enter sclpsolve() in the Scilab command window. If it gives the following, then everything is ok:

sclpsolve  scilab Interface version 5.5.0.6
using lpsolve version 5.5.0.15

Usage: [ret1, ret2, ...] = sclpsolve('functionname', arg1, arg2, ...)

All this is developed and tested with Scilab versions 2.7 and 3.0 both under Windows and Linux (RedHat).

Solve an lp model from Scilab via sclpsolve

In the following text, --> before the Scilab commands is the Scilab prompt. Only the text after --> must be entered.

To call an lpsolve function, the following syntax must be used:

-->[ret1, ret2, ...] = sclpsolve('functionname', arg1, arg2, ...)

The return values are optional and depend on the function called. functionname must always be enclosed between (single or double) quotes to make it alphanumerical and it is case sensitive. The number and type of arguments depend on the function called. Some functions even have a variable number of arguments and a different behaviour occurs depending on the type of the argument. functionname can be (almost) any of the lpsolve API routines (see lp_solve API reference) plus some extra Scilab specific functions. Most of the lpsolve API routines use or return an lprec structure. To make things more robust in Scilab, this structure is replaced by a handle or the model name. The lprec structures are maintained internally by the lpsolve driver. The handle is an incrementing number starting from 0. Starting from driver version 5.5.0.2, it is also possible to use the model name instead of the handle. This can of course only be done if a name is given to the model. This is done via lpsolve routine set_lp_name or by specifying the model name in routine read_lp. See Using model name instead of handle.

Almost all callable functions can be found in the lp_solve API reference. Some are exactly as described in the reference guide, others have a slightly different syntax to make maximum use of the Scilab functionality. For example make_lp is used identical as described. But get_variables is slightly different. In the API reference, this function has two arguments. The first the lp handle and the second the resulting variables and this array must already be dimensioned. When lpsolve is used from Scilab, nothing must be dimensioned in advance. The sclpsolve driver takes care of dimensioning all return variables and they are always returned as return value of the call to sclpsolve. Never as argument to the routine. This can be a single value as for get_objective (although Scilab stores this in a 1x1 matrix) or a matrix or vector as in get_variables. In this case, get_variables returns a 4x1 matrix (vector) with the result of the 4 variables of the lp model.

Note that you can get an overview of the available functionnames and their arguments by entering the following in Scilab:

-->help sclpsolve

An example

(Note that you can execute this example by entering command per command as shown below or by just entering exec example1.sce. This will execute example1.sce.)

-->lp=sclpsolve('make_lp', 0, 4);
-->sclpsolve('set_verbose', lp, 3);
-->sclpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
-->sclpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
-->sclpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
-->sclpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);
-->sclpsolve('set_lowbo', lp, 1, 28.6);
-->sclpsolve('set_lowbo', lp, 4, 18);
-->sclpsolve('set_upbo', lp, 4, 48.98);
-->sclpsolve('set_col_name', lp, 1, 'COLONE');
-->sclpsolve('set_col_name', lp, 2, 'COLTWO');
-->sclpsolve('set_col_name', lp, 3, 'COLTHREE');
-->sclpsolve('set_col_name', lp, 4, 'COLFOUR');
-->sclpsolve('set_row_name', lp, 1, 'THISROW');
-->sclpsolve('set_row_name', lp, 2, 'THATROW');
-->sclpsolve('set_row_name', lp, 3, 'LASTROW');
-->sclpsolve('write_lp', lp, 'a.lp');
-->sclpsolve('get_mat', lp, 1, 2)
 ans  =

    78.26

-->sclpsolve('solve', lp)
 ans  =

     0.

-->sclpsolve('get_objective', lp)
 ans  =

   31.782759

-->sclpsolve('get_variables', lp)
 ans  =

!   28.6      !
!   0.        !
!   0.        !
!   31.827586 !

-->sclpsolve('get_constraints', lp)
 ans  =

!   92.3      !
!   6.864     !
!   391.29283 !

Note that there are some commands that return an answer. To see the answer, the command was not terminated with a semicolon (;). If the semicolon is put at the end of a command, the answer is not shown. However it is also possible to write the answer in a variable. For example:

-->obj=sclpsolve('get_objective', lp)
 obj  =

    31.782759

Or without echoing on screen:

-->obj=sclpsolve('get_objective', lp);

The last command will only write the result in variable obj without showing anything on screen. get_variables and get_constraints return a vector with the result. This can also be put in a variable:

-->x=sclpsolve('get_variables', lp);

-->b=sclpsolve('get_constraints', lp);

It is always possible to show the contents of a variable by just giving it as command:

-->x

 x  =
!   28.6      !
!   0.        !
!   0.        !
!   31.827586 !

Don't forget to free the handle and its associated memory when you are done:

-->sclpsolve('delete_lp', lp);

Using model name instead of handle

From driver version 5.5.0.2, it is possible to use the model name instead of the handle. From the moment the model has a name, you can use this name instead of the handle. This is best shown by an example. Above example would look like this:
-->lp=sclpsolve('make_lp', 0, 4);
-->sclpsolve('set_lp_name', lp, 'mymodel');
-->sclpsolve('set_verbose', 'mymodel', 3);
-->sclpsolve('set_obj_fn', 'mymodel', [1, 3, 6.24, 0.1]);
-->sclpsolve('add_constraint', 'mymodel', [0, 78.26, 0, 2.9], 2, 92.3);
-->sclpsolve('add_constraint', 'mymodel', [0.24, 0, 11.31, 0], 1, 14.8);
-->sclpsolve('add_constraint', 'mymodel', [12.68, 0, 0.08, 0.9], 2, 4);
-->sclpsolve('set_lowbo', 'mymodel', 1, 28.6);
-->sclpsolve('set_lowbo', 'mymodel', 4, 18);
-->sclpsolve('set_upbo', 'mymodel', 4, 48.98);
-->sclpsolve('set_col_name', 'mymodel', 1, 'COLONE');
-->sclpsolve('set_col_name', 'mymodel', 2, 'COLTWO');
-->sclpsolve('set_col_name', 'mymodel', 3, 'COLTHREE');
-->sclpsolve('set_col_name', 'mymodel', 4, 'COLFOUR');
-->sclpsolve('set_row_name', 'mymodel', 1, 'THISROW');
-->sclpsolve('set_row_name', 'mymodel', 2, 'THATROW');
-->sclpsolve('set_row_name', 'mymodel', 3, 'LASTROW');
-->sclpsolve('write_lp', 'mymodel', 'a.lp');
-->sclpsolve('get_mat', 'mymodel', 1, 2)
 ans  =

    78.26

-->sclpsolve('solve', 'mymodel')
 ans  =

     0.

-->sclpsolve('get_objective', 'mymodel')
 ans  =

   31.782759

-->sclpsolve('get_variables', 'mymodel')
 ans  =

!   28.6      !
!   0.        !
!   0.        !
!   31.827586 !

-->sclpsolve('get_constraints', 'mymodel')
 ans  =

!   92.3      !
!   6.864     !
!   391.29283 !

So everywhere a handle is needed, you can also use the model name. You can even mix the two methods. There is also a specific Scilab routine to get the handle from the model name: get_handle.
For example:

-->sclpsolve('get_handle', 'mymodel')
0

Don't forget to free the handle and its associated memory when you are done:

-->sclpsolve('delete_lp', 'mymodel');

In the next part of this documentation, the handle is used. But if you name the model, the name could thus also be used.

Matrices

In Scilab, all numerical data is stored in matrices; even a scalar variable. Scilab also supports complex numbers (a + b * %i with %i=SQRT(-1)). sclpsolve can only work with real numbers. Scilab also supports sparse matrices. Sparse matrices are matrices where only the non-zero elements are provided and stored. This results in both less storage and faster calculation if there are a sufficient number of zero values in the matrix and there usually are. The sclpsolve driver supports both dense and sparse matrices and their use is totally transparent to the user. Everywhere a matrix can be provided, it can be dense or sparse. However, Scilab requires for interface programs that sparse matrixes are converted to MATLAB sparse matrices via the function mtlb_sparse(mat). In the above example all matrices were dense. For example:
-->sclpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);

In sparse matrix notation, this can be written:

-->sclpsolve('add_constraint', lp, mtlb_sparse(sparse([0.24, 0, 11.31, 0])), 1, 14.8);

Most of the time, variables are used to provide the data:

-->sclpsolve('add_constraint', lp, a1, 1, 14.8);

Where a1 is a dense matrix variable. A sparse matrix is then provided as follows:

-->sclpsolve('add_constraint', lp, mtlb_sparse(a1), 1, 14.8);

The sclpsolve driver sees all provided matrices as sparse matrices. sclpsolve also uses sparse matrices internally and data can be provided sparse via the ex routines. For example add_constraintex. The sclpsolve driver always uses the ex routines to provide the data to lpsolve. Even if you call from Scilab the routine names that would require a dense matrix (for example add_constraint), the sclpsolve driver will always call the sparse version of the routine (for example add_constraintex). This results in the most performing behaviour. Note that if a dense matrix is provided, the dimension must exactly match the dimension that is expected by sclpsolve. Matrices with too few or too much elements gives an 'invalid vector.' error. Sparse matrices can off course provide less elements (the non provided elements are seen as zero). However if too many elements are provided or an element with a too large index, again an 'invalid vector.' error is raised.

Most of the time, sclpsolve needs vectors (rows or columns). In all situations, it doesn't matter if the vectors are row or column vectors. The driver accepts them both. For example:

-->sclpsolve('add_constraint', lp, [0.24; 0; 11.31; 0], 1, 14.8);

Which is a column vector, but it is also accepted.

An important final note. Several lp_solve API routines accept a vector where the first element (element 0) is not used. Other lp_solve API calls do use the first element. In the Scilab interface, there is never an unused element in the matrices. So if the lp_solve API specifies that the first element is not used, then this element is not in the Scilab matrix.

Sets

All numerical data is stored in matrices. Alphanumerical data, however, is more difficult to store in matrices. Matrices require that each element has the same size (length) and that is difficult and unpractical for alphanumerical data. In a limited number of lpsolve routines, alphanumerical data is required or returned and in some also multiple elements. An example is set_col_name. For this, Scilab sets are used.
To specify a set of alphanumerical elements, the following notation is used: cellstr([element1; element1; ...]).
Note the cellstr() function and the ; between each element.
An alternative is the Scilab makecell() function. For example makecell([1,3], element1, element2, element3).
Another alternative is the Scilab cell() function. For example x=cell(1,3); x(1).entries=element1; x(2).entries=element2; x(3).entries=element3

Don't forget that a set of strings must be provided. Don't make the mistake of using the syntax {element1, element2, ...} because then the following error occurs:

                                                                           !--error  9999
Invalid string matrix (at most one column!)
                                                                           !--error   999
SIGSTP: aborting current computation

And also not {element1; element2; ...} because then the following error is given:

                                                                           !--error  9999
invalid vector
                                                                           !--error   999
SIGSTP: aborting current computation

This is not an error generated by the sclpsolve driver, but from the Scilab parser because both are not sets.

Maximum usage of matrices/sets with sclpsolve

Because Scilab is all about matrices, all lpsolve API routines that need a column or row number to get/set information for that column/row are extended in the sclpsolve Scilab driver to also work with matrices. For example set_int in the API can only set the integer status for one column. If the status for several integer variables must be set, then set_int must be called multiple times. The sclpsolve Scilab driver however also allows specifying a vector to set the integer status of all variables at once. The API call is: return = sclpsolve('set_int', lp, column, must_be_int). The matrix version of this call is: return = sclpsolve('set_int', lp, [must_be_int]). The API call to return the integer status of a variable is: return = sclpsolve('is_int', lp, column). The matrix version of this call is: [is_int] = sclpsolve('is_int', lp)
Also note the get_mat and set_mat routines. In Scilab these are extended to return/set the complete constraint matrix. See following example.

Above example can thus also be done as follows:
(Note that you can execute this example by entering command per command as shown below or by just entering exec example2.sce. This will execute example2.sce.)

-->lp=sclpsolve('make_lp', 0, 4);
-->sclpsolve('set_verbose', lp, 3);
-->sclpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
-->sclpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
-->sclpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
-->sclpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);
-->sclpsolve('set_lowbo', lp, [28.6, 0, 0, 18]);
-->sclpsolve('set_upbo', lp, [%inf, %inf, %inf, 48.98]);
-->sclpsolve('set_col_name', lp, cellstr(['COLONE';'COLTWO';'COLTHREE';'COLFOUR']));
-->sclpsolve('set_row_name', lp, cellstr(['THISROW';'THATROW';'LASTROW']));
-->sclpsolve('write_lp', lp, 'a.lp');
-->sclpsolve('get_mat', lp)
 ans  =

!   0.       78.26    0.       2.9 !
!    .24     0.       11.31    0.  !
!   12.68    0.        .08      .9 !

-->sclpsolve('solve', lp)
 ans  =

    0.

-->sclpsolve('get_objective', lp)
 ans  =

    31.782759

-->sclpsolve('get_variables', lp)
 ans  =

!   28.6      !
!   0.        !
!   0.        !
!   31.827586 !

-->sclpsolve('get_constraints', lp)
 ans  =

!   92.3      !
!   6.864     !
!   391.29283 !

Note the usage of %inf in set_upbo. This stands for 'infinity'. Meaning an infinite upper bound. It is also possible to use -%inf to express minus infinity. This can for example be used to create a free variable.

Starting from driver version 5.5.0.3, get_mat can also return the matrix in sparse format. By default the function returns it in dense format for backwards compatibility. However if a 3rd argument is provided that is non-zero, the returned matrix is sparse:

-->sclpsolve('get_mat', lp, 1)
 ans  =

(3,    4) m sparse matrix

(2,    1)         .24
(3,    1)        12.68
(1,    2)        78.26
(2,    3)        11.31
(3,    3)         .08
(1,    4)        2.9
(3,    4)         .9

To show the full power of the matrices, let's now do some matrix calculations to check the solution. It works further on above example:

-->A=sclpsolve('get_mat', lp);

-->X=sclpsolve('get_variables', lp);

-->B = A * X
 B  =

!   92.3      !
!   6.864     !
!   391.29283 !

So what we have done here is calculate the values of the constraints (RHS) by multiplying the constraint matrix with the solution vector. Now take a look at the values of the constraints that lpsolve has found:

-->sclpsolve('get_constraints', lp)
 ans  =

!   92.3      !
!   6.864     !
!   391.29283 !

Exactly the same as the calculated B vector, as expected.

Also the value of the objective can be calculated in a same way:

-->C=sclpsolve('get_obj_fn', lp);

-->X=sclpsolve('get_variables', lp);

 obj  =

    31.782759

So what we have done here is calculate the value of the objective by multiplying the objective vector with the solution vector. Now take a look at the value of the objective that lpsolve has found:

-->sclpsolve('get_objective', lp)
 ans  =

   31.7828

Again exactly the same as the calculated obj value, as expected.

Using string constants

From driver version 5.5.0.15 on, it is possible to use string constants everywhere an lp_solve constant is needed or returned. This is best shown by an example. In the above code we had:
-->lp=sclpsolve('make_lp', 0, 4);
-->sclpsolve('set_verbose', lp, 3);
-->sclpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 2, 92.3);
-->sclpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8);
-->sclpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 2, 4);

Note the 3rd parameter on set_verbose and the 4th on add_constraint. These are lp_solve constants. One could define all the possible constants in Scilab and then use them in the calls, but that has several disadvantages. First there stays the possibility to provide a constant that is not intended for that particular call. Another issue is that calls that return a constant are still returning it numerical.

Both issues can now be handled by string constants. The above code can be done as following with string constants:

-->lp=sclpsolve('make_lp', 0, 4);
-->sclpsolve('set_verbose', lp, 'IMPORTANT');
-->sclpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 'GE', 92.3);
-->sclpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 'LE', 14.8);
-->sclpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 'GE', 4);

This is not only more readable, there is much lesser chance that mistakes are being made. The calling routine knows which constants are possible and only allows these. So unknown constants or constants that are intended for other calls are not accepted. For example:

-->sclpsolve('set_verbose', lp, 'blabla');

BLABLA: Unknown.

-->sclpsolve('set_verbose', lp, 'GE');

GE: Not allowed here.

Note the difference between the two error messages. The first says that the constant is not known, the second that the constant cannot be used at that place.

Constants are case insensitive. Internally they are always translated to upper case. Also when returned they will always be in upper case.

The constant names are the ones as specified in the documentation of each API routine. There are only 3 exceptions, extensions actually. 'LE', 'GE' and 'EQ' in add_constraint and is_constr_type can also be '<', '<=', '>', '>=', '='. When returned however, 'GE', 'LE', 'EQ' will be used.

Also in the matrix version of calls, string constants are possible (hm). For example:

-->sclpsolve('set_constr_type', lp, cellstr(['LE'; 'EQ'; 'GE']));

Some constants can be a combination of multiple constants. For example set_scaling:

-->sclpsolve('set_scaling', lp, 3+128);

With the string version of constants this can be done as following:

-->sclpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_INTEGERS');

| is the OR operator used to combine multiple constants. There may optinally be spaces before and after the |.

Not all OR combinations are legal. For example in set_scaling, a choice must be made between SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC or SCALE_CURTISREID. They may not be combined with each other. This is also tested:

-->sclpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_RANGE');

SCALE_RANGE cannot be combined with SCALE_MEAN

Everywhere constants must be provided, numeric or string values may be provided. The routine automatically interpretes them.

Returning constants is a different story. The user must let lp_solve know how to return it. Numerical or as string. The default is numerical:

-->sclpsolve('get_scaling', lp)
 ans  =

    131.

To let lp_solve return a constant as string, a call to a new function must be made: return_constants

-->sclpsolve('return_constants', 1);

From now on, all returned constants are returned as string:

-->sclpsolve('get_scaling', lp)
 ans  =

 SCALE_MEAN|SCALE_INTEGERS

Also when an array of constants is returned, they are returned as string when return_constants is set:

-->sclpsolve('get_constr_type', lp)
 ans  =


!"LE"  "EQ"  "GE"  !

This for all routines until return_constants is again called with 0:

-->sclpsolve('return_constants', 0);

The (new) current setting of return_constants is always returned by the call. Even when set:

-->sclpsolve('return_constants', 1)
 ans  =

    1.

To get the value without setting it, don't provide the second argument:

-->sclpsolve('return_constants')
 ans  =

    1.

In the next part of this documentation, return_constants is the default, 0, so all constants are returned numerical and provided constants are also numerical. This to keep the documentation as compatible as possible with older versions. But don't let you hold that back to use string constants in your code.

Script files

Scilab can execute a sequence of statements stored in diskfiles. Scilab has two kinds of these. The first kinds are ASCII files where Scilab commands are written in the same way as in the command window. These files normally have the extension .sce. These script files must be executed via the exec command. For example:

exec example1.sce

The second kinds are binary files. However the user enters the commands first in an ASCII file (normally with extension .sci) and then these are translated to binary files via the Scilab genlib command. The .sci files also may only contain Scilab commands. There are two advantages of using these. The first is that you don't have to use the exec command or provide the extension to execute them. So it is as if you execute a regular Scilab command. The second advantage is that they are somewhat faster.

The lpsolve distribution contains some sample .sce files that must be executed via exec and also some .sci high-level routines that can be executed without exec. They are already precompiled.

example1.sce

Contains the commands as shown in the first example of this article. Execute via exec example1.sce

example2.sce

Contains the commands as shown in the second example of this article. Execute via exec example2.sce

example3.sce

Contains the commands of a practical example. See further in this article.

example4.sce

Contains the commands of a practical example. See further in this article.

example5.sce

Contains the commands of a practical example. See further in this article.

example6.sce

Contains the commands of a practical example. See further in this article.

lp_solve.sci

This script uses the API to create a higher-level function called lp_solve. This function accepts as arguments some matrices and options to create and solve an lp model. See the beginning of the file or type help lp_solve to see its usage:

 LP_SOLVE  Solves mixed integer linear programming problems.

   SYNOPSIS: [obj,x,duals] = lp_solve(f,a,b,e,vlb,vub,xint,scalemode,keep)

      solves the MILP problem

              max v = f'*x
                a*x <> b
                  vlb <= x <= vub
                  x(int) are integer

   ARGUMENTS: The first four arguments are required:

            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) = -1  ==> Less Than
                      e(i) =  0  ==> Equals
                      e(i) =  1  ==> Greater Than
          vlb: n vector of lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
         keep: Flag for keeping the lp problem after it's been solved.
               If omitted, the lp will be deleted when solved.

   OUTPUT: A nonempty output is returned if a solution is found:

          obj: Optimal value of the objective function.
            x: Optimal value of the decision variables.
        duals: solution of the dual problem.

Example of usage. To create and solve following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

-->[obj, x]=lp_solve([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])
 x  =

!   1. !
!   2. !
 obj  =

    3.

Note that you can also provide sparse matrices to this function without having to use mtlb_sparse. The script is taking care of this.

lp_maker.sci

This script is analog to the lp_solve script and also uses the API to create a higher-level function called lp_maker. This function accepts as arguments some matrices and options to create an lp model. Note that this scripts only creates a model and returns a handle. See the beginning of the file or type help lp_maker or just lp_maker to see its usage:

-->help lp_maker

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            x >= vlb >= 0
            x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Example of usage. To create following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

-->lp=lp_maker([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])
 lp  =

    0.

To solve the model and get the solution:

-->sclpsolve('solve', lp)
 ans  =

    0.

-->sclpsolve('get_objective', lp)
 ans  =

    3.

-->sclpsolve('get_variables', lp)
 ans  =

!   1. !
!   2. !

Don't forget to free the handle and its associated memory when you are done:

-->sclpsolve('delete_lp', lp);

Note that you can also provide sparse matrices to this function without having to use mtlb_sparse. The script is taking care of this.

lpdemo.sce

Contains several examples to build and solve lp models. Execute via exec lpdemo.sce

ex.sce

Contains several examples to build and solve lp models. Also solves the lp_examples from the lp_solve distribution. Execute via exec ex.sce

A practical example

We shall illustrate the method of linear programming by means of a simple example, giving a combination graphical/numerical solution, and then solve both a slightly as well as a substantially more complicated problem.

Suppose a farmer has 75 acres on which to plant two crops: wheat and barley. To produce these crops, it costs the farmer (for seed, fertilizer, etc.) $120 per acre for the wheat and $210 per acre for the barley.The farmer has $15000 available for expenses. But after the harvest, the farmer must store the crops while awaiting favourable market conditions. The farmer has storage space for 4000 bushels.Each acre yields an average of 110 bushels of wheat or 30 bushels of barley. If the net profit per bushel of wheat (after all expenses have been subtracted) is $1.30 and for barley is $2.00, how should the farmer plant the 75 acres to maximize profit?

We begin by formulating the problem mathematically. First we express the objective, that is the profit, and the constraints algebraically, then we graph them, and lastly we arrive at the solution by graphical inspection and a minor arithmetic calculation.

Let x denote the number of acres allotted to wheat and y the number of acres allotted to barley. Then the expression to be maximized, that is the profit, is clearly

P = (110)(1.30)x + (30)(2.00)y = 143x + 60y.

There are three constraint inequalities, specified by the limits on expenses, storage and acreage. They are respectively:

120x + 210y <= 15000
110x + 30y <= 4000
x + y <= 75

Strictly speaking there are two more constraint inequalities forced by the fact that the farmer cannot plant a negative number of acres, namely:

x >= 0,y >= 0.

Next we graph the regions specified by the constraints. The last two say that we only need to consider the first quadrant in the x-y plane. Here's a graph delineating the triangular region in the first quadrant determined by the first inequality.

-->clear
-->X = 0.1:0.1:125;
-->Y1 = (15000. - 120*X)/210;
-->plot2d3(X, Y1)

Source

Now let's put in the other two constraint inequalities.

-->clear
-->X = 0.1:0.05:38;
-->Y1 = (15000. - 120*X)/210;
-->Y2 = max((4000 - 110.*X)./30, 0);
-->Y3 = max(75 - X, 0.);
-->Ytop = min(min(Y1, Y2), Y3);
-->plot2d3(X, Ytop)
-->xtitle("Solution space")

Source

The black area is the solution space that holds valid solutions. This means that any point in this area fulfils the constraints.

Now let's superimpose on top of this picture the objective function P.

-->X = 15:20:35;
-->plot2d(X, (6315.63 - 143.0 * X) / 60.0)
-->xtitle("Solution space and objective")

Source

The line gives a picture of the objective function. All solutions that intersect with the black area are valid solutions, meaning that this result also fulfils the set constraints. The more the line goes to the right, the higher the objective value is. The optimal solution or best objective is a line that is still in the black area, but with an as large as possible value (as shown here).

It seems apparent that the maximum value of P will occur on the level curve (that is, level line) that passes through the vertex of the polygon that lies near (22,53).
It is the intersection of x + y = 75 and 110*x + 30*y = 4000
This is a corner point of the diagram. This is not a coincidence. The simplex algorithm, which is used by lp_solve, starts from a theorem that the optimal solution is such a corner point.
In fact we can compute the result:

-->x = [1, 1; 110, 30] \ [75; 4000]
 x  =

!   21.875 !
!   53.125 !

The acreage that results in the maximum profit is 21.875 for wheat and 53.125 for barley. In that case the profit is:

-->P = [143, 60] * x
 P  =

    6315.625

That is, $6315.625.

Note that these command are in script example3.sce

Now, lp_solve comes into the picture to solve this linear programming problem more generally. After that we will use it to solve two more complicated problems involving more variables and constraints.

For this example, we use the higher-level script lp_maker to build the model and then some lp_solve API calls to retrieve the solution. Here is again the usage of lp_maker:

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            x >= vlb >= 0
            x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Now let's formulate this model with lp_solve:

-->f = [143, 60];
-->A = [120, 210; 110, 30; 1, 1];
-->b = [15000, 4000, 75];
-->lp = lp_maker(f, A, b, [-1, -1, -1], [], [], [], 1, 0);
-->solvestat = sclpsolve("solve", lp)
 solvestat  =

    0.

-->sclpsolve("get_objective", lp)
 ans  =

    6315.625

-->sclpsolve("get_variables", lp)
 ans  =

!   21.875 !
!   53.125 !

-->sclpsolve("delete_lp", lp);

Note that these command are in script example4.oms

With the higher-level script lp_maker, we provide all data to lp_solve. lp_solve returns a handle (lp) to the created model. Then the API call 'solve' is used to calculate the optimal solution of the model. The value of the objective function is retrieved via the API call 'get_objective' and the values of the variables are retrieved via the API call 'get_variables'. At last, the model is removed from memory via a call to 'delete_lp'. Don't forget this to free all memory allocated by lp_solve.

The solution is the same answer we obtained before. Note that the non-negativity constraints are accounted implicitly because variables are by default non-negative in lp_solve.

Well, we could have done this problem by hand (as shown in the introduction) because it is very small and it can be graphically presented.
Now suppose that the farmer is dealing with a third crop, say corn, and that the corresponding data is:

cost per acre$150.75
yield per acre125 bushels
profit per bushel$1.56

With three variables it is already a lot more difficult to show this model graphically. Adding more variables makes it even impossible because we can't imagine anymore how to represent this. We only have a practical understanding of 3 dimentions, but beyound that it is all very theorethical.

If we denote the number of acres allotted to corn by z, then the objective function becomes:

P = (110)(1.30)x + (30)(2.00)y+ (125)(1.56) = 143x + 60y + 195z

And the constraint inequalities are:

120x + 210y + 150.75z <= 15000
110x + 30y + 125z <= 4000
x + y + z <= 75
x >= 0,y >= 0, z >= 0

The problem is solved with lp_solve as follows:

-->f = [143, 60, 195];
-->A = [120, 210, 150.75; 110, 30, 125; 1, 1, 1];
-->b = [15000, 4000, 75];
-->lp = lp_maker(f, A, b, [-1, -1, -1], [], [], [], 1, 0);
-->solvestat = sclpsolve("solve", lp)
 solvestat  =

    0.

-->sclpsolve("get_objective", lp)
 ans  =

    6986.8421

-->sclpsolve("get_variables", lp)
 ans  =

!  0.        !
!  56.578947 !
!  18.421053 !

-->sclpsolve("delete_lp", lp);

Note that these command are in script example5.oms

So the farmer should ditch the wheat and plant 56.5789 acres of barley and 18.4211 acres of corn.

There is no practical limit on the number of variables and constraints that Scilab can handle. Certainly none that the relatively unsophisticated user will encounter.Indeed, in many true applications of the technique of linear programming, one needs to deal with many variables and constraints.The solution of such a problem by hand is not feasible, and software like Scilab is crucial to success.For example, in the farming problem with which we have been working, one could have more crops than two or three. Think agribusiness instead of family farmer.And one could have constraints that arise from other things beside expenses, storage and acreage limitations. For example:

  • Availability of seed.This might lead to constraint inequalities like xj < k.
  • Personal preferences. Thus the farmer's spouse might have a preference for one variety over another and insist on a corresponding planting, or something similar with a collection of crops; thus constraint inequalities like xi < xj or x1 + x2 > x3.
  • Government subsidies. It may take a moment's reflection on the reader's part, but this could lead to inequalities like xj > k.

Below is a sequence of commands that solves exactly such a problem. You should be able to recognize the objective expression and the constraints from the data that is entered. But as an aid, you might answer the following questions:

  • How many crops are under consideration?
  • What are the corresponding expenses? How much is available for expenses?
  • What are the yields in each case? What is the storage capacity?
  • How many acres are available?
  • What crops are constrained by seed limitations? To what extent?
  • What about preferences?
  • What are the minimum acreages for each crop?
-->f = [110*1.3, 30*2.0, 125*1.56, 75*1.8, 95*.95, 100*2.25, 50*1.35];
-->A = [120,210,150.75,115,186,140,85;110,30,125,75,95,100,50;1,1,1,1,1,1,1;
           1,-1,0,0,0,0,0;0,0,1,0,-2,0,0;0,0,0,-1,0,-1,1];
-->b = [55000, 40000, 400, 0, 0, 0];
-->lp = lp_maker(f, A, b, [-1,-1,-1,-1,-1,-1],[10,10,10,10,20,20,20],[100,%inf,50,%inf,%inf,250,%inf],[],1,0);
-->solvestat = sclpsolve("solve", lp)
 solvestat  =

    0.

-->sclpsolve("get_objective", lp)
 ans  =

    75398.043

-->sclpsolve("get_variables", lp)
 ans  =

!   10.       !
!   10.       !
!   40.       !
!   45.652174 !
!   20.       !
!   250.      !
!   20.       !

-->sclpsolve("delete_lp", lp);

Note that these command are in script example6.oms

Note that we have used in this formulation the vlb and vub arguments of lp_maker. This to set lower and upper bounds on variables. This could have been done via extra constraints, but it is more performant to set bounds on variables. Also note that %inf is used for variables that have no upper limit. This stands for Infinity.

Note that despite the complexity of the problem, lp_solve solves it almost instantaneously. It seems the farmer should bet the farm on crop number 6.We strongly suggest you alter the expense and/or the storage limit in the problem and see what effect that has on the answer.

Another, more theoretical, example

Suppose we want to solve the following linear program using Scilab:

max 4x1 + 2x2 + x3
s. t. 2x1 + x2 <= 1
x1 + 2x3 <= 2
x1 + x2 + x3 = 1
x1 >= 0
x1 <= 1
x2 >= 0
x2 <= 1
x3 >= 0
x3 <= 2

Convert the LP into Scilab format we get:

f = [4, 2, 1]
A = [2, 1, 0; 1, 0, 2; 1, 1, 1]
b = [1, 2, 1]

Note that constraints on single variables are not put in the constraint matrix. lp_solve can set bounds on individual variables and this is more performant than creating additional constraints. These bounds are:

l = [ 0, 0, 0]
u = [ 1, 1, 2]

Now lets enter this in Scilab:

-->f = [4, 2, 1];
-->A = [2, 1, 0; 1, 0, 2; 1, 1, 1];
-->b = [1, 2, 1];
-->l = [ 0, 0, 0];
-->u = [ 1, 1, 2];

Now solve the linear program using Scilab: Type the commands

-->lp = lp_maker(f, A, b, [-1, -1, -1], l, u, [], 1, 0);
-->solvestat = sclpsolve("solve", lp)
 solvestat  =

    0.

-->sclpsolve("get_objective", lp)
 ans  =

    2.5

-->sclpsolve("get_variables", lp)
 ans  =

!   0.5 !
!   0.  !
!   0.5 !

-->sclpsolve("delete_lp", lp)

What to do when some of the variables are missing ?
For example, suppose there are no lower bounds on the variables. In this case define l to be the empty set using the Scilab command:

-->l = [];

This has the same effect as before, because lp_solve has as default lower bound for variables 0.

But what if you want that variables may also become negative?
Then you can use -%inf as lower bounds:

-->l = [-%inf, -%inf, -%inf];

Solve this and you get a different result:

-->lp = lp_maker(f, A, b, [-1, -1, -1], l, u, [], 1, 0);
-->solvestat = sclpsolve("solve", lp)
 solvestat  =

    0.

-->sclpsolve("get_objective", lp)
 ans  =

    2.6666667

-->sclpsolve("get_variables", lp)
 ans  =

!   0.6666667 !
! - 0.3333333 !
!   0.6666667 !

-->sclpsolve("delete_lp", lp)

Overview of API routines

Note that everwhere where lp is used as argument that this can be a handle (lp_handle) or the models name.

  • add_column, add_columnex
    • return = sclpsolve('add_column', lp, [column])
    • return = sclpsolve('add_columnex', lp, [column])
    • Both have the same interface from add_column but act as add_columnex
  • add_constraint, add_constraintex
    • return = sclpsolve('add_constraint', lp, [row], constr_type, rh)
    • return = sclpsolve('add_constraintex', lp, [row], constr_type, rh)
    • Both have the same interface from add_constraint but act as add_constraintex
  • add_SOS
    • return = sclpsolve('add_SOS', lp, name, sostype, priority, [sosvars], [weights])
    • The count argument in the API documentation is not needed in Scilab since the number of elements is derived from the size of the sosvars and weights matrices. These must have the same size.
  • column_in_lp
    • return = sclpsolve('column_in_lp', lp, [column])
    • No special considerations.
  • copy_lp
    • lp_handle = sclpsolve('copy_lp', lp)
    • No special considerations.
  • default_basis
    • sclpsolve('default_basis', lp)
    • No special considerations.
  • del_column
    • return = sclpsolve('del_column', lp, column)
    • No special considerations.
  • del_constraint
    • return = sclpsolve('del_constraint', lp, del_row)
    • No special considerations.
  • delete_lp
    • sclpsolve('delete_lp', lp)
    • No special considerations.
  • free_lp
    • sclpsolve('free_lp', lp)
    • lp is not changed as in the lpsolve API since it is a read_only input parameter. So it acts the same as delete_lp.
  • get_anti_degen
    • return = sclpsolve('get_anti_degen', lp)
    • No special considerations.
  • get_basis
    • [bascolumn] = sclpsolve('get_basis', lp {, nonbasic})
    • The bascolumn argument in the API documentation is here the return value. The nonbasic argument is optional in Scilab. If not provided, then 0 is used.
  • get_basiscrash
    • return = sclpsolve('get_basiscrash', lp)
    • No special considerations.
  • get_bb_depthlimit
    • return = sclpsolve('get_bb_depthlimit', lp)
    • No special considerations.
  • get_bb_floorfirst
    • return = sclpsolve('get_bb_floorfirst', lp)
    • No special considerations.
  • get_bb_rule
    • return = sclpsolve('get_bb_rule', lp)
    • No special considerations.
  • get_bounds_tighter
    • return = sclpsolve('get_bounds_tighter', lp)
    • No special considerations.
  • get_break_at_value
    • return = sclpsolve('get_break_at_value', lp)
    • No special considerations.
  • get_col_name
    • name = sclpsolve('get_col_name', lp, column)
    • [names] = sclpsolve('get_col_name', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_column get_columnex
    • [column, return] = sclpsolve('get_column', lp, col_nr)
    • [column, return] = sclpsolve('get_columnex', lp, col_nr)
    • The column argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_constr_type
    • return = sclpsolve('get_constr_type', lp, row)
    • [constr_type] = sclpsolve('get_constr_type', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_constr_value
    • return = sclpsolve('get_constr_value', lp, row {, primsolution})
    • The primsolution argument is optional. If not provided, then the solution of last solve is used.
  • get_constraints
    • [constr, return] = sclpsolve('get_constraints', lp)
    • The constr argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_dual_solution
    • [duals, return] = sclpsolve('get_dual_solution', lp)
    • The duals argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_epsb
    • return = sclpsolve('get_epsb', lp)
    • No special considerations.
  • get_epsd
    • return = sclpsolve('get_epsd', lp)
    • No special considerations.
  • get_epsel
    • return = sclpsolve('get_epsel', lp)
    • No special considerations.
  • get_epsint
    • return = sclpsolve('get_epsint', lp)
    • No special considerations.
  • get_epsperturb
    • return = sclpsolve('get_epsperturb', lp)
    • No special considerations.
  • get_epspivot
    • return = sclpsolve('get_epspivot', lp)
    • No special considerations.
  • get_improve
    • return = sclpsolve('get_improve', lp)
    • No special considerations.
  • get_infinite
    • return = sclpsolve('get_infinite', lp)
    • No special considerations.
  • get_lowbo
    • return = sclpsolve('get_lowbo', lp, column)
    • [return] = sclpsolve('get_lowbo', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_lp_index
    • return = sclpsolve('get_lp_index', lp, orig_index)
    • No special considerations.
  • get_lp_name
    • name = sclpsolve('get_lp_name', lp)
    • No special considerations.
  • get_mat
    • value = sclpsolve('get_mat', lp, row, col)
    • [matrix, return] = sclpsolve('get_mat', lp[, sparse])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix in the first return value. If sparse is different from zero then the returned matrix is a sparse matrix. The return code of the call is the second return value.
  • get_max_level
    • return = sclpsolve('get_max_level', lp)
    • No special considerations.
  • get_maxpivot
    • return = sclpsolve('get_maxpivot', lp)
    • No special considerations.
  • get_mip_gap
    • return = sclpsolve('get_mip_gap', lp, absolute)
    • No special considerations.
  • get_nameindex
    • return = sclpsolve('get_nameindex', lp, name, isrow)
    • No special considerations.
  • get_Ncolumns
    • return = sclpsolve('get_Ncolumns', lp)
    • No special considerations.
  • get_negrange
    • return = sclpsolve('get_negrange', lp)
    • No special considerations.
  • get_nonzeros
    • return = sclpsolve('get_nonzeros', lp)
    • No special considerations.
  • get_Norig_columns
    • return = sclpsolve('get_Norig_columns', lp)
    • No special considerations.
  • get_Norig_rows
    • return = sclpsolve('get_Norig_rows', lp)
    • No special considerations.
  • get_Nrows
    • return = sclpsolve('get_Nrows', lp)
    • No special considerations.
  • get_obj_bound
    • return = sclpsolve('get_obj_bound', lp)
    • No special considerations.
  • get_objective
    • return = sclpsolve('get_objective', lp)
    • No special considerations.
  • get_orig_index
    • return = sclpsolve('get_orig_index', lp, lp_index)
    • No special considerations.
  • get_origcol_name
    • name = sclpsolve('get_origcol_name', lp, column)
    • [names] = sclpsolve('get_origcol_name', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_origrow_name
    • name = sclpsolve('get_origrow_name', lp, row)
    • [names] = sclpsolve('get_origrow_name', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_pivoting
    • return = sclpsolve('get_pivoting', lp)
    • No special considerations.
  • get_presolve
    • return = sclpsolve('get_presolve', lp)
    • No special considerations.
  • get_presolveloops
    • return = sclpsolve('get_presolveloops', lp)
    • No special considerations.
  • get_primal_solution
    • [pv, return] = sclpsolve('get_primal_solution', lp)
    • The pv argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_print_sol
    • return = sclpsolve('get_print_sol', lp)
    • No special considerations.
  • get_ptr_constraints
    • Not implemented.
  • get_ptr_dualsolution
    • Not implemented.
  • get_ptr_primal_solution
    • Not implemented.
  • get_ptr_sensitivity_obj, get_ptr_sensitivity_objex
    • Not implemented.
  • get_ptr_sensitivity_rhs
    • Not implemented.
  • get_ptr_variables
    • Not implemented.
  • get_rh
    • return = sclpsolve('get_rh', lp, row)
    • [rh] = sclpsolve('get_rh', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_rh_range
    • return = sclpsolve('get_rh_range', lp, row)
    • [rh_ranges] = sclpsolve('get_rh_range', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_row get_rowex
    • [row, return] = sclpsolve('get_row', lp, row_nr)
    • [row, return] = sclpsolve('get_rowex', lp, row_nr)
    • The row argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_row_name
    • name = sclpsolve('get_row_name', lp, row)
    • [names] = sclpsolve('get_row_name', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_scalelimit
    • return = sclpsolve('get_scalelimit', lp)
    • No special considerations.
  • get_scaling
    • return = sclpsolve('get_scaling', lp)
    • No special considerations.
  • get_sensitivity_obj, get_sensitivity_objex
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = sclpsolve('get_sensitivity_obj', lp)
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = sclpsolve('get_sensitivity_objex', lp)
    • The objfrom, objtill, objfromvalue, objtillvalue arguments in the API documentation are here the return values. Note that Scilab allows the return of fewer variables. For example if only objfrom and objtill are needed then the call can be [objfrom, objtill] = sclpsolve('get_sensitivity_obj', lp). The unrequested values are even not calculated.
    • Since the API routine doesn't calculate the objtillvalue value at this time, Scilab always returns a zero vector for this.
    • The return code of the call is the last value.
    • get_sensitivity_obj and get_sensitivity_objex are both implemented, but have the same functionality.
  • get_sensitivity_rhs, get_sensitivity_rhsex
    • [duals, dualsfrom, dualstill, return] = sclpsolve('get_sensitivity_rhs', lp)
    • [duals, dualsfrom, dualstill, return] = sclpsolve('get_sensitivity_rhsex', lp)
    • The duals, dualsfrom, dualstill arguments in the API documentation are here the return values. Note that Scilab allows the return of fewer variables. For example if only duals is needed then the call can be [duals] = sclpsolve('get_sensitivity_rhs', lp). The unrequested values are even not calculated.
    • The return code of the call is the last value.
    • get_sensitivity_rhs and get_sensitivity_rhsex are both implemented, but have the same functionality.
  • get_simplextype
    • return = sclpsolve('get_simplextype', lp)
    • No special considerations.
  • get_solutioncount
    • return = sclpsolve('get_solutioncount', lp)
    • No special considerations.
  • get_solutionlimit
    • return = sclpsolve('get_solutionlimit', lp)
    • No special considerations.
  • get_status
    • return = sclpsolve('get_status', lp)
    • No special considerations.
  • get_statustext
    • return = sclpsolve('get_statustext', lp, statuscode)
    • No special considerations.
  • get_timeout
    • return = sclpsolve('get_timeout', lp)
    • No special considerations.
  • get_total_iter
    • return = sclpsolve('get_total_iter', lp)
    • No special considerations.
  • get_total_nodes
    • return = sclpsolve('get_total_nodes', lp)
    • No special considerations.
  • get_upbo
    • return = sclpsolve('get_upbo', lp, column)
    • [upbo] = sclpsolve('get_upbo', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_var_branch
    • return = sclpsolve('get_var_branch', lp, column)
    • [var_branch] = sclpsolve('get_var_branch', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_var_dualresult
    • return = sclpsolve('get_var_dualresult', lp, index)
    • No special considerations.
  • get_var_primalresult
    • return = sclpsolve('get_var_primalresult', lp, index)
    • No special considerations.
  • get_var_priority
    • return = sclpsolve('get_var_priority', lp, column)
    • [var_priority] = sclpsolve('get_var_priority', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • get_variables
    • [var, return] = sclpsolve('get_variables', lp)
    • The var argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_verbose
    • return = sclpsolve('get_verbose', lp)
    • No special considerations.
  • get_working_objective
    • return = sclpsolve('get_working_objective', lp)
    • No special considerations.
  • guess_basis
    • [basisvector, return] = sclpsolve('guess_basis', lp, [guessvector])
    • In the API, element 0 of guessvector is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
    • In the API, element 0 of basisvector is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
  • has_BFP
    • return = sclpsolve('has_BFP', lp)
    • No special considerations.
  • has_XLI
    • return = sclpsolve('has_XLI', lp)
    • No special considerations.
  • is_add_rowmode
    • return = sclpsolve('is_add_rowmode', lp)
    • No special considerations.
  • is_anti_degen
    • return = sclpsolve('is_anti_degen', lp, testmask)
    • No special considerations.
  • is_binary
    • return = sclpsolve('is_binary', lp, column)
    • [binary] = sclpsolve('is_binary', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • is_break_at_first
    • return = sclpsolve('is_break_at_first', lp)
    • No special considerations.
  • is_constr_type
    • return = sclpsolve('is_constr_type', lp, row, mask)
    • No special considerations.
  • is_debug
    • return = sclpsolve('is_debug', lp)
    • No special considerations.
  • is_feasible
    • return = sclpsolve('is_feasible', lp, [values] {, threshold})
    • The threshold argument is optional. When not provided, the value of get_epsint will be taken.
  • is_free is_unbounded
    • return = sclpsolve('is_free', lp, column)
    • return = sclpsolve('is_unbounded', lp, column)
    • [free] = sclpsolve('is_free', lp)
    • [free] = sclpsolve('is_unbounded', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • is_infinite
    • return = sclpsolve('is_infinite', lp, value)
    • No special considerations.
  • is_int
    • return = sclpsolve('is_int', lp, column)
    • [int] = sclpsolve('is_int', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • is_integerscaling
    • return = sclpsolve('is_integerscaling', lp)
    • No special considerations.
  • is_maxim
    • return = sclpsolve('is_maxim', lp)
    • No special considerations.
  • is_nativeBFP
    • return = sclpsolve('is_nativeBFP', lp)
    • No special considerations.
  • is_nativeXLI
    • return = sclpsolve('is_nativeXLI', lp)
    • No special considerations.
  • is_negative
    • return = sclpsolve('is_negative', lp, column)
    • [negative] = sclpsolve('is_negative', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • is_piv_mode
    • return = sclpsolve('is_piv_mode', lp, testmask)
    • No special considerations.
  • is_piv_rule
    • return = sclpsolve('is_piv_rule', lp, rule)
    • No special considerations.
  • is_presolve
    • return = sclpsolve('is_presolve', lp, testmask)
    • No special considerations.
  • is_scalemode
    • return = sclpsolve('is_scalemode', lp, testmask)
    • No special considerations.
  • is_scaletype
    • return = sclpsolve('is_scaletype', lp, scaletype)
    • No special considerations.
  • is_semicont
    • return = sclpsolve('is_semicont', lp, column)
    • [semicont] = sclpsolve('is_semicont', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • is_SOS_var
    • return = sclpsolve('is_SOS_var', lp, column)
    • [SOS_var] = sclpsolve('is_SOS_var', lp)
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Scilab matrix.
  • is_trace
    • return = sclpsolve('is_trace', lp)
    • No special considerations.
  • is_use_names
    • return = sclpsolve('is_use_names', lp, isrow)
    • No special considerations.
  • lp_solve_version
    • versionstring = sclpsolve('lp_solve_version')
    • The sclpsolve API routine returns the version information in 4 provided argument variables while the Scilab version returns the information as a string in the format major.minor.release.build
  • make_lp
    • lp_handle = sclpsolve('make_lp', rows, columns)
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
  • print_constraints
    • sclpsolve('print_constraints', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
    • The same information can also be obtained via sclpsolve('get_constraints', lp). This shows the result on screen.
  • print_debugdump
    • return = sclpsolve('print_debugdump', lp, filename)
    • No special considerations.
  • print_duals
    • sclpsolve('print_duals', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
    • The same information can be obtained via sclpsolve('get_dual_solution', lp). This shows the result on screen.
  • print_lp
    • sclpsolve('print_lp', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
  • print_objective
    • sclpsolve('print_objective', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
    • The same information can be obtained via sclpsolve('get_objective', lp). This shows the result on screen.
  • print_scales
    • sclpsolve('print_scales', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
  • print_solution
    • sclpsolve('print_solution', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
    • The same information can also be obtained via sclpsolve('get_variables', lp). This shows the result on screen.
  • print_str
    • sclpsolve('print_str', lp, str)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
  • print_tableau
    • sclpsolve('print_tableau', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Scilab (Windows) this means that the output is not shown.
  • put_abortfunc
    • Not implemented.
  • put_logfunc
    • Not implemented.
    • However, the sclpsolve driver sets a log function to redirect the output of lpsolve from stdout (which is not visible in Windows Scilab) to the command window of Scilab. As such, all reported output can be seen in Scilab. How much output is seen is controlled by the verbose level that can be defined by set_verbose or can be specified in the read_ routines.
  • put_msgfunc
    • Not implemented.
  • read_basis
    • [ret, info] = sclpsolve('read_basis', lp, filename)
    • No special considerations.
  • read_freemps, read_freeMPS
    • lp_handle = sclpsolve('read_freemps', filename {, options})
    • lp_handle = sclpsolve('read_freeMPS', filename {, options})
    • In the lpsolve API, read_freemps needs a FILE handle. In Scilab it needs the filename and thus acts the same as read_freeMPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_lp, read_LP
    • lp_handle = sclpsolve('read_lp', filename {, verbose {, lp_name}})
    • lp_handle = sclpsolve('read_LP', filename {, verbose {, lp_name}})
    • In the lpsolve API, read_lp needs a FILE handle. In Scilab it needs the filename and thus acts the same as read_LP.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not provided then NORMAL is used.
    • lp_name is optional. If not provided then no name is given to the model ('').
  • read_mps, read_MPS
    • lp_handle = sclpsolve('read_mps', filename {, options})
    • lp_handle = sclpsolve('read_MPS', filename {, options})
    • In the lpsolve API, read_mps needs a FILE handle. In Scilab it needs the filename and thus acts the same as read_MPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_params
    • return = sclpsolve('read_params', lp, filename {, options })
    • options is optional.
  • read_XLI
    • lp_handle = sclpsolve('read_XLI', xliname, modelname {, dataname {, options {, verbose}}}
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • dataname is optional. When not provided, '' (NULL) is taken. '' is taken as NULL.
    • options is optional. When not provided, '' is taken.
    • verbose is optional. If not specified, then NORMAL is used.
  • reset_basis
  • set_basisvar
    • sclpsolve('set_basisvar', lp, basisPos, enteringCol)
    • No special considerations.
  • set_add_rowmode
    • return = sclpsolve('set_add_rowmode', lp, turnon)
    • No special considerations.
  • set_anti_degen
    • sclpsolve('set_anti_degen', lp, anti_degen)
    • No special considerations.
  • set_basis
    • return = sclpsolve('set_basis', lp, [bascolumn], nonbasic)
    • In the API, element 0 of bascolumn is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
  • set_basiscrash
    • sclpsolve('set_basiscrash', lp, mode)
    • No special considerations.
  • set_bb_depthlimit
    • sclpsolve('set_bb_depthlimit', lp, bb_maxlevel)
    • No special considerations.
  • set_bb_floorfirst
    • sclpsolve('set_bb_floorfirst', lp, bb_floorfirst)
    • No special considerations.
  • set_bb_rule
    • sclpsolve('set_bb_rule', lp, bb_rule)
    • No special considerations.
  • set_BFP
    • return = sclpsolve('set_BFP', lp, filename)
    • No special considerations.
  • set_binary
    • return = sclpsolve('set_binary', lp, column, must_be_bin)
    • return = sclpsolve('set_binary', lp, [must_be_bin])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds
    • return = sclpsolve('set_bounds', lp, column, lower, upper)
    • return = sclpsolve('set_bounds', lp, [lower], [upper])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds_tighter
    • sclpsolve('set_bounds_tighter', lp, tighten)
    • No special considerations.
  • set_break_at_first
    • sclpsolve('set_break_at_first', lp, break_at_first)
    • No special considerations.
  • set_break_at_value
    • sclpsolve('set_break_at_value', lp, break_at_value)
    • No special considerations.
  • set_col_name
    • return = sclpsolve('set_col_name', lp, column, name)
    • return = sclpsolve('set_col_name', lp, [names])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_column, set_columnex
    • return = sclpsolve('set_column', lp, col_no, [column])
    • return = sclpsolve('set_columnex', lp, col_no, [column])
    • Both have the same interface from set_column but act as set_columnex
  • set_constr_type
    • return = sclpsolve('set_constr_type', lp, row, con_type)
    • return = sclpsolve('set_constr_type', lp, [con_type])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_debug
    • sclpsolve('set_debug', lp, debug)
    • No special considerations.
  • set_epsb
    • sclpsolve('set_epsb', lp, epsb)
    • No special considerations.
  • set_epsd
    • sclpsolve('set_epsd', lp, epsd)
    • No special considerations.
  • set_epsel
    • sclpsolve('set_epsel', lp, epsel)
    • No special considerations.
  • set_epsint
    • sclpsolve('set_epsint', lp, epsint)
    • No special considerations.
  • set_epslevel
    • sclpsolve('set_epslevel', lp, epslevel)
    • No special considerations.
  • set_epsperturb
    • sclpsolve('set_epsperturb', lp, epsperturb)
    • No special considerations.
  • set_epspivot
    • sclpsolve('set_epspivot', lp, epspivot)
    • No special considerations.
  • set_free set_unbounded
    • return = sclpsolve('set_free', lp, column)
    • return = sclpsolve('set_unbounded', lp, column)
    • No special considerations.
  • set_improve
    • sclpsolve('set_improve', lp, improve)
    • No special considerations.
  • set_infinite
    • sclpsolve('set_infinite', lp, infinite)
    • No special considerations.
  • set_int
    • return = sclpsolve('set_int', lp, column, must_be_int)
    • return = sclpsolve('set_int', lp, [must_be_int])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lowbo
    • return = sclpsolve('set_lowbo', lp, column, value)
    • return = sclpsolve('set_lowbo', lp, [values])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lp_name
    • return = sclpsolve('set_lp_name', lp, name)
    • In Scilab, when you name a model, this name can be used everywhere where lp is specified. This to access the model via the name instead of via a handle.
  • set_mat
    • return = sclpsolve('set_mat', lp, row, column, value)
    • return = sclpsolve('set_mat', lp, [matrix])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows to set the whole matrix (all rows/columns) at once. This is the most performant way to provide the constraint matrix. Consider using a Scilab sparse matrix for maximum performance and least memory usage. The matrix must be two-dimentional.
  • set_maxim
    • sclpsolve('set_maxim', lp)
    • No special considerations.
  • set_maxpivot
    • sclpsolve('set_maxpivot', max_num_inv)
    • No special considerations.
  • set_minim
    • sclpsolve('set_minim', lp)
    • No special considerations.
  • set_mip_gap
    • sclpsolve('set_mip_gap', lp, absolute, mip_gap)
    • No special considerations.
  • set_negrange
    • sclpsolve('set_negrange', negrange)
    • No special considerations.
  • set_obj
    • return = sclpsolve('set_obj', lp, column, value)
    • return = sclpsolve('set_obj', lp, [values])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables. It is then the same as set_obj_fn
  • set_obj_bound
    • sclpsolve('set_obj_bound', lp, obj_bound)
    • No special considerations.
  • set_obj_fn, set_obj_fnex
    • return = sclpsolve('set_obj_fn', lp, [row])
    • return = sclpsolve('set_obj_fnex', lp, [row])
    • Both have the same interface from set_obj_fn but act as set_obj_fnex
    • In the API, element 0 is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
  • set_outputfile
    • return = sclpsolve('set_outputfile', lp, filename)
    • In the API description it says that setting filename to NULL results in writing output back to stdout. In Scilab under Windows, output to stdout it not shown. However it results in closing the file. Use '' to have the effect of NULL.
  • set_outputstream
    • Not implemented.
  • set_pivoting
    • sclpsolve('set_pivoting', lp, pivoting)
    • No special considerations.
  • set_preferdual
    • sclpsolve('set_preferdual', lp, dodual)
    • No special considerations.
  • set_presolve
    • sclpsolve('set_presolve', lp, do_presolve {, maxloops})
    • The maxloops argument is optional in Scilab. If not provided, then infinite is used.
  • set_print_sol
    • sclpsolve('set_print_sol', lp, print_sol)
    • No special considerations.
  • set_rh
    • return = sclpsolve('set_rh', lp, row, value)
    • return = sclpsolve('set_rh', lp, [values])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows. Note that in this case, the value of row 0 is not specified in the matrix.
  • set_rh_range
    • return = sclpsolve('set_rh_range', lp, row, deltavalue)
    • return = sclpsolve('set_rh_range', lp, [deltavalues])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_rh_vec
    • sclpsolve('set_rh_vec', lp, [rh])
    • In the API, element 0 is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
  • set_row, set_rowex
    • return = sclpsolve('set_row', lp, row_no, [row])
    • return = sclpsolve('set_rowex', lp, row_no, [row])
    • Both have the same interface from set_row but act as set_rowex
    • In the API, element 0 is not used and values start from element 1. In Scilab, there is no unused element in the matrix.
  • set_row_name
    • return = sclpsolve('set_row_name', lp, row, name)
    • return = sclpsolve('set_row_name', lp, [names])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_scalelimit
    • sclpsolve('set_scalelimit', lp, scalelimit)
    • No special considerations.
  • set_scaling
    • sclpsolve('set_scaling', lp, scalemode)
    • No special considerations.
  • set_semicont
    • return = sclpsolve('set_semicont', lp, column, must_be_sc)
    • return = sclpsolve('set_semicont', lp, [must_be_sc])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_sense
    • sclpsolve('set_sense', lp, maximize)
    • No special considerations.
  • set_simplextype
    • sclpsolve('set_simplextype', lp, simplextype)
    • No special considerations.
  • set_solutionlimit
    • sclpsolve('set_solutionlimit', lp, simplextype)
    • No special considerations.
  • set_timeout
    • sclpsolve('set_timeout', lp, sectimeout)
    • No special considerations.
  • set_trace
    • sclpsolve('set_trace', lp, trace)
    • No special considerations.
  • set_upbo
    • return = sclpsolve('set_upbo', lp, column, value)
    • return = sclpsolve('set_upbo', lp, [values])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_use_names
    • sclpsolve('set_use_names', lp, isrow, use_names)
    • No special considerations.
  • set_var_branch
    • return = sclpsolve('set_var_branch', lp, column, branch_mode)
    • return = sclpsolve('set_var_branch', lp, [branch_mode])
    • In Scilab, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_weights
    • return = sclpsolve('set_var_weights', lp, [weights])
    • No special considerations.
  • set_verbose
    • sclpsolve('set_verbose', lp, verbose)
    • No special considerations.
  • set_XLI
    • return = sclpsolve('set_XLI', lp, filename)
    • No special considerations.
  • solve
    • result = sclpsolve('solve', lp)
    • No special considerations.
  • str_add_column
    • Not implemented.
  • str_add_constraint
    • Not implemented.
  • str_set_obj_fn
    • Not implemented.
  • str_set_rh_vec
    • Not implemented.
  • time_elapsed
    • return = sclpsolve('time_elapsed', lp)
    • No special considerations.
  • unscale
    • sclpsolve('unscale', lp)
    • No special considerations.
  • write_basis
    • sclpsolve('write_basis', lp, filename)
    • No special considerations.
  • write_freemps, write_freeMPS
    • return = sclpsolve('write_freemps', lp, filename)
    • return = sclpsolve('write_freeMPS', lp, filename)
    • In the lpsolve API, write_freeMPS needs a FILE handle. In Scilab it needs the filename and thus acts the same as write_freemps.
  • write_lp, write_LP
    • return = sclpsolve('write_lp', lp, filename)
    • return = sclpsolve('write_LP', lp, filename)
    • In the lpsolve API, write_LP needs a FILE handle. In Scilab it needs the filename and thus acts the same as write_lp.
  • write_mps, write_MPS
    • return = sclpsolve('write_mps', lp, filename)
    • return = sclpsolve('write_MPS', lp, filename)
    • In the lpsolve API, write_MPS needs a FILE handle. In Scilab it needs the filename and thus acts the same as write_mps.
    • No special considerations.
  • write_XLI
    • return = sclpsolve('write_XLI', lp, filename {, options {, results}})
    • No special considerations.

Extra Scilab routines

These routines are not part of the lpsolve API, but are added for backwards compatibility. Most of them exist in the lpsolve API with another name.

  • [names] = sclpsolve('get_col_names', lp)
    • The same as get_col_name. Implemented for backwards compatibility.
  • [constr_type] = sclpsolve('get_constr_types', lp)
    • The same as get_constr_type. Implemented for backwards compatibility.
  • [int] = sclpsolve('get_int', lp)
    • The same as is_int. Implemented for backwards compatibility.
  • return = sclpsolve('get_no_cols', lp)
    • The same as get_Ncolumns. Implemented for backwards compatibility.
  • return = sclpsolve('get_no_rows', lp)
    • The same as get_Nrows. Implemented for backwards compatibility.
  • name = sclpsolve('get_objective_name', lp)
    • The same as get_row_name with row=0. Implemented for backwards compatibility.
  • [row_vec, return] = sclpsolve('get_obj_fn', lp)
    [row_vec, return] = sclpsolve('get_obj_fun', lp)
    • The same as get_row with row 0. Implemented for backwards compatibility.
  • name = sclpsolve('get_problem_name', lp)
    • The same as get_lp_name. Implemented for backwards compatibility.
  • [costs] = sclpsolve('get_reduced_costs', lp)
    • The same as get_dual_solution. Implemented for backwards compatibility.
  • [names] = sclpsolve('get_row_names', lp)
    • The same as get_row_name. Implemented for backwards compatibility.
  • [obj, x, duals, return] = sclpsolve('get_solution', lp)
    • Returns the value of the objective function, the values of the variables and the duals. Implemented for backwards compatibility.
    • The return code of the call is the last value.
  • value = sclpsolve('mat_elm', lp)
    • The same as get_mat. Implemented for backwards compatibility.
  • [handle_vec] = sclpsolve('print_handle')
    • Returns a vector with open handles. Can be handy to see which handles aren't closed yet with delete_lp or free_lp.
  • lp_handle = sclpsolve('read_lp_file', filename {, verbose {, lp_name}})
    • The same as read_LP. Implemented for backwards compatibility.
  • lp_handle = sclpsolve('get_handle', lp_name)
    • Get the handle for this model from the models name. If an unknown model name is given (or already deleted), -1 is returned.
  • return_constants = sclpsolve('return_constants'[, return_constants])
    • Returns the setting of return_constants and optionally sets its value.

Compile the sclpsolve driver

Windows, Unix/Linux

Under Windows, the sclpsolve Scilab driver is a dll: sclpsolve.dll
Under Unix/Linux, the sclpsolve Scilab driver is a static library sclpsolve.a
The library is an interface to the lpsolve55 library that contains the implementation of lp_solve. Under windows this is a dll lpsolve55.dll and under Unix/Linux it is a shared library liblpsolve55.so
They are distributed with the lp_solve package (archive lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). See at the beginning of this article where these files must be installed. The sclpsolve Scilab driver is just a wrapper between Scilab and lp_solve to translate the input/output to/from Scilab and the lp_solve library.

The sclpsolve Scilab driver is written in C. To compile this code, under Windows the Microsoft C compiler is needed and under Unix the standard compiler is used.
This compiler must be called from Scilab. To make the compilation process easier, a script can be used: builder.sce
To make everything, just enter exec builder.sce and everything is build.
This compiles the source files to the needed libraries, compiles the sci scripts and makes the manuals. It also generates a new loader.sce file to load the driver into the Scilab workspace.

This build process is the same under Windows and Unix/Linux. Note that builder.sce generates Makefiles that are then used to build the code. Don't edit the Makefiles since your changes will be lost when build.sce is executed again.

See also Using lpsolve from MATLAB, Using lpsolve from O-Matrix, Using lpsolve from Sysquake, Using lpsolve from Octave, Using lpsolve from FreeMat, Using lpsolve from Euler, Using lpsolve from Python, Using lpsolve from Sage, Using lpsolve from PHP, Using lpsolve from R

doc/get_epsd.htm0000644000175000017500000000561210237176654012612 0ustar renerene get_epsd

get_epsd

Returns the value that is used as a tolerance for the reduced costs to determine whether a value should be considered as 0.

REAL get_epsd(lprec *lp);

Return Value

get_epsd returns the value of epsd.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_epsd function returns the value that is used as a tolerance for the reduced costs to determine whether a value should be considered as 0.
The default value for epsd is 1e-9

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL epsd;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  epsd = get_epsd(lp); /* will return 1e-9 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epsd, set_infinite, is_infinite, get_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap

doc/set_constr_type.htm0000644000175000017500000000705010237176662014241 0ustar renerene set_constr_type

set_constr_type

Set the type of a constraint.

unsigned char set_constr_type(lprec *lp, int row, int con_type);

Return Value

set_constr_type returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the constraint type must be set. Must be between 1 and number of rows in the lp.

con_type

The type of the constraint. Can by any of the following values:

LE (1) Less than or equal (<=)
EQ (3) Equal (=)
GE (2) Greater than or equal (>=)
FR (0) Free

Remarks

The set_constr_type function sets the constraint type for the specified row.
The default constraint type is LE.
Note the free (FR) constraint type. This is new from version 5.1.0.1
A free constraint will act as if the constraint is not there. The lower bound is -Infinity and the upper bound is +Infinity.
This can be used to temporary disable a constraint without having to delete it from the model. Note that the already set RHS and range on this constraint is overruled with Infinity by this.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_constr_type(lp, 1, GE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_constr_type, is_constr_type, add_constraint, add_constraintex, str_add_constraint, del_constraint

doc/read_XLI.htm0000644000175000017500000000627110661665222012444 0ustar renerene read_XLI

read_XLI

Create an lprec structure and read a model via the External Language Interface.

lprec *read_XLI(char *xliname, char *modelname, char *dataname, char *options, int verbose);

Return Value

Returns a pointer to a new lprec structure. This must be provided to almost all lp_solve functions.
A NULL return value indicates an error.

Parameters

xliname

Filename of the XLI package.

modelname

Filename to read the model from.

dataname

Filename to read the data from. This may be optional. In that case, set the parameter to NULL.

options

Extra options that can be used by the reader.

verbose

The verbose level. Can be one of the following values:
CRITICAL (1), SEVERE (2), IMPORTANT (3), NORMAL (4), DETAILED (5), FULL (6)

See also set_verbose and get_verbose.

Remarks

The read_XLI function constructs a new lprec structure and reads the model from filename via the specified XLI. See External Language Interfaces for a complete description on XLIs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"
int main(void)
{
  lprec *lp;

  /* Read LP model */
  lp = read_XLI("xli_MathProg", "model.mat", NULL, "", NORMAL);
  if(lp == NULL) {
    fprintf(stderr, "Unable to read model\n");
    return(1);
  }

  /* Model read */

  /*
  .
  .
  .
  */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, copy_lp, write_lp, write_LP, write_lpex, read_mps, read_freemps, read_MPS, read_freeMPS, write_mps, write_freemps, write_MPS, write_freeMPS, MPS_writefileex, write_XLI, has_XLI, is_nativeXLI, set_XLI

doc/sensitivity.htm0000644000175000017500000001701710205467740013406 0ustar renerene Sensitivity

Sensitivity

Sensitivity or post-optimal analysis is extra information that is provided about the current optimal solution. lp_solve provides a substantial amount of sensitivity information. Several API calls are available to retrieve the sensitivity: get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult. The lp_solve program doesn't show the sensitivity by default. So to see the sensitivity information, use the -S4 option. The best way to explain this is via an example.

min: +COLONE +3 COLTWO +6.24 COLTHREE +0.1 COLFOUR;
THISROW: +78.26 COLTWO +2.9 COLFOUR >= 92.3;
THATROW: +0.24 COLONE +11.31 COLTHREE <= 14.8;
LASTROW: +12.68 COLONE +0.08 COLTHREE +0.9 COLFOUR >= 4;
COLONE >= 28.6;
COLFOUR >= 18.00;
COLFOUR <= 48.98;

The solution of this model is (with the -S4 option):

Value of objective function: 31.7828

Actual values of the variables:
COLONE               28.6
COLTWO               0
COLTHREE             0
COLFOUR              31.8276

Actual values of the constraints:
THISROW              92.3
THATROW              6.864
LASTROW              391.293

Objective function limits:
                              From            Till          FromValue
COLONE                              0          1e+030         -1e+030
COLTWO                       2.698621          1e+030       0.5123946
COLTHREE                            0          1e+030       0.7016799
COLFOUR                             0       0.1111679         -1e+030

Dual values with from - till limits:
                          Dual value          From            Till
THISROW                   0.03448276             52.2         142.042
THATROW                            0          -1e+030          1e+030
LASTROW                            0          -1e+030          1e+030
COLONE                             1        -1.943598        61.66667
COLTWO                     0.3013793       -0.6355993       0.5123946
COLTHREE                        6.24         -4841.16       0.7016799
COLFOUR                            0          -1e+030          1e+030

First look at 'Objective function limits' (via API obtained by get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex). There is a list of all variables with for each variable 3 values. From, Till and FromValue. From - Till gives the limits where between the objective value may vary so that the solution stays the same. For example, variable COLFOUR has a From value of 0 and a Till value of 0.1111679. The coefficient in the objective function of this variable is 0.1. This means that as this coefficient varies between 0 and 0.1111679, the solution doesn't change. The values for the variables and the constraints will remain unchanged as long as the objective coefficient stays in this range. The objective function value will vary of course and also the sensitivity information of the other variables, but the solution will stay the same if only the objective coefficient value for this variable is changed. When the objective coefficient of variable COLFOUR is above 0.1111679 then the solution will change. The FromValue is only meaningful if the variable has a value of 0 (rejected). This is the value that this variable becomes when the From (minimization) or Till (maximization) value is reached. For example, the variable COLTWO that has an amount of 0 will become 0.5123946 if the coefficient in the objective function of COLTWO reaches 2.698621. Note that you only get information about this variable. There is no information what the values will be of the other variables. In a blending example where the coefficients of the objective function are generally the prices of ingredients this information tells you at what point a price may change to have the same composition and the FromValue says at what value a relected ingredient will be taken when the price lowers till the lower range value.

Another piece of information are the Dual values with the from - till limits. This is provided for both the constraints and the variables. The information is the same for both. For example, constraint THISROW has a dual value of 0.03448276 with a From value of 52.2 and a Till value of 142.042. This means that the Dual value specifies how much the objective function will vary if the constraint value is incremented by one unit. This implies that there is only a non-zero dual value if the constraint is active. Constraint THATROW for example is not active because the constraint is <= 14.8, but its value is only 6.864. However constraint THISROW is >= 92.3 and its value is also 92.3, thus active. If the constraint is changed to 93.3 (+1), then the objective value will be the current value + change * dual value = 31.7828 + 1 * 0.03448276 = 31.81728. However this is only true for the range From - Till, which means that the dual value stays only the same as long as the constraint lies between the From - Till limits. The moment that you are outside of these limits, the dual value will change. The dual value gives a very good indication how much this restriction costs. If the dual value is very high then this constraint is very influential on the objective function and if you are able to change it a bit then the solution will be much better. Also the sign of the dual value has a meaning. A positive value means that as the restriction becomes larger, the objective value will be larger, and as it becomes more negative, the objective value will be smaller. Also note that changes in the restrictions, even between the limits, can cause the solution to change. The from - till limits only say that the cost will remain the same, nothing less, nothing more.

Inaccurate sensitivity analysis in a model with integer variables

The sensitivity analysis doesn't take the integer restrictions in account. This is almost impossible since it would ask too much calculation time. In particular the from - till limits on both the objective function and the dual values are trustworthy. They only apply for the current solution without the integer restrictions. Keep this in mind. The dual values are correct.
doc/set_lowbo.htm0000644000175000017500000000573211127442622013006 0ustar renerene set_lowbo

set_lowbo

Set the lower bound of a variable.

unsigned char set_lowbo(lprec *lp, int column, REAL value);

Return Value

set_lowbo returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable on which the bound must be set. It must be between 1 and the number of columns in the lp.

Remarks

The set_lowbo function sets a lower bound on the variable identified by column.
Setting a bound on a variable is the way to go instead of adding an extra constraint (row) to the model. Setting a bound doesn't increase the model size that means that the model stays smaller and will be solved faster.
Note that the default lower bound of each variable is 0. So variables will never take negative values if no negative lower bound is set.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_lowbo(lp, 1, 1.0);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_lowbo, set_upbo, get_upbo, set_bounds, set_unbounded, is_unbounded, is_negative

doc/get_epsel.htm0000644000175000017500000000564610237176654012776 0ustar renerene get_epsel

get_epsel

Returns the value that is used as a tolerance for rounding values to zero.

REAL get_epsel(lprec *lp);

Return Value

get_epsel returns the value of epsel.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_epsel function returns the value that is used for rounding values to zero.
epsel is used on all other places where epsint, epsb, epsd, epspivot, epsperturb are not used.
The default value for epsel is 1e-12

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL epsel;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  epsel = get_epsel(lp); /* will return 1e-12 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epsel, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsb, get_epsb, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap

doc/print_debugdump.htm0000644000175000017500000000546410237176420014204 0ustar renerene print_debugdump

print_debugdump

Do a generic readable data dump of key lp_solve model variables; principally for run difference and debugging purposes.

unsigned char print_debugdump(lprec *lp, char *filename);

Return Value

print_debugdump returns TRUE if data could be written, else FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The print_debugdump function creates a generic readable data dump of key lp_solve model variables; principally for run difference and debugging purposes
This function is meant for debugging purposes.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_debugdump(lp, "debug.txt"); /* dump to file debug.txt in current directory */

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, print_lp, print_objective, print_constraints, print_duals, print_scales, print_tableau, print_str

doc/set_var_weights.htm0000644000175000017500000000602510237176666014217 0ustar renerene set_var_weights

set_var_weights

Set the weights on variables.

unsigned char set_var_weights(lprec *lp, REAL *weights);

Return Value

set_var_weights returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

weights

The weights array.

Remarks

The set_var_weights sets a weight factor on each variable. This is only used for the integer variables in the branch-and-bound algorithm. Array members are unique, real-valued numbers indicating the "weight" of the variable at the given index. The array is 0-based. So variable 1 is at index 0, variable 2 at index 1. The array must contain get_Ncolumns elements.
The weights define which variable the branch-and-bound algorithm must select first. The lower the weight, the sooner the variable is chosen to make it integer.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL weights[2];

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  weights[0] = 2;
  weights[1] = 1;

  set_var_weights(lp, weights);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_var_priority, set_var_branch, get_var_branch, set_bb_floorfirst, get_bb_floorfirst

doc/simpletreemenu.js0000644000175000017500000001334611034212635013667 0ustar renerenevar persisteduls=new Object() var ddtreemenu=new Object() ddtreemenu.closefolder="closed.gif" //set image path to "closed" folder image ddtreemenu.openfolder="open.gif" //set image path to "open" folder image //////////No need to edit beyond here/////////////////////////// ddtreemenu.createTree=function(treeid, enablepersist, persistdays){ var ultags=document.getElementById(treeid).getElementsByTagName("ul") if (typeof persisteduls[treeid]=="undefined") persisteduls[treeid]=(enablepersist==true && ddtreemenu.getCookie(treeid)!="")? ddtreemenu.getCookie(treeid).split(",") : "" for (var i=0; i lp_solve command

lp_solve command

The lp_solve program is a command line application that can use as good as all functionality of the library.

Installation

There is no installation procedure for this application. There is no need for it. You only need one file: lp_solve.exe under Windows or lp_solve under Unix/Linux. It can be found in the archive lp_solve_5.5.0.15_exe.zip (Windows) or lp_solve_5.5.0.15_exe.tar.gz (Unix/Linux). Just extract the file and you can use it. Note for Windows users, that you can not just run the lp_solve program by double clicking on it from Windows Explorer. The program needs arguments and this is best done from the command line (cmd.exe / command.com) or via batch files. lp_solve has many options as shown further.

Usage

This program reads the MIP model from standard input or from a file and outputs the result back to the console or to a file. There are several possible input formats: The 'lp' format (See lp-format), and the 'mps' format (See mps-format) are build in, but other formats are also supported via the XLI functionality (See external language interface). For example a MathProg interface is developed via the XLI functionality (See external language interface for an example). These input formats have nothing to do with the API. So lp1 = make_lp(0,4) is a totally wrong input for the lp_solve program. The lp format is the default. Optionaly you can use the -lp option for it. To enable the mps format, use the -mps option. To enable the XLI, use the -rxli option. If lp_solve is started without an input file, then it gives a blinking cursor and waits for input. It is then possible to enter the model in the specified format (lp by default). But this is not very handy. You must enter the whole model each time you want to solve it and must be careful that you don't type any errors. To stop input mode, press Ctrl Z.
However it is much better to write your model in a disk file with your favourite editor (make sure it is in text format) and then provide this file to lp_solve. For example:

lp_solve input.lp

It is also possible to use input redirection:

lp_solve <input.lp

Or more sophisticated constructs like:

gen_model | lp_solve

gen_model is here a user written program that outputs the model to standard output and via the pipe character (|) this output is redirected to lp_solve. So no intermediate file is needed in this case.

Examples:

lp_solve input.lp

lp_solve -s input.lp

lp_solve -s input.lp >output.txt

lp_solve -s -mps input.mps >output.txt

lp_solve -s -S4 -mps input.mps >output.txt

lp_solve -s -S4 -mps input.mps -wpar par.ini -wparopt "-HMyPar" >output.txt

A list of all options is given by entering the following command:

lp_solve -h

This gives:

Usage of lp_solve version 5.5.0.15:
lp_solve [options] [[<]input_file]
List of options:
-h              prints this message
-lp             read from LP file (default) See read_LP, See lp-format
-mps            read from MPS file, default in fixed format See read_MPS, See mps-format
-mps_free		use free format See read_MPS, See mps-format
-mps_ibm		interprete integers accoring to ibm format See read_MPS, See mps-format
-mps_negobjconst	negate objective constant See read_MPS, See mps-format
-fmps           read from MPS file in free format See read_freeMPS, See mps-format
-rpar filename  read parameters from filename. See read_params
-rparopt options
                options for parameter file:
                 -H headername: header name for parameters. By default 'Default'
-rxli xliname filename
                read file with xli library See external language interface
-rxlidata datafilename
                data file name for xli library. See external language interface
-rxliopt options
                options for xli library. See external language interface
-rbas filename  read basis from filename. See read_basis, See mps bas file format
-gbas filename	guess basis with variables from filename. See guess_basis
-plp		print model. See print_lp
-wlp filename   write to LP file See write_lp, See lp-format
-wmps filename  write to MPS file in fixed format See write_mps, See mps-format
-wfmps filename write to MPS file in free format See write_freemps, See mps-format
-wxli xliname filename
                write file with xli library See external language interface
-wxliopt options
                options for xli library. See external language interface
-wxlisol xliname filename
                write solution file with xli library See external language interface
-wxlisolopt options
                options for xli library. See external language interface
-wbas filename  write basis to filename. See write_basis, See mps bas file format
-wpar filename  write parameters to filename. See write_params
-wparopt options
                options for parameter file:
                 -H headername: header name for parameters. By default 'Default'
-wafter         Write model after solve (useful if presolve used).
-parse_only     parse input file but do not solve
-nonames        Ignore variables and constraint names See set_use_names
-norownames     Ignore constraint names See set_use_names
-nocolnames     Ignore variable names See set_use_names

-min            Minimize the lp problem (overrules setting in file) See set_minim
-max            Maximize the lp problem (overrules setting in file) See set_maxim
-r <value>      specify max nbr of pivots between a re-inversion of the matrix See set_maxpivot
-piv <rule>     specify simplex pivot rule See set_pivoting
         -piv0: Select first
         -piv1: Select according to Dantzig
         -piv2: Select Devex pricing from Paula Harris (default)
         -piv3: Select steepest edge
These pivot rules can be combined with any of the following:
-pivf           In case of Steepest Edge, fall back to DEVEX in primal. See set_pivoting
-pivm           Multiple pricing. See set_pivoting
-piva           Temporarily use First Index if cycling is detected.  See set_pivoting
-pivr           Adds a small randomization effect to the selected pricer. See set_pivoting
-pivll          Scan entering/leaving columns left rather than right. See set_pivoting
-pivla          Scan entering/leaving columns alternatingly left/right. See set_pivoting
-pivh           Use Harris' primal pivot logic rather than the default. See set_pivoting
-pivt           Use true norms for Devex and Steepest Edge initializations. See set_pivoting
-o0             Don't put objective in basis. See set_obj_in_basis
-o1             Put objective in basis (default). See set_obj_in_basis
-s <mode> <scaleloop>   use automatic problem scaling. See set_scaling
         -s0: No scaling
         -s1: Geometric scaling (default)
         -s2: Curtis-reid scaling
         -s3: Scale to convergence using largest absolute value
          -s:
         -s4: Numerical range-based scaling
         -s5: Scale to convergence using logarithmic mean of all values
         -s6: Scale based on the simple numerical range
         -s7: Scale quadratic
These scaling rules can be combined with any of the following:
-sp             also do power scaling. See set_scaling
-si             also do Integer scaling (default). See set_scaling
-se             also do equilibration to scale to the -1..1 range (default). See set_scaling
-presolve       presolve problem before start optimizing (rows+columns) See set_presolve
-presolverow    presolve problem before start optimizing (rows only) See set_presolve
-presolvecol    presolve problem before start optimizing (columns only) See set_presolve
-presolvel      also eliminate linearly dependent rows See set_presolve
-presolves      also convert constraints to SOSes (only SOS1 handled) See set_presolve
-presolver      If the phase 1 solution process finds that a constraint is
                redundant then this constraint is deleted See set_presolve
-presolvek      Simplification of knapsack-type constraints through
                addition of an extra variable, which also helps bound the OF See set_presolve
-presolveq      Direct substitution of one variable in 2-element equality
                constraints; this requires changes to the constraint matrix See set_presolve
-presolvem	Merge rows See set_presolve
-presolvefd	COLFIXDUAL See set_presolve
-presolvebnd	Presolve bounds See set_presolve
-presolved	Presolve duals See set_presolve
-presolvef      Identify implied free variables (releasing their expl. bounds) See set_presolve
-presolveslk	IMPLIEDSLK See set_presolve
-presolveg      Reduce (tighten) coef. in integer models based on GCD argument See set_presolve
-presolveb      Attempt to fix binary variables at one of their bounds See set_presolve
-presolvec      Attempt to reduce coefficients in binary models See set_presolve
-presolverowd   Idenfify and delete qualifying constraints that
                are dominated by others, also fixes variables at a bound See set_presolve
-presolvecold   Deletes variables (mainly binary), that are dominated
                by others (only one can be non-zero) See set_presolve
-C <mode>       basis crash mode See set_basiscrash
         -C0: No crash basis
         -C2: Most feasible basis
         -C3: Least degenerate basis
-prim           Prefer the primal simplex for both phases. See set_preferdual
-dual           Prefer the dual simplex for both phases. See set_preferdual
-simplexpp      Set Phase1 Primal, Phase2 Primal. See set_simplextype
-simplexdp      Set Phase1 Dual, Phase2 Primal. See set_simplextype
-simplexpd      Set Phase1 Primal, Phase2 Dual. See set_simplextype
-simplexdd      Set Phase1 Dual, Phase2 Dual. See set_simplextype
-degen          use perturbations to reduce degeneracy,
                can increase numerical instability See set_anti_degen
-degenc         use column check to reduce degeneracy See set_anti_degen
-degend         dynamic check to reduce degeneracy See set_anti_degen
-degenf         anti-degen fixedvars See set_anti_degen
-degens         anti-degen stalling See set_anti_degen
-degenn         anti-degen numfailure See set_anti_degen
-degenl         anti-degen lostfeas See set_anti_degen
-degeni         anti-degen infeasible See set_anti_degen
-degenb         anti-degen B&B See set_anti_degen
-degenr         anti-degen Perturbation of the working RHS at refactorization See set_anti_degen
-degenp         anti-degen Limit bound flips See set_anti_degen
-trej <Trej>    set minimum pivot value See set_epspivot
-epsd <epsd>    set minimum tolerance for reduced costs See set_epsd
-epsb <epsb>    set minimum tolerance for the RHS See set_epsb
-epsel <epsel>  set tolerance for rounding values to zero See set_epsel
-epsp <epsp>    set the value that is used as perturbation scalar for
                degenerative problems See set_epsperturb
-improve <level>        iterative improvement level See set_improve
         -improve0: none
         -improve1: Running accuracy measurement of solved equations on Bx=r
         -improve2: Improve initial dual feasibility by bound flips (default)
         -improve4: Low-cost accuracy monitoring in the dual
         -improve8: check for primal/dual feasibility at the node level
-timeout <sec>  Timeout after sec seconds when not solution found. See set_timeout
-bfp <filename> Set basis factorization package. See set_BFP

-noint          Ignore integer restrictions
-e <number>     specifies the tolerance which is used to determine whether a
                floating point number is in fact an integer.
                Should be < 0.5 See set_epsint
-g <number>
-ga <number>    specifies the absolute MIP gap for branch-and-bound. See set_mip_gap
                This specifies the absolute allowed tolerance
                on the object function. Can result in faster solving times.
-gr <number>    specifies the relative MIP gap for branch-and-bound. See set_mip_gap
                This specifies the relative allowed tolerance
                on the object function. Can result in faster solving times.
-f              specifies that branch-and-bound algorithm stops at first found
                solution See set_break_at_first
-b <bound>      specify a lower bound for the objective function See set_obj_bound
                to the program. If close enough, may speed up the
                calculations.
-o <value>      specifies that branch-and-bound algorithm stops when objective
                value is better than value See set_break_at_value
-c
-cc             during branch-and-bound, take the ceiling branch first See set_bb_floorfirst
-cf             during branch-and-bound, take the floor branch first See set_bb_floorfirst
-ca             during branch-and-bound, the algorithm chooses branch See set_bb_floorfirst
-depth <limit>  set branch-and-bound depth limit See set_bb_depthlimit
-n <solnr>      specify which solution number to return See set_solutionlimit
-B <rule>       specify branch-and-bound rule See set_bb_rule
         -B0: Select Lowest indexed non-integer column (default)
         -B1: Selection based on distance from the current bounds
         -B2: Selection based on the largest current bound
         -B3: Selection based on largest fractional value
         -B4: Simple, unweighted pseudo-cost of a variable
         -B5: This is an extended pseudo-costing strategy based on minimizing
              the number of integer infeasibilities
         -B6: This is an extended pseudo-costing strategy based on maximizing
              the normal pseudo-cost divided by the number of infeasibilities.
              Similar to (the reciprocal of) a cost/benefit ratio
These branch-and-bound rules can be combined with any of the following:
-Bw             WeightReverse branch-and-bound See set_bb_rule
-Bb             BranchReverse branch-and-bound See set_bb_rule
-Bg             Greedy branch-and-bound See set_bb_rule
-Bp             PseudoCost branch-and-bound See set_bb_rule
-Bf             DepthFirst branch-and-bound See set_bb_rule
-Br             Randomize branch-and-bound See set_bb_rule
-BG             GubMode branch-and-bound See set_bb_rule
-Bd             Dynamic branch-and-bound See set_bb_rule
-Bs             RestartMode branch-and-bound See set_bb_rule
-BB             BreadthFirst branch-and-bound See set_bb_rule
-Bo             Order variables to improve branch-and-bound performance See set_bb_rule
-Bc             Do bound tightening during B&B based of reduced cost info See set_bb_rule
-Bi             Initialize pseudo-costs by strong branching See set_bb_rule

-time           Print CPU time to parse input and to calculate result. See time_elapsed
-v <level>      verbose mode, gives flow through the program. See set_verbose
                 if level not provided (-v) then -v4 (NORMAL) is taken.
         -v0: NEUTRAL
         -v1: CRITICAL
         -v2: SEVERE
         -v3: IMPORTANT (default)
         -v4: NORMAL
         -v5: DETAILED
         -v6: FULL
-t              trace pivot selection See set_trace
-d              debug mode, all intermediate results are printed,
                and the branch-and-bound decisions See set_debug
-R              report information while solving the model See put_msgfunc See get_working_objective
-Db <filename>  Do a generic readable data dump of key lp_solve model variables
                before solve. See print_debugdump
                Principally for run difference and debugging purposes
-Da <filename>  Do a generic readable data dump of key lp_solve model variables
                after solve. See print_debugdump
                Principally for run difference and debugging purposes
-i              print all intermediate valid solutions. See set_print_sol
                Can give you useful solutions even if the total run time
                is too long
-ia             print all intermediate (only non-zero values) valid solutions. See set_print_sol
                Can give you useful solutions even if the total run time
                is too long
-stat		Print model statistics
-S <detail>     Print solution. If detail omitted, then -S2 is used.
         -S0: Print nothing
         -S1: Only objective value See print_objective See get_objective
         -S2: Obj value+variables (default) See print_solution See get_variables, get_ptr_variables
         -S3: Obj value+variables+constraints See print_constraints See get_constraints
         -S4: Obj value+variables+constraints+duals
              See print_duals
              See get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult,
              See get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex
         -S5: Obj value+variables+constraints+duals+lp model See print_lp
         -S6: Obj value+variables+constraints+duals+lp model+scales See print_scales
         -S7: Obj value+variables+constraints+duals+lp model+scales+lp tableau See print_tableau

A practical example

Enter the following in your favorite text editor (Windows users, don't use Word or Wordpad, that won't work. If you don't have an editor, use notepad).

max: 143 x + 60 y;

120 x + 210 y <= 15000;
110 x + 30 y <= 4000;
x + y <= 75;

Save this on your hard disk with name model.lp (don't forget in which directory/folder you save it).

Now enter the following:

lp_solve -S3 model.lp

This gives:

Value of objective function: 6315.63

Actual values of the variables:
x                          21.875
y                          53.125

Actual values of the constraints:
R1                        13781.2
R2                           4000
R3                             75

Note that this is the model presented in Formulation of an lp problem in lpsolve. The model is formulated in the lp format. See lp-format for a description of it.

doc/set_row_name.htm0000644000175000017500000000522510237176664013503 0ustar renerene set_row_name

set_row_name

Set the name of a constraint (row) in the lp.

unsigned char set_row_name(lprec *lp, int row, char *new_name);

Return Value

set_row_name returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the name must be set. Must be between 0 and the number of rows in the lp.

new_name

The name for the row.

Remarks

The set_row_name sets the name of the row.
The row must already exist. row 0 is the objective function. Row names are optional.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_row_name(lp, 1, "row1");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_row_name, get_origrow_name, set_col_name, get_col_name, get_origcol_name, get_nameindex

doc/add_lag_con.htm0000644000175000017500000001075611022520127013214 0ustar renerene add_lag_con, str_add_lag_con

add_lag_con, str_add_lag_con

Add a Lagrangian constraint to the lp.

The Lagrangian solver does not work. Do not use this call.

unsigned char add_lag_con(lprec *lp, REAL *row, int con_type, REAL rhs);

unsigned char str_add_lag_con(lprec *lp, char *row_string, int con_type, REAL rhs);

Return Value

add_lag_con and str_add_lag_con returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

An array with column elements that contains the values of the row.

row_string

A string with column elements that contains the values of the row. Each element must be separated by space(s).

con_type

The type of the constraint. Can by any of the following values:

LE (1) Less than or equal (<=)
EQ (3) Equal (=)
GE (2) Greater than or equal (>=)

rhs

The value of the right hand side (RHS).

Remarks

The Lagrangian solver does not work. Do not use this call.

The add_lag_con, str_add_lag_con functions adds a Lagrangian row to the model (at the end) and sets all values of the row at once.
Note that element 0 of the array is not considered (i.e. ignored). Column 1 is element 1, column 2 is element 2, ...

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL row[1+2]; /* must be 1 more then number of columns ! */

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  row[1] = 1.0;
  row[2] = 1.0;
  add_lag_con(lp, row, LE, 1.0); /* constructs the Lagrangian row: +v_1 +v_2 <= 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, get_constr_type, del_constraint, add_column, add_columnex, str_add_column, set_column, set_columnex, get_column, get_columnex, get_row, get_rowex, get_mat, lag_solve, get_Lrows

doc/set_basiscrash.htm0000644000175000017500000000734610472143112014003 0ustar renerene set_basiscrash

set_basiscrash

Determines a starting base.

void set_basiscrash(lprec *lp, int mode);

Return Value

None

Parameters

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

mode

Specifies which basis crash mode is used. Can by any of the following values:

CRASH_NONE (0) No basis crash
CRASH_MOSTFEASIBLE (2) Most feasible basis
CRASH_LEASTDEGENERATE (3) Construct a basis that is in some measure the "least degenerate"

Remarks

The set_basiscrash function specifies which basis crash mode must be used. Default is CRASH_NONE.

When no base crash is done (the default), the initial basis from which lp_solve starts to solve the model is the basis containing all slack or artificial variables that is automatically associates with each constraint.

When base crash is enabled, a heuristic ``crash procedure'' is executed before the first simplex iteration to quickly choose a basis matrix that has fewer artificial variables. This procedure tends to reduce the number of iterations to optimality since a number of iterations are skipped. lp_solve starts iterating from this basis until optimality.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  set_basiscrash(lp, CRASH_MOSTFEASIBLE);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_basiscrash, default_basis, read_basis, write_basis, guess_basis, get_basis, set_basis

doc/get_Norig_rows.htm0000644000175000017500000000525310237176654014010 0ustar renerene get_Norig_rows

get_Norig_rows

Returns the number of original rows (constraints) in the lp.

int get_Norig_rows(lprec *lp);

Return Value

get_Norig_rows returns the number of original rows (constraints) in the lp.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_Norig_rows function returns the number of original rows (constraints) in the lp.
Note that the number of rows (get_Nrows) can change when a presolve is done. get_Norig_rows does not change and thus returns the original number of rows in the lp.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int Norig_rows;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  Norig_rows = get_Norig_rows(lp); /* Will return 1 */

  set_presolve(lp, PRESOLVE_ROWS);
  solve(lp);

  Norig_rows = get_Norig_rows(lp); /* Will return 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_Nrows, get_Lrows, get_Ncolumns, get_Norig_columns, get_orig_index, get_lp_index

doc/set_binary.htm0000644000175000017500000000625310237176662013160 0ustar renerene set_binary

set_binary

Set the type of the variable. Binary or floating point.

unsigned char set_binary(lprec *lp, int column, unsigned char must_be_bin);

Return Value

set_binary returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be set. It must be between 1 and the number of columns in the lp.

must_be_bin

TRUE (1) if the variable must be binary, FALSE (0) if not.

Remarks

The set_binary function defines if a variable must be binary or not. Default a variable is not binary. A binary variable is an integer variable with a lower bound of 0 and an upper bound of 1. This function also sets these bounds. The argument must_be_bin defines what the status of the variable becomes. From the moment there is at least one integer variable in the model, the Branch and Bound algorithm is used to make these variables integer. Note that solving times can be considerably larger when there are integer variables. See integer variables for a description about integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_binary(lp, 1, TRUE); /* sets variable 1 to binary */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_binary, is_int, set_int

doc/set_verbose.htm0000644000175000017500000000752310255113000013313 0ustar renerene set_verbose

set_verbose

Set the verbose level.

void set_verbose(lprec *lp, int verbose);

Return Value

set_verbose has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

verbose

The verbose level. Can be one of the following values:

NEUTRAL (0) Only some specific debug messages in de debug print routines are reported.
CRITICAL (1) Only critical messages are reported. Hard errors like instability, out of memory, ...
SEVERE (2) Only severe messages are reported. Errors.
IMPORTANT (3) Only important messages are reported. Warnings and Errors.
NORMAL (4) Normal messages are reported. This is the default.
DETAILED (5) Detailed messages are reported. Like model size, continuing B&B improvements, ...
FULL (6) All messages are reported. Useful for debugging purposes and small models.

Remarks

The set_verbose function sets the verbose level.
lp_solve reports information back to the user. How much information is reported depends on the verbose level. The default verbose level is NORMAL (4). lp_solve determines how verbose a given message is. For example specifying a wrong row/column index values is considered as a SEVERE error. verbose determines how much of the lp_solve message are reported. All messages equal to and below the set level are reported.
The default reporting device is the console screen. It is possible to set a used defined reporting routine via put_logfunc.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_verbose(lp, NORMAL);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_verbose, put_logfunc

doc/distribution.htm0000644000175000017500000006647111247042710013534 0ustar renerene lpsolve distributed files

lpsolve distributed files

lpsolve is distributed as several separate archive files. It is most unlikely that you need them all for your purpose. This text describes each archive's contents.

There are two kind of archive files:

  • ziped files (.zip)
  • gziped tar files (.tar.gz)

Ziped files are basically binaries (executables/libraries) for the Windows platform.

gziped tar files can be divided into two categories:

  • binaries (executables, libraries) for the Linux/Mac OSX platform.
  • source files that are operating system independent.

lpsolve library

Most of the links from lpsolve to other software need the lpsolve library lpsolve55.dll (Windows) or lpsolve55.so (Unix/Linux/Mac). This library is in general not included in the archives. It must be installed separately. It is contained in archive lp_solve_5.5.0.15_dev_win*.zip (Windows) / lp_solve_5.5.0.15_dev_ux*.tar.gz (Linux) / lp_solve_5.5.0.15_dev_osx*.tar.gz
This library must be put in a path known by the system. That is:

Under Windows, the following search order is used:

  1. Current directory.
  2. A semi-colon-separated (;) list of directories in the user's PATH environment variable. windows\system32 is a common folder that is normally defined in this environment variable. This folder is a good place to put the dll.

Under Unix/Linux, following search order is used:

  1. A colon-separated (:) list of directories in the user's LD_LIBRARY_PATH environment variable.
  2. The list of libraries specified in /etc/ld.so.cache (which is generated from /etc/ld.so.conf).
  3. /lib, followed by /usr/lib. Note the order here; this is the reverse of the order used by the old a.out loader. The old a.out loader, when loading a program, first searched /usr/lib, then /lib (see the man page ld.so(8)). This shouldn't normally matter, since a library should only be in one or the other directory (never both), and different libraries with the same name are a disaster waiting to happen.

List of archives

Archive Contents See also
Executables
lp_solve_5.5.0.15_IDE_Setup.exe LPSolve IDE (Integrated Development Interface) for Windows.
A user-friendly interface to lpsolve to formulate your model. At this moment only available for Windows.
lp_solve_5.5.0.15_exe_win32.zip 32 bit lp_solve stand-alone program and bfp/xli libraries for Windows.

lp_solve_5.5.0.15_exe_win64.zip 64 bit lp_solve stand-alone program and bfp/xli libraries for Windows.

lp_solve_5.5.0.15_exe_ux32.tar.gz 32 bit lp_solve stand-alone program and bfp/xli libraries for ubuntu linux.

lp_solve_5.5.0.15_exe_ux64.tar.gz 64 bit lp_solve stand-alone program and bfp/xli libraries for ubuntu linux.

lp_solve_5.5.0.15_exe_osx32.tar.gz 32 bit lp_solve stand-alone program and bfp/xli libraries for Mac OSX (Intel).

Libraries
lp_solve_5.5.0.15_dev_win32.zip 32 bit lpsolve libraries for Windows.
The libraries are needed by many of the examples and when you statically or dynamically link the lpsolve library with your application.
lp_solve_5.5.0.15_dev_win64.zip 64 bit lpsolve libraries for Windows.
The libraries are needed by many of the examples and when you statically or dynamically link the lpsolve library with your application.
lp_solve_5.5.0.15_dev_ux32.tar.gz 32 bit lpsolve libraries for ubuntu linux.
The libraries are needed by many of the examples and when you statically or dynamically link the lpsolve library with your application.
lp_solve_5.5.0.15_dev_ux64.tar.gz 64 bit lpsolve libraries for ubuntu linux.
The libraries are needed by many of the examples and when you statically or dynamically link the lpsolve library with your application.
lp_solve_5.5.0.15_dev_osx32.tar.gz 32 bit lpsolve libraries for Mac OSX (Intel based).
The libraries are needed by many of the examples and when you statically or dynamically link the lpsolve library with your application.
Documentation
lp_solve_5.5.0.15_doc.tar.gz lp_solve reference guide in HTML format.
For use under Unix/Linux. Can also be used under Windows, however lp_solve_5.5.0.15.chm is handier under that platform.
http://lpsolve.sourceforge.net/5.5/
lp_solve_5.5.0.15.chm lp_solve reference guide in HTML HELP (Windows) format http://lpsolve.sourceforge.net/5.5/
Sources
lp_solve_5.5.0.15_source.tar.gz lp_solve library & stand-alone program source for all platforms.
lp_solve_5.5.0.15_IDE_source.zip LPSolve IDE (Integrated Development Interface) sources.
BFP packages
lp_solve_5.5.0.15_bfp_etaPFI_source.tar.gz etaPFI BFP source.
Can be compiled under Windows or Linux to generate the etaPFI 2.0 bfp
lp_solve_5.5.0.15_bfp_GLPK_source.tar.gz GLPK BFP source.
Can be compiled under Windows or Linux to generate the GLPK bfp.
lp_solve_5.5.0.15_bfp_LUSOL_source.tar.gz LUSOL BFP source.
Can be compiled under Windows or Linux to generate the LUSOL bfp.
XLI packages
lp_solve_5.5.0.15_xli_CPLEX_source.tar.gz CPLEX XLI reader/writer source.
Can be compiled under Windows or Linux to generate the CPLEX xli interface.

lp_solve_5.5.0.15_xli_Xpress_source.tar.gz Xpress XLI reader/writer source.
Can be compiled under Windows or Linux to generate the Xpress xli interface.

lp_solve_5.5.0.15_xli_LINDO_source.tar.gz LINDO XLI reader/writer source.
Can be compiled under Windows or Linux to generate the LINDO xli interface.
lp_solve_5.5.0.15_xli_LPFML_source.tar.gz LPFML (XML) XLI reader/writer source.
Can be compiled under Windows to generate the XML xli interface.
lp_solve_5.5.0.15_xli_MathProg_source.tar.gz MathProg XLI reader source.
Can be compiled under Windows or Linux to generate the MathProg xli interface. Note that you also need GLPK source to do this.
lp_solve_5.5.0.15_xli_DIMACS_source.tar.gz DIMACS XLI reader/writer source.
Can be compiled under Windows or Linux to generate the DIMACS xli interface.


Call lpsolve from another programming language or environment
lp_solve_5.5.0.15_AMPL_exe_win32.zip 32 bit AMPL lpsolve executable driver for Windows
lp_solve_5.5.0.15_AMPL_exe_ux32.tar.gz 32 bit AMPL lpsolve executable driver for ubuntu linux
lp_solve_5.5.0.15_AMPL_source.tar.gz AMPL lpsolve driver source
lp_solve_5.5.0.15_c.tar.gz example calling lp_solve API from C.
A starting point if you want to use the lpsolve API from C.
lp_solve_5.5.0.15_COM.zip lpsolve COM object (COM interface to lpsolve55 dll) + VB example
A COM interface to the lpsolve API
lp_solve_5.5.0.15_cs.net.zip example calling lp_solve API from C#.
A starting point if you want to use the lpsolve API from C# (.NET).
lp_solve_5.5.0.15_Delphi.zip example calling lp_solve API from Delphi.
A starting point if you want to use the lpsolve API from Delphi/Pascal.
lp_solve_5.5.0.15_access.zip example calling lp_solve API from Access.
A starting point if you want to use the lpsolve API from Access.
lp_solve_5.5.0.15_excel.zip example calling lp_solve API from EXCEL.
A starting point if you want to use the lpsolve API from EXCEL.
lp_solve_5.5.0.15_java.zip java wrapper for lpsolve, java documentation and examples
lp_solve_5.5.0.15_MATLAB_exe_win32.zip 32 bit MATLAB driver to lpsolve for Windows and examples
lp_solve_5.5.0.15_MATLAB_exe_win64.zip 64 bit MATLAB driver to lpsolve for Windows and examples
lp_solve_5.5.0.15_MATLAB_exe_ux32.tar.gz 32 bit MATLAB driver to lpsolve for ubuntu linux and examples
lp_solve_5.5.0.15_MATLAB_exe_ux64.tar.gz 64 bit MATLAB driver to lpsolve for ubuntu linux and examples
lp_solve_5.5.0.15_MATLAB_exe_osx32.tar.gz 32 bit MATLAB driver to lpsolve for Mac OSX (Intel) and examples
lp_solve_5.5.0.15_MATLAB_source.tar.gz MATLAB driver source to lpsolve with examples
lp_solve_5.5.0.15_OMATRIX_exe_win32.zip 32 bit O-MATRIX driver to lpsolve for Windows and examples
lp_solve_5.5.0.15_OMATRIX_source.tar.gz O-MATRIX driver source to lpsolve with examples
lp_solve_5.5.0.15_Sysquake_exe_win32.zip 32 bit Sysquake driver to lpsolve for Windows and examples
lp_solve_5.5.0.15_Sysquake_exe_ux32.zip 32 bit Sysquake driver to lpsolve for ubuntu linux and examples
lp_solve_5.5.0.15_Sysquake_exe_osx32.zip 32 bit Sysquake driver to lpsolve for Mac OSX (Intel) and examples
lp_solve_5.5.0.15_Sysquake_source.tar.gz Sysquake driver source to lpsolve with examples
lp_solve_5.5.0.15_scilab_exe_win32.zip 32 bit Scilab driver to lpsolve for Windows and examples
lp_solve_5.5.0.15_scilab_exe_win64.zip 64 bit Scilab driver to lpsolve for Windows and examples
lp_solve_5.5.0.15_scilab_exe_ux32.zip 32 bit Scilab driver to lpsolve for ubuntu linux and examples
lp_solve_5.5.0.15_scilab_exe_ux64.zip 64 bit Scilab driver to lpsolve for ubuntu linux and examples
lp_solve_5.5.0.15_scilab_exe_osx32.zip 32 bit Scilab driver to lpsolve for Mac OSX (Intel) and examples
lp_solve_5.5.0.15_scilab_source.tar.gz Scilab driver source to lpsolve with examples
lp_solve_5.5.0.15_octave_exe_win32.zip 32 bit octave driver to lpsolve for Windows and examples
lp_solve_5.5.0.15_octave_exe_ux32.zip 32 bit octave driver to lpsolve for ubuntu linux and examples
lp_solve_5.5.0.15_octave_exe_ux64.zip 64 bit octave driver to lpsolve for ubuntu linux and examples
lp_solve_5.5.0.15_octave_exe_osx32.zip 32 bit octave driver to lpsolve for Mac OSX (Intel) and examples
lp_solve_5.5.0.15_octave_source.tar.gz octave driver source to lpsolve with examples
lp_solve_5.5.0.15_FreeMat_exe_win32.zip 32 bit FreeMat driver to lpsolve for Windows and examples
lp_solve_5.5.0.15_FreeMat_exe_ux32.tar.gz 32 bit FreeMat driver to lpsolve for ubuntu linux and examples
lp_solve_5.5.0.15_FreeMat_exe_ux64.tar.gz 64 bit FreeMat driver to lpsolve for ubuntu linux and examples
lp_solve_5.5.0.15_FreeMat_exe_osx32.tar.gz 32 bit FreeMat driver to lpsolve for Mac OSX (Intel) and examples
lp_solve_5.5.0.15_FreeMat_source.tar.gz FreeMat driver source to lpsolve with examples
lp_solve_5.5.0.15_Euler_exe_win32.zip Euler driver to lpsolve for Windows and examples
lp_solve_5.5.0.15_Euler_source.tar.gz Euler driver source to lpsolve with examples
lp_solve_5.5.0.15_Python2.4_exe_win32.zip 32 bit Python 2.4 driver to lpsolve for Windows and examples
lp_solve_5.5.0.15_Python2.5_exe_win32.zip 32 bit Python 2.5 driver to lpsolve for Windows and examples
lp_solve_5.5.0.15_Python_source.tar.gz Python driver source to lpsolve with examples
lp_solve_5.5.0.15_Sage_source.tar.gz Sage driver source to lpsolve with examples
lp_solve_5.5.0.15_PHP_exe_win32.zip 32 bit PHP driver to lpsolve for Windows and examples
lp_solve_5.5.0.15_PHP_exe_ux32.zip 32 bit PHP driver to lpsolve for ubuntu linux and examples
lp_solve_5.5.0.15_PHP_exe_ux64.zip 64 bit PHP driver to lpsolve for ubuntu linux and examples
lp_solve_5.5.0.15_PHP_source.tar.gz PHP driver source to lpsolve with examples
lp_solve_5.5.0.15_vb.net.zip example calling lp_solve API from VB.NET.
A starting point if you want to use the lpsolve API from VB.NET).
lp_solve_5.5.0.15_vb.zip example calling lp_solve API from VB6.
A starting point if you want to use the lpsolve API from VB6.
doc/set_var_branch.htm0000644000175000017500000000750410237176664014003 0ustar renerene set_var_branch

set_var_branch

Specifies, for the specified variable, which branch to take first in branch-and-bound algorithm.

unsigned char set_var_branch(lprec *lp, int column, int branch_mode);

Return Value

set_var_branch returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable on which the mode must be set. It must be between 1 and the number of columns in the lp.

branch_mode

Specifies, for the specified variable, which branch to take first in branch-and-bound algorithm.
Can by any of the following values:

BRANCH_CEILING (0) Take ceiling branch first
BRANCH_FLOOR (1) Take floor branch first
BRANCH_AUTOMATIC (2) Algorithm decides which branch being taken first
BRANCH_DEFAULT (3) Use the branch mode specified with set_bb_floorfirst

Remarks

The set_var_branch function specifies which branch to take first in branch-and-bound algorithm. This can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
The default is BRANCH_DEFAULT (3). BRANCH_DEFAULT (3) means that the branch mode specified with set_bb_floorfirst function must be used.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_var_branch(lp, 1, BRANCH_AUTOMATIC);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_var_branch, set_bb_floorfirst, get_bb_floorfirst, set_var_weights, get_var_priority

doc/closed.gif0000644000175000017500000000055511034166173012236 0ustar renereneGIF89a  0( @80P@@PP@`PP``Pp`Ppp`p x p`xp pА И Р 0000P@@PP``p`pppӿ؀!, @_E$|Ȥep1KIeY֕vCv6N$?oeةU־,J# Hz875}c&#!6d~!H)63 H4&  >A;doc/print_tableau.htm0000644000175000017500000000530410461512134013631 0ustar renerene print_tableau

print_tableau

Prints the tableau.

void print_tableau(lprec *lp);

Return Value

print_tableau has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The print_tableau function prints the tableau. This function only works after a successful solve
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_tableau(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, print_objective, print_solution, print_constraints, print_duals, print_scales, print_str, set_outputstream, set_outputfile, print_debugdump

doc/is_scaletype.htm0000644000175000017500000000706710237176660013507 0ustar renerene is_scaletype

is_scaletype

Returns if scaling type specified in scaletype is active.

unsigned char is_scaletype(lprec *lp, int scaletype);

Return Value

is_scaletype returns if scaling mode specified in scaletype is active.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

scaletype

SCALE_EXTREME (1) Scale to convergence using largest absolute value
SCALE_RANGE (2) Scale based on the simple numerical range
SCALE_MEAN (3) Numerical range-based scaling
SCALE_GEOMETRIC (4) Geometric scaling
SCALE_CURTISREID (7) Curtis-reid scaling

Remarks

The is_scaletype function returns if scaling mode specified in scaletype. This can influence numerical stability considerably. It is advisable to always use some sort of scaling.
set_scaling must be called before solve is called.
SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC, SCALE_CURTISREID are the possible scaling algorithms.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int scaletype;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  scaletype = is_scaletype(lp, SCALE_MEAN);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_scaling, get_scaling, set_scalelimit, get_scalelimit, is_integerscaling, is_scalemode

doc/MathProg.htm0000644000175000017500000002115010455256256012533 0ustar renerene GNU MathProg

GNU MathProg

GNU MathProg is a modeling language intended for describing linear mathematical programming models.
Model descriptions written in the GNU MathProg language consist of a set of statements and data blocks constructed by the user.

See http://gnuwin32.sourceforge.net/downlinks/glpk-doc-zip.php for a complete description of this modeling language.

GNU MathProg is part of the GLPK solver. See http://www.gnu.org/software/glpk/glpk.html and http://gnuwin32.sourceforge.net/packages/glpk.htm for the homepage of it.
Note that MathProg is a subset of the AMPL modeling language. See Using lpsolve from AMPL.
The XLI used by lp_solve to read these models is derived from this code.

lp_solve can read/write and solve these MathProg models directly via the xli_MathProg XLI driver (see External Language Interfaces). It reads such a model in above format and can solve it then.

For example:

lp_solve -rxli xli_MathProg Diet1.mod

This gives as result:

Value of objective function: 88.2

Actual values of the variables:
Buy[BEEF]                       0
Buy[CHK]                        0
Buy[FISH]                       0
Buy[HAM]                        0
Buy[MCH]                  46.6667
Buy[MTL]                        0
Buy[SPG]                        0
Buy[TUR]                        0

MathProg has also the possibility to have the model and data in two separate files. lp_solve can handle this also. For example:

lp_solve -rxli xli_MathProg diet.mod -rxlidata diet.dat

This gives as result:

Value of objective function: 88.2

Actual values of the variables:
Buy[BEEF]                       0
Buy[CHK]                        0
Buy[FISH]                       0
Buy[HAM]                        0
Buy[MCH]                  46.6667
Buy[MTL]                        0
Buy[SPG]                        0
Buy[TUR]                        0

Generating MathProg models

The XLI can also create a MathProg model, however it doesn't use the strength of the language. Constraints are written out line per line. But it can be a starter. For example:

lp_solve model.lp -wxli xli_MathProg model.mod

This gives as model.mod:

/* Variable definitions */
var x >= 0;
var y >= 0;

/* Objective function */
maximize obj: +143*x +60*y;

/* Constraints */
R1: +120*x +210*y <= 15000;
R2: +110*x +30*y <= 4000;
R3: +x +y <= 75;

API

Use the lpsolve API call read_XLI to read a model and write_XLI to write a model. See also External Language Interfaces.

IDE

Also from within the IDE, this XLI can be used. However, some entries must be added in LpSolveIDE.ini (in the folder where the IDE is installed).

In the [XLI] section the following must be added:

lib1=xli_MathProg

And a new section for the MathProg XLI must also be added:

[xli_MathProg]
extension=.mod
language=MATHPROG

Then make sure that the xli_MathProg.dll is available for the IDE. This must be done by placing this dll in the IDE folder or in the Windows system32 folder.

Example models/data

Diet1.mod
set NUTR;
set FOOD;

param cost {FOOD} > 0;
param f_min {FOOD} >= 0;
param f_max {j in FOOD} >= f_min[j];

param n_min {NUTR} >= 0;
param n_max {i in NUTR} >= n_min[i];

param amt {NUTR,FOOD} >= 0;

var Buy {j in FOOD} >= f_min[j], <= f_max[j];

minimize total_cost:  sum {j in FOOD} cost[j] * Buy[j];

subject to diet {i in NUTR}:
   n_min[i] <= sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i];


data;

set NUTR := A B1 B2 C ;
set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ;

param:   cost  f_min  f_max :=
  BEEF   3.19    0     100
  CHK    2.59    0     100
  FISH   2.29    0     100
  HAM    2.89    0     100
  MCH    1.89    0     100
  MTL    1.99    0     100
  SPG    1.99    0     100
  TUR    2.49    0     100 ;

param:   n_min  n_max :=
   A      700   10000
   C      700   10000
   B1     700   10000
   B2     700   10000 ;

param amt (tr):
           A    C   B1   B2 :=
   BEEF   60   20   10   15
   CHK     8    0   20   20
   FISH    8   10   15   10
   HAM    40   40   35   10
   MCH    15   35   15   15
   MTL    70   30   15   15
   SPG    25   50   25   15
   TUR    60   20   15   10 ;
end;
diet.mod
set NUTR;
set FOOD;

param cost {FOOD} > 0;
param f_min {FOOD} >= 0;
param f_max {j in FOOD} >= f_min[j];

param n_min {NUTR} >= 0;
param n_max {i in NUTR} >= n_min[i];

param amt {NUTR,FOOD} >= 0;

var Buy {j in FOOD} >= f_min[j], <= f_max[j];

minimize total_cost:  sum {j in FOOD} cost[j] * Buy[j];

subject to diet {i in NUTR}:
   n_min[i] <= sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i];
diet.dat
set NUTR := A B1 B2 C ;
set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ;

param:   cost  f_min  f_max :=
  BEEF   3.19    0     100
  CHK    2.59    0     100
  FISH   2.29    0     100
  HAM    2.89    0     100
  MCH    1.89    0     100
  MTL    1.99    0     100
  SPG    1.99    0     100
  TUR    2.49    0     100 ;

param:   n_min  n_max :=
   A      700   10000
   C      700   10000
   B1     700   10000
   B2     700   10000 ;

param amt (tr):
           A    C   B1   B2 :=
   BEEF   60   20   10   15
   CHK     8    0   20   20
   FISH    8   10   15   10
   HAM    40   40   35   10
   MCH    15   35   15   15
   MTL    70   30   15   15
   SPG    25   50   25   15
   TUR    60   20   15   10 ;
model.lp
/* model.lp */

max: 143 x + 60 y;

120 x + 210 y <= 15000;
110 x + 30 y <= 4000;
x + y <= 75;
doc/semi-cont.htm0000644000175000017500000001766410503616032012711 0ustar renerene semi-continuous variables

semi-continuous variables

Semi-continuous variables are variables that must take a value between their minimum and maximum or zero. So these variables are treated the same as regular variables, except that a value of zero is also accepted, even if there is a minimum bigger than zero is set on the variable.

image\img00340.gif

The practical usage of such variables is the following. If the variable is taken then take at least the minimum or else don't take it at all. For example in a blending problem this could mean if an amount of a raw material is taken then it must be at least the minimum or else take none at all. This because less than the minimum cannot be weighted for example. If a fixed minimum would be set then it would not be allowed to not to use the raw material at all. However via semi-continuous variables it is possible to state this kind of restrictions.

Since release 4, lp_solve has supported semi-continuous variables via the API call set_semicont or in the mps format in the bounds section via the SC bound type. See mps-format. If there is no minimum set on a semi-continuous variable then the default minimum is 1. The SC bound type normally needs the maximum in field 4. However this value may be omitted. In that case an upper bound of infinity is taken.

Example:

NAME
ROWS
 N  r_0
 L  r_1
 G  r_2
 G  r_3
 G  r_4
COLUMNS
    x1        r_0                 -1   r_1                  1
    x1        r_2                  2   r_3                 -1
    x2        r_0                 -2   r_1                  1
    x2        r_2                 -1   r_3                  3
    x3        r_0                  4   r_4                  1
    x4        r_0                  3   r_4                  1
RHS
    RHS       r_1                  5   r_4                0.5
BOUNDS
 SC BND       x3                  10
 LO BND       x3                 1.1
ENDATA

The red lines are two lines that specify that variable x3 is a semi-continuous variable with a maximum of 10 and a minimum of 1.1. If the LO entry would not be there then the minimum would be 1, the default. If the 10 is omitted in the SC entry then there is no maximum.

Since lp_solve version 4.0.1.10, lp_solve also supports semi-continuous variables in the lp-format See lp-format. The above mps example would be in lp-format:

max: x1 + 2x2 - 4x3 -3x4;
x1 + x2 <= 5;
2x1 - x2 >= 0;
-x1 + 3x2 >= 0;
x3 + x4 >= .5;
x3 >= 1.1;
x3 <= 10;

sec x3;

If the line x3 >= 1.1; is omitted then there is an implicit minimum of 1. If the line x3 <= 10; is omitted then there is no maximum on the variable. The new section sec is analogue as the int section and specifies all the variables that are semi-continuous. Multiple variables can be specified separated by a comma (,) or space.

The solution for this model is:

Value of objective function: 6.83333

Actual values of the variables:
x1                   1.66667
x2                   3.33333
x3                   0
x4                   0.5

Why does it take 0 and not 1.1? Because the objective value is better if 0 is taken than 1.1. If the variable would not be semi-continuous (delete sec x3;) then the solution would be:

Value of objective function: 3.93333

Actual values of the variables:
x1                   1.66667
x2                   3.33333
x3                   1.1
x4                   0

6.83333 is a better solution than 3.93333

If the model is changed to:

max: x1 + 2x2 - 0.1x3 -3x4;
x1 + x2 <= 5;
2x1 - x2 >= 0;
-x1 + 3x2 >= 0;
x3 + x4 >= .5;
x3 >= 1.1;
x3 <= 10;

sec x3;

Only the cost of x3 is changed here from -4 to -0.1. The solution of this model is:

Value of objective function: 8.22333

Actual values of the variables:
x1                   1.66667
x2                   3.33333
x3                   1.1
x4                   0

Now the solver takes the 1.1 as value because this solution is better than if 0 would be taken. This can be proven with the following model:

max: x1 + 2x2 - 1x3 -3x4;
x1 + x2 <= 5;
2x1 - x2 >= 0;
-x1 + 3x2 >= 0;
x3 + x4 >= .5;
x3 <= 0;

sec x3;

This gives as solution:

Value of objective function: 6.83333

Actual values of the variables:
x1                   1.66667
x2                   3.33333
x3                   0
x4                   0.5

6.83333 is worse than 8.22333, thus the solver takes the 1.1 solution.

Note that semi-continuous variables may be combined with integer variables. The same rules then apply, but the variable must also be integer then.

For example:

max: x1 + 2x2 - .1x3 -3x4;
x1 + x2 <= 5;
2x1 - x2 >= 0;
-x1 + 3x2 >= 0;
x3 + x4 >= .5;
x3 >= 1.1;
x3 <= 10;

sec x3;

int x3;

The solution of this model is:

Value of objective function: 8.13333

Actual values of the variables:
x1                   1.66667
x2                   3.33333
x3                   2
x4                   0

Because x3 must now be integer, it takes the value 2 instead of 1.1. The objective value 8.13333 is still better than he objective value if x3 would be 0 (6.83333).

In the mps format this can be either specified via the SI attribute or via SC attribute with the MARKER INTORG, MARKER INTEND in the COLUMNS section:

ROWS
 N  r_0
 L  r_1
 G  r_2
 G  r_3
 G  r_4
COLUMNS
    x1        r_0                 -1   r_1                  1
    x1        r_2                  2   r_3                 -1
    x2        r_0                 -2   r_1                  1
    x2        r_2                 -1   r_3                  3
    x3        r_0                0.1   r_4                  1
    x4        r_0                  3   r_4                  1
RHS
    RHS       r_1                  5   r_4                0.5
BOUNDS
 SI BND       x3                  10
 LO BND       x3                 1.1
ENDATA

Or

ROWS
 N  r_0
 L  r_1
 G  r_2
 G  r_3
 G  r_4
COLUMNS
    x1        r_0                 -1   r_1                  1
    x1        r_2                  2   r_3                 -1
    x2        r_0                 -2   r_1                  1
    x2        r_2                 -1   r_3                  3
    MARK0000  'MARKER'                 'INTORG'
    x3        r_0                0.1   r_4                  1
    MARK0001  'MARKER'                 'INTEND'
    x4        r_0                  3   r_4                  1
RHS
    RHS       r_1                  5   r_4                0.5
BOUNDS
 SC BND       x3                  10
 LO BND       x3                 1.1
ENDATA
doc/set_break_at_first.htm0000644000175000017500000000557610237176662014662 0ustar renerene set_break_at_first

set_break_at_first

Specifies if the branch-and-bound algorithm stops at first found solution.

void set_break_at_first(lprec *lp, unsigned char break_at_first);

Return Value

set_break_at_first has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

break_at_first

TRUE or FALSE. Stop branch-and-bound algorithm at first found solution or not.

Remarks

The set_break_at_first function specifies if the branch-and-bound algorithm stops at the first found solution or not. Stopping at the first found solution can be useful if you are only interested for a solution, but not necessarily (and most probably) the most optimal solution.
The default is not (FALSE) stop at first found solution.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_break_at_first(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_break_at_first, set_break_at_value, get_break_at_value, set_obj_bound, get_obj_bound, set_mip_gap, get_mip_gap

doc/get_upbo.htm0000644000175000017500000000606111127442423012610 0ustar renerene get_upbo

get_upbo

Gets the upper bound of a variable.

REAL get_upbo(lprec *lp, int column);

Return Value

get_upbo returns the upper bound on the specified variable. If no bound was set, it returns a very big number, the value of get_infinite, the default upper bound.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable. It must be between 1 and the number of columns in the lp.

Remarks

The get_upbo function returns the upper bound on the variable identified by column.
Setting a bound on a variable is the way to go instead of adding an extra constraint (row) to the model. Setting a bound doesn't increase the model size that means that the model stays smaller and will be solved faster.
The default upper bound of a variable is infinity (well not quite. It is a very big number, the value of get_infinite).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL a;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  a = get_upbo(lp, 1); /* will return 1e30 since no upper bound was set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_upbo, set_lowbo, get_lowbo, set_bounds, set_unbounded, is_unbounded, is_negative

doc/set_obj_fn.htm0000644000175000017500000001312710351321432013107 0ustar renerene set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj

set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj

Set the objective function (row 0) of the matrix.

unsigned char set_obj_fn(lprec *lp, REAL *row);

unsigned char set_obj_fnex(lprec *lp, int count, REAL *row, int *colno);

unsigned char str_set_obj_fn(lprec *lp, char *row_string);

unsigned char set_obj(lprec *lp, int column, REAL value);

Return Value

set_obj_fn, set_obj_fnex, str_set_obj_fn and set_obj return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

count

Number of elements in row and colno.

row

An array with 1+get_Ncolumns (count for set_obj_fnex) elements that contains the values of the objective function.

colno

An array with count elements that contains the column numbers of the row. However this variable can also be NULL. In that case element i in the variable row is column i.

row_string

A string with column elements that contains the values of the objective function. Each element must be separated by space(s).

column

The column number for which the value must be set.

value

The value that must be set.

Remarks

The set_obj_fn, set_obj_fnex, str_set_obj_fn functions set all values of the objective function at once.
Note that for set_obj_fn (and set_obj_fnex when colno is NULL) element 0 of the array is not considered (i.e. ignored). Column 1 is element 1, column 2 is element 2, ...
set_obj_fnex has the possibility to specify only the non-zero elements. In that case colno specifies the column numbers of the non-zero elements. This will speed up building the model considerably if there are a lot of zero values. In most cases the matrix is sparse and has many zero value. Thus it is almost always better to use set_obj_fnex instead of set_obj_fn. set_obj_fnex is always at least as performant as set_obj_fn. Note that unspecified values by set_obj_fnex are set to zero.
The set_obj function sets the objective value for the specified column. If multiple objective values must be set, it is more performant to use set_obj_fnex.
Note that it is advised to set the objective function before adding rows via add_constraint, add_constraintex, str_add_constraint. This especially for larger models. This will be much more performant than adding the objective function afterwards.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL row[1+2]; /* must be 1 more then number of columns ! */

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  row[1] = 1.0;
  row[2] = 2.0;
  set_obj_fn(lp, row);  /* constructs the obj: +v_1 +2 v_2 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex, add_column, add_columnex, str_add_column, set_column, set_columnex, get_column, get_columnex, get_row, get_rowex, get_mat

doc/MATLAB3.jpg0000644000175000017500000023221510251411702012012 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?i_[yfHix>K som>Ah[uVmP:_>$/_ 9 bWks H7^gßx~*~$iϧxkZ& n-/Jkk ./u YX{u,6I"z7!K ? ۯ5{qez  wڧ<_ͨYxK42">|[h~$]~_M轞q.E! 3?_ RT希Zzt儤`RHrSqUZE88ejFgxpf_ VgWN 4ʝ9h]3?<#Fɯ$ֿ=f+({](-Osm!9' , }yi߈lm\1yz%?)_SK|-kvↁolV֖ClX50nsex߱7Ri߳7}Mj?|?O^⾍WM #$ԠhOxbmO[{xAniqsqkzQpsFqyn[_ᬧ#eVW1E<^i[/QS.1r%K AT^%F8.skp^O 48ƿ ,G7z_٧M}?\t>$tψ¿5/[MGjz&iDe"KJ 1 ?!ᄭUYYOȝ9RWF8q3 .aBCRU4jSU(UV5 ?-_G4O Y-uz7Rk퇇m?P4dxZW챬^Icg(g-> WCYjYi}վuIOw$_~xs_~X|Bف| uo~3|.5M+ķ?<==oK+;cOxG#|51 Ҝc'^1qj2Njr늫EN h7$K,ESZIJn4Q-tRݣ8OD5" ?-_^ǞOCx7_O|+|}kh t=_2oi}'ŭb}xW^%>!M> d |?/zΚ±/HG_r?xrZ O~s C ; aUq 9ޭjY-)E̳ԕ jxLGvUwyv6aZj1u*2Xp4 =U7W5UR !OD5" ?-_\?'|izsZg??~x!^,oV🈬&|WXxmw73iۺnyx+OÞ#$ZŞ /|Ak/ h_l;S YOW2WKZWG`*ԫG*8 kҮհVNPFEUgØ=x6i̡R}L^ JxҝV*]HT8:t ߒJO?"ehAk/EY?fo??g߈~-W9<; 5}M\/mz7to^vszW79N<ᬯ8s-ɳx*G `xjX5Hbp`WNyW4"]Gα?{\>g:RM8_Bp>,y/>AhAk,t~yg/F _PPOb"~__8y-cGF Yo_/8]?y1U/G???'=?ݏ]Kv?td`U P_ [t} A?>"~__8y-cGF Yo_/8]?y1U/G???~_>xk7>5|)EaI>|@1>&l ռ3+O>)%[={A5m7[ɤW>Kv?u o|;$q~߱MɅ[ybL9r99'J? )T̿x_>YW .[_&{?ײfnTSZv7MԔpgu3Z!J*~ҳסZJ8F0N7)IO1>d23\ڿtAq| c3~mϦq>'<x_Zg7~|Q5ޭaĺօ=GQ5M3rkĖ6hzgS1lƖ'S(d&pAyVGuc-B >aRtq ]*OU0~5*|F&γ uyíNWb),Ni(Nxy7Fu9SRTOz=O~X_|~|Ok࡮4O\|->"Fso趞)4-F;[O,onz{ZbU$1o~$q u`JxmK+$0)9MJ^ơUxs]ŃYxf?&[kvZI< ݵfk=R5FE;To4+]gƞ Ӽ9]j7u{o}[=}wLWS\kb18 C3̱ r<'.K N|AFcbhU1gK4sSbSeVZyqļj9tn"J4bQJ+CǺ'|MGk?K|`m~OuC7>O kģIlmrQ,4ϡ/دm%jٿ[F]͏%'hIm_\O jlmG^#KiӵK9"#5<]<V;@.M~|OK㎿3 hÿڎtO>-+-IԼ3HmWQo[Q7&РgL~ypRY ^uż3TƼ b25S`*agՆw{RVW{.#bR3fa,2%W* KK0ż.v+xL/b*X1/$@;{>1| zm?$K<>w=;N^u95η˻ {~muEk_5~? zYOp,EsSÙyH昼-V˫B!(}<.7 "ki.Yycc?c,JG6Xxg<|~C,uJZhC>M徚.7W³9_lӿTb}\ T GBG4W^+xsX?oWHbsPO=!Jq TNh1_|)aJU9J&۝6pmMj|῅ U!u/KK+χv:g%+Kwgv:ǥz6g[^m?߲;|P|xwD^<) m?ivyZֵFѴm'Z|;iuo~5I?lOxG1xqc4qH|)??Sa.?4x<ٵSTm;[_Sm|mq2|1#w>}\u9WI Ӏq|Oxi5g^#SϪPQӝ84^\;V'ZSq+,fOe> |O#x4 HzocY_^啍学}~!~G9|yg=> c obG N/Q%kî+1'\e^< L偩`ʘ/9fҧ QUqOm|q^6mpN>\t TrYOjQ*/ K%˰zէYQaP%пcO˥|6k <1|+֭hk; k_ |N<þ4<=|V,o]ZQ5Nk ߀1i=oVWw)?Hb5/_n5ƞ_xoP>8KO[LWoỎf5x_Z|@,-浼ˋ[[kySSC*4r̎A?߿O?jo߱o_}o6h?'|W/}c|}q-/ C8y# x(yc3Zx:K2]\." c%丵9j@8/.+cypq a93\>#uppyKpW:cprvU0#{?!.|mOi>c}|}?~'~v?'#~ ~7~%j_k xQe៊~d5sZ;~_Rd-0I}IF}qy'!͂P0yl^/a8-[Kes8 U)eҡNl./K0xh*p7p[x:85<3b)iѪ™^7 V8bwg?>d~>|)?doi ojr|@xOEMSzπlcv5ψu i5"KFa'N~0g?e%xs[״6?g~xj-NSeO>:Y7>xK~jOOr4É?o)?_?񟉟A/}*; 8r8c<5Lk.̲|-L,cr|1'B+c=xB=Jy/ VK*uiJtpTxu\~\K*T|s_jO|T_?/gBm+GO1Ӽui>/ş <'x?UMO2=ωmU[h>oz_:RInlm./s^oZyQoxli-CqA$[`#G8%o}w}"~aq8<ǜ3 ~.mW78:l9'aeb*88a?Tj8*PRo jpc…  άO?\QUγ _ j"Fex,ENxʮ5jTf:N7 QmX(E+KI}IFq'E'K9OߢN0K??̿<7?mX(E+KI}IFq'E'K9?s~y8G\/W?^])w/M[/֦;U7oM7O_&f?# oS?d-2'CG?#P>KώG?=o_F/G# ٯqE3H/9z??# o-OztkkCL?^qE3H/9z?t>xC2>_lļD~?޶ea40?S?d-2CL?^>̏@[/>:/0_oM~x{o_oO@|esKc ^KM{V? hL %1:eEM8y}M:?qE3H/9z eH|;^Ni~L>x[㖻[iZwW_PO|AnILz!Դ{x.3|BuzWʺ%mݢ#V/g簲a=ZHGb'@H%dRX*F+L) 0C0߱F:c 1ڹO%^4DŽ5 ?Ut/P4k|E>']Xh|`{˖ɲG7p3Ď9Lrꘘ׆VxZ5<5 'TT% 4̳/&'e.ᬇ*us<RWx'7FXϬ֩ j%M9: U}?[WjVa\g]>]:+?09ReZU~\Qv_~|K/o?f+SoiR6CP:}ؼ++ȓT]曦i4^%]MvM a=+NKνJM;IҬ :&@Dpx;c~l>R3|`_|6rҎsj5pyl[_8*cr R1O;5eWWqWةc0+}NxꙌ(a-^JhJ%8ԩ%"|Qᛵ>æT? ź_VYc)%H$]Z~oo hh#jk/ .LW^'ƚ[k^a-ksϡxL y} 9=:Lj/ |$ѵ?MtQُ^œA鶲JZi6[Kxc[&K_KOze/Vzʢ}[ľ-?=nOxU^IMByf>K9 V yG,,l&U=hUӴ/8>^k?? >z;x=o_:uu _RծΥq@ߣI?UwTpY?+qSęxp8ns#<0n3C ˡMa+?G-ϣ\ߊ4s rCE 9eVeZF/ Ub1^l]jYHʼn5a>OTsNO{UMnXuyԸY;T2.]6@8$g4W'*vZve]k7m7O||_eT?:iDumҞ)࠺ρZڟSue~> Qxv[sn]ŏHE4V |-5V}8aeTG::h>]Uf~6x;2|3&xO :,  t:#OSi&r|A>Y6wZBσlޙJO_ֵm4wm>W:~ܿ>%_xg_?inw~Zh k:-9> /3FUi:7 xO_?]~"s[j}sz7.i~/Ak=oO |CѼ3E|(վ'[Y|CG? xc:7~ xuZtggJN6IhҼs)%i4JK^_k_4w?]{?V(|k't#&ໟR|(GJե𞁯i]lGC~_6:?M~9>|~?-M~,9 G?N:w>WsᏌǞewïxKZ?|3iK¾;SP$4ԟZ_-wSĽ{Cdxf:M[ίk2ow kk[  oyzğ$WգICk+x>675|_w<៉^#w;J<['uSRsQn9{4T9FnI(ەg+%k4io8_~6_A^#^'%zlj36:ÍӢ_/_ |}Z/OB~%j_.⷇4[xg.Oo /gG~ x7OG.uǓ´|%kjimjMR%i;OEz/?/>J~> Gwk O엮|Q>^M[߈߷+Ea^/ߨ]H? ?~,oG ?hw:5 |kko~lٟ߇>Y~߱W/:׎;?K/׊e}Iaku4fo/7|X|g}?/o,|"cc?? 'xB~& CSH֮uVO :j_ ~_:ǝo|^Ok_QOxov5 |\  xv$3*pUa+\Z.[= ^mNnZ쯥_icXo:>,j7 ٮ+/3_':cx^/7v__/JMGI 3C}wo{~WWMw OWǟQߍF¦6g"Ϳѿ'.Et*JQPrr5Zsh+rm*3O C5ߊ_ƿ| NW~ş u/ÿ|Mj W| Mw^>^=𾣫|N|3GcEόG]+Zu\(_⟌_@-#I|Fw 3Q>)xG&{'V<-Hʂ8ݢԣǟ[KE9Y]>WeeK;iu?>+W<3Nυ6|B~3? 3O _ |w[GAo-^ 7AޟM=5%S<)ğ(#s/ݮaH5O/x^&|]7v_Ou-[> ?Ooxƺ_/.?`Oٖo CF/?i ~> <]_H5j bi_ᆇx_Iᛝ =M _~ZxCf/~h t/ x⮻x>|!&]'¯^"f|3i7?߄ r?: |37ï xL$\Z&ԮqiU J ;IT%k/}{]g÷~54/B.<[_Z3xm>M{Huo UFwgxSW5 oOSndm0%xG_ׂu _⏎ kw~%|56uk Fÿgس5/HZN6ǦkZv;C>q^д~(Gqk?D;xƺZ{޹ßgό ; u?xB5ំg<{C/ UGi/ZůO_r(?7@WKOxTQue^T>jQqWYܚ\I=,PRJiַk%uGoҿC4iOG~|9=_IC[~>ϊ?'״ɼ {u>+E~ki򏏿:.b:|uV~_3sOfଞ?[ƝE σ/' _ƿ>0լ~B/KD|U ,~Ҿ kB>f7K>k~1ßcmƅ!mx ikW:xi|'~|k/Υ'=λL|B{O#=so|C׿oo:?uoiPxPkּ'|1cT# J֒JJVV2P]Ϋoߖwk}/m]: տn^g2qQi_x]So><_ٻWů׿t}__uOs¿hu/='/#'?x7<} Ꮗd࿉E{P}>x2[ߴ/ k^(mS39lEs? sD~ͷ7~.I|MxgO NA7S?#^_{o Oi=ҿkGf3w:~'g?j~~v x=C_7>7՗IᝩO #+AŨ^ә4ʣfp+Hwf֩k$W}뾧??n/cφ]bֳþ>;xkտf`_#Wo/SּYúmmQ}w]7 ~ U7|%xO6៉kI*]ҵK}^Lu}> B;;d_=x#ſĿ'x+FO>jkm? _I6ྥ|1 xw^{1,QJl8˲8]e`)q؅9a8iJ8exѫ*8ZNuƕYB o*MSbT&S6M7~ VM7~ V /ͷ;nOz:O?lߌ|.]x>CDtW_ ?ٓ&Q|L5+ۻV%ލW:ve%~_N?ٛ> Aj~&7xD'gi߲-Nn<+PC? ^R񗆣 |xNf.xJ/Z(FW߰iF2mJN8;rIw5ӏ(Z[{>gk8͊5Ÿ!xcU߹E [&/ O>zO%~s~?&iW6?Oi~+㯁Ze՗v"J4a)ʥdBJRMTi(n&s%IZ_iNA?IaXwf~uxꚮj6;msZjs5ś{okLk԰s{HK[?io~Пko_ׄ-me|;ƛ|'i?~*ʿ|.,kgZֵO(k3IG|q^5W/7|m x > >;i7zVkzUݦjeΟi6w[Mx߭`a:q%Y$入yY7ʥtrʗ%EtZY{t:}iVa|AN+\.?wБ}KmWLf"(!:MJ;C?| Fjb^m]YSakŵfו]ջjMB0Sq^]eؚoAؚoA~x0৿+~zxg+E3Zm|mq,oM_gw ~%X~}'Oԭ ><H*e)ʝI(Bv5fwMwJM+i/?%zؚoAؚoA~xZ?kO~Ɵ/??h1C_v>so?I_|C;8IxIyxD׊%uSUW"%aϧ%nKr)N[ܧdSirRPK+v_ԟM7~ VM7~ V>#e{8v_3?4=Z?4=Z9 Ek3R-~߳?FV<Y?mE.L [O[>7Cf&C?~%G¿etW7JXBW7&zSX;/Gg{履K$ש>>֝~4 W3o~6“ׇ)'㙵> ~Ϳ Ԯ߂+i~&4K6x/Ś߆|I?T3Tr婤"98Qcme'+F+yI+:q]nI6zlSM߈?|?ժ}iVa|AN+\.?wБ}KmWLf"(!.ֿQ|t];Ii6 ?b, B;;d_(~%xZO D)~_<;>cO}~?t߆?N_)#('/j4> O7<?|QYCXJ2MߖWQwB-~rZrOuzw=M߈?|?գM߈?|?կn(γiNMKQ𷎿:ѵ450x'ڶ7<) |g OȾ#a~^~H?h?kN>#a~^~H?h?kN>#a~^~H?h?kN>#a~^~H?h?kN>#a~^~H?h?kN>#a~^~H?h?kN>#a~^~H?k M[3?i%mV[?DO .|-"[/-g#oG,^"_H_*^3x_a|o&}W~)x6[pw[W%ۯF5]|Mw*3 ç(JO7GR>U?T|-#/~տu6ZoG؛VˉoM֓?eԭ-o,f?6_iMuks։zo|BmtMoS,VC^*c-ւ9SH U7% 8jYkZ*Rwo k!*Z]_LF%e(O#_nS4/o?kK:|n?9|xo]ޕ[ާuxF.t闚}ݱHix~~7/ں>)xZ ~<//i|C?|4{/Ӵ!5M[Ķi}_kG$C$W1Q<"7FTyjsZqq浭tݾPu=WRմj_oo|/?5Y7A ?gx@_u~<߷ +^ gڏ|!;_?>_06?' : ?":nx*e9̳-,mx.7a0%8Kc^PҮסVZPGMΛܩʜ?z2NMZ2+{4icb_Wߨ'*ӡh"Z< ekUHS|UB_ygz|u(ǟgֽ⏆?~!|_1qSCsǎ? |{_w~  kڧë ҵ{;x'ǿj2."|Z⿏='|=RCOZEAUvq=iޛU..f=/Dw>*<+ykG$C$WD8cysͱcsLΎ ,d *Yu::tWJUI\8NQR\m٧w;]-C%D~~+5/GFP?ڵq7|o_ٳ_ q5ڛg# {~4#+;o⟋JGOWcj\s u,$qڗmV2.NY([ S^.E)IrEJ֌[劲V6SoI|Iu|#xW/λmW#OƾO|:OW),u_ZPGtxgF9 g|'3Gt= K<;xkN~]=4K [ۛxyH,!3;PDTZ_06QD҅T ƜӴ%xRM])+pQbnϽ~gwk6GoaտeM ¾2>+>'o~oڗA] ;_V~7|WOzG ᇁ5 |+փo\ͫ/maOt?XEkSYb+ԕYR.^ornJRWZsJZGK.I)FmV>)@EgطG|Cv|T/_?hR7¿>7rύ4/|t?}[3c~$q[Sfػe[_~߶/=B7τ쵢$W_ρU]WΫa3Džuh>)[9)gG$C$Q ?amaT2iJmڹ[Tpח܄mˡ.0r\ImfܯƟ)_~&|>y~?]?OY?ٷच]o+?oڻ.;XY\׉<3wH5O_$C$Q ?ama(U5?m'ʧNn*VdkK%^-IJ-Rq:W]4KjC_'?~wOu}K#Χ3I窌jmoY=l̟4m%ݸ[Gf|#| >6?٧ផNOh /t_޻w_6|I3׎t ߳߉h~~?z'3мڇ /Q=S׃?[85^V_ÿZOڋO13GѼ[^_X_$C$Q ?ama5x0RMT'(Z(.q9Eӏ,_+zZ-֩$dٻ5|+^м!hZG%/ 3 OtwAm4B4KM3H4Km?Mᶆ83L|~>bo_ xoB~ڟ~JN'?^]B>$~:V?Z꿴?fOI5CkH á*)F9=JTݒ/dQmEǛ7di}5tυQ(O? ்uٻu Wwi7x㗋3׵?o)ҿd]-O6VxNρ3x+ú< H𿄼%}#O|/N:MhZ&iiiFim}6$C$Q ?ama2y$hӚMmoK+^QNN+&׭Z.[Kǂ/\BÏxw爴~"'>|Ҽ~(}}/Om+k^o@txoBw'>w}SEGLO3ǎ*xF$ǿj> #_k /~ ?amaOt?XE%JԺO}5/x2uߝr_06?' : ?"U\}G_UV$C$Q ?ama{ y9} ?amaOt?XEƷ^kh4~u_yEaOt?XEkG>Ú?]WnQXkG$C$QkϪ._G_UV$C$Q ?ama{ y9} ?amaOt?XEƷ^kh4~u_yEaOt?XEkG>Ú?]WnWQN׷_^  á+ G藿LfYҮdOj6&ώ d}E3#Fvڧj+1‚GGUWvTIxsmI$"mk%nx(?yW q wC'ѭE-~]5*_S?ikJNJ?"o6eYJ &ɣkUTZM) GI&ㄿY8+P((((((((((((((((((((((((ί+'o~uY?{|5^>C$#ğƟ+{?z(˿F%OJg4KIG?k/ۧoxOGxUXQ<{^hOoi >i[ i֚|v9=otge?_g, euG:323u2躠:]QŝL.hfF~_fο_Tã?c/?g_S/+ٿџ~ٟ)E~lY=-ix'u|F׈J5/ Y>_N_C/u?nk|!׋?R=; X麞/:g홬閺ݮ:׈<x_x NTQ_e)IJN^*JX}jnM:S ߻2(fF~_fο_Tã?c/?g_S/n~ٟ<9 : X!gſ:]P^ŝL.F~_fο_T4Wã?c/?g_S/?џ~ٟ)Ex~lYtge?_g, eu@3E{7:323u2躯>4?f=#ďlƶ?nM*sK'^ot]|?jE?|cc_&Xӝ(II*pD ;FU"yjN*vx|uz9`)SVsIb%OeWF.έ<-YЎ&jf4a៵wHi2G߅;~ oOxqjG~㟆=|:ƛxv]?PGIε8(:ଟ{_d~~Ww'/;e!5OKN׭#ZBZׂ'Ϡ|Eߏ|Y d޷i~Bn3?''*~~_>x?DŽ |q z'o4i6L_L~1xGŸ#{ n|X|?=?jz7tOS-[3Su-CJ/nm 2;21,e͞: ^K h1Y{úIU}U r1PabjFS'O03S w3I{6k]^Q_3?Xٓ*/IG,~9$^|Gxg?lF>ics~z6!:[ݢI #&|7rl'7$?ő?;i N*(xگOk/9a?H\Wᡟe쾱d׋kyIY?tW1Q_w{4_wEk&xX{_Eeö76_uVuo4h^Ưx-߆gkB$s03<1 chN2% \]:UJ3:qjQZhaRbNp$EL( ( (1|KxÚah+MW^)twÞ%c>Auk:&]]iڮ73]5F0|/ N2k޻qk~5j]VZǀ!t_E/ ú>=oD+?5^-/"|;woko>iP4MSN4MR_׉1]K7kizG| j'| C5&֥'(֢⹛TӓNTjI2qNcN2JrBӣ[-#VWNGAFX.gNcJjӅIkṴt*Ub[_0|?7zh~~UdBo__Í;F4M3O[dMT>"I |kƯՍh)J7PJt*umFpzI&XE lS ZTДa߱*NS ^+NJNXT(N ((((>"|;h~&BCK4K4O?5 rKσixgKt^ԴO|\vh> |mJ5br%:u ҩJM)ҒMũFP NXN v1ҩN4RM־+w 6(~ a]*Q_%']w?KE 5*1RX5 )(էw'8OIEPn-G Tcb#Y)Og_p85]>OhښvEL *B5!%iBqRiFI7bq8:XԿhvchgg:|EVK?^^q3?`:B#v}|J>8xŸPh?iPGFWKHmJQI94irW+b(t7QAӜu4/m΢wNwRtX63>89#qxz1O O*WMEPN<)ᬣPt(O<+ (/+__VOG^ q|=׾~y) \n~]5褻'эE?Srҙ-)S]IG*O3߆~xO> |9}n?򐿆f wҕW3A8UuKoᶡ lKͨ[KGYlc["ib}V+Γh}3,6Qfi%GMxCJC(TbcC/FֳeFp4DVyu|aeKU))TLmzUiԆ ~tp8_vxTa0(qhnm#Aʷj_4-'ǖ? )x@Yx wtxsGNJtgÐ(ExAœ1ŘXรN"Sʆu:teUENt2oaR\ߵQJ9))B-kF|">#? )$a_π~xN9VÞ.G߉zޅ?_jZ2 ,q?]ycZ?/xQgrh~ ?.,o-q:_Q_μQ8OLUp*pmYQu>x =("#RN,ʍSEtM^ߜ?I6nmR~:wÚ¿^? 3>ƺ߄ ccž<.o5{xo<ǭ=ׅO!50״ "__7>7^>&Auy&~')ψX1灵Okg?v_ u6x]@|=}>!{ J` YW_d[TWqnanim+ ^]FAпQx_Ư_>:o/&~k>")Þ*<}+o=^-ҾFmĆG >4|6Zqm>Y|1O-XJ"\#^ݥEJRZVTMpCMՍ1"Wv6"BK^cRXͩe3L-H96|9{×Əes^s_mcx_7Sռ'LԵ2[5^5}Z<xKgoz}tBqR]TѧfiGW׫ҕdRx&i2R g JeQT`QEQEQEQE\?z48?"ƾkj_144w~> x^/tnc>!1Xj.acX%ׇ*kz?fo>!oK_-~=B{x[>.SAj7?G~z?<9៊5Tj/gVӨ8iqd%i{,x # x ]4OZh^9Bq4+Qn\(Š((((ɯ*_L?UWgK gvJ(+ (/+__VOG^ q|=׾~y)> H']|M[k_-OT~#Iޕ7ޜ?M#UTj"G?쫯o_қRş+1_?WM سvqEW'EP_7,CM %X)#IrG"2:As_) afgW)_DtxTjӅZUaŴҩΝJs~%Ԅ8FIQm4h򳺓b*Ҝէ<5Ju)¥9BP'IJ2N-&h|=F4mR4XrO 6Jc$9>Ym4zkIJ%Qёѣ)b^)'xgdxgh'tkVlu;$[^Zvs A$qct2ZVD!KmCR`0*p&f6cq4d9I9+]QC3*FSk*%GS}W1>#T!yHBVucѢVe N=S\5:}gW8Y]Q_Z|QEQEW+⎓f4O>[gFCx|#=-L|7~"k'ĿXM|3EcTW?e،>+ǓxJ%eb!R[&NV%$ӫRJS9Xqi}O ^- q=I~5|\mEğ;7>@W5K/eYZjkw|V=h'~xI<&uk;OwHA+>|p>x_>3|\O>kSgQk hڟ o4CKJ| KϭxV5|S^-?ς? ?iO?b<[?|mg[І MTӵMTluxÚޗ=֙ΙukZuscXwiW?_ xÖ:v_ _t?:~ ~$k_|=iH 8}?^+.Zt¿}~0Zz/Vx;⎅ OD4x&WZߍ>D|@u~j柷^I,E('B|GY=IJ>ƬTjb)^qjreXq*O'TP0ʔjUTۧBoN̲J*SU0~,+_-*|+^6O[Lпb]|.k_ۿ^(_C8 RKlirw_3עk_-OT~%GT??M#UTj"G?쫯o_қRş+1_?WM سvqEW'_ m|=e]W |2מ 3༿u ʼ *xU~[|<#C_y[Ig2Wao? ~5… '3gU۟V41|8y?F<-7/"_Ԛ'V.䳑%T0LٕD7{yh.x_30հx0atҨ,tM5(NQ:jRԧ(1 `qqxJӡ5:U`M4(N-¥9B%*u#(JQz7¶Vc|IU涒); cU.X{+綳bŝWl>C4i. ~gʞ vko2Ckt#%xlno,K?ysC'lnwK_`-}̌]Z$ȧ[;˟,brM,9:jk9Uq+/NR ,M ΰZ_:}ppwхTCk+>Sxc~Z +(iAO%用sB(((O_~#7?|&oOE#|/_ۚEGg OF.jzfjvZ.iW}ͼ]řenqy_rm7GfXJ.jN' W^qMӫNqm'kT':rTxq_x-4?O'? ||Mc*owNVx7"ן!~ uo!~עhfJЮuMhxO7>EҦ=-?WiO7о& τ-o1ksH!%?t OSеoNKEԵ *ϰ X<5|? bq/[6=IJIy# >*\pvzot/ٛλg~8ow? Ox[_^~Ҟ:~|q>?|+Ŗ j>&~̺։>-ЬhM?֣ckzf3|?KO_'<#DӾ"`񿌮n#~Vz*Iho'8~?AizP|ֵQk o7]}q[i+/??mM S_?gO|USE7'~"xE/N(YjV9>Z9*Pڝ.5ajaЕR? 8 Z|CÿͰ8jЭNͰtΞ1Ҳ̰NeO1QE~vy!EPEPEPEPEPxV>«~kv:_7UG}Szf\Y|/%o/!ǀ?xNJ>+]&&ϋ4{-oÚ5|Euk; X麞/:f閺ݮ:׈<x_x E۔cxB7rNSQWN:tb{s,-,V >,^)…ZWN['**գ ^'^tpƺ~Dwoh=oB'O4MSN4MR@/"_w^%a|teGgį?'D? >6c]O;sNw"-}?]/F&_??Q*((ί+'o~uY?{|5^>CGM?V?.Q{?z+Jh {'ɤxʺ-_OHu-Z_zSBef+Qɸ/ ((+C! ?+q03_Oućȧp?&Eji0o4opU,]y*Dy`X./l?0 ]Y[]^9gZ]l.#(Ge>e{Zu0\e*XiЍfl=N1c! UZV^3 V{*k–3ajUWB18lL)W=ʹ֓=l6##Keέl콼Sb)VcR)ў*bӡO2a S`EWxEPEPEPEPO6qhH m&Ỉe%OpA+x3xzqCBjEΕXNjQh`1xJ5Zu؜=YaҚJ ԥҜc:u)3&?'wwa͖7틠f| g<_s}gڟ~!Ա/~?X ݎw7_y'Ӭ5C~¿R Ũ˟=sv~Ox7+k{O|EXu]c~|wMo&>%xW񨴻FtT9Psm0ffV{{VF(YDx9Y ums^ x_𧈼1=;>wux>3펱k~>h~'ƥh>(nl/Sӧu8e i|'V~aZ2d9`獭fj,-<661ԯOx_(eZ7w[_3TSo/|Y+Pvoټ# oVK}?`*+(ZC?t!_ U<7Mg~nK6/xkSW.m%z7/<%F˫T<u^aZ_F:Jm<&k#TҴN 2c|=O}+ʌ%XI.)l}z(&;Š((((%k>*?#@Dj>үokH|x, .׉|9?h0~x^+4[>luxÚޗ=֙ΙukZuscXwi D5>}ow/SX[>?j\rdjsiN~hWBN&OުϤ>_:aT]GZJ8(|Ptœi߳c_) afgW)_?Ïs`/3io@?~2s['?M_Gv|D,m|_W^ŏukKLJw}.~?򐿆f wҕIbx?(ڣp(ol-[ڼhԕ*\N7,4+<((((wi#C ŕלmx%&k{S\A0IFjTW?p8^[ٹENѫ |NBtLfJ+գb+QQVX,n+.R`*[:N9ѯP 1X\U pؼ&&\./ VF )GSu{VwQ%*g{#q=-ʪK&*Z diyz_?$+_|%_?Ŀ|y4}Gúx>o譫x{WմQJ&7m>njanI$Im3-ՅmkU͎vo>jGYI>j ;##7Qٿc$3m.R{;VF-TRvmOa҆fOpVcBFy|"0 ֩zx.UfxZU8%pwe=*? IFRM,F.0 ެ1u0xg*<|X~տ|E?¯6L~ ߢ|9vV?E)߷'ofh?k^ sNe'[4 UU.7g^t_~0S`JV|(KsiXJr^&7')SMUL\c1F}Nԫ1O/娚{]+aEWᇨQEQEQEQE|W? oI%|@/zZ޻hڏG @_ûoD -Ꮘ~=|?5دb^5@+xUռWI!ٷž/TxڮS}Wϊ8i?,$IT%ln%cFR<6t^$}%(1:|ƒYBiIkReJxҦ&1iޖaQ}sEWaaEP/F&_??Q*+ࡿ>"_w^%a|teGgį?'D? >6c]O;sNw"-}?@Q@~uY?{|5Ek (/Oׂ_w|6%>C x%.49[kE~]5*_S?*_J?&*[~?M#UTjM) GI&ㄿY8+P> ,Arj sO?a:g .%?uw-k(o߲_/aaQEzQEQEQEQEtA4^I4jVʊQSj5+hlr76 PrL63 (S'|~JuaGg:Ui:PV 2c)•ess㰳kqԥ:LL%hB:ZBXOsm5op%ME,RMO 3 ;S?u{R+:v>'W$'<-i^6> n+eSw9> j5 ǞK^zux|)x@Ҿ!|= :>#j<;/ ]I}\ke'NsRR  pn2$FIEM4>4ӺzkQE QEQEQE|Dw<o:|hhcĺox&^O:&k'M+Uhc8g EQR%iFQwN-6ikVVիCB:+ѩ*U֥5:UiUէ8tBQ'(g "x_mf:%_$W>"|%oz//|6,t?kt+G>I z[p~o|^喏^~׼9x_\?W:R4 VgLtgZu}#^|A#-a?^7Yx'\W>#M'ooA|t<;m}S+ɯ*_L?UWgK gvJ(+ (/+__VOG^ q|=~~Y) Hq/q|^/gѯE?SrҙRpQD4W_R ?i W_JoH_>_O7%bQ_V6?hw5{E/Ss:~X* \>sZ|Oy2;|={Zt}Bf?9RRo߳_~*GW'& |C'F5_ <=/=k:宓{! ?+;)!)I;tQEGEPEPEP+,.້Q b3Aq&Y PP =+SG ]ZI$aWHh,.V>\ciloku]7 `/^*x%'ٯ ЎO/̖ ⹱=/oQK ʥ:2rV lDY~'_UNj\.vG8jbr{JsJ N2"_(JXxUҥ 6ccu<Jg)RO>x! Om:nRT4KKآx*2~5as_oQz:d5~Z+|=h;ӯR֌ץN9>V;q6aj΍j|NקZQJjӣ^J+Ҕ*ѩR9QEvEPEPEPEP[,IJpWif$#y-4OڤYEmڈom-m\+2Zyx!β֭D1,VA΋eY(Ɔg|<Ӎ,NͰYfiyza+S/(Jk΂SQס[fXUwUp67,v74?࠿~>QrxPJl|l? C?'^]?l &%W"Wk|>~|i]1|#K$:^Mω|iG:=N擨ڢiZl/e' 3&+ '.w=KkMHWŗ5Y5jvz<=k xc_n| o jڗ!w[yl14ۭC(,<b._Ĕ&s U,%|Kc0xOR4!X$¾[T5#F*x:u4x\X=L>/Q_'hQEQEQEQEW`? xO_5|:׸WRHo']OBW/kGuֽnax_ƞ Gï_\uTTT t湣+uqiũFQZ' %8N3QS]8L^#us)է8TV^Xԣb(Υ VNWVJ0vjk߅~˫lx/G+{k3ޡh ľ>O/O)¨| }_ /5O _NHWŚo3Ox{\槭h:.x;Z~5M.Pn=xF^\hzDŽU OiZM,j?Oo⿝9RRo?ï~*?|W&/I_xh1S3HN+14ui88|UJYWf* WfYF=b $hwXFHI 0  E2JuӫJ*ҫԥV:u)*PNqn3ԣ(EM3S*VVN:pNpn3$IQN-4h(((((,I KrE$l9#dt`He` k[?:WYk=w[kk~t-;ľ#{_k7~k_ C՞ "xGe~w: R*ťZ\Ep0BDdE1Y|;K[v` $`l' 6OZy.ޫ_ZXO-]CFn|N,2L1sl%\kcYfgxiPa9N*yN*FJS5L-HnZTҗ՗5NBu|ЩU(((((+⿌>/??j߂ֿ蚏]{~2¤,i=S^-4S+_g4nwm>hOoڔV5KP%F[RUFQH+)J:rR2eyL9T8\M5p5C0:kՓyN+xtxJq4iU#s ìˮܾ6/_?jfjNᮿ|8~|?ΉOUߊV:64 A.4z`s ?]Ǐo)'$D/~"LCX|=/~,S)/Cq$OzI4%[yah֋b~IWq#) a(J2pnX:xvZ1EQZ!__VOG^ q|=Z??h?k~~ OH7CK?V?.Q{?z+JĨ {'ɤxʺ-_OHu-Z_zSBef+Qɸ/ ((+C! ?+;tQqbQ[mnnZaխtY -Q쪭7ZCygws|J-:pۆ)> r-ĿWQy|-uK:&7a]{úř?/$^g]|juoS]Ư|Jf _-zw]BGi_|\G;DhUtudtu !!$_a1jSًWx'K;"}3MkϫK?S+ ]u O߭x[_kOjψ QYӇ,NW``0geg <C3EPʳZяK( ?G. 0WQ'6^\-gkV1R"jyuY 8ҥ`_*|9{×Əes^s_mcx_7Sռ'LԵ2[5^5}Z<xKgoz}BqR]TѧfiGW׫ҕdRx&i2R g JeQT`QEQEQEQE~MRle]2?*_L?UPEP__VOG^ q|=Zsǭ_\_kߣmJ|?@K\irw_3עn<Zi3*_§^?i W~@Gقl|oπVo?m?涒/H [2-ѴW7)sgƺ &C~?򐿆f wҕs-;&OBt|#0X=Dౘz5KIBsqN/eJ+)BJ5,&/ ^asVTk廴EGd9PMms ffeKweF(Y7I9k[`x#Zw0m&xUӥ͵W>cx5Y#G5-Osm5op%ME,RMO 3 1XgͰuYUtӕ8CUrc֫J_䵱`0WeJo,QPs2lNWIB 2x4U^:^mK Q_BxAEPEPEPEPOY 9Ib'hHWRqu',:_6%88UMYS*_ZUX..YLi*D1ci<kaXTRSq qPhkM G3GK4uQ_Z|QEQEQEQEWNOSe[|+?-Wօ㿅~(%_ YIωu=vqx2\U WÿZ^ Q^O\;pO`qT'Y­7Kx-d)Rx#ZaSJ\)IJ/uukdStϊ»o)3?ď?~iھ E譢V_M+¯6kZߴNK¿~&~kľ4x?_,=jqKB5gF,NԪy97V)ՊF1QE{QEQEQEQEwO}f_dwFDyd}~xgT2\.)Q\y `Yv>c(΅zju)IjP:zvGKVVZpz8V[cU}+ VTpV*pwF*QJjB:+Ҕ֧R ]742}y ^6 'ٯթO/̊x%Z:uvyO F10V=Fd,䶸l.- EGd9PMms ffeKweF(Y7I9k[`x#~/ ys[#EWiSB9.R 8z9^|6085p_KGr?W0q854U],SZY6-8JZZKsuU'ե1up|8EWQEQEQEQE|6|_e-/7<Cϊ?s=x:bxF5?wLԴ]Kbt -h'Gm_WiA|j:>*83ۿ¶ o Z/Ð_KPO?߶N|LOw/Gv>~ Ɓ/z}j]¾*?➋/xI[}3N?M? ֎xѾu8iztsU8b&5;/ ]lF:T֫&RKxo1:m!]Fַ=Q}yM-1w/~ʿAuk:&]]iڮ73]5F0x ľ#S_wuoƞxT+xUԼW HuٷⷋE;\|FxKRԼwKU~*|`/ M2>~_$jN0 9-FZ)QF1=3,\M|әZ/2 *8y浪W'V}sEWaaEPEPEP/F&_??Q*+Gg %\eQEd~~Wί+'oG?~[<?o$xTogѯEw_3עZĩ9LF׸(@"G?쫯o_D4W_Rǯ7/?Vb ~'g(OB+ok[A?g S_BC?iWοM-/]_e> _(f?9RR?ߵ_/<xKƯ|) .+ Og~sizϏ- ^3ᦃ~s/]G} ?X$<|E84On(|R кK;G$RF9GFԆV& jVp5̱ iYZP_X}d-͍%>)dHGh]%X)#`C#C+A^q}vTsTpYOB'(J pXP*<.˱xok*; tjLo7r?v5)S8ܡqtZbT.!VQiFj+o ZM+7ZA|8ӓl5Jx\^[ewSY+7 Cc^2éaq'>|-Y?k Nc&cUu7tN*1T<ce+%Q^Q@Q@Q@Q@h]Ʊµō*ȥʤiwhGq,\aaEpfYn5<.)M%8V^,VIC M >ju#tӕ:)ԧ>ܿ0eø6:UՊa+V⨻Ftj3Vm]Ig"K&[۳2Ż,50]<խc&D=WZ}˺Ķڌgr]LZY-Ė-/smdHX t wx^9tv|ڳV*3Ǔ<'xPX()׬6qQS+\)eܓ0,,Գ̪Wb ܧS*V9F.mFSr3,Fc9tQE}!Q@Q@Q@G4QJ7E.RV#*C y(QWN:kЭN5h֣V.iU5(TR*S\g$hiMif4֩kcz?SOLa9׼k?'DqYJ 6/hG][ú_ K[IuG!?V"|;woko>iP4MSN4MR_׉1]K7kizG| j'| C5&WwD<`~͟o/W\|>7h͹Q'=F'5kW"ThӞ+PwBgif8J` x0XygXT9g8zq5g`][~+Т((k #g/(qRle]2 ( ??h?k~WQA׷_\_k?xkJ|:p8To9??j).&эE?Srҙ/??M#UTj"G?쫯o_қRş+1_?VM سvqEW'_kc~ȉK~O_]OD:OZ_,࿀?îտ !~7xm UѴEM7Ɵ|N7E~~_x?yq5hzo4i6L¯C1xŸ S ֏=/&OkZns8Bٙ/JWy_) afgW)_DH?'?N/Mۢ+?7 ('d} TtdthXWh&y!7- :l亷FyL/70\A}y֙}prեܖr3ʆi5ݻ2"1BȒ#oe a 2榫C*ؼ( ( ( (#G"#dt`U A W7' cx~ j YBx>3o+~|c^$|{O |Ru]z7?<3+Yg<=~Z<+%q ⧄ƅo>+׬tWǿ 4O6^%":dRx7S'hUKdT|:pe(E:*ciaB4aF CZGGQ8«nʛMUE}9{^+-//B(|$[Ǔi~ck*]OFςSx{]w6gCOGu_ )xφ|2x3X?"'i,-?H_O?5+L,>]OO{hV4en-8(2R$ pc8J2k&/Saj{:ԹnӜ*BTQFjQagR+ WԫRFJr_?bE?xwƯ_>jۿ_ۿkx'ĭh_~ E׮|Qt//x/ƞuτ{~">5|(4ߏOx{x/xJ34wSO_H- U¿'^'B~&| &ϋ4{-oÚ5|Euk; X麞/:f閺ݮ:׈<x_x ,Ç89IKx, fކqSULF/3O xzl/,.)t7e>"|;h~&BCK4K4O?5 rKσixgKt^ԴO|\vh> |mҍXܣ(NH4RJpm4qjQ*BSV9_[J8ӭJ7` sc'S ӜJtէRJ8.&al6&'+x;G <~jvj|1 k:__xK%H*?#@Dj>үokH|x, .׉|9?h0~x^+4[>luxÚޗ=֙ΙukZuscXwikm>A,^!׉<9 1 StGԼc&~>#vv:}Ck7 m{wvCqkV<1u}9κn[zg/ 8as^c}RAs,Cz?5Օ6$I Ѽ3BJI9#pt`X@ em$Q5 &mk vֶ/HKkxXc(uU־65xFa:|+TO 18-YNX\3"BqeX| qFss`f>$•L*dѡId0+8s)bQEGɅQ@Q@Q@Q@Q@.䳑%T0LٕD7{yh.xm#ϳgLyOB!I(6$I{UPͿaugsqWl>C4i. ~gʞ vko2Ckt#%xlno,~o2x\rj^.iC=MTj՝*s4UJ+(jG.'Lگʪn+K%ŵ55V8UW%9L>z.gb$KӦ%CH<$)O)үc/3\1Uÿ<Kzιgh~5$x#{0x^-𮳩xs>O5+mgþ&ψk-c@YYjFgkiVז̟~CnA^GcyNZTUcgB,ڸܻ,."<)Մ^+sI(Կ>7K?}m>ᾕݺw m7^?7~,Vֺ\C_&e|03<5\ecqYna`kRm*1RiN &֧0jB!%(Tg -%(y4A_gx\/|k㯉^2&,|Es'ĿxP}zKxU]2߷<4m.H~|`?᥿\R5}_4}XYV36e+GzuRuI;_ ѭ#_?e f2qR.zW$NԃV/F&_??Q*+ࡾK'WĿW_4EkO¿j}An# /~?%? &x __JGug32>[hQEW_QA׿_\_kR: {_}?!g{_lS-д'm|Z}~.%x><'txtOŷpx]e~(Xn\{,-9,[+Suqjm8iJޥ'nHQETq_;ï|&C⇂UZnx;ƺOjwfi蚝i>8g~D~uO~εz{T>ť9O|;cg ƾ)Ǎ_t |`}?^ag7>/xrG/uk_/.lt+ciO|jznZvfh:h G0/,񿍼.zlAr7Is?c7qͦϚ)Ɲj񟳗ch{ ^dDZT]JN>N^cjrj4cp*5jS˲ʘoΟ*_L?UW/){RWjg>Tï _Q_ Kw_Y5> ^/|#Ŀ/1^:vom}hWM=$NwX?v9ZPqMy_1U0|No*<k(bX%[ GBPJreQZA_V?G^ q|=J??h?k~| O_w%_Ɵ)ww_7j)ogѯE?Srҙ'zTzp|QUYK| 'ɤxʺ-_=})!|Yc ?p?gQE~~QE!?򐿆f wҕ>P~xr]5xOşiw!_R/צҝFkPJt3ihhF< ō+8(ʤivrKp\aaWl/>3ַv MxGwe,قS5 ?\i'-_t76G}ddt47ds-Ogrhq1\=V!Ofuus<.j.Q\ڹTjajTSؼ/ N\sOk0aASG ԓTExa1U'JSk *X̫TsB((((( 6ƭi[)ѻ\ꖨ&f]:aq(#E!(`VmvЪ˫۱;$f[F7<֒&O;p>"*OnXxyTWrsJEjʲ rdU/ɰҫ`P:q?˰wMW=β4(Ү<㋝y 0瘔QE}EPEP_JO(ßs6V/1YxGZdž +4+o ~`q!9QS ctcUmz85jPMmS ^"MIjҋٜ[X?xWǾώ o>4xzΝ? ¾#ӭx>!o4{yghΗyujuյ+tzlkUn߄O4KEx* SY^>,|4æ ^ƞ3߈?<;g/|f_|9=+?lТ> 5N ԅ|&0֣07RfY|E*lM)BoSxzUԊCN8(]9SڄQwVѠ+N q<>)i k{GDP˥U[,rA<̉xz62QWI$Ivҵݒ쒻"9B2qp&89ΣmB.Jcd9mQE2B:ଟ{_d~~W{';g#|md~]5?.WKS?/)/%OHu-Z_&*[~gW$q_,ݜ@QE (QEi1|Gy?FĿ{ucYQ#-|#qWbkНNeZ,E9Qԧ;sB[>Y)+J)4~K*:s=GBi?Q_xG+?~>? ?WOL螣!Q4D˟(&39\Ia*:s=GBi?QGLgr,*?s3Tu_??2zGU.'?q'?݇>Y@T~g"eD G&\OW8㿇O,񟁴YiO$_mc_𬴽MQj?c.xYϋk:Guo'l{ 6]']>|-u "Mc][T>'~%9?cY@T~g"eD G&\OWE18O/ϻ|!Q4D˟?WOL螯?c?iFꭵՑR }!' N jeN*uiTR'I=he<-z8-ӯPJ5W5Rj5i5)UR1:g J2RIEy,%cg G)\rH.R4 f^)4VwE%WOL螯3IK ~ٟ}'N27HoGu-76<3FƟ 7ۏ>}")ƓF}x[ZwxR/>hнi$g/|!Q4D˟?WOL螯?c???GU.'[ <L_ uO>|7>-+T>'_I𭧄jOxSӼ7[|6յo_ =σu\.-G cx:8t`TPUe}Z87TƺVpUT"| )KF4\RrJI^˚ҵݮkg/?*oGg~+{]q C'|U?^ G`5_Ox3CuRֵ/M_ꗞO, >b~ _Cğ_U5_H<_Ş$4]/W{3~eQ@~uY?{|5Ek (/Oׂ_w|6%>C %649Kn3xσ>3OŏIJ>$it(((((M?d7Ogǟ| ~i_|9u-Cǿ>(||ƿ|Dt|?gEпho? ǿ e Cм}}eExo_/ 0ğI;w|_Ct_WҾC}xsJYlo(FQ@Q@Q@Q@|g~Ⱦ$/ske/"^#otO/V<q+xS~=go|MuKS_~ ^>ٔP b |0> g|dby'Iyσ<+Kᦵ߄ 3=S_36_ /^>x/xO_"izo:[A񞵠~gm/Ɨ_xO$A; >/|!:V_|!ᾇ< aaoxKK%e6Zox_j((ί+'o~uY?{|5^>C$#ğƟ+{?z(gѯE?Srҙ/RpQD4W_R{kJg 4aW&l|9Ipv[x|J׭K*ezui^&FW(< ׿?/_4Jwi,>"VZ/Gq_}wE8-G" {-G" {)wEr/yD2v=GwE8-G" {'oWWL_)DȟOOې+K2T# Ȣ:[®niM5ej_qPiZ|hdoc/get_nameindex.htm0000644000175000017500000000627110467174654013634 0ustar renerene get_nameindex

get_nameindex

Gets the index of a given column or row name in the lp.

int get_nameindex(lprec *lp, char *name, unsigned char isrow);

Return Value

get_nameindex returns the index (column/row number) of the given column/row name. A return value of -1 indicates that the name does not exist. Note that the index is the original index number. So if presolve is active, it has no effect. It is the original column/row number that is returned.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

name

The name of the column or row for which the index (column/row number) must be retrieved.

isrow

Set to FALSE (0) if column information is needed and TRUE (1) if row information is needed.

Remarks

The get_nameindex function returns the index (column/row number) of the given column/row name. Note that this index starts from 1. Some API routines expect zero-based indexes and thus this value must then be corrected with -1.
This routine is new from version 5.1.1.1.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int column;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_row_name(lp, 1, "col1");

  column = get_nameindex(lp, "col1", TRUE); /* will return 1 */
  column = get_nameindex(lp, "col", TRUE); /* will return -1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_row_name, get_row_name, get_origrow_name, set_col_name, get_col_name, get_origcol_name

doc/write_params.htm0000644000175000017500000001073710252424324013504 0ustar renerene write_params

write_params

Write settings to a parameter file.

unsigned char write_params(lprec *lp, char *filename, char *options);

Return Value

Returns TRUE (1) if parameters could be written, else FALSE (0).

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

filename

Filename to write the parameters to.

options

Optional options. Can be:
-h header: Write parameters at specified header. By default this is Default

Remarks

All lp_solve parameters (options) are written to a parameter file. This file has an ini-format as used by Windows applications. All parameters are written under a header. This is by default [Default]. The header can be specified in the options parameter. Other headers are preserved.

Example parameter file:

[Default]
; lp_solve version 5.5 settings

anti_degen=ANTIDEGEN_FIXEDVARS + ANTIDEGEN_STALLING + ANTIDEGEN_INFEASIBLE
basiscrash=CRASH_NONE
improve=IMPROVE_DUALFEAS + IMPROVE_THETAGAP
maxpivot=250
negrange=-1e+006
pivoting=PRICER_DEVEX + PRICE_ADAPTIVE
presolve=PRESOLVE_NONE
presolveloops=2147483647
scalelimit=5
scaling=SCALE_GEOMETRIC + SCALE_EQUILIBRATE + SCALE_INTEGERS
simplextype=SIMPLEX_DUAL_PRIMAL
bb_depthlimit=-50
bb_floorfirst=BRANCH_AUTOMATIC
bb_rule=NODE_PSEUDONONINTSELECT + NODE_GREEDYMODE + NODE_DYNAMICMODE + NODE_RCOSTFIXING
;break_at_first=0
;break_at_value=-1e+030
mip_gap_abs=1e-011
mip_gap_rel=1e-011
epsint=1e-007
epsb=1e-010
epsd=1e-009
epsel=1e-012
epsperturb=1e-005
epspivot=2e-007
infinite=1e+030
;debug=0
;obj_bound=1e+030
;print_sol=0
;timeout=0
;trace=0
;verbose=NORMAL

Note that there are some options commented out (;). This is done because these options can not be used in general for all models or because they are debug/trace/print options. These options can be made active and will be read by read_params but note again that they are possible dangerous to be used in general (except for the debug/trace/print options). Note that there are two kind of entries:

  • Numerical values
  • Options

Numercial values can be integer values like maxpivot or floating point values like epsel

Options are a combination of constants as defined in the manual. Multiple options are added with +. For example option anti_degen.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  write_params(lp, "a.ini", "-h MyParams"); /* Will write parameters in file a.ini under section MyParams */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, read_params, reset_params

doc/MATLAB2.jpg0000644000175000017500000016435510251412320012017 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?~CsW5?A'N>Ǧx37<;k]Z .4&;ӿ5IYկ~G©Ǐq?xqT y$K b8"O^&u xSBK?IHм=iƻ:Z^ij:uu"Aigem5:O&~k oh:֧{/_I͢xjz햋ietOkB_~mG/;VfF.#/|1pUfN[CS2jtiF'ȩUIJUNN_}>f ˃&_J"a*%WVQuIB0)gJ(i m< ^&IмOST6Ow?$[Z=̂4p4ˉz iψm98`$@@Ol+c'` xIO@񯆴4CH}_ڞCЛC "Y.$}Q&]k>Ş IO]TVÿGkYxk/O;r[~˿+/4~/D~7k3Ho! g/'xw)Xds % ] fs˱i:rh/~8 ]^Wcx; q̳J m:}\tc^G2B5bsQR_?2 eȴOD5"׷c3Ogo2wS_Zg_ t | 5aGU_ zE8# T|'x ǺKŋ;Euj} Ǟ"| \X!Ӑ)6fZռ|o'[1cs 1V'4cÙf?,̳W<6UU,Bn9NmQ:?b?ia *? ^[6YO|_:כkl|I\iW~y#h%ԿhoC~$zu|\=7ĭs⾝<}ĞƇ?^&'u hu$z8WG~a(bUPgXWSq שQFs&'+(hCbN ӥJfwZjVQhS*t$:]j(ETUxz.''[ioZAow2ſ _ֵu.^:/toxO_O?xJA.u g::o'),pm<;dlfl8pFI,V-<ʦuea'GZْc|AF72~S/|<<3N_=^ߌ|S:|N4. A{mZ߄_:i_XhEG5pWp 8p|NU<:ʡW.yq1xC1Qa}RՌ*(QU#.INI# ?-_G4O Y-|M[td(݇^POOoy俦}# ?-_G4O Y-|M[tУ/vz~A 7VKg??2 eȴ7/Z-|M7?{F_˰Ϸz/~q=?2jzJQFܿ iȴQFܿ iȵ_?J_Bp>,y/>AhAk,t~yg/F _PPOb? {G AN0?1IcMeV\YoCV_*X.}cw} A?>"~__8y-cGF Yo_/8]?y1U/G???'=?ݏ]Kv?td`U P_ [t} A?>"~__8y-cGF Yo_/8]?y1U/G???'=?ݏ]Kv?td`U P_ [t} AgW{UwZGW߉:4mZ |U-?e-/V^ K[ѵ7FRе[Ϗo|+(ɚ%фjgx 8BH2#03g8χ2\\7߉pM|EL/V#9+ xN8<>|Fa*э(V:>î7(W ɫcѧҍLJ*q*UiVtq'jU›MNG=ifgv| c0H# 1Au<`>i/|W=Kߴ/t _| |lY]"7C[[{:_O>ތX֤渊9(ϒ&(4xz|a_QO+O Y5υCa^| OL,MY i /^M%t}_Js;eff$lgןLi>+Z?:5톩~g6[sk>&u6#{IU- UiːI_-1׎ ~7ka. ,2ܻ>O8GÜf]`3 Rѣ5wR*5)U}FxQ*Uj`jU,hb18%<4׌2 JUB[9?~3^14:oX|3>XxwEg-R>x>!.+37f%bqXrd/9敱-Rz Wb9}[ GR߲b<*.vǀ0#uC5|7KƷfho-|0U-"^t gZ֪νţkz-/{Y𵖻kj[nb_SeCL-WsXgW{#CKY|2qe`3L&eCae8V V7ᰱb0R5Ӗ&T1XN'/^ϣ爾1xk_ļogywms̷eJṣ4bZ8p̱.*,̰ -w ğO>noAǚ;ޛAh^Xm4OVnt9|GjM\ٕ01߲_炗:-7.G{}Ũ5 |[) P4eh+?Ď1̓)<Vqeϲ|\$㉓tL+יP)FJ4’_-|+̱XZ,$#׍h::N5nymW??u? MQ',-7PФ|Vj wl[ym"{iz-?iC_ x[{῁եďIjzm'Bt<3mWN5MJM7jr9Gv>jޑi>&^4&SxJ>Gy ڊ^5Qq5[Ŵ>߶|K_kۑ~FrG~pI\OH^0WVmVwp {p8<*1؜1eq5^9V*u08b0;WHOexSxl9N?. EUpiG ̚Rp8?i{G/i^3/HyCƗ^6mψ/ GR%WO{UOO[Mk׺n~Zx` -"KSw+Z}X4YCgyS!y?dN2;̽|5RO!G#n?d%8${ v['xø|A{V=C7úE?ń|S}v;؇ƿMOw◆M;ayeOǿhoZ7ď^㗂!/÷_Knh.KW)KJ,JHbrB7"!qy@p!Ɯ-c*YSym,1ⲼM|<&WlVA*ٔx|øo 8 qsl%\Aai0p[1ףG4s*0!W 6_uzGE9ZM_< 3gUk|Bдk;{K]F{Ӭ_,/; gi~ ?j_Git_|,7|7Z}þ_{o^+P<>uuߢğ/ h~_Rd-0󑯣}+ٶf[:,f>\ZxNjx9,4xV2S:%Zr{),&?Jxc?f_O/K [ _!xvx**\Xur걝<},\qxm)T;4FlhĿs3ύ|5j_|o_QM g6]gčO^h~gu<=d6-Ŀٟ7c|U3Csw:OO{WZ?>#h>oBImGE}ŚDÉ?o)?_?$[`#_Q>'}&aVahG7sep]N_Pyף̷W-M֥[粮S䘩c2^##JUqV xx}jXtxz0Uѧ!)RM|CI_{k/gx{xo?tx<1?|^i'Ě/7 ; xߞG->x_~??>&`,:T~Qh&։g]^7G3É?o)?_?$[`#^^=}2<`઺qLWbSԱ)abx aTa<*ey={yk"yG|%$[`#G8%o}G (\!pG5|Ӊ8+_^k4ęDzagb冢 2Rj[V˱ ¦Y?Cʅ%<EpS͉xZzJsTRmX(E+KI}IFq'E'K9OߢN0K??̿<7?mX(E+KI}IFq'E'K9?s~y8G\/W?^g_r?趒_A۫Yl ]K?GlǯZkU2/# 8$mg_rt>xC2>_l^|t?^ao[~20??oM~Èo)G!~[|e/GNoG}?/{[ߌ7O_&F/__g_rÈo)G[_c%O#?V/# 8$mg_r}d|yOyսmtk3¿7v[U rb5 Zߋt]2xM ViZ%[I'Èo)G״x/ =A7m'ϋ-gkF zPC]F|Zo/#OWKt7>F.ɲQjgOgCGRXl.aG D)F>ÿ`l+;eSPq)ֆif4L32סQeՄTڍU>Z2~ӟciϿ>-#5?xzցh^!:enk:yNZW~A_:lq'y'p3,2X4Q "d[ pF: ?FO$&zO7 i$ C}Pk'1!xĚdž翱棫\w6WWVOgm$_🍞 p g< k ,Fs)qf],v ,;N % ;r01u+rmZRVژ*(TZ[xœU4߇čK\?>VwOkVt=gĞ5k~%oh,/m㼎V3"տawi~> 0/OA0uO%#A{8|qb]3S|`AoZin{DW_~(Ҽ354 BN/eM?Svaaactc/ >/)Ì!x'fxifxTʔ?5][A7 PWA േUҼi#KPk.vyoi[%"E~~_šďxSxo:gk3[[M%[\H]VX..^H)ǎ9s?OWPMg@;_u ";{ZU57U+>-뭿Vhlt-COc2Zf[>9{+I[-&X;1g|Ao鍮QNҭ,mAcpH:\7^!Wĸ1βZ6k~ڔ8!1-/dp期XoCsie>8-<@"X=`<=օ8`ج? G>Nħśowt%t˥h/'7DNrT[m+L;mQE&P%> x__{KYmj؝#@1z ƓD %d ?3}& =Nz '*p~SW>`_Ryxǟ~-~)<}f-' a ͭxV<semS:贸un-F+m;M-t&}r >xǟKYi:Yo>9^y_>2Q^my5E ,vc/CkwrO/ '>+0-*1<#Dž\0xL+qcfWG YjJ ֫)v߱'""x>\>j\fo'0')8C&I6()e )ʂsc(#]*M3N oAر>~_z_ڻ?~5t(0x{W4?_'O6Z?'iwI25 s//x1{?{Je(O8Er5.E+4Si-tx'q m/?!g*-'·+_hwGxo i~K$?v:Q~!uOcx-#$ _Sw+6߇??X~D&xO_?ؾ.-CN]ټGJn~x_ l=:/~пwOvOg;¶>Zu->7>:xF"/ρ3x+ú< H𿄼%}#O|/N:MhZ&iiiFim}6!b*aӔ$ݬҊJIkkսlX~EywW_⏂׎گOᮓ}N;LIb|=-ݷa^$WC?N WO*MN<o!/WWㆅ^U~ ~ 7_>*'ᆩ&|7s_ ^/ 2?7ş 4FoZ|\5oW">;~ > 5_ MCC5kzUu~:M77>4.tv\c/(^:~a7ߴ?_ǍkG$onLJ#xx'Ş29PTR̪M{6(B0JjPc5)8sF;IsYRM^_kE]wmhOn~ڿO }K/죢jǏVZvc_Co7~>3hwŋ⇏'oxŞ-|7Y24NW#i]mwz焵|][zu?|M߅٧ NjmwŭC?[S>2캌EJU%JFҺIM).+$*wڷ.?>m_ڳP_Go5Sj<3]l߶iI|=mޑg-cú6i?goٷ_5ڗ𞻣x7iuz"u|B"|>u~?P/2w S:x B֕~^x:+{8am G}#YTQZWzM[%')%IJkzuOƟ~/__߅~0|-CK7_?_{KBφS>(<3q?u\sS߉G.pٟ>E!l#<i|aɥx[~w{ړn>Ǯh^Y_YEC7]nWi;~?] žռ+Ưii-gn|Apcxct/2?%órΟ㿋l, @OMw?g/K//⏉0jW>?vtARJy%RQ)1 7)&hj\]+oukfZ{+_k/?]r~z[iߴ?jڇ|s~_b~?ƻ?&:㯂M߉Gτ~sO|_q /;> OG'}'w<7S^o'uOW5]_]ŏ~ӟiQxfO1jߴÝ B|?C|/Ͷf4_m<_x7B IоWzW߅?g5߈:Z'3}7eo|C|e/#w~+xQ~Zx75 KOGm.oyW:w$^*4 #:i{(5߆|Ei_Bt-^Z<;x:'#uxKIG_hZn֗tCPn4?x~=ZӑۙdJ]7'd7.{m}}t;i"t~ {~Ud_0%&x@u}G_ۿ!_ ~&_~:~ >!|ax3? >9~> ʱX%#a7Sm˿ Of'y~~!F9brÏ7|(:¶WڇL_|K?Ѱ>#xϊ4/_[:(kE(x'읭inWt+ fwO>Â[|*> ڗ:F&,YC?#>:;w:i<xgX%uaVT+Ӌܜչ6VVVVCVOd躟_Y~^/Q75?Hhy\g6o4$BK{HS3mSE{|4__?ǽNNx][Goz |uτ> /H65o_?:|0~/xWE!񷌾5~C?ƚ/Aáx7mwq^kxOZO/]sAg|ُ lo 4ɾyGktc/'<5DxğKςnomoYk_;MM~Jux'~?Пo;? '7|%[+]/tolQ5xWt߇!qfZt_ygcr;][¯o"-|+_C3^O3> ύ4<9⟷j-UҴJL:ik&R,hW_'~;~vc/ G7Z]s*_zg| }OJL%.ned$<];^>Jj:i--.o޷em/ *? #Ӽk?+ƉxW|M|#,~Ŀ|[^׆KŮ+d]_ឋ=r}?Pq|]q_Ɵi/ٟw3OZ~+Bѿ?$8Z7k~Zo~1{/ k -?Γυ>|#hzW/ i_~'Em<3i"Vz'5YPi{*rRWzM[%4VOGƟ?g ugP?'Džsog?|*w'|io׉K=?@mxQ!|/KM6x4g c㯊l7Z "|?|RJ oxW𯂵x&]_ :4_~%/gO5 |)S ÿ<3➁߆φ?j| j_n~(iO_>9׋ύ6t>5O~^пQյ[SյZ^(WQ+[>6׍Sk>1c6ƞ4뺾{5燒\Zoݢգ}ܦډ4׶okQ\ŅQ@Q@Q@Q@Q@Q@Q@Q@Q@|pɕkSn2wk'_^?K s n-?b8uoۓcu闲n??gE K{iq*b5qb3b$ؓoۛ⊏UG =NMoҞU}FH3SKOdHk\ ݖ?ً+kφ?a1?l߮;/3j}y?fU?FOĺibuԘ>7~&l[KI& d1i;^I t:2looůOeH>&sgae]KxVw3w&ӟ8UKu}og)S$|ӌgǠbizbiz#ŏCoK`<ك S৆?g-w^)Wߊ߰| ߴWOF;H ZZΕ55;W?`گ«mg?j~$Y~ψԢݟUSú߂s='4O ටOe:\/֧(rJ{VZ:\v+QΌge{}m_jؚoAؚoAiǾ/? B-/G/;Gxg?_ l~+xkwĿ_4W_Wx;f[ 8|Z+q[-<95e3,aZ&8Ɩ R4PZ$NT II&JIFWn>?h?k\09gB/_Oω_g?<+Cm_bi}⮝dx|L$?4 ckc6s~ /xƷޯ^>xCGx:e6-DiE-n6]N禎a,F+ \:yҫN|pN0 SHQSg &{Ovz[Y'&?G&?_߶X^g?e؋K_|' ~^!,%<4u ac&!6&gE6iC|;;W>!~<%м? +'4C95-KZ޲Qm}4sPw jN[u1(TQ$xlsJ.biNrM֭;ГgZ.k;_OM7~ VM7~ Vd%x?9|aI;|J:CxZ,4 Ju[LӴ?mP]g ᆣ=? wQi5xU>i]Ꮖ<%7?O;OiW4cjW/RU=akf*v)n&sdk%}C>>S|Ow/M]?SP5&[ ~? ⵮e^yaį_N mwJ{[Bմ[Bկ; "|Sx':N:6oxBMBN]c\ִ%{:q\]IJ7JbխצI,< -SR=zŊK uցբލYo(#iy&[_ؚoAdxD0_^?f%w+G5߆뿳w_jV_;{K.oB׬5O :}OLVν*0gUЊr,Z4ݡ~U)vnN0e'IuؚoAؚoA~/5(/= o+kO4K?~ RUkzݝ]j&GmR^5_?u5khT*pp|i4Nq9%(V_q>>׀ccZޕ;G h>"-?ƾ&4k<źmkv[o@Bо#'Y] 5'V.ӕ7uZN6t*m{߮g3?4=Z?4=ZӯƟ۳ W3_?_N࡞:gͯ?~_G>,z׃u-+]ҿt-WO_ xF,vU )ISQ#g)N6bo]͸S]նޖI_WO?M7~ VYhw:%,R_]${ wT֭7(dmJyAfMi5+_ju(bF Kݧu)_skI霐Vӯw_Q>>׀|M7'|uw89~}ȴmOH |(-LfZrէ<#k~&JѯxS/?z(gO[32o0g3o;Do^o_9~i8OW (>-37qx߆/<]h&UѬ4WJ1R)/iES溺9|Z7g]ESK.k[GgZiz>>̟훬.| o/@ZNNmz ~'se|+m#OJjڄ~(d&3q> .K/Cg_K"x [k}|&h7"|1#A>>G|ELqEK4ܜTdͧ-6{)Mi+jۄwMۧy+?C4=Z?4=Zxg|- ~x^-𾯧>(ψ4}[Au&J-oJ_L->kik?bWzw:۾_v?gߋFg&?G&?ZtR'~݇oy#3M߈?|?գM߈?|?խ:('~݇oy#3M߈?|?գM߈?|?խ:('~݇oy#3M߈?|?գM߈?|?խ:('~݇oy#3M߈?|?գM߈?|?խ:('~݇oy#3M߈?|?գM߈?|?խ:('~݇oy#3M߈?|?գM߈?|?խ:('~݇oy#3M߈?|?կm"/ػ.rn2|p-OVLվ%_Z u;>2I g_.?eT-~" u]p~6yogĔ̗4??؟2O+ϟ?؟2O+ϟO)<oO'c~-~?h_\xYWE 7F?'vo+#<17+MA1xT]~*|A T|z+>(xG{[._I5CkH á+CbXcrHԿ%)^[N{.|R(J;(ׯ{~_w?m5Z>~տf \|?<{{׊"мw?|K&G`>6|O ?amaOt?XE~\qIS i1Tm] UX=JqԥFt0s>8PS9is]IY2MM5tֶ?ςR|q~PxBF7 L|M))<-I78ռo'u 'P_ïkm:ė ?3>G| Ӿ|"|ǿW{P |* 'ׂtWwo á(_06zRJJR^ӚqiJqz%{j]ǝ{kkt[cؓºk?r|gw_+7;g|Þ/ ?.xǿ=gx{d wh؏f:kоxm ^+/bͷ|\?|vᝏΗ-'I$C$Q ?amaF2|0 &ZJ4 /pqV8L;V TJ"\NI)b*b9^M);ɨȟccW^(k(Gx7⮻ž&𽆟x 9⮽xtjVJ=߅jv:]CY-Ym[]?Wfzv x.CHs4(^ Q"MO7pX[4sMoc W -Զ' : ?"kƬ*S^jq%NzN:jJ:kK=7LwM7;]lߓ G_<1hZMKBѿl/؛ԾO{Co5k&h5 3o]| 7OW'C;f á(_06+}fIҪQ8GTrmEYJ6j-ekĿ-o0r|5ggֿj|{֗s>~{ WIJ|%x_߰j?U_xjgZ:|o|o''{/:mi?O-;^ދ'Ï#hߊZΩ>ck ?amaOt?XEkN&8Xy:j5cRڪ9J>Eū{8Ik.0rrr\{6i-uMoy_S?_|3FW|Q&?wyiE~3pnZkV|hږ}wE]k:OOߤkG$C$VՄ7Ey'Nn I&ғqףejo6t/|,>&?tMw5|B7B//7 v_mc[֞>4-֏x/zo `֮|Gx^5_$C$Q ?amaTXʤk͹9 ۚJ)Y]FR\VI8-Vh5묯z|ោ?5ҿF?'4c sO/<[㇈u*]ҵCsFԴ/%"^~ |V_NN߄zτ%~6|U[?OBiB}CPc_Q5VBuzO.M{YPk:֭k^,ψ?|iO$C$Q ?ama_Q -Tq>jNm|0MrAZ<ͧ&=ng$Z+KW[o\O?{ á*3Hmt;_Ӆ^!${J[x^GdZ&,-9+ۅY*5SR{9)toV%vyov4~9_=|r7cе}o]_?d_ M᩵گXama_o|⯄xTϊO}SG? bLC F‹j) .Bڿ$?K?oc:W$C$Q ?amauNᆚSrIJs.E*R+sN3mrϺniWVIY-՚8O3'J]Qi~-uΟxV/h,WZⷍ-5EG_#jG~_kk/+B |Zv ||77׿jc2O Rǟ >)?Og'O :~Ot?XEkSJ5UUFRu7ey%78cn.#躅|W/΅M.վ.x~ k;o/^iA௃Zާ7?<cBAG|MA/ |2ѵ|e>8GB\#ៈ"h4~u_yEaOt?XEkG>Ú?]WnQXkG$C$QkϪ._G_UV$C$Q ?ama{ y9} ?amaOt?XEƷ^kh4~u_yEaOt?XEkG>Ú?]WnQXkG$C$QkϪ._G_U&W_ٮO á+s^0]ѦoكQEe$'Ÿ$qN]w!Qf!T@ڍU/J_ Jk%w>"\Ӫ~><~ğO?/hb?h>o?g+_?GZf>ׂ8Y0?f'ƿoo-ԇD_M0طcR5WNJ_3?wӋ+DH((((((((((((((((((((((((+MCyĵ5|]ɨ~o?[xÿ8 e xG$}blPk_dO7R_dO7RҟR#-3?¿$队M/ص_O+%k mů>< kJO/wӋ+HH((s࿅?iy)7_K ~3?goG~|C~x⇏'Lu]GGRO FQ^ŝL.F~_fο_T4Wã?c/?g_S/?џ~ٟ)Ex~lYtge?_g, eu@3E{7:323u2躣:]P^ŝL.?io$gW^t?`@~ο?B Q]bɲf6hfF~_fο_Tã?c/?g_S/+ٿџ~ٟ)E~lY`Xx&zo?ٳo{?i?:/|?gTM^K^y#;aj(+MCyĵ5|]ɨ~o?[xÿ8 e xG$}blPk?dW?/S<~ğO?/h~/i H~&L mſy蚿7I A⿢Zҗw ɻ?iqQE~Q_o,~_߆?.xW~/kt߃mᏂ5xs]l<5W}a7*~ l[|C-`K3g7wE0S?3 ?}+}_3g > g_E W-g~q~"ss^2fM/𾯨{^_ukU<--Y4 VS5Uuk{>O^d<aXlV1UxZ5NHJJte*t(̡6_>+."qJ.(ĺޜǯ>S^h^-tCz|QGÆ}J|5l%+0/gUym{4xzΝ? ¾#ӭx>!o4{yghΗyujuյ+>guQdy8e9J shЯqRtrէZ6i5ϊد2O'ϛO6'LcySDxeg8#lb|o6b?x薿7I DӁ[Ku? Ɯ_Q_'A\eiQVH|}?xuixCᖹ~?当E־-A}kj_}WҴH4Ί/,?Y?/ƯP?/3&Q sW^ƿ:Bk?)k`Jf'_)(A,חG袊sB)H~o?g#9mn2|H83Y<.o&+h_׎پ:I5sŨ;\'8"K;0Y2?cWӄ.KBNMiJZ2V)Jr+mnh4mo~ _Xk?7 /B3&6O+OM34FuzWM ' x]ooBB|JqCnyW "VC3п;?ı~'x|dY bgω/yp9s|Е9{ "_i:zCUa^+hצOz7k$?7 C] g|Ox{K? =A[vcd44o~+tGRmas ŪB$Ȫee`C+C)H#?QooO?e/izO37ľ'ƚ#G┹֮[i,k_Ĩ[xk̜gLeN0s.G8j621TQP?0x2p7 V=7їΓz2U#%mWOO{?5 w5 |@mUcǟF񮷪M~=yžCu#߱?z&oJ4 Q<__& WOm =߃|MsO c6:WqkʜjE7U]EPQEQEQEQEQEQEQEQEQEQEQEQEQEQEs2b̿dZo+g^e"׌EP_<_jƟV%MCyĵ>_,xcWx?'f\ $)hb?h>o?g+_?GZf<>w}L 1>6||_k?'/?w&T  SP?toE?g_B!?nxʺc;|}B<DѾ F\:' D?c*~߉ 'o| <; M? kz[mRBğo|MAǟ %[S c??}oCSѼKljٚjUa{so//?B>xk٬a_UFFm{JJl%8F|UxJ֞洧VDwr&%hNO;gi?= d6cG<%xXEh'ESj;t2'\Q>7hz> oW߇2ᖱ2dž) )|>Mu |J%ͤ_ f)R=gF.:gx< )Z/v{VG=z(/;((((((((((((+g^e"׌׳\̭?/f ( P~4-} _<_jƟV%Nc7=؛4?lW'gGTElW'gGTEkLqC0f'oo-|NJk||_k/߲?gw>2j7Ÿ?`<> >nx? ?Lh>iFo+?g4=4"/Wf@p}!ο`Zϰ *+?ҟنdd??g _\BfX_ο G*]_z _+f? aھ|<5nq"oyO~(8(((((+cÞ"I?_<%/xGo_}_Q#{sewĚkk{e:wouR=͌ -|acXr(Rqf:U:Ui*u!(he(IJex-Ij53rO?OD%a\^XWW, ;9-Zz/ō;E?/VCi@?`*+(ZC?t!_ U<7Mg~nK6/xkSW.m%z爼Cxo~ x [_W|=÷jGEk>&z&jNmo}Agг||?*b_USyiϗԫ )eRgxBT֜Q/M)7C(}пQ_?nkgߋ{O7 9^h:VoxG?4};2ivOo>ٷik|7sEhɮ GR>8.􋯉?jH/(9qVCRYBl2C)_ T瀩^w &oqչe:xYSJo0YԴ+Gji-M+g+~QEQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@W?TZ"N?_f1(#?D@d_Ƚ - 5!n8?kٿfVyL_y^3@Q@|]ɨ~o?[xk5{Oow']OϿM s6+L_y6+L_ySDxeg!WĘ3o7I DM/ص_O+%>+g 'x1&(eEWQEWWWg? `YO_}xke%17G*, SAG TVuQR_^J5VkQ Қ*S J).3qi4iM4ӳMjkT5">_(eZ7w[_3TSo/|Y+Pvoټ# oVK}zpR4 '7l4vҾr"QoDdu[|#M_)|L zEğC5[C?5tC5YO_>œ_W^?X_:Ń_/?Rk>7H+`Jf'_)(A,חG袊sB(((((((((7O3~|CxC״oxKžu/xž)mwseh"5+-[C4=SH,u >cp،3CЫaq4bpʕ|>"XΕjNTҩSNR()E-J2jQwM5i=Q?k_wfE/yIOb5[M(ߊ<[?_;Goz|KO>o~3~1]OO{h +g 'x1&(eEWWd<_~)'_^Sg]g?|Bߍox߁|g M L@?_ڳh#ѴIt{ItM@ڋ=[L渴<+iMңᯛp2P>P%:}IScV8Ba2SR Q= , ںour&WW,Uڳi6<7(~zt޹yw,:?+ Vtq*jtEEte3R-SOM4QEsQEQEQEQEQEQE~f\̭?/f &ekgי~ȵ4QEW?=fUkjP~4-}p8I٧>)b?h>o?g(b?h>o?g+_?GZf<=I1>6||_k3 -co&۟șwXe+?ҟنj9Jcy1q?((((((((((((E^࠿_Q]ௌu oO;u1%~ O5ž$%/oY?u~X}L 9 W|SFHeQr*eHa5Co)?Ï5uړF|8%t߈PԴm#⮭/^?%oe{SUm:οk¹\W3)MeY`Ѧ 04aN":12tN1\~YbkuqR*%/a*Wzʌ]_w )Z,+Xp((((((7 &ekgי~ȵ5W?3+_<&/E(y?i7?K_CW?=fUk|;X'Og&?O&ID|Q// +_uw`?S05 =gU"!?R33) ȱWWWg? ~s? sc#QE!EPEPEPEPEPEPEPEPEPEPEP_AO)o|P~;uҬ|OhtM ڿÿ6>( ΰbiFҩ F0é J"Q~Τb`4*R+J-ZTm#4ؓh?2zxs ,ㅳ73WiNhI*lE)Sak$[VXMPOFzRV*Q{;=]%u%ѦQ^QEQEQEQEQEsO gf_l&/]io ?-2w+(Lȝ{7L3 2kh(k5{Oou&OټimZp/<1 qOA|Sɒ~?|K4Qɒ~?|K4VJHx{$? ؓb|m6b?x薿7I DӃR ado?4l(Q?R ( ? a:Bk?)k 줡1ȳ^_+?1 ( ( ( ( ( ( ( ( ( ( ( (>^*n~?jO^xK^ ow<_^2ht~0.X~h>.6x#ᇊ|Gէ*e ¾=|u_xƞ ox;>tWŞmx{sykt=SFt˭;TӮng)[)+s5+t;'k>%oL=Ԧm"hh袊7 ( ( ( ( (?3fVyL_y^3^s2b̿dZ(+MCyĵ5|]ɨ~o?[xÿ8 e xG$}blPk_dO7R_dWH~_gEkLqC0f'oo-|NJk||_kwmj_ QgNfg|kğ+i~'x{>|}zOyck[Ƶ xgŠfG~_?||DC?oȱ _LL@,A_uYO_d_V% aھ|<5nq"oyO~(8((((((((((((+fwA|> ~|@ 5,^]N ռ'zwfw·:ZWQ^nqeAYsʳ|'.pU%Z6𶭩}_KO~ݾ|w=x~~>{B S&Oa/kZ^=t;蚮9+ :O[?8@C: 93.*۟21 LiQѕ*v`ѧGKXu,:9cca)"*}(Կ>7K?}m>ᾕݺw m7^?7~,Vֺ\C?5FQ_?g' ?!O¬ծlx>ѿNCn~xwF\ ;~>Tyi3(>jՄ'`_#Wl8qZ4ULUa?긿aQ ^Wtk_2nгZ(((((7 &ekgי~ȵ5W?3+_<&/E(y?i7?K_CW?=fUk|;X'Og&?O&ID|Q/O> |jŸoB>6xx?uC~k_F5YO_?5_X 3q )_an!4+g_LaŦ_.au3uw`?S0_G?>ICLb78f7'?EW~bQEQEQEQEQEQEQEQEQEQEQEQEQEQE/c _Dc >Ooii$? Rh?t[HPFi_?g+_?GZf<=I1>7||_k2|:Ÿ<=hwzxI?/wڗ+,Zx[-~9|`Rn> |ROX?N+yi{/,gJ4?__?Ÿw,/C?Q)_n'WWg? `YO_}xke%1S?u{R+:v>'W$'<-i^6> IoCƋtTgz߆C|=˫x Wt{I|>/-q{sQwf N(=ub\u* b2VΰR_'qVoJ߽y䤿.5~ݿ/_-߈.aSCŚVwZςii/5> W<7Ok7ZSStKS'GotMZl=j|E*1*T^jrZjRpJ)ΝJsR '$GIM4it4֍5kp+1Q@Q@W?~-|C ebŢi R"X¿7Ck.%l׳\̭?/f ( P~4-} _<_jƟV%Nc7=؛4?lW'gK/<(b?h>o?g+_?GZf<=I1>6||_k x7pͨ7_]͖*w4+ohSz~M 7Q/<cUѼEsEK)x\E(Hab20A`!.O)Oj_%YƶiJYn;^?xwtx g+k]^Uf!*~S*xa}OUjasMKa'_mS((əZ1_-x{7L3 2kh(k5{Oou&OټimZp/<1 qOA|Sɒ~?|K4Q_|K4VJoH̿*A+bL$_⿢Zv?&Z/?NJ_3?wӋ+DH+_{ok~;^,~.yf>7^4KlḸE;{zx{LwExWJ}2|9_C mEfY^ּOcuxW~uMj8R4_j^1vww3X*ޟƹta¶o'_5… 3Z_۟}QYO_œV_Xh^<?X_:?Rt7Ok+`Jf'_)(A,חG袊sB((((((((((((((({?)|7x:+Zwz-%5*> box>^?"O|Nֵ/>y{:kHсVVV2$2A0k|JLĞ ;5?e`N5%e(NqZ>'TX4۽9'(nx='(k#ި x|kӟ4cG]Wo~6]wX3! h]'|#~oE^yHq''<3PmfXI7(,Ftj8ar\DcznHЯJjOXFp}m%t%馞( B(+g^e"׌7ß?*_?h~"ȶ?q?M&"wP[4QEW?=fUkjP~4-}p8I٧>*c?ɿh>_g)?ؾb_/ϣcyVJHx{$? ؓb|m6b?x薿7I C濢j)Kp2|7nq\@QE(Q@uw`?S0_]!_5WORP?Y/EQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@/n7?nߵn'/<%/7}F//4:?O ?xLw,tFǿ xv<>#KτY_W>:/?O7< :w+ N<=o G5E垩k:]֝iV73OigoH/1;?o}xXf7"ix[OA]Gv#_ >kt59q9|.?V|p8 4o+MЦOw0z/i¢K3ݢ+>(əZ1_-x{7L3 2kh(k5{Oou&OټimZp/<1 qOA|Sɒ}L~TQɒ~?|K4VJHx{$? ؓb|k6bH>&;s'VU(ՊSZSqiJԅZrqNJpӺOfj?iO߶'k16wt/xu.|={[}J0j~<1wy%s}nൾ mxGWO ~_ :ߎυu W+}C|GuASW3}ZkOŞ|34O\|k O(S1#m - Hk` 5~3?᭿e|f2|.PቿlM(TO{k7\2\5dxnmX? kJ*'(*J2WZJjrV*tg m%ٟ G&\OQ"eD`W18O/ϻ8???GU.'Tu_??2z (W?3~}cG G&\OQ"eD`Q$g? ?WOL螣!Q4D˟(&39\Ia*:s=GBi?W=׋>9x[O|s`4?&O.x ΟR}kৃv>-ouqoFZ?cY@T~g"eD G&\OWE18O/ϻ|!Q4D˟?WOL螯?c???GU.'Tu_??2z M+?oWE=Pi_ w7+߃Ҿ|=/|WGc[gNF~6O~$g? Tu_??2zGU.'~'q m +7.oy3?w^C  M3g&mGo§_18O/ϻ|!Q4D˟?WOL螯?c???GU.'Tu_??2z (W?3~}cG G&\OQ"eD`7=Z>9uoga ֩iVzM;K#ºǟ |<4k_Ե©<.xG+?~>???GU.'Tu_??2zSeM3Y xo?ׄ2nooƾ7?? ?~:> 񷌼m㿍^<{ƾ=qC|Z1AſKWfo|o}Kҿ_?uMt-kRXiv~w,m#?q'?݇>Y@T~g1"eD G&\OWE18O/ϻ|!Q4D˟?WOL螯?c9|L3߃'9_q@eoڋ1^%o4x3>ho/}9 k¿ O~4 jY7^_S_~-Q'ǿ"~ g W |EE|=C᥵ςQ<;']ou-|Z( P~4-} _<_jƟV%Nc7=؛4lO?'gK/<(b?h>_?g+_?GZf<=I1>7||_ks<5ֿf߅lG1W__h7^!COo=|-{gX~i!>s}mg~о 2=ELj~&K|'uK6~"^h<3Q@Q@Q@Q@|gE'~9j_KX|>9K<n,MHe$,i_>%iO-o7n௳(<1 >\Lc-[џW CNC//F?'3Z2((((\~8fOkZ_w/=w6]WC>3|9XwO~x7^ߍ"h0j(;Ѽ5s>xTo4< ooWuψ|g[֟ǯ>X> ;G⮳G|/|$y?_G}hv>֑Z֥VoREܒ'gEQEQEQE?x{>׼#EWU? ~'/<CĞ>g j_>,w \ {U?l?Zx>3ψ>h~:<7\~xƾ;?>(xE_a]x B+ëm!/<5/oz΅;HϿ@Q@|]ɨ~o?[xk5{Oow']OϿM s6+L_y6+L_ySDxeg"8WĘ3o7I Dqſ}|7o_Ni>U1a̰$2PkռIM2Z47-y< H_VI_IOsc^|a-?c^|a-?}xs,̗is">_D9fJtW[0/~0~?PXEv[X_?Uxfd_#Nq#[|)Q_g< H[XOK0/~0~?PjkfI~#i4s*E5,W"!oa=(b/~0GJ?ןfd]ymD4s<3Ry#}梓a^`,%SkfI5X?$eNq#XJTWY0/>0R)+</>0bGJs,̓kD|3wOJkXEBOy+{暅TW5σ_2ND4sJkXK?ݜPXKߌ'ST_.|77$o//?$eNq#XJ4WY1/>0Q1/>0Qƿ\3nnI__#??Gqa^|a_ط'4?_ߌ4ԿU8:֗_2'8G,?*+b kj)XEBz*kEσ=?m">3wOJkXEBj?XEBj?U8z:D4sJkXEBj?XEBj_*kEσ]?dm?K2'8G,?*+b? ?kib? ?ki_EN5\5\̑oo9Ɵba)Q_o< HYXMG< HYXMGJs,̗i#})Q_o< HYXMG< HYXMGJ|śywD4sJkXEBj?XEBj?Uxfd_GOG1JkXEBj?XEBj?Uxfd_HOG1?a^`,a^`?e8%W^σ_2_."F_D9E5,W"!oaE/< HYXMGJs,̓kGOG1JkXEBj?XEBj*kEσ=?mD4sJkXEBj?XEBj?U8z:i#ҕ|]ɨ~o?[x XEBj$~Wo{[c|o~!x/>TYh7:lz7Zjg-Սw iqh_xGř7pqV *3ź^%d*.2btNu*rpiIF睜q*9N/.h&05ZT,y湥mSɒ~_|L~4Wy|${1١kK7׊ set_simplextype

set_simplextype

Sets the desired combination of primal and dual simplex algorithms.

void set_simplextype(lprec *lp, int simplextype);

Return Value

set_simplextype has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

simplextype

The desired combination of primal and dual simplex algorithms. Can by any of the following values:

SIMPLEX_PRIMAL_PRIMAL (5) Phase1 Primal, Phase2 Primal
SIMPLEX_DUAL_PRIMAL (6) Phase1 Dual, Phase2 Primal
SIMPLEX_PRIMAL_DUAL (9) Phase1 Primal, Phase2 Dual
SIMPLEX_DUAL_DUAL (10) Phase1 Dual, Phase2 Dual

Remarks

The set_simplextype function sets the desired combination of primal and dual simplex algorithms. The default is SIMPLEX_DUAL_PRIMAL (6).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_simplextype(lp, SIMPLEX_PRIMAL_DUAL);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_simplextype, set_preferdual

doc/set_lag_trace.htm0000644000175000017500000000445110553536732013612 0ustar renerene set_lag_trace

set_lag_trace

Sets a flag if Lagrangian progression must be printed while solving.

void set_lag_trace(lprec *lp, unsigned char lag_trace);

Return Value

set_lag_trace has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

lag_trace

TRUE or FALSE. Print or do not print.

Remarks

The set_lag_trace function sets a flag if Lagrangian progression must be printed while solving. This function is mend for debugging purposes. The default is not to print (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_lag_trace(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_lag_trace

doc/set_trace.htm0000644000175000017500000000436710237176664013000 0ustar renerene set_trace

set_trace

Sets a flag if pivot selection must be printed while solving.

void set_trace(lprec *lp, unsigned char trace);

Return Value

set_trace has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

trace

TRUE or FALSE. Print or do not print.

Remarks

The set_trace function sets a flag if pivot selection must be printed while solving. This function is mend for debugging purposes. The default is not to print (FALSE).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_trace(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_trace

doc/guess_basis.htm0000644000175000017500000000730610474153144013321 0ustar renerene guess_basis

guess_basis

Create a starting base from the provided guess vector.

unsigned char guess_basis(lprec *lp, REAL *guessvector, int *basisvector);

Return Value

guess_basis returns TRUE if a valid base could be termined and FALSE if not.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

guessvector

A vector that must contain a feasible solution vector. It must contain at least 1+get_Ncolumns elements. Element 0 is not used.

basisvector

When successful, this vector contains a feasible basis corresponding to guessvector. The array must already be dimentioned for at least 1+get_Nrows+get_Ncolumns elements. When the routine returns successful, basisvector is filled with the basis. This array can be provided to set_basis.

Remarks

This routine is ment to find a basis based on provided variable values. This basis can be provided to lp_solve via set_basis. This can result in getting faster to an optimal solution. However the simplex algorithm doesn't guarantee you that.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;
  REAL guessvector[1 + 2];
  int basis[1 + 2 + 2];

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_maxim(lp);
  str_add_constraint(lp, "1 0", LE, 3);
  str_add_constraint(lp, "0 1", LE, 3);

  guessvector[1] = 3;
  guessvector[2] = 3;

  ret = guess_basis(lp, guessvector, basis);
  set_basis(lp, basis, TRUE);
  set_print_sol(lp, TRUE);

  solve(lp); /* notice that the number of iterations is NULL because we provided a base that is immediately optimal */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_basis, set_basis, default_basis, get_basiscrash set_basiscrash

doc/search.htm0000644000175000017500000000356310552476302012261 0ustar renerene Search

Freefind search

Search this site powered by FreeFind

Google search

Enter keyword(s) or phrase for which to search http://lpsolve.sourceforge.net/5.5/:
Google
doc/print_solution.htm0000644000175000017500000000572510237176420014104 0ustar renerene print_solution

print_solution

Prints the solution (variables) of the lp.

void print_solution(lprec *lp, int columns);

Return Value

print_solution has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

columns

Number of columns to print solution.

Remarks

The print_solution function prints the solution (variables) of the lp. This can only be done after a successful solve.
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_solution(lp, 1);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_variables, get_ptr_variables, print_lp, print_objective, print_constraints, print_duals, print_scales, print_tableau, print_str, set_outputstream, set_outputfile, print_debugdump

doc/solve.htm0000644000175000017500000001474410500510234012131 0ustar renerene solve

solve

solve the model.

int solve(lprec *lp);

Return Value

NOMEMORY (-2) Out of memory
OPTIMAL (0) An optimal solution was obtained
SUBOPTIMAL (1) The model is sub-optimal. Only happens if there are integer variables and there is already an integer solution found. The solution is not guaranteed the most optimal one.
  • A timeout occured (set via set_timeout or with the -timeout option in lp_solve)
  • set_break_at_first was called so that the first found integer solution is found (-f option in lp_solve)
  • set_break_at_value was called so that when integer solution is found that is better than the specified value that it stops (-o option in lp_solve)
  • set_mip_gap was called (-g/-ga/-gr options in lp_solve) to specify a MIP gap
  • An abort function is installed (put_abortfunc) and this function returned TRUE
  • At some point not enough memory could not be allocated
INFEASIBLE (2) The model is infeasible
UNBOUNDED (3) The model is unbounded
DEGENERATE (4) The model is degenerative
NUMFAILURE (5) Numerical failure encountered
USERABORT (6) The abort routine returned TRUE. See put_abortfunc
TIMEOUT (7) A timeout occurred. A timeout was set via set_timeout
PRESOLVED (9) The model could be solved by presolve. This can only happen if presolve is active via set_presolve
PROCFAIL (10) The B&B routine failed
PROCBREAK (11) The B&B was stopped because of a break-at-first (see set_break_at_first) or a break-at-value (see set_break_at_value)
FEASFOUND (12) A feasible B&B solution was found
NOFEASFOUND (13) No feasible B&B solution found

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The solve function solves the model. solve can be called more than once. Between calls, the model may be modified in every way. Restrictions may be changed, matrix values may be changed and even rows and/or columns may be added or deleted.
If set_timeout was called before solve with a non-zero timeout and a timout occurs, and there was already an integer solution found (that is possibly not the best), then solve will return SUBOPTIMAL. If there was no integer solution found yet or there are no integers or the solvers is still in the first phase where a REAL optimal solution is searched for, then solve will return TIMEOUT.
If set_presolve was called before solve, then it can happen that presolve eliminates all rows and columns such that the solution is known by presolve. In that case, no solve is done. This also means that values of constraints and sensitivity are unknown. solve will return PRESOLVED in this case.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  ret = solve(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, lag_solve, statustext, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_constraints, get_ptr_constraints, get_constr_value, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex

doc/MATLAB1.jpg0000644000175000017500000017202510251412056012015 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?!khpx_`^?/'N-bεya+.&a`Mk`-M# #RmaH  |NiMG KK1,@bWξ*o⿉?KxƺO xgG}KLP5B͵=fOh7ge$1Bַƿ~k_?g|\񞩨|0дoxTM ZKa:4ޥMOi:nj=cW>_ue3O7,b8-5MfGᥖO $,=a'UUNjҧ(BEA47Ǜ[r9.7*:L¾acN8gqʘxz8,3<u7Ş/ށ71}N?j/M+*Pԭt]6GKyh|Hӧ`-c^'v'9$׀C~Yx BAYugM.fK)k*GZ\-iL{GfkoXyo[7)?h{m~VDkO?šPYgZ[jZ76mK\៤gpO>,0yGpmlk5C2q0ts,a~IN-~;ˀ=NXV7%ibL p"!n_'g{?@om~E~ =׌|w>\%/u &-?;o]+G7ſ~Z__=h_G4 ˦~V.o ׇaXHKZwT99Ͱ|7dXera9w՞U0pr,xM,7Y~[$ f_K:tpux첎)Ъ,EGo00Дp^\N>9^?ux-g~@_#׾ EIs _|=w# EΡ?мK OѼGoGhmg⽶]ox{㧄x[N|AB_/|/|M>MgX]ߊlOK8 ج>+rWFR'^eӅkQhajuTSc)ўxGŘt;2:ϒoFY!V8{*?yWFaөUjte.Ŭ ǿ1k?0GEO(c+H-,\~J|3{ּ'߆ >-Ix@t s?#oyjEMGTVXӼEۛ2 `?dgƾ'{X:i %(h?Si_PCj$okzW~(|3M:KNwpVk ;gX,M 9|* 09|M ' γZ R638(f$%ӟck_ ~%i y|9~/2Qx:N+? Dݯxg?1p3eS5(g^#kRP*ѧNu0ըbiak:YnyTqЄ*>& 2)ԧ8SOJs+RFN5hԄ=OWba{^)|*^64zw@^ω2/ |Ch<zux_:$4'/"_י\]L1E<.y+(xg>8{0XW)2(Ūt'N8& J=UiO)Y[S.HUqpͰ41oeҬJa:\4 O _t?]^=YWba{<G/k O|ux-g~]^=Y,%Dݣ^_|;-4?]^=Y Z n"ȗL?SOaiMewJt]տOˣ=Kg?bcw Z n"ɓoɓoKiPߘKERE__{|RvosԿvx-g7G.Ŭ+|?& Ou/v]>)t迻o_/O]) 1k6?2]^8^ɕ_g<|7Gԥ>i1}> i}:yz~>G Z LW?b׿mey>/#)Ϛ}?Oe~N^qCmC(j^ey}_nt}J_Osw`vӫ痧zo.ůP:?e?X7>;B&{=_\VgMvºDտ>/#7¿]xw]thnd?goQj~؈ mqz7&LVʱaF3;rL4 T&/ [A{IIAԌ9e>h sfT̲&#' br)Ta#Z ϕ˙.W_͟ jcݸG0|2cHH=9# w m;7#=D'c s8;W<7[i='W4ZđFѵ?u~Y'+Ƚqױ\߉H\ٓTgbLx||*~'xžiAoxgx k!Op&3_|IsFek6v7pjV:3ӕȏy&#q9\~t?RM'|Dǃ?b5o+%π|kiũḯf{٠IκH/[XѺTf-5?u0 Ϭ|;|oIk^tZzH4kM~-z] [&-[^.OxK]嗋CS.58nGP6ZDhךl['t+F~ց.x'FhEh;l4'JӬM-,4H`+{x(Gf^9E?_~UỖ=[N5~&n+豫OIujumexoT6Y xaS ոlj7?_sll2QX -z3+pCy5:TCq]b~Dc?p-~%3c=繾XxgS< ..RR1[R T g#1e_r7$g-~>>>CO|]>O4g ů¯xC8Gi@)dGI Ÿx3/|5o .?hht [WZ!O\F~mGU~ԬǍ4T~و)r dӷYƟJ <#<:x3pR. bdن+-,߇r,F"8-<6>^c){ m=R4=1m$}B-3T)|b'iUG x|I^kgUARk}J8xic0RW/~%.E?v;ę V SB9MT)J[tjÙ_ 6+-˱~_^ <4]/aE+7$֫Ky3K+Z'lx\yҴt8W;/ukD:un/"aX4iqB|H|ig/Q:| ^ V;υuXu"A mn4mkK$uxB8S5uO1ᮋ[ . 8 wS|=L]1 U cwlyqI?YouG#?[2Qg̳~;8sXl}wK9A✖0u()VK۪*qۧǿfWug_ƞm4k۟xCm=h%&tgԭ4 úlei"ɨ_~ ,~غg|It_ ޻:Zr^y%ߊ{~ʟ7|K~̖N:~@o'$;?(9+W_`7/sG sxP7(T)v]8s8!ӥMIJ !}.|Iz|U.AGOƖ<˫a՜ULޭ\4!m^H:{4i: [|tz _|%xwO^1?>Ǘ/¿^׋_ |:7^ou k:744.|Ci57؟Ҿ)3ǿx/~ho{ğfo?_UiW?Ɵu' C=&d8P01gVwGWSK2%0*_ѡG>8U1.KKk_.J78^SS f9mLm:Yʳ ᾷ8| ѧK/_Px {b- ^0{RY)D 𖡧j7M=$奇]7g)~ؾ0eO ~x {>"~)N|.3g~CN𶨾? u51`. C|XaG/2՞TЅ|J y^`ZxNt1:<<Дl*_6.~׺y4opѿgO %[ 3¾+>;΃,<%[}S_ƞ<{:Ěo:sm;^&o4h =w>/PxX}M%A |LqW2b {<^,]8RWF.2eLV3sxy*Rt/_?c'zf~ȞOKU jgŏFw"u<k}xė>!Լ;2_?;W#xcGC>Ui}'}8-`OL6egK. /ϜqFqLgኵ!fmcqqk N0so'> r*҆uTyrK/˩N4sJ5+r*:s?/9G#H?B?W?<*_FW$ϭhO<4*<ЇZ==" ;W#xcGC>UiPG?Jzypp<?/9P9k=o9_C>Ui3!G_Gu~!׿bk*><'$<<_ߓ?7W!G_!G_}bo7yJ_!E?G-~M(rz7r_w|q3w|q3G'?wĩxB'$\?rz7rG-~M+w|QG#<_hw|QG#<_h}bo7yJ_!E?G-~M(rz7r_w|q3w|q3G'?wĩxB'$\?rz7rG-~M+w|QG#<_hw|QG#<_h}bo7yJ_!E?G-~M(rz7r_w|q3w|q3G'?wĩxB'$\?rz7rG-~M+w|QG#<_hw|QG#<_h}bo7yJ_!E?i<7V0?1;{jD I?ndLgw|wnxF[_~K}VJ}x ;Jy<g9 {مWj/c?ƏF?kvUG?mQx2 $үh[_*^<Гj/L<51ȟG#Q5 ;^*(vUG?mQ $үh[_?Ty& 9N_yWj/c?ƏF?kvUG?mQx2*H_>!R_ĩxBLOr0_"EL'3x2!WHeGT/GJO|CoR.P=9a_OD&1wV׊;aQkGOk^ ?iOᆩiƗa oMu9-<=MRn5KX~vUG?mW6,_muKUO_ l? |Q[]b9b-/Fp<[MvIsJ2#}7~\a`0XOhT̪*a3 CYsb01˸B3/ 9̱tqT00ʂTun<*q9w,.5ka13*U†&yjԣR%^UyO?io*u࿌+&k~%Ҿ&cT$!Qk|YӴ]}rf]KcM>;xE^x{ßwZ,6Zx5s7EW7d'X-No)E\7#ugCj3Kw {xC[}i>#+wv :-ͱq<%, f'VO2V^0XF$N԰l&uMΦ!V"Ů 0|M^+4ʎ Od*XzxeY\|LZ'K[S+<|'|ojO|(<'O? <~.|52;xw]g?6skxyN7f]\؋_ i?c_^'>[~74𰽹ԇ>t,Kw~4oznۥ7:F; ISC14|I˫ ||F?+>?-8 5G^xӯrVj5FL'_'RukVV*gc1qfJt`Ft1NyM/Fx Hmjt_o▉/5mx+O6iZ+ĺZMOKOr~<7|-JƯ|+cy?)Wr*xGmPI+][Kլ:6=7~&iPi+Zh>k#ᇊsmqq6?i V;n#UIXedfxS júW< ) B׆kV[Ҵ-4fy KXcyWVwf??K,_ѯ)xy %xkp*Ge pcxo/bqC:N 1*ԥWO(q?G ZYx.sN^#pqG+*e\|)as^/[ MxJSU,M\5?-Mѯ~/AB>|vZ^Va5 f]?A¶|Phh>&/w)ۤ/y1A7G;:j72 ͮ6P"s->+ړi#?+`s??Eώ >(z%X+/ 𽏈S7^ҍ[Y^Eg%^:E/< +y' _^K'7$q٦clNYG<3a*fYŵ[ W^:qK)?_<+ᯢ'.:^*98gK춖W<^41xOG+h "hQ?mO(\?fXx=I?@T_l؛vP?mq6 g </xBXv|n%|qp$8,\pph?J< JNY_۽#ͯ]olwşOߴ]})Ak>|_O5*? 3Ɵ?w/jAxĞ=>!şx^ oxeS]>*at7ln< ~^o-wy(7}kc;N?u(O>xjW?j~xoD<xgZ'N&'J1%ƳNnΔ[nɫmN?J rEukWv~~cWWWO>1ԟ?ij__>$#i_FO!O3 KƟ__}~ ^a P7[Bм/TQ> Aů wPDŽ4^h^LдRM?H'o OͥjV"fgc(ai_+V#su|$zruin-<3#@M_fUQԃVN^|(*RMrW-Mbo8+t~o$~qOyi"Y4/^*a?x?nٿq3}c^(4_'u^KuM.<+V&-/ߌ M~~~mSÿŏُ'wxjo? 'ᮭoNW}G4i_ن)O^9 xKU>'?APߴOO53Q_X|17fcxO|Jм _-|3'~?Oh?7o}:|==~Mrg}G[MבC||+[м |QF/Ť7g ~D𮜞[?xß x_v o@u ;B ot^&3S]T(4*(ٯfnNNI]ˮid-g(y%g7g쫯 <|__kභ?xkY_<N;xU4+źt:??ٛOm&xUMZ)nƩ |ڋg]tgQ?ox??__ h( >':O5 T'O_/\KIக}wOE֙?^&߉'_"li٣ӵ߅2~߇ڿx^Ե]z0_3mD,Z>0+ -4A?ƞ7O o|u/'xKu 3nP>ww{$s7iEUQqd?uTvrvZ2M+6ͭ5*CY5?/]' >+x3WWXnğ9K~*м=glş;usx"OeL34??xπ?%7<.gou_Σms3>GſUÞ&[O k?}ߎtK| e d[s'OOI_[{kPԃnfRMۺ{zO&մ'7/^Oe?xg >Ɵu OOtKNI6EmgZѵ?h~/i:k^l؟ >|]HO< EYE#_,~'[#^&|95:w|yw+ßcQ|js*F|Y(o''σ癨~/>3LJS p ~> 9C@.k E߃|)x l|ExKwτ -߂~c |55xgtCOՅӌIFTjMI^{䛍qjq纶oI-[wm>ϮG`[{B&|WS3OM-g/?՞W^h^$xw+W;i~(G|Tnd>nOo]"EQ|`|j^ ?Vz}~?4|Oa]߲w0V+U~ٻS6xćW# ms \[wC?;,w &5?~}7| g~$~b6_f/K|U7a٠xKo`iΣ.I(^I%8QRRrikEvV2>4|]_|FK/|5w(NiؾG M3NԾ+ğںmgV<;>"qi^(еw~Gkm?[4ˏZe vk$mn.|E74>Zx.wojqggx/mλմKP^5ޙsrmSwz>Xv_Bm}֯{~¯'?kk)%_?kO ~1E]O#Iu?'gnx<;.(I'mG+o5wh/Yj_R;k~-{eɟüa +Yͧw/ x~J)}S[iZ>iG!H5/?O~_O2+To1.i:+I k-w>4]6ڛ*٥>9|BxZօ^j#\h~,ASOXY\?_ Ogw]+⋭3oٓMxOƿ|EӟG mk |e3ſGCF3.wqj?(  xox:hZǎ>8k[g_<WNoW ?aυ/|.y_{;N[GxSPB𵞊S8Qnqw+s~])8^PHͧ4i6g']?Fڨ^ɨo(}|]UfaEu>|M?gxz5_(O|zOݨjwSn~/i1H~k#eooG#C㏍~GſUÞ&[O k?}ߎtK| e d[s'OOI_[{krISԦזrE+kܤ}W'.ZV_>gf'j';i7uO?2fW|/k/ ] OuK go >|bԿj~ ٲmzu ~|YZ <CbI||r6| >5|:Ծɩ7:|QxaxG|yៈtO >00:o i7F|ռsiO~bMܥ&VrqQP\ݔwh];ZImIY}]Oڟ_| +@~ў?fo~?ŗˆO%P,-^,e]"_[oQ|Nռ]⯅^(Ŀ|>g'|a7KV~2+wn/mi/f#xú4/«S]CZyRx\>/7f0|~ ~_O |{{{ľg |o o(I~_[1y&xm-\5ϫ/(|!hZG%/ YF?G ]+bn1%)h~|7|1x[&?ۺn/aW|>kV>!@O n/ |;_7-qg] 0;#kjE7looůOeH>&sgae]IxQWxiM{<_{;TnXь{TIw_q+-sN2oD۷gի^HmD?χo% |>n;F?ok৏OѴje fuEswK=?io|~_7W?fi_/_8~Ԟ, ~l5 WߨH|6)⿄*ߊ|YIGXbTJMS5n[WdڻkGVj{7W5,_|6Y gfτk>7]U|G_t_~?h<OV⟃_ >:['4 | >^ko:?`í~#|sęoaiS?:u2qF*C NrN>Rɥ:raEԗ-:|j1ҶJ-oM>τk>7G  |'YbKs'-kIk {xhPl~!>|U'o|7ѿ7[?+|sʞNֵ/t?G 3F㏏'zG^ O G<;im[[h^ :έ[KCtHtnkp8|(p]s 8#թBzzb)UP Ҝ!RN(e)FI4ikZo  |'Y?mD?χj;?fG_#?>=ˏ|1=Nп<3O [^χ]WZWW:{4 /˿Z~boks |PQGs S ˧!ź?7'퉤zx{WM]ωRž+𧉭v*4:Ux0\V.S ʤ:Rs('S-hA+ݝwZkmO7"~|!7S,Vv] CXᑙ^r-®UBg4^ex8aZewG|[_PQo~~յx^ծ.]o][OW;CR.n//.&I(OඥkG~,GKk/1xş* t4 ~"_k᷊ӿe/υ=:+RtSRurZiWPF*Rڤg'vRed{-SD /U L!ßW=C&u7yQ>6b_K%->[>w:u_5Wz_Oo߅ s<=E?㗄sAG|6߇Z&/>.|+~/?]wŷ޷_ԯ'_qT/ ou[Wx a GoU폣'QOʝLBvN)VI֋~JQ}F}i~V'? 56-RWo2;M+DiV/Msj?i+S]beJJe_GRM'g8EEG٫/y  |'Y?mD?χPڳOb/oЭ5_? =ss~>+ܿwr|$~=Vho~پ??G¿O.i׼K C⇇oMpXѩYW7]IM'Q]}NR_dU[+/徝\l$~g5K>}uTV޿'ec/WK>}|6Y gflK?ZQ}wI2k?iT~Ě/_ςu>=~8W_YAi&Zk^!-/{]5ቡ 5%re' ʩɩqq Gu($\[rJqg{m;8ɫnmD?χo% |>n?ooG?IohZ':?= G?ػ6̿h[Po_Gŗ:6ˏ_Gw3h"~Җ&jS:Pm+IRj0u.Hx۲I+/J?@>,O3uGᆱŪZ*Yڇ4I|;Y^Ac"Sl$/%ku\O?0ZQj'NOaOv;]K>}|6Y gfgW~Ξ$~_F㯁<}mU|xi2W'"xֻn+i,k~{\= <g4(j_x44;wQ?-O s-mF8єz֊,v5ZkiǖͶt8ťm_o|@>,O3tg5bo^6:xoQY9?v_⯌~\K_4T~]F@_ԏgW~Ξ$~_F㯁<}mU|xi2W'"xֻn+i,k~Ts9;Isr{tPqRVW} o% |>n@>,O3uYL:W?ig\,Zl@d­ebo^6:xoQY9?v_⯌~\K_4T~]F@_Դӊgˤ$ZRw+Zhݹc{_E}{wV'  |'Y?mD?χ߶~O__ϋ}koA'? O?W톫㿇0\5V)Zs yG1W/ 1GWt?m-;oּ{G?_~+=SQ~"~ߏ ?g߁~+iϋ_  >*(߀? bcRrԌQr촴-"$RwJPM$|K{g],Ͼ?mD?χo% |>n_Z36 Hi &>Skx^a=_-tOxP['^4V[֫'c^_r|6Y gfτk>7]U{z ?]r|6Y gfτk>7]U{z ,?r/mD?χo% |>n(_?X,~t_qg5K>}uTQ2Xτk>7G  |'Yꨣd9c}+o% |>n@>,O3uQG?rc/WK>}|6Y gf몢o_U0_E  |'YG-?c/+oًťoXYrAue}inTh-Dc&W_ٮO_ ~" Uׅ{͞t_n.OGk^& ծZ_|5u\ڮawKum5ELo留D2(a#[)NoQitw%(/2K 4$ӒO^4 hu? mٿGO?f#ৌ4'/x[_+~:&X_i#+{ k6T7T6ڤW?Ǐ_|g=] |JּKǟO'=|Cֵ~{wO|4#iw| ][TA`Aw,g)گ #v5CPì403t9av)IݩF7NNֽ(Pt {%5+SSgCQ񟋿dOǂ~4xߌ>wпd߁:?=|4/i-%=_itxSgg #v4_ |g^.y1*/aQajƭjq))s:+Z}4 ՄdM4N;k_k?_>0I|{gj>8+3m9`K|+fgO},5|D/Yo|3|| iG?<|3IBþ Wb4+OI缻UoU׼QzT7|Mj'>W;Y S_AG3Wj8kp +5aٞ/11Ug:tgVpFj|*({Jg2"5$)M+%g]#ewew[$!~g>7xٳ?|6Ѻ<6GGv]< KW,;Z+E4]^_/s $^.bڋJq_Ǐ]E|> KįxށZiZ޵NF; MJPҿ4qE<AjG,g)گ EN ʱ4cqMu_06"G"ʸya+*8w(tܟX߄ZL_?x׍1?eB-O7ğV '_p]ZEF |ߴ Ǟ.Ѿ#Km+|I[B?K|#'|9}k?&O^'Ρs?|% ãQ4,t/5 Uq fobS^";5J*Vp%]PTXQQJ5'9TwqS%S*mɶ=?'WSGlg]>x]iD?5 )x/⽧58Ut/j.4#:|BgtT;{ :Kyu[6~!ͽ5Wĺ^u/Zgok+[[Ha9dx/?NFtؤ}#?xGn#ρ|3jZmx? k+|J+{-?ox>/Ot'O|!>υ/,g)گ #v5n9ҍF IGU:>WbT9IsRrnWt]_wվI._ȟccW^,g)گ V?}cgoa^cio.r"3y滪XKخkQxxmekki 0F5So8(*)kԧufU7 u~ȿ s[xoUvÞ'g?~ ]itx-kZo:ѼӾ&b 5ǁ] 5 SE +iϴ1 /+`A?qdx/?NY S_AXS Ty9msJNtQych7廓ku"k/hV5]m{ _?>;=EoGᯀ<;k ._º/뺯VXXhZ_yiԯ/%O?*v:d_9 7|sa3?E |Lk~:|JмW Nݵ]Ýhi~1~<AjG,g)گ SiU~^rMsЭ%ϯ,ei%+ŵi&Ls*ӲK4]B~$~ŭ ?b'I7RTW '?9Q_5umc>4 WE]wUд kSuk#:\HY S_AG3WiK WJpnMSWkZN?;aj_T[_<kZOOV'Z/|+7 ~):΅|8&6maO({LO?!Gdx/?NY S_AX{J(G3Wh ;U>LO?!Gdx/?NY S_AX{J(G3Wh ;U>LO?!Gdx/?NY S_AX{J(G3Wh ;U>LO?!G]k5ߏ[^ #v5' ^Ɵ\̟d+\Q&,4#vT\($}G/<(b?h>o?g+?GZf>ׂ8[Ę3_7I C濢jv/&?[1NJ/ ɻ?iqQE~QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEu&OټimZy?i7?K_cdž?w6i5ϊد2O'ϛ?د2O'ϛO)_`?O?&Z/6bqx薿wo[_X~>7yG8[. (ԂcC}qMx_߱|W?~+/#| Kx­3!?į  u$>տ𾙦F~ڋ^"~ҿ_ a6 iLcCg,/R `T> 51_(R ?Jw~M¤2(C߂^ɿ῿kEg -Gw3.OHTگg/OG~ |Mk/R+ #hc~?߅ #?I5WQ?)ԮCsєWã?c/?g_S/?џ~ٟ)Ex~lYtge?_g, eu@3E{7:323u2躣:]PS~_G??ߴgjz7oxO c+>2~ l~'6v|??Ak5'uPgBWKtge?_g, eu@3E{7:323u2躣:]P^ŝL.F~_fο_T4TO~W ?fLs>=5?/'9fu,AgA|usskx.vMf&w=:]P^ŝL.F~_fο_T4Wã?c/?g_S/?џ~ٟ)Ex~lYྗOj'4]gso) G_?Y,?%/?h=㷎nONlֶֶ4Wã?c/?g_S/?џ~ٟ)Ex~lYtge?_g, eu@3E{7:323u2躯G ㇇g?՞o>:g Wy_e<X0gi_[]xÞ6C5kx ;λ6t ~lYtge?_g, eu@3E{7:323u2躣:]P^ŝL.F~_fο_T4T~xCYg>i8h s1G^}'Ś5~ҷW0x~ P]j>=dv:]P^ŝL.F~_fο_T4Wã?c/?g_S/?џ~ٟ)Ex~lYz9/`Xx&zo?ٳo{?i?:/|?gTM^K^y#;aj(+MCyĵ5|]ɨ~o?[xÿ8 e xG$}blPk?dW?/SlPIDR?Z)"<_3A+bL$?!_5;_oo-|NJkJ_|g 'x1&(eEWQEW3R;ـ@U3R;ـ@TEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPoL3 2kkٿfVyL_y^3@Q@|]ɨ~o?[xk5{Oow']OϿM s6+L_y $)h~/i Ne$队M/ص_O+%k mů_-~Kado?4l(Q?R (g"r3O A|#_o Q}b֟ !syW>+_~',[['a I?i F%?\8q?)Z+ __k?+koY_s̿1 *T?boD?6oo;?$DߴGiҿ/_<+c[Xjz^ޥ_> eiG◅*gSiO_xCœ1|/…L9<._KZ8zUJZJӧJU/eNu\(ƬUK1^mSһQMwkݥwd웲]~_U?O'4?^R?VR]EkYşٺϊvNxHu[+<'ׁL̲&1Vkٖ]`qgCPZz5gN9QM5HF9FpT((tZ4QEPQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEs2b̿dZTZΟ~??P'~ ?/M2J?n3[4QEW?=fUkjP~4-}p8I٧>(b?h>_?g)د2O'ϛO)#|O?&Z/6b?x薿xpRa1? Ɯ_Q_'A^g|*ǟ-5g?_ ~kZ|-_|WƯxbKNRZԾ; zVӼ9iwzαPŞ.sA1C -hK+C !'!# g-}9uw`?S0_]!_5WORP?Y/gl 1+ף'm4HA5-h:u}xK:v?WS<# \Ƴi@k.~2W +Ƈ5 oOԴ]%< &wC|;n|%/~ ?#G"#dt`U A Tj=oy}ZؚT>/N˸,STa8fSsOqbѯnm˦[mД.^T޼te4[_E; ^9wwg7źrO7w{O;ejxOŞ|34OqG|Qn){M㨩/2NQel5nWFQ|-xQѫJ?`1#^N}a5KZgAEWaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPoL3 2kkٿfVyL_y^3@Q@|]ɨ~o?[xk5{Oow']OϿM s6+L_y6+L_ySDxeg!WĘ3o7I DM/ص_O+%+__X~>7yG8[. (Ԃ+o?_/x; }sƯ)M.- gj7S o^ 7ᦽ~,4o}3_]!_53_ ?Wš "L½uZoEin)ZGW1WWg? ~s? sc#QE!_g ?/߁0E}>ߛ'$㬿u?ٛw#=Mk//񵶣Ek?>"|T?:+<@넼N5ds 9af:0(f20غ*rL>"`c1*ʶ|ZI5xN7MqzJ.M;J.2Ij]g2w]M_^mG5h>+oxDc~BҴ~Ŀ(70?>|5{]KoZKkiwu gÿf >)i:n#Mlo D_^ |q-|/?~{'t?f%i )eoO< ?e F >OSng3_J?+O2 a:Bk?)k 줡1ȳ^_+?1 ( /~,͟||{w?z~$3-zƃ&ҵ^Ү? xNռ'_ zDŽ|akum"h?5ʲ.e ey ~>_,xcWx?'f\ $(h $(h~/i H~&L mů_-;_oo-|NJkJ_l_ 'x1&(eEWQEWWWg? `YO_}xke%1!{ J)VM/o×>|5'o~WX6i5ϊد2O'ϛ?د2O'ϛO)_`?O?&Z/6b?x薿xpRa1? Ɯ_Q_'A_l^8~ןKh<%i/#;&&_x*CwQ֭3z7|B#?xoDּ+j~K/*}(OldoR_o {O47.C?s3Gf?%_?uw`?S0w3 Bf\[|ߟK#XJXY1+?ҟنj9Jcy1q?(((((>|o5\ǟ? A MoX%zޑ{w~S~D*Ow~+.(9Qde܎ 0 29x[^$ǎ-u wtWŞmx{sykt=SFt˭;TӮng)[)b?h>o?g(b?h>o?g+_?GZf<=I1>6||_k~}![ɢj~Q7Ưf¾< Hk^*މiZ5M|G?7Ok[#VJ:9SeYUJpغqף:l^Vxѯew {¤S\{M)E$|w;tGrKa K{-c@Yj>w|Gi>+gk~,tohڮg4N*ܞ+$$x{q~>8ռM=ϋ|?q|01~rr*, ۫Ut{L!XcC6f1F)ԡ-ו9mRv:(=P(((((((((((7 &ekgי~ȵ5W?3+_<&/E(y?i7?K_CW?=fUk|;X'Og&?O&ID|Q/8| ~ [? C\Ʊ|C+j-x¯_o7M7?'[Tq~WWWg? ~¸y s?O\G/yla HJŬ "̯:Bk?)k 줡1ȳ^_+?1 ( ( ( ( ( ( Kwƺį|}GQ C_?=X CSѼG_VuFu+Shy+f,V[`]S cq,f\*X\D*PPRZs8Eb9Ӕg JR'FKg&kM4 ?BX)>M+㞕߆Zھk(>Xx_Kv+oxGφ~gH(|7O3~|CxC״oxKžu/xž)mwseh"5+-[C4=SH,u >:֚lj ǿΙ >%|;];o19e8y RSj/00uOEK uJV>Pib=BoJuޑZ~]*먢*>((((((((((əZ1_-xc\2|EQk; X)|M"44ɺ$+٠(y?i7?K_CW?=fUk|;X'Og&?O&ID|Q/gK<^jZ-u@3 | '?X %3u]J?VnZX1WWg? `YO_}xke%1fօ7d*eoG3Ő`r)n .-*#.Q9J:S]{HT[V7T:_*YӣʒZ^pII4tWWo (SfmwVW ׏>& cx{'#[g%v|;'K xĞb׼:տ|~XV[`yncS cհx&*X\D)ץ4RZp 'E5c8Tg FpR%(/g&OMQErQEQEQEQEQEQEQEQE~f\̭?/f &ekgי~ȵ4QEW?=fUkjP~4-}p8I٧>)b?h>o?g(bho۟ ~#QZ)"<_3A+bL$_⿢Zv?&Z/NJ_3?wӋ+DH(MXCVƺ_Z,#A>i {J>5>⿁/O| KoxTT'7ů >`Jf?1 >SL|-[) {CNC,o(/F?'k] r aھ|<5nq"oyO~(8(((((((((dGoٟtoxFWlAO:Hi|? wQ'oi>%ѴoxgYm*?p^~oF*`?x~ "|>2k>+&xgGmWW-[+k~$(h|+n![~>Ş'ӣ'-3ῆ4"ּq%ޑ.~iz|UԾ??*x߁8ü|[W,,%0 )Se^7 VV'*GNT1[QNJ/gd=WMQE|QEQEQEQEQEQEQE~f\̭?/f &ekgי~ȵ4QEW?=fUkjP~4-}p8I٧>)bh>?g(bh۟O+_?GZf<=I1>6||_k OoY|~eF<OX>-x/m5O~>*e7ě{ox|:?u/~].g'\$µ e RP¡l] 'O3V??'-/.o/WWg? `YO_}xke%1Ym(aR?8).^ie~̿oO_wŭۯk\xwUUɡM[>._4o ^ KmtooDu? km{_x{XO^h$?xφ~H}?z_lo-zx;z /DW/ xosZkCXŸWɿQ:Ws⦃mڿ~oZ׬l'͎פ|) K )ixIN:x_3ԣ_0<~..xŸR!`Rf)taVb O<4N-B"jw\oTygi5h8Š((((((+-~.X?~ ?/ai\O8 [5W?3+_<&/E(y?i7?K_CW?=fUk|;X'Og&?O&ID|Q/|MѾ ^*} ]_I?!񎷡kOZ? I|W_k:5Vz%k |?_!]DhUtudtu !!$_Ic e/(> x ?~G? 13XDž"sV7򚒩<\~, OU=/N!$;¾ѮXTVW5pR_ڵQ_хQ@Q@Q@Q@Q@W?3+_<&/EfəZ1_-xQEu&OټimZy?i7?K_cdž?w6i5ϊأؓ?/Ȣ $)h~/i H~&L mů_-;_oo-|NJk/ ɻ?iqQE~픿|o|Jt?P@m%qKoM]o|D?? |NG_~A⎃Ipl5[qqa}iwcoeh"5-GÞ.'~ ^xOŚ.MUҬÖGS UDn#qsT< mĖVqoi7|yu~Uu=s汨jV~+{⟈ w/0)=X!skTxʳ,Bq0\EXũejվ*㜪RqM;$uudfɿQ:Ws⦃mڿ~oZ׬l'͎פ|) K )ixINX6'`zL^\6+ R' RT*hףVVHƥ:'42%(-8-]4֍5kFAEV ( ( (? \ᦿ?>ȿ?G IW?/ȝ7ӫf &ekgי~ȵ4QEW?=fUkjP~4-}p8I٧>)b?h>o?g(b?h>o?g+_?GZf<=I1>6||_k~2SoV_[[^'?x!׼!k7% :*|b/=Ƌ=/ڣXb~"t{~Wxi|J־$i xÖZW|MO|mdwW?"8N%pc0x:5Ⱈ iMas &qFO4x|6.|=/chƾ\ЕӺqd E([]=\eQ_tQ@Q@W?3+_<&/EfəZ1_-xQEu&OټimZy?i7?K_cdž?w6i5ϊد2O'ϛ?ؾ?b_(z~K4VJm>/g~T!WĘ3o7I DM/ص_O+%~+g 'x1&(eEWV6?hw5{E/Ss:~X* \>sZ|Oy2;|={Zt}Bf>xAk''Ytx?g5R ~}#]Ƌ?K5}ǗӴS!-o{ O_?߳-g_}[,m$s??/?W],uw`?S0Gc:Bk?)k 줡1ȳ^_+?1 ( ( ( ( ( ( ( ( ( ( ( ( ( ( (#G"#dt`U A s?b |7m/^,h|s5-WմB|5{+m Z~6|ܾh>ź+ZOOI(#Ӵ3zN?h74mWJ%/Vx࿊?/Oi>30xmixcR\~;o/5c^?.टL(_x^#- ^!7-8-,|)]E#6,OƟ8R̩i3'ᢣʤ1,uiToUF^x,N**#nka>J5Zf^ӧ$R[H+ (?3fVyL_y^3XW?-|= oeb R"ɺ'¿\k-lEP_<_jƟV%MCyĵ>_,xcWx?'f\ &)hbh>?g+_?GZf<=I1>6||_k7yG8[. (OԂOx{\槭h:.x;Z~5M.Pn=xF^\hzDŽU OiZM,j4P8_CE?oȱO?LLGC_,ăA_YO_uw`?S0_G?>ICLb78f7'?EW~bQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE?G}~O/:7okⷈ<[kռgT.|gӼ;ee/ u+FҼY;J|UyMxᏊ< Q^'pCŹ>7 \dم7KF xU:QKB# Zzp(֫jJH;pvk}ZQiI$hX#?wz5σԭ>"ѮlZeehz{gi[^[C2}H; ~TX4\׼%^ д !wzI-kڿ+Cm1~|5_>x_1r<)B2JJ)NR ҍ)b0XZU^qN41sgԱj41n4q:F3nFFpnғ^\ܨ3>əZ1_-x{7L3 2kh(k5{Oou&OټimZp/<1 qOA|Sɒ}L~TQɒ~?|K4VJHx{$? ؓb|k6b DM/ص_O+%>+g 'x1&(eEWQEWWWg? F~g)s>NlC -g?D !'!7#g g.9uw`?S0_G?>ICLb78f7'?EW~bQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQED9]YC#e`He `Ө!RRNe 8NN2$(-Em4wNj>/3 <% Oy/ /xg#bI{FW|;xc:5-J?w wF߇g OŞ|34Oq~!C AE}Yu]gŸ⟆,x/gg>ws/qO8l6]* u:qj|=VTLu2MX`*+)B3 JqPJk8iRw\̭?/fn0টNKę7yG8[. (OԂ(x2O+__y!{*{O6%7ɷc cIb}^\K7~ / 7={z//W> [t%ѩ |'i )j@ ?eq  >?\ag3X?E"+?Ċr1l(1Ve` _VIW ԥU&ҩJ$i;6L *B5!%iBqRiFI<!}~ٟ\o!}~ٟ\o~.& w_\l.~7_\l.~7E]?'M@?_a/._g??_a/._g??Dߍ߳۟^!ڗo|s=RnAO[uAM߃>3|2į[›O^[> fO5oF?x?5@_a/._g??_a/._g??f/<^g8Fe=N?ƏX&?#O)X׿!xV_4]7Uˣ#u2=ៈ<ϯ\ºfIٛ+YסM?現Zwcx_¯h:/.;φ %o_=?ĝwA/h,=ZxV?i:|g^A6-^O8ozv_@8?& %E'C} %E'C}HQ:#qpMC?fsfsJ(O8ozv_@8?&B r? GB r? _c~6?#~3Xtľ OE~~^,Ҿ&`_k{ x|HK 1/5 cO)?큥> 7/|jL^M~ɟ7Hڿ~$x+~ {9"T_IĺCS?1GSN8 gB r? GB r? _%cwq7=;/P!}~ٟ\o!}~ٟ\o?1GSN8 w_\l.~7_\l.~7_w4's>'~ɟGC්/l:͢ߵgzkZmj?3UxmM@xO8ozv_@8?&_\l.~7_\l.~7g> n~~2??gy?7? |1C5|;׼k'J^~%Fk49mU1GF?x?5@nKO?KO(#uE?1GSN8 B r? GB r? ^ )j@ ?eq  >?\ag3X?E"+?Ċً90|xo? ѿ|9}D&/>"i6/ /SNJ:5H~%c;վMm~.&gej %E'C} %E'C}HQ:#qpMC?fsfsJ}x{^t^ԵTxr]x·څ#m]wևq4z1?M}kzփis]?'M@?_a/._g??_a/._g??ٓ~ž,ǽ?EGO~"=gžۇmC_uM7⮋4KMKTy_:Rsv??j|.|NgA_7φl_ <+ٳĚ3ŏ '?gƍE{w/A:#qpMC1>C~:_ŗ cK7ω:W~vŞo jOk3ki߼>z$|Lܟ<E/>~/Ղmм><}.+]~EҬ,̯s눱s^ 3L4Pg9/3օ qFq#F!JgQtA(%N:0TS(+ p wmF)%wŠ(,k5{Oou&OټimZp/<1 qOA|Qɒ~_|L~4Qɒ~_|L~4VJHx{$? ؓb|o6b?x薿7I DӃR ado?4l(Q?R ( /,?Y?/ƯP?/3&Q sW^ƾ ( ( 7K>|GE4xl\_]i Wmalm-sEм+AO^ ^~GNYQ@3|>>/~?xq[[~5xOow_Rs ~dxCT|oTg! 54/|Ar(((oOưk>֬/t W!|Ht/ |~"xjo >j3aykZo"M ) ï h^ ( ( 7AfMyGux#7~++gAc ־>Ix ENoP૝Mߋ`n<I4(+Gx\q?ZO|A}yR_B>Śĝ@]}hU߃<4Gi~..4=k^t_O`~S|dU,O=/㼟[NoKOCXO|9C,j*(} "O)&L mů_-(e1wς?"m~"oZ'XͿ|KJ`\D\;l_WO783xNF}p9'ⲉ0ج>ge;dpiU՜*YN?%=.wa1y2*O2 4úRgx_R}Q_OD[/'/.y/$WV}TGy_?ՐI>mE9?so|]?M/<{+= ?׼j|/ފr??O" '/h?.%%+ϿeFď5ѽ`E}} OO%%*Ͽy_?אI369 _9__O_QOe_Dy ?׼k?%ڊr???" '/iF9-x u_.y/$[^{HyO?אJFW8?]>{I9 .y/$W^{TG{x_?ϱQ_G ?:iF9矂;~gOĹE_YyQ1kG?+FW8?]>{I9 ?\_I,?Ѵ# YTc69˿ctt9˷c>{GKKI?Uŗ>?m?m|H^A)_O <(.y/$WV}TGyO?אKYѵ`ΟEO^`E~</='}z_?_69__O_Q9 ?\_I,?1iG/|>'r-`_E}KKI=VŕcFď5d>_RQ_OD[/'/5s_W^{TO?m_RyQ_OD[/'/.y/$W^{TG{x_?ϳ?j+so%%*Ͽy_?ՐI>mE9?sor-ĹE_YYA՟1iG/|>'r-`} 4\_I,^6$ 369 _9__O_Ss'/<cFď5=n%}369__O_Q9 ?\_I,?1iG/|>'r-`_E}</='}{x_??jP~4-~'`_E}4|{x?Nxs\7˭W/ ֟yqlno lp_solve_version

lp_solve_version

Returns the full version number of lp_solve.

void lp_solve_version(int *majorversion, int *minorversion, int *release, int *build);

Return Value

lp_solve_version has no return value.

Parameters

majorversion

major version number.

minorversion

minor version number.

release

release number.

build

build number.

Remarks

The lp_solve_version function returns the full version number of lp_solve.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  int majorversion, minorversion, release, build;

  lp_solve_version(&majorversion, &minorversion, &release, &build);

  return(0);
}

lp_solve API reference

See Also

doc/is_piv_mode.htm0000644000175000017500000001055710256364046013314 0ustar renerene is_piv_mode

is_piv_mode

Returns if pivot mode specified in testmask is active.

unsigned char is_piv_mode(lprec *lp, int testmask);

Return Value

is_piv_mode returns TRUE or FALSE.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

testmask

PRICE_PRIMALFALLBACK (4) In case of Steepest Edge, fall back to DEVEX in primal
PRICE_MULTIPLE (8) Preliminary implementation of the multiple pricing scheme.This means that attractive candidate entering columnsfrom one iteration may be used in the subsequent iteration, avoiding full updating of reduced costs. In the current implementation, lp_solve only reuses the 2nd best entering column alternative
PRICE_PARTIAL (16) Enable partial pricing
PRICE_ADAPTIVE (32) Temporarily use alternative strategy if cycling is detected
PRICE_RANDOMIZE (128) Adds a small randomization effect to the selected pricer
PRICE_AUTOPARTIAL (512) Indicates automatic detection of segmented/staged/blocked models.It refers to partial pricing rather than full pricing. With full pricing, all non-basic columns are scanned, but with partial pricing only a subset is scanned for every iteration. This can speed up several models
PRICE_LOOPLEFT (1024) Scan entering/leaving columns left rather than right
PRICE_LOOPALTERNATE (2048) Scan entering/leaving columns alternatingly left/right
PRICE_HARRISTWOPASS (4096) Use Harris' primal pivot logic rather than the default
PRICE_TRUENORMINIT (16384) Use true norms for Devex and Steepest Edge initializations

Remarks

The is_piv_mode function checks if the pivot mode specified in testmask is active. The pivot mode is an extra modifier to the pivot rule. Any combination (OR) of the defined values is possible.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char piv_mode;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  piv_mode = is_piv_mode(lp, PRICE_ADAPTIVE); /* Will return TRUE, because this is the default */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_pivoting, get_pivoting, is_piv_rule

doc/Xpress-format.htm0000644000175000017500000005024010724547102013556 0ustar renerene Xpress lp files

Xpress lp files

The Xpress LP file format provides a facility for entering a problem in a natural, algebraic LP formulation from the keyboard. The problem can be modified and saved from within lpsolve. This procedure is one way to create a file in a format that lpsolve can read. An alternative technique is to create a similar file using a standard text editor and to read it into lpsolve.

The Xpress LP format is provided as an input alternative to the MPS file format. An LP format file may be easier to generate than an MPS file if your problem already exists in an algebraic format or if you have an application that generates the problem file more readily in algebraic format (such as a C application).

Note that the Xpress LP format is not the same as the lpsolve LP format. See LP file format for a description about the native lpsolve lp format. To read/write this format from lpsolve, you need an XLI (see External Language Interfaces). The XLI for the Xpress format is called xli_Xpress.

Options

The XLI accepts several options:

Reading

  -objconst      Allow constants in the objective (default).
  -noobjconst    Don't allow constants in the objective.

From the documentation of the format it is not sure if Xpress allows a constant in the objective. Tests have shown that it allows a constant as first term in the objective function. Note that the lp_solve XLI allows a constant in the objective by default and it can be anywere in the objective. Use the option -noobjconst if this should not be allowed. The parser will then give an error.

Writing

  -objconst      Allow constants in the objective.
  -noobjconst    Don't use constants in the objective (default).

From the documentation of the format it is not sure if Xpress allows a constant in the objective. Tests have shown that it allows a constant as first term in the objective function. The lp_solve XLI writes the constant as first term when the option -objconst is active. By default or when the option -noobjconst is used, a constant in the objective is translated to a variable objconst_term with a bound equal to the constant set to it. So no error is generated when there is a constant.

Example

lp_solve -rxli xli_Xpress input.lp
lp_solve -mps input.mps -wxli xli_Xpress output.lp -wxliopt "-objconst"

Syntax Rules of LP File Format

lpsolve will accept any problem saved in an ASCII file provided that it adheres to the following syntax rules.

  1. Comments and blank lines

    Text following a backslash (\) and up to the subsequent carriage return is treated as a comment. Blank lines are ignored. Blank lines and comments may be inserted anywhere in an .lp file. For example, a common comment to put in LP files is the name of the problem:

    \Problem name: prob01
    
  2. File lines, white space and identifiers

    White space and carriage returns delimit variable names and keywords from other identifiers. Keywords are case insensitive. Variable names are case sensitive. Although it is not strictly necessary, for clarity of your LP files it is perhaps best to put your section keywords on their own lines starting at the first character position on the line. No line continuation character is needed when expressions are required to span multiple lines. Lines may be broken for continuation wherever you may use white space.

  3. Sections

    The LP file is broken up into sections separated by section keywords. The following are a list of section keywords you can use in your LP files. A section started by a keyword is terminated with another section keyword indicating the start of the subsequent section.

    Section keywordsSynonymsSection contents
    maximize or minimizemaximum
    max
    minimum
    min
    One linear expression describing the objective function.
    subject tosubject to:
    such that
    st
    s.t.
    st.
    subjectto
    suchthat
    subject
    such
    A list of constraint expressions.
    boundsboundA list of bounds expressions for variables.
    integersinteger
    ints
    int
    A list of variable names of integer variables. Unless otherwise specified in the bounds section, the default relaxation interval of the variables is [0, 1].
    generalsgeneral
    gens
    gen
    A list of variable names of integer variables. Unless otherwise specified in the bounds section, the default relaxation interval of the variables is [0, infinite].
    binariesbinary
    bins
    bin
    A list of variable names of binary variables.
    semi-continuoussemi
    continuous
    semis
    semi
    s.c.
    A list of variable names of semicontinuous variables.
    semi integers.i.A list of variable names of semiinteger variables.
    partial integerp.i.A list of variable names of partial integer variables.
    Not supported by lp_solve

    Variables that do not appear in any of the variable type registration sections (i.e., integers, generals, binaries, semi-continuous, semi integer, partial integer) are defined to be continuous variables by default. That is, there is no section defining variables to be continuous variables.

    With the exception of the objective function section (maximize or minimize) and the constraints section (subject to), which must appear as the first and second sections respectively, the sections may appear in any order in the file. The only mandatory section is the objective function section. Note that you can define the objective function to be a constant in which case the problem is a so-called constraint satisfaction problem. The following two examples of LP file contents express empty problems with constant objective functions and no variables or constraints.

    Empty problem 1:

    Minimize
    
    End
    

    Empty problem 2:

    Minimize
    
    0
    
    End
    

    The end of a matrix description in an LP file can be indicated with the keyword end entered on a line by itself. This can be useful for allowing the remainder of the file for storage of comments, unused matrix definition information or other data that may be of interest to be kept together with the LP file.

  4. Variable names

    Variable names can use any of the alphanumeric characters (a-z, A-Z, 0-9) and any of the following symbols:

    !"#$%&/,.;?@_`{}()|~'
    

    A variable name can not begin with a number or a period. Care should be taken using the characters E or e since these may be interpreted as exponential notation for numbers.

  5. Linear expressions

    Linear expressions are used to define the objective function and constraints. Terms in a linear expression must be separated by either a + or a - indicating addition or subtraction of the following term in the expression. A term in a linear expression is either a variable name or a numerical coefficient followed by a variable name. It is not necessary to separate the coefficient and its variable with white space or a carriage return although it is advisable to do so since this can lead to confusion. For example, the string " 2e3x" in an LP file is interpreted using exponential notation as 2000 multiplied by variable x rather than 2 multiplied by variable e3x. Coefficients must precede their associated variable names. If a coefficient is omitted it is assumed to be 1.

  6. Objective function

    The objective function section can be written in a similar way to the following examples using either of the keywords maximize or minimize. Note that the keywords maximize and minimize are not used for anything other than to indicate the following linear expression to be the objective function. Note the following two examples of an LP file objective definition:

    Maximize
    - 1 x1 + 2 x2 + 3x + 4y
    

    or

    Minimize
    - 1 x1 + 2 x2 + 3x + 4y
    

    Generally objective functions are defined using many terms and thus the objective function definitions are typically always broken with line continuations. No line continuation character is required and lines may be broken for continuation wherever you may use white space.

    The objective function can be named in the same way as for constraints (see later).

  7. Constraints

    The section of the LP file defining the constraints is preceded by the keyword subject to. Each constraint definition must begin on a new line. A constraint may be named with an identifier followed by a colon before the constraint expression. Constraint names must follow the same rules as variable names. If no constraint name is specified for a constraint then a default name is assigned. Constraint names are trimmed of white space before being stored. The constraints are defined as a linear expression in the variables followed by an indicator of the constraint's sense and a numerical right-hand side coefficient. The constraint sense is indicated intuitively using one of the tokens: >=, <=, or =. For example, here is a named constraint:

    depot01: - x1 + 1.6 x2 - 1.7 x3 <= 40
    

    Note that tokens > and < can be used, respectively, in place of the tokens >= and <=.

    Generally, constraints are defined using many terms so the constraint definitions are typically broken with line continuations. No line continuation character is required and lines may be broken for continuation wherever you may use white space.

  8. Bounds

    The list of bounds in the bounds section are preceded by the keyword bounds. Each bound definition must begin on a new line. Single or double bounds can be defined for variables. Double bounds can be defined on the same line as 10 <= x <= 15 or on separate lines in the following ways:

    10 <= x
    15 >= x
    

    or

    x >= 10
    x <= 15
    

    If no bounds are defined for a variable, default lower and upper bounds are used. An important point to note is that the default bounds are different for different types of variables. For continuous variables the interval defined by the default bounds is [0, infinity] while for variables declared in the integers and generals section (see later) the relaxation interval defined by the default bounds is [0, 1] and [0, infinity], respectively.

    If a single bound is defined for a variable the appropriate default bounds are used as the second bound. Note that negative upper bounds on variables must be declared together with an explicit definition of the lower bound for the variable. Also note that variables can not be declared in the bounds section. That is, a variable appearing in a bounds section that does not appear in a constraint in the constraint section is ignored.

    Bounds that fix a variable can be entered as simple equalities. For example, x6 = 7.8 is equivalent to 7.8 <= x6 <= 7.8. The bounds +inf (positive infinity) and -inf (negative infinity) must be entered as strings (case insensitive):

    +infinity, -infinity, +inf, -inf.
    

    Note that the keywords infinity and inf may not be used as a right-hand side coefficient of a constraint.

    A variable with a negative infinity lower bound and positive infinity upper bound may be entered as free (case insensitive). For example, x9 free in an LP file bounds section is equivalent to:

    - infinity <= x9 <= + infinity
    

    or

    - infinity <= x9
    

    In the last example here, which uses a single bound is used for x9 (which is positive infinity for continuous example variable x9).

  9. Generals, Integers and binaries

    The generals, integers and binaries sections of an LP file is used to indicate the variables that must have integer values in a feasible solution. The difference between the variables registered in each of these sections is in the definition of the default bounds that the variables will have. For variables registered in the generals section the default bounds are 0 and infinity. For variables registered in the integers section the default bounds are 0 and 1. The bounds for variables registered in the binaries section are 0 and 1.

    The lines in the generals, integers and binaries sections are a list of white space or carriage return delimited variable names. Note that variables can not be declared in these sections. That is, a variable appearing in one of these sections that does not appear in a constraint in the constraint section is ignored.

  10. Semi-continuous and semi-integer

    The semi-continuous and semi integer sections of an LP file relate to two similar classes of variables and so their details are documented here simultaneously.

    The semi-continuous (or semi integer) section of an LP file are used to specify variables as semi-continuous (or semi-integer) variables, that is, as variables that may take either (a) value 0 or (b) real (or integer) values from specified thresholds and up to the variables' upper bounds.

    The lines in a semi-continuous (or semi integer) section are a list of white space or carriage return delimited entries that are either (i) a variable name or (ii) a variable name-number pair. The following example shows the format of entries in the semi-continuous section.

    Semi-continuous
    x7 >= 2.3
    x8
    x9 >= 4.5
    

    The following example shows the format of entries in the semi integer section.

    Semi integer
    x7 >= 3
    x8
    x9 >= 5
    

    Note that you can not use the <= token in place of the >= token.

    The threshold of the interval within which a variable may have real (or integer) values is defined in two ways depending on whether the entry for the variable is (i) a variable name or (ii) a variable name-number pair. If the entry is just a variable name, then the variable's threshold is the variable's lower bound, defined in the bounds section (see earlier). If the entry for a variable is a variable name-number pair, then the variable's threshold is the number value in the pair.

    It is important to note that if (a) the threshold of a variable is defined by a variable namenumber pair and (b) a lower bound on the variable is defined in the bounds section, then:

    Case 1) If the lower bound is less then zero, then the lower bound is zero.

    Case 2) If the lower bound is greater than zero but less than the threshold, then the value of zero is essentially cut off the domain of the semi-continuous (or semi-integer) variable and the variable becomes a simple bounded continuous (or integer) variable.

    Case 3) If the lower bound is greater than the threshold, then the variable becomes a simple lower bounded continuous (or integer) variable.

    If no upper bound is defined in the bounds section for a semi-continuous (or semi-integer) variable, then the default upper bound that is used is the same as for continuous variables, for semi-continuous variables, and generals section variables, for semi-integer variables.

  11. Partial integers

    The partial integers section of an LP file is used to specify variables as partial integer variables, that is, as variables that can only take integer values from their lower bounds up to specified thresholds and then take continuous values from the specified thresholds up to the variables' upper bounds.

    lp_solve does not support partial integers. An error will be generated by the parser if a partial integer section is found.

  12. Special ordered sets

    Special ordered sets are defined as part of the constraints section of the LP file. The definition of each special ordered set looks the same as a constraint except that the sense is always = and the right hand side is either S1 or S2 (case sensitive) depending on whether the set is to be of type 1 or 2, respectively. Special ordered sets of type 1 require that, of the non-negative variables in the set, one at most may be non-zero. Special ordered sets of type 2 require that at most two variables in the set may be non-zero, and if there are two non-zeros, they must be adjacent. Adjacency is defined by the weights, which must be unique within a set given to the variables. The weights are defined as the coefficients on the variables in the set constraint. The sorted weights define the order of the special ordered set. It is perhaps best practice to keep the special order sets definitions together in the LP file to indicate (for your benefit) the start of the special ordered sets definition with the comment line \Special Ordered Sets as is done when a problem is written to an LP file. The following example shows the definition of a type 1 and type 2 special ordered set.

    Sos101: 1.2 x1 + 1.3 x2 + 1.4 x4 = S1
    Sos201: 1.2 x5 + 1.3 x6 + 1.4 x7 = S2
    

Some examples

Example 1

Minimize
 COST:    XONE + 4 YTWO + 9 ZTHREE + 2
Subject To
 LIM1:    XONE + YTWO <= 5
 LIM2:    XONE + ZTHREE >= 10
 MYEQN:   - YTWO + ZTHREE  = 7
Bounds
 0 <= XONE <= 4
-1 <= YTWO <= 1
End

Example 2

Minimize
obj: - 2 x3

Subject To
c1: x2 - x1 <= 10
c2: x1 + x2 + x3 <= 20

Bounds
x1 <= 30
2 <= x3 <= 3

s.i.
x3
x1 >= 2.1

End

Example 3

Minimize
obj: - 2 x3

Subject To
c1: x2 - x1 <= 10

\SOS
sos101: 4 x2 + 2 x3 = S2

c2: x1 + x2 + x3 <= 20

sos102: x1 + x2 + x3 = S1
sos201: 1.2 x3 +1.3 x2 + 1.4 x1 = S2

Bounds
x1 <= 30
2 <= x3 <= 3

End
doc/get_total_iter.htm0000644000175000017500000000467110616401002014004 0ustar renerene get_total_iter

get_total_iter

Returns the total number of iterations.

long long get_total_iter(lprec *lp);

Return Value

get_total_iter returns the total number of iterations.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

If the model contains integer variables then it returns the number of iterations to find a relaxed solution plus the number of iterations in the B&B process.
If the model contains no integer variables then it returns the number of iterations to find a solution.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  long long total_iter;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  total_iter = get_total_iter(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_max_level, get_total_nodes

doc/get_bb_depthlimit.htm0000644000175000017500000000573510255113024014451 0ustar renerene get_bb_depthlimit

get_bb_depthlimit

Returns the maximum branch-and-bound depth.

int get_bb_depthlimit(lprec *lp);

Return Value

get_bb_depthlimit returns the maximum branch-and-bound depth.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_bb_depthlimit function returns the maximum branch-and-bound depth.
This is only useful if there are integer, semi-continious or SOS variables in the model so that the branch-and-bound algorithm must be used to solve them. The branch-and-bound algorithm will not go deeper than this level. When 0 then there is no limit to the depth. Limiting the depth will speed up solving time, but there is a chance that the found solution is not the most optimal one. Be aware of this. It can also result in not finding a solution at all. A positive value means that the depth is absoluut. A negative value means a relative B&B depth limit. The "order" of a MIP problem is defined to be 2x the number of binary variables plus the number of SC and SOS variables.A relative value of -x results in a maximum depth of x times the order of the MIP problem.
The default is -50.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int bb_maxlevel;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  bb_maxlevel = get_bb_depthlimit(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_bb_depthlimit

doc/get_Norig_columns.htm0000644000175000017500000000555210237176654014500 0ustar renerene get_Norig_columns

get_Norig_columns

Returns the number of original columns (variables) in the lp.

int get_Norig_columns(lprec *lp);

Return Value

get_Norig_columns returns the number of original columns (variables) in the lp.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_Norig_columns function returns the number of original columns (variables) in the lp.
Note that the number of columns (get_Ncolumns) can change when a presolve is done or when negative variables are split in a positive and a negative part. get_Norig_columns does not change and thus returns the original number of columns in the lp.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int Norig_columns;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  Norig_columns = get_Norig_columns(lp); /* Will return 1 */

  set_presolve(lp, PRESOLVE_COLS);
  solve(lp);

  Norig_columns = get_Norig_columns(lp); /* Will return 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_Ncolumns, get_Nrows, get_Norig_rows, get_orig_index, get_lp_index, get_Lrows

doc/lp_solve_5.5.0.13.chw0000644000175000017500000010060011122544451013560 0ustar renereneITSF`BlZ |{ "|{ "`8 aT .!"T Uncompressed MSCompressed{7FC28940-9D31-11D0LZXC Cd;)X44 %/'absolute valuesadd_column add_columnexadd_constraint'add_constraintex4add_lag_con Aadd_SOS NBasis Factorization Packages[Calling the lpsolve API from your applicationhChanges from version 4 to version 5.1uChanges from version 5.1 to version 5.5column_in_lp copy_lp CPLEX lp filesdefault_basis del_columndel_constraintdelete_lpDIMACS maximum flow problemsDIMACS minimum assignment problemsDIMACS minimum cost flow problemsDownloaddualize_lpExternal Language Interfaces+Formulation of an lp model in lpsolve8free variablesEfree_lpRFrequently Asked Questions_get_anti_degenlget_basisy%get_basiscrashget_bb_depthlimitget_bb_floorfirstget_bb_ruleget_bounds_tighterget_break_at_valueget_col_nameget_columnget_columnexget_constr_typeget_constr_valueget_constraintsget_dual_solution "get_epsb!/get_epsd"<get_epsel#Iget_epsint$Vget_epsperturb%cget_epspivot&pget_improve'}get_infinite(get_lambda)get_lowbo*get_lp_index+get_lp_name,get_Lrows-get_mat.get_max_level/get_maxpivot0get_mip_gap1get_nameindex2 get_Ncolumns3get_negrange4&get_nonzeros53get_Norig_columns6@get_Norig_rows7Mget_Nrows8Z!get_obj_bound9gget_objective:tget_orig_index;get_origcol_nameget_origrow_name<get_pivoting=get_presolve>get_presolveloops?get_primal_solution@get_print_solAget_ptr_constraintsget_ptr_dual_solution get_ptr_lambda)get_ptr_primal_solution@get_ptr_sensitivity_objBget_ptr_sensitivity_objexB*get_ptr_sensitivity_rhs 7get_ptr_variablesCDget_rhDQget_rh_rangeE^get_rowFkget_row_name<xget_rowexFget_scalelimitGget_scalingHget_sensitivity_objBget_sensitivity_objexBget_sensitivity_rhs get_simplextypeIget_solutioncountJget_solutionlimitKget_statusLget_statustextM8Z$get_timeoutNget_total_iterO!get_total_nodesP.get_upboQ;get_var_branchRHget_var_dualresult Uget_var_primalresult@bget_var_prioritySoget_variablesC|get_verboseTget_working_objectiveUGNU LESSER GENERAL PUBLIC LICENSEGNU MathProgguess_basisVhas_BFPWhas_XLIXInfeasible modelsinteger variablesIntroductionis_add_rowmodeY is_anti_degenZis_binary[%is_break_at_first\2is_constr_type]?is_debug^Lis_feasible_Yis_infiniteafis_intbsis_integerscalingcis_lag_tracedis_maximeis_nativeBFPfis_nativeXLIgis_negativehis_obj_in_basisiis_piv_modej#is_piv_rulekis_presolvelis_scalemodemis_scaletypenis_semicontois_SOS_varp)is_traceq6is_unbounded`Cis_use_namesrPlag_solves]LINDO lp filesjLinear programming basicswLinear Programming FAQlp file formatlp_solve API referencelp_solve commandlp_solve Yahoo grouplp_solve_versiontlpsolve distributed filesLPSolve IDEmake_lpumps bas file formatmps file formatMPS_writefileexvPresolve print_constraintsw-print_debugdumpx:print_dualsyGprint_lpzTprint_objective{aprint_scales|nprint_solution}{print_str~print_tableauput_abortfuncj*%put_bb_branchfuncput_bb_nodefuncput_logfuncput_msgfuncQuick startratio'sread_basisread_freemps read_freeMPS read_lp$ read_LP1 read_mps> read_MPSK read_paramsX read_XLIe reset_basisr reset_params resize_lp scaling semi-continuous variables sensitivity set_add_rowmode set_anti_degen set_basis set_basiscrash set_basisvar set_bb_depthlimit set_bb_floorfirst set_bb_rule set_BFP( set_binary5 set_boundsB set_bounds_tighterO set_break_at_first\ set_break_at_valuei set_col_namev set_column j 'set_columnex set_constr_type set_debug set_epsb set_epsd set_epsel set_epsint set_epslevel set_epsperturb set_epspivot set_improve set_infinite set_int, set_lag_trace9 set_lowboF set_lp_nameS set_mat` set_maximm set_maxpivotz set_minim set_mip_gap set_negrange set_obj set_obj_bound set_obj_fn set_obj_fnex set_obj_in_basis set_outputfile set_outputstream set_pivoting set_preferdual set_presolve# set_print_sol0 set_rh= set_rh_rangeJ set_rh_vecW set_rowd set_row_nameq set_rowex~ j,!set_scalelimit set_scaling set_semicont set_sense set_simplextype set_solutionlimit set_timeout set_trace set_unbounded set_upbo set_use_names set_var_branch set_var_weights' set_verbose4 set_XLIA solveN special ordered sets[ str_add_columnh str_add_constraintu str_add_lag_con  str_set_obj_fn str_set_rh_vec time_elapsed unscale Usefull links Using lpsolve from AMPL Using lpsolve from Java Using lpsolve from MATLAB Using lpsolve from Octave Using lpsolve from O-MatrixUsing lpsolve from PHPUsing lpsolve from PythonUsing lpsolve from R+x~ jH Using lpsolve from Scilab8write_basisEwrite_freempsvRwrite_freeMPSv_write_lplwrite_LPywrite_lpexwrite_mpsvwrite_MPSvwrite_paramswrite_XLIXpress lp filesZimpl' set_verbose4 set_XLIA solveN special ordered sets[ str_add_columnh str_add_constraintu str_add_lag_con  str_set_obj_fn str_set_rh_vec time_elapsed unscale Usefull links Using lpsolve from AMPL Using lpsolve from Java Using lpsolve from MATLAB Using lpsolve from Octave Using lpsolve from O-MatrixUsing lpsolve from PHPUsing lpsolve from PythonUsing lpsolve from R+x~ j>get_basiscrashget_obj_bound9get_timeoutNis_piv_rulekput_bb_branchfuncset_columnexset_scalelimitUsing lpsolve from Scilab $bFVOf/'ITSPT  j].!"TPMGL^/ /$HHTitleMap_! /$OBJINSTW4/$WWAssociativeLinks//$WWAssociativeLinks/PROPERTY:/$WWKeywordLinks//$WWKeywordLinks/BTREEkL/$WWKeywordLinks/DATA a/$WWKeywordLinks/MAP>J/$WWKeywordLinks/PROPERTY7 ::DataSpace/NameList4<(::DataSpace/Storage/MSCompressed/Content,::DataSpace/Storage/MSCompressed/ControlData)::DataSpace/Storage/MSCompressed/SpanInfo/::DataSpace/Storage/MSCompressed/Transform/Listp&_::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/i::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/ResetTablealp_solve_5.5.0.13 doc/SpecialOrderedSetsOfTypeTwo_files/0000755000175000017500000000000010762557070017027 5ustar renerenedoc/SpecialOrderedSetsOfTypeTwo_files/img00357.gif0000644000175000017500000000231707755241560020676 0ustar renereneGIF89a!,H*\ȰÇ#JHŋ3jȱG|0$ɏ!ETŔ]tɁ0WH4})0N o `iыB=TJVECIR,Ӄf_LT&KZ%]Yo6;wgݢi[28l\uZ;8᳅>ױڧ'70[A;=XtYͦI^ly@鲮ngs9L1=ZgZѽɾ.6o;5G˖y։cG}˓Y{l}=y_~w^MrwysIݧ)H]&! ~7zؒ$b.1'܇ {+faQ5}auhR8~\Jg#VHeYecD[f`\9a^ihlV;doc/SpecialOrderedSetsOfTypeTwo_files/img00361.gif0000644000175000017500000000235107755241560020667 0ustar renereneGIF89a!,H*\ȰÇ#JHŋ3jȱǏ '2Ȓ(!Lɲ%F$])@6s,s˞=w*4ȕ*<ӧP"m)©?uRMVy :j٭bU 4ɚ[ךl6\i%ekPߘn;W``>DVW/~+#WկW'^R"MdzT3Ԝ;yhLGۖmO-pv]'Ӭr=SƬ7Bgz+n9cߙE__r|Σޗ`{6a EgU-e8yךa1~y )ȚvHbU}~ŷcq,(_B޸֥lȣܩw$F:yaC/q-^?Fx~hlei$ jws|矀S@;doc/SpecialOrderedSetsOfTypeTwo_files/img00356.gif0000644000175000017500000000163207755241560020674 0ustar renereneGIF89a%!,%wH*\ȰÇH,@aŇ/ ԘB<rdG98qIGlҢA,)Ir͝0V fOBDӧ=*jHAԚ$͏/!Kك;doc/SpecialOrderedSetsOfTypeTwo_files/img00360.gif0000644000175000017500000000250207755241560020664 0ustar renereneGIF89a!,H*\ȰÇ#JHŋ3jȱǏ CM\ R%K&OyƘi9'I3{)˟.a*5ZeS JSМ,}:ԣB*+EffD1ښSd{#݆n[1ݶƻMW{)8'bE{Uj)G.yhRsƬ:SΘ\MՎ7O/Ҳg750[=obבG |,Sy' :ކO3w>sWago:S_2yot|c~R|vf xȞy%A7`A4]WWV*(g Hہ"&݇(VHߋi^|"NA"*%c rᙶ:귕N{MfkX~)Fady&fr؜PH`^ ؞EՕYgTtٖoߟ:Y-(&|oXm6i-#np56ᠢ:m؉jH!7i_)ykp;+k;doc/SpecialOrderedSetsOfTypeTwo_files/img00350.gif0000644000175000017500000000211607755241560020664 0ustar renereneGIF89a!,H*\ȰÇ#JHŋ3jȱǏ C OD9PA`BtyQfƓ(qڌ2'Ia 4hʚ49 EHRO#61gөPMlG LP'זcFuXюmʤJcmנNvֵ ]Ef)ƁX|ɾXXִ1M,cq}lt5^Ѯa'E ;v=l:rk+89ڡ}&^Z'Wݚvޝ_,$VWN|g{GW>Ͽ(_@;doc/SpecialOrderedSetsOfTypeTwo_files/img00359.gif0000644000175000017500000000173607755241560020704 0ustar renereneGIF89ad!,dH*\ȰÇ#JHŋ3jQ#Av QdI#I^,R@-aV$͎7'\)p'ˏAR(C!,>H*\ȰÇ#JA1J`Nj>R 9qH'M(2%K%c:LRF6]΄iM>H%$yTNN;:](UҞLGNmx#ͭ&Y:&$ u)Lgl[iܰuzweؠY%5(G EZgT} (Z23k9@@;doc/SpecialOrderedSetsOfTypeTwo_files/img00349.gif0000644000175000017500000000212007755241560020667 0ustar renereneGIF89a!,H*\ȰÇ#JHŋ3jȱǏ CII'!hKarl)̇7 r'ž%%Tr& i$iB8?, T5f*4E9WR*slCGy*V%ϘVQ=;ۡ6mhnA^-\NMq۩Aq%EKBuiػ5:m\7jֶvsḘٺ.ԓ zRn::vsۥ>FG5Yk.cjkr΀9ˎ^xǷ,XϿ(hG;doc/SpecialOrderedSetsOfTypeTwo_files/img00355.gif0000644000175000017500000000217607755241560020677 0ustar renereneGIF89a!,H*\ȰÇ#JHŋ3jȱǏ CI (S,x2#+\rf̑57ڼIs'ˁ>-9TbQ_"S : Uԩ'>֨^ iS*ՈEl *ֶncٟIM(bͿf z}j0ܮbT|wC딩x |XQ*<s.fFVb9K4kz굍Wٞώ:xmxy^ͦn.dX!~u52wu\/=ٹ˼1Gvc{>}뫁Mqk7t '_ARtfa~Qh($;doc/SpecialOrderedSetsOfTypeTwo_files/img00351.gif0000644000175000017500000001102207755241560020661 0ustar renereneGIF89a$a!,$aH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ NȱX<FNt׫k={^:x{Gݮ_>ߪUt~AXu6 g|MHliAz7g9, '">XP7ҨN6ߎգ?V"DYCxPFcPK>b9Fx.B9`jy5"Ydf)idh¹h*H%thb*湡3'(JfJ"ђx**dEWy([JjgsuUi)תjea! #]zdOZQ ʟ>,CJl-,{2 ٱ%\6C^EiQkKضuK޲k&.KpD˯HG0w&0I?U1< Xo*HpI3U%&J2R3ӷ{W.;#n1Ypر-z#.<~|UKs[p5{?a}_'{5wϦ"=K2SNZHwO4lḔ1'@Dc$<΂-qG2։n ^H>*Uq+`hȩ ^ w9-\Np#:&VbȤpK#t^XxqgaVDXˁV;u0{|&=1rk4@PٴFCStx ˑ|ĈkI"Sd@I% Гnd">2t;Y)JFrSާ_x)=i$"y˅QH i)0`2)cJ# ̚"D>Db +?陵8yV"g,n(IX2ԉxtBI@Sr!jIφ(: *E$ HRFԣJզ>Ҏ&)f*Җ(;C*^y@fRMjbN% *65YRA&T|YFmVիr*"V|RuC'MEVhm!ZǶԔxkGZU:uQ] u<`qJĘ+% YcӟUjg&ٯR -W5KHβ6'TZZNUgllGx5-Qm&6Ǖ(f59JkJEݖ(6}nʪE[;RĮmwZ񚗚٥n~+_BNY|_؆W}?z[Wv05Y#8n xD/l]X*F,pƤNu_qd8Ja#M}#K8X2,[l-9jż`:Oa6n5'Y$<zys ]e>Gxϊ%f'yv>#}eL;%Ov. K/:q4AljI^qW425OkY'nr)jkmgYif{9S&oZڜOY(=evHkݹj|9. v<6kB<(ZtS,$h#x4&}/wxMJnqS~e pKr2Fi΅7ژ+=.Q8qosbvĹKsԹ3T<6#YLS?][$/iߙ d~qmHƳ{>XHQslgvwʋ_W.mQ]etOݝ:ҫmVl[q;Ey(u]Xg=雾~_X]~s]")8z{ 7otW?tVEρy?oQufsT}WwrW{ysXbO8{=q&}wt}&V~q!tw8-xYTu~|,H{c)ۇ5xw9+'wkVLs×}FԂvM8}pQCjiC!4!_ƷFHkMȆ}g_jYVTlFm~HoxkhFz6pjvV)gwi[dC熉<nH{戾hȇȉcy(Q_(jȈhnmHfhŸH5JXdXB8Hx5ŎƨZ%؋8eh7Xxy~U yHiy yxz6Ɋih+IXq݈%& $YXȓ=B;I'ْؑGqWYgJ9UYy3I,y 3GIicɔ&ŕ.ɖ)fKy &H0؁qYCwi:9h9xِٔx|)`Jَni~k畞ٙ)9Ysg٘iɚ Y)ewH_I鏼 i("ɘǹIlYM\ٚA9IVYiG89䉞ʩOٝY} )8  ٠Zz#ir(i )Yiɟ0y 6ʣ &آ9MJYԙNJZH:D]9ɤ阝ڜQazߨ`2,Zo{FP:^jmO}ZꝈ:y\t_Zڥ(joY@(ʦIz7=J~EJE詿iڨ"Hm Aj9z:Jκ'ӺZګJJjtX)Uڭ+t5Pi 5]A;[{ / ;;C8=uV۱ :+G3uSwʹ@,O?-/ '6{8+*wWQ=]g ;2A&wRXKK`IOO=5 X8 WS[3MZ@V<_+N3 6j{I)73o+)d~#KmkMe;s:)2Ҫ)*Q1t}1(TD'B[c4 g2r/e(7+WjHKD9[{ۻ;[{țʻۼ;B;doc/SpecialOrderedSetsOfTypeTwo_files/img00358.gif0000644000175000017500000000163207755241560020676 0ustar renereneGIF89a%!,%wH*\ȰÇH,@aŇ/ ԘB<rdG98qIGlҢA,)Ir͝0V fOBDӧ=*jHAԚ$͏/!Kك;doc/SpecialOrderedSetsOfTypeTwo_files/img00362.gif0000644000175000017500000000232407755241560020670 0ustar renereneGIF89a !, H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ%I\ʜISc̐7gEwݸ3hњHqTaΡN/%jƪR+HW;Nc=4Tb5{\۾]v-՞nmTZcҥpWi&cQrK8!'W*8(ˁ1mh.i?~f칶+6ǐ#6Zpq̚CT6h V]i#-y\~Wxɦ;ܰaZd2^~EZcI~I[X֟ICvW^jEW xuxe9[QMWRq^6‡~Q.8id>HcO@'\N'sJD\J%dm_&c?hlp^;doc/SpecialOrderedSetsOfTypeTwo_files/img00348.gif0000644000175000017500000000163207755241560020675 0ustar renereneGIF89a%!,%wH*\ȰÇH,@aŇ/ ԘB<rdG98qIGlҢA,)Ir͝0V fOBDӧ=*jHAԚ$͏/!Kك;doc/SpecialOrderedSetsOfTypeTwo_files/img00352.gif0000644000175000017500000000152407755241560020670 0ustar renereneGIF89a!,1H*,! tqB+fŽ d8rɓ(;doc/SpecialOrderedSetsOfTypeTwo_files/img00354.gif0000644000175000017500000000206107755241560020667 0ustar renereneGIF89a~!,~H*\ȰÇ#JHŋ3jȱ"3~ I H%)Le,B6'3bϏ8y Ϟ2Z܉KLMM%,QT)ϋXю}zkY7ϪJV&;wۯc-*x*[MiYR2&lǃu* kX1Ya- ytі/E+Ƭ5uf8O=L:dƉ2lޥs?IwǨ@5.4ylၫqeZo1Kz]9ӫ_^`@;doc/SpecialOrderedSetsOfTypeTwo_files/bsscdhtm.js0000644000175000017500000021432307755240700021176 0ustar renerene//////////BSSCDHTML Section 1////////// // RoboHELP Dynamic HTML Effects Script // Copyright 1998-2000 eHelp Corporation. All rights reserved. // Version=3.72 // Warning: Do not modify this file. It is generated by RoboHELP and changes will be overwritten. //{{HH_SYMBOL_SECTION var HH_ChmFilename = ""; var HH_WindowName = ""; var HH_GlossaryFont = ""; var HH_Glossary = ""; var HH_Avenue = ""; var HH_ActiveX = false; //}}HH_SYMBOL_SECTION var gbNav4 = false; var gbIE4 = false; var gbIE = false; var gbIE5 = false; var gbIE55 = false; var gAgent = navigator.userAgent.toLowerCase(); var gbMac = (gAgent.indexOf("mac") != -1); var gbWindows = ((gAgent.indexOf("win") != -1) || (gAgent.indexOf("16bit") != -1)); var error_count = 0; gbIE = (navigator.appName.indexOf("Microsoft") != -1); if (parseInt(navigator.appVersion) >= 4) { gbNav4 = (navigator.appName == "Netscape"); gbIE4 = (navigator.appName.indexOf("Microsoft") != -1); if (gbIE4) { if (gAgent.indexOf("msie 5.0") != -1) { gbIE5 = true; } if (gAgent.indexOf("msie 5.5") != -1) { // curently IE 5.5 has some buggy stuff. we need do some remedy to our code. gbIE55 = true; } } } function HHActivateComponents() { if (HH_ActiveX && (HH_ChmFilename != "") && ((self == top) || (self == top.frames[0]))) { var objBody = document.all.tags("BODY")[0]; if( typeof(objBody) == "object" ) { objBody.insertAdjacentHTML("beforeEnd", ''); if (HHComponentActivator.object) { HHComponentActivator.Activate(HH_ChmFilename, HH_WindowName, HH_GlossaryFont, HH_Glossary, HH_Avenue); } } } } var gAmc = new Array(); var BSSCSequenceIndex = 0; function animationContext(el, progressAnimation, finishAnimiation, animationDuration, animationPeriod) { this.el = el; this.progressAnimation = progressAnimation; this.finishAnimiation = finishAnimiation; this.animationDuration = parseFloat(animationDuration); this.animationPeriod = animationPeriod; this.animationStartTime = (new Date()).getTime(); this.continueAnimation = true; } function progressFade(ndx) { if( typeof( gAmc[ndx].el.filters.alpha ) != "object" ) return; percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0){ percent = 1.0; gAmc[ndx].continueAnimation = false; } gAmc[ndx].el.filters.alpha.opacity = gAmc[ndx].initialOpacity*(1.0-percent) + gAmc[ndx].finalOpacity*percent; } function finishFade(ndx) { if( typeof( gAmc[ndx].el.filters.alpha ) == "object" ) gAmc[ndx].el.filters.alpha.opacity = parseInt(gAmc[ndx].finalOpacity); } function progressTranslation(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } gAmc[ndx].el.style.pixelLeft = gAmc[ndx].startX*(1.0-percent) + gAmc[ndx].finalX*percent; gAmc[ndx].el.style.pixelTop = gAmc[ndx].startY*(1.0-percent) + gAmc[ndx].finalY*percent; } function progressSpiral(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } rf = 1.0 - percent t = percent * 2.0*Math.PI rx = Math.max(Math.abs(gAmc[ndx].el.initLeft), 200) ry = Math.max(Math.abs(gAmc[ndx].el.initTop), 200) gAmc[ndx].el.style.pixelLeft = Math.ceil(-rf*Math.cos(t)*rx) gAmc[ndx].el.style.pixelTop = Math.ceil(-rf*Math.sin(t)*ry) gAmc[ndx].el.style.visibility="visible" } function progressElasticFromRight(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } rf=Math.exp(-percent*7) t = percent * 1.5*Math.PI rx =Math.abs(gAmc[ndx].el.initLeft) gAmc[ndx].el.style.pixelLeft = rf*Math.cos(t)*rx gAmc[ndx].el.style.pixelTop = 0 gAmc[ndx].el.style.visibility="visible" } function progressElasticFromBottom(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } rf=Math.exp(-percent*7) t = percent * 1.5*Math.PI rx =Math.abs(gAmc[ndx].el.initTop) gAmc[ndx].el.style.pixelLeft = 0 gAmc[ndx].el.style.pixelTop = rf*Math.cos(t)*rx gAmc[ndx].el.style.visibility="visible" } function progressZoomIn(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1; gAmc[ndx].continueAnimation = false; } for (var index=0; index= 1.0) { finishZoom(ndx); } } function progressZoomOut(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } for (var index=0; index= 1.0) { finishZoom(ndx); } } function finishTranslation(ndx) { gAmc[ndx].el.style.pixelLeft = parseInt(gAmc[ndx].finalX); gAmc[ndx].el.style.pixelTop = parseInt(gAmc[ndx].finalY); } function finishZoom(ndx) { for (i=0; i BSSCSequenceIndex && (!bFound || objectOrder < minBSSCSequenceIndexFound)) { minBSSCSequenceIndexFound = objectOrder; bFound = true; } } } if (bFound) { BSSCSequenceIndex = minBSSCSequenceIndexFound; bStarted = startAnimationSet(BSSCSequenceIndex); } } function getOffsetFromTopOfBrowser(el) { if (null == el.offsetParent) return el.offsetTop; else return el.offsetTop + getOffsetFromTopOfBrowser(el.offsetParent); } function startAnimationSet(ndx) { var m = 0; bStarted = false; // Find document elements with "BSSCAnimationType" attribute divElements = document.all.tags("DIV"); for (var index = 0; index < divElements.length; index++) { el = divElements[index]; animationType = el.getAttribute("BSSCAnimationType", false); if(null != animationType) { framePeriod = el.getAttribute("BSSCFramePeriod", false); frameCount = el.getAttribute("BSSCFrameCount", false); sequenceIndex = el.getAttribute("BSSCObjectOrder", false); // Stop any currently running RevealTrans filters if ("RevealTrans" == animationType && parseInt(sequenceIndex) == ndx-1 && gbWindows) el.filters.RevealTrans.stop(); // Filter on ndx if (0 == ndx && null == sequenceIndex || ndx == parseInt(sequenceIndex)) { if ("FlyInFromRight" == animationType) { animationDuration = el.getAttribute("BSSCDuration", false); if (null == animationDuration) animationDuration = 1000; // default to 1s gAmc[m] = new animationContext(el, progressTranslation, finishTranslation, animationDuration, 10); gAmc[m].startX = document.body.clientWidth + document.body.scrollLeft; gAmc[m].startY = 0; gAmc[m].finalX = 0; gAmc[m].finalY = 0; animationPump(m++); bStarted = true; } if ("FlyOutToRight" == animationType) { animationDuration = el.getAttribute("BSSCDuration", false); if (null == animationDuration) animationDuration = 1000; // default to 1s gAmc[m] = new animationContext(el, progressTranslation, finishTranslation, animationDuration, 10); gAmc[m].startX = 0; gAmc[m].startY = 0; gAmc[m].finalX = document.body.clientWidth + document.body.scrollWidth; gAmc[m].finalY = 0; animationPump(m++); bStarted = true; } if ("FlyInFromLeft" == animationType) { animationDuration = el.getAttribute("BSSCDuration", false); if (null == animationDuration) animationDuration = 1000; // default to 1s for (childIndex=0; childIndex 0) && (document.images[0].src.indexOf('bsscnav1.gif') != -1)) { document.links[0].href = "javascript:void(null);"; } } } return; } ////////////////////////////////////////////////////////////////////////////////////////////// // // Begin DHTML Popup Functions // ////////////////////////////////////////////////////////////////////////////////////////////// //variables used to isolate the browser type var gBsDoc = null; var gBsSty = null; var gBsHtm = null; var gBsStyVisShow = null; var gBsStyVisHide = null; var gBsClientWidth = 640; var gBsClientHeight = 480; var gBsBrowser = null; // here is the varible for judge popup windows size. these parameter is for IE5.0, it may need adjust for others. var gBRateH_W = 0.618; // 1.618 Golden cut. var gBMaxXOfParent = 0.8; var gBMaxYOfParent = 0.8; var gBscrollHeight = 16; var gBscrollWidth = 16; var gBpermitXDelta = 3; var gBpermitYDelta = 3; //the browser information itself function _BSPSBrowserItself() { var agent = navigator.userAgent.toLowerCase(); this.major = parseInt(navigator.appVersion); this.minor = parseFloat(navigator.appVersion); this.ns = ((agent.indexOf('mozilla') != -1) && ((agent.indexOf('spoofer') == -1) && (agent.indexOf('compatible') == -1))); this.ns2 = ((this.ns) && (this.major == 2)); this.ns3 = ((this.ns) && (this.major == 3)); this.ns4 = ((this.ns) && (this.major >= 4)); this.ie = (agent.indexOf("msie") != -1); this.ie3 = ((this.ie) && (this.major == 2)); this.ie4 = ((this.ie) && (this.major >= 4)); this.op3 = (agent.indexOf("opera") != -1); if (this.ns4) { gBsDoc = "document"; gBsSty = ""; gBsHtm = ".document"; gBsStyVisShow = "show"; gBsStyVisHide = "hide"; } else if (this.ie4) { gBsDoc = "document.all"; gBsSty = ".style"; gBsHtm = ""; gBsStyVisShow = "visible"; gBsStyVisHide = "hidden"; } } //Here is the browser type function _BSPSGetBrowserInfo() { gBsBrowser = new _BSPSBrowserItself(); } //Get client size info function _BSPSGetClientSize() { if (gBsBrowser.ns4) { gBsClientWidth = innerWidth; gBsClientHeight = innerHeight; } else if (gBsBrowser.ie4) { gBsClientWidth = document.body.clientWidth; gBsClientHeight = document.body.clientHeight; } } var gstrPopupID = 'BSSCPopup'; var gstrPopupShadowID = 'BSSCPopupShadow'; var gstrPopupTopicID = 'BSSCPopupTopic'; var gstrPopupIFrameID = 'BSSCPopupIFrame'; var gstrPopupIFrameName = 'BSSCPopupIFrameName'; var gstrPopupSecondWindowName = 'BSSCPopup'; var gPopupDiv = null; var gPopupDivStyle = null; var gPopupShadow = null; var gPopupTopic = null; var gPopupIFrame = null; var gPopupIFrameStyle = null; var gPopupWindow = null; var gnPopupClickX = 0; var gnPopupClickY = 0; var gnPopupScreenClickX = 0; var gnPopupScreenClickY = 0; var gbPopupTimeoutExpired = false; var gbScriptName = "EHELP_DHTM"; var gbPathofJS = ""; if (gbIE4) { var aScripts = document.scripts; var aScript = null; var i = 0; for (i = 0; i < aScripts.length ; i ++ ) { if (aScripts[i].name == gbScriptName) { aScript = aScripts[i]; break; } } if (aScript != null) { var nPathPos = 0; var strCurrentSrc = ""; strCurrentSrc = aScript.src; var nPathPos1 = strCurrentSrc.lastIndexOf("\\"); var nPathPos2 = strCurrentSrc.lastIndexOf("/"); if (nPathPos1 > nPathPos2) nPathPos = nPathPos1 + 1; else nPathPos = nPathPos2 + 1; gbPathofJS = strCurrentSrc.substring(0, nPathPos); } } // Replace point - Used by SingleSource // var gbBlankPageForIFrame = gbPathofJS + "_blank.htm"; var gbBlankPageForIFrame = "about:blank"; if (BSSCPopup_IsPopup()) { document.write(""); } function DHTMLPopupSupport() { if ((gbIE4) && (!gbMac)) { return true; } return false; } function BSSCPopup_IsPopup() { if (DHTMLPopupSupport() && (this.name == gstrPopupIFrameName)) { return true; } else if ((gbNav4 || gbIE4) && (this.name == gstrPopupID)) { return true; } else { return false; } } function _BSSCCreatePopupDiv() { if (gPopupDiv == null) { if (DHTMLPopupSupport()) { document.write(""); var tempColl = document.all.tags("DIV"); for (var iDiv = 0; iDiv < tempColl.length; iDiv++) { if (tempColl(iDiv).id == gstrPopupID) { gPopupDiv = tempColl(iDiv); } if (tempColl(iDiv).id == gstrPopupShadowID) { gPopupShadow = tempColl(iDiv); } if (tempColl(iDiv).id == gstrPopupTopicID) { gPopupTopic = tempColl(iDiv); } } gPopupIFrame = eval("gPopupDiv.document.frames['" + gstrPopupIFrameName + "']"); gPopupDivStyle = eval("gPopupDiv" + gBsSty); gPopupIFrameStyle = eval(gBsDoc + "['" + gstrPopupIFrameName + "']" + gBsSty); } } } function BSSCPopup_Timeout() { if ((gPopupIFrame.document.readyState == "complete") && (gPopupIFrame.document.body != null) && (gPopupIFrame.location.href.indexOf(gbBlankPageForIFrame) == -1)) { BSSCPopup_TimeoutReal(); } else { setTimeout("BSSCPopup_Timeout()", 100); } } function BSSCPopup_TimeoutReal() { window.gbPopupTimeoutExpired = true; if (gPopupIFrame.document) { BSSCPopup_ChangeTargettoParent(gPopupIFrame.document); gPopupIFrame.document.body.onclick = BSSCPopupClicked; } document.onmousedown = BSSCPopupParentClicked; } function BSSCPopup_ChangeTargettoParent(tagsObject) { var collA = tagsObject.all.tags("A"); var j = 0; if (collA != null) { for (j = 0; j < collA.length; j ++ ) { collA[j].target = "_parent"; } } } function BSPSPopupTopicWinHelp(strURL) { _BSSCPopup(strURL); return; } function _BSSCPopup(strURL) { if (DHTMLPopupSupport()) { // If we are already in a popup, replace the contents if (BSSCPopup_IsPopup()) { location.href = strURL; parent.window.gbPopupTimeoutExpired = false; if (gbMac) { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 400); } else { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 100); } } else { // Load the requested URL into the IFRAME gPopupIFrame.location.href = strURL; window.gbPopupTimeoutExpired = false; if (gbMac) { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 400); } else { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 100); } } } else { _BSSCPopup2(strURL); } return; } function _BSSCPopup2(strURL) { if (window.name == gstrPopupSecondWindowName) { window.location = strURL; } else { BSSCHidePopupWindow(); var nX = 0; var nY = 0; var nHeight = 300; var nWidth = 400; _BSPSGetClientSize(); if (gBsBrowser.ns4) { nX = window.screenX + (window.outerWidth - window.innerWidth) + window.gnPopupClickX; nY = window.screenY + (window.outerHeight - window.innerHeight) + window.gnPopupClickY; if (nY + nHeight + 40 > screen.availHeight) { nY = screen.availHeight - nHeight - 40; } if (nX + nWidth + 40 > screen.availWidth) { nX = screen.availWidth - nWidth - 40; } } else { nX = window.gnPopupScreenClickX; nY = window.gnPopupScreenClickY; } // Launch a separate window var strParam = "titlebar=no,toolbar=no,status=no,location=no,menubar=no,resizable=yes,scrollbars=yes"; if (gBsBrowser.ns) { strParam += ",OuterHeight=" + nHeight + ",OuterWidth=" + nWidth; strParam += ",screenX=" + nX + ",screenY=" + nY; strParam += ",dependent=yes"; } else { strParam += ",height=" + nHeight + ",width=" + nWidth; strParam += ",left=" + nX + ",top=" + nY; } window.gPopupWindow = window.open(strURL, gstrPopupSecondWindowName, strParam); if (gBsBrowser.ns4) { window.gPopupWindow.captureEvents(Event.CLICK | Event.BLUE); window.gPopupWindow.onclick = NonIEPopup_HandleClick; window.gPopupWindow.onblur = NonIEPopup_HandleBlur; } else if (gBsBrowser.ie4) { window.gPopupWindow.focus(); } } return; } function NonIEPopup_HandleBlur(e) { window.gPopupWindow.focus(); } function NonIEPopup_HandleClick(e) { // Because navigator will give the event to the handler before the hyperlink, let's // first route the event to see if we are clicking on a Popup menu in a popup. document.routeEvent(e); // If a popup menu is active then don't do anything with the click if (window.gPopupWindow.gbInPopupMenu) { window.gPopupWindow.captureEvents(Event.CLICK); window.gPopupWindow.onclick = NonIEPopup_HandleClick; return false; } // Close the popup window if (e.target.href != null) { window.location.href = e.target.href; if (e.target.href.indexOf("BSSCPopup") == -1) { this.close(); } } else { this.close(); } return false; } function BSSCPopup_AfterLoad(strURL) { if (typeof(window.gPopupIFrame.document) == "unknown") { _BSSCPopup2(strURL); return; } if ((window.gPopupIFrame.document.readyState == "complete") && (window.gPopupIFrame.document.body != null) && (window.gPopupIFrame.location.href.indexOf(gbBlankPageForIFrame) == -1)) { BSSCPopup_ResizeAfterLoad(strURL); } else { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 200); } } function BSSCPopup_ResizeAfterLoad(strURL) { window.gPopupDivStyle.visibility = gBsStyVisHide; // Determine the width and height for the window //var size = new BSSCSize(0, 0); //BSSCGetContentSize(window.gPopupIFrame, size); //var nWidth = size.x; //var nHeight = size.y; _BSPSGetClientSize(); var size = new BSSCSize(0, 0); BSSCGetContentSize(window.gPopupIFrame, size); // Determine the width and height for the window var nWidth = size.x; var nHeight = size.y; window.gPopupDivStyle.width = nWidth; window.gPopupDivStyle.height = nHeight; // Determine the position of the window var nClickX = window.gnPopupClickX; var nClickY = window.gnPopupClickY; var nTop = 0; var nLeft = 0; if (nClickY + nHeight + 20 < gBsClientHeight + document.body.scrollTop) { nTop = nClickY + 10; } else { nTop = (document.body.scrollTop + gBsClientHeight) - nHeight - 20; } if (nClickX + nWidth < gBsClientWidth + document.body.scrollLeft) { nLeft = nClickX; } else { nLeft = (document.body.scrollLeft + gBsClientWidth) - nWidth - 8; } if (nTop < document.body.scrollTop ) nTop = document.body.scrollTop + 1; if (nLeft< document.body.scrollLeft) nLeft = document.body.scrollLeft + 1; window.gPopupDivStyle.left = nLeft; window.gPopupDivStyle.top = nTop; // Set the location of the background blocks window.gPopupShadow.style.left = 6; window.gPopupShadow.style.top = 6; if (gbIE55) { window.gPopupShadow.style.left = 4; window.gPopupShadow.style.top = 4; } window.gPopupShadow.style.width = nWidth; window.gPopupShadow.style.height = nHeight; window.gPopupTopic.style.width = nWidth; window.gPopupTopic.style.height = nHeight; if (gbIE55) { window.gPopupShadow.style.width = nWidth + 2; window.gPopupShadow.style.height = nHeight + 2; window.gPopupTopic.style.width = nWidth + 2; window.gPopupTopic.style.height = nHeight + 2; } if (gbMac) { // Total hack on the iMac to get the IFrame to position properly window.gPopupIFrameStyle.pixelLeft = 100; window.gPopupIFrameStyle.pixelLeft = 0; // Explicitly call BSSCOnLoad because the Mac doesn't seem to do it window.gPopupIFrame.window.BSSCOnLoad(); } //var nOriWidth = window.gPopupIFrameStyle.width window.gPopupIFrameStyle.width = nWidth; window.gPopupIFrameStyle.height = nHeight; if (gbIE55) { window.gPopupIFrameStyle.top = 0; window.gPopupIFrameStyle.left = 0; } gPopupIFrame.location.href = strURL; // reload again, this will fix the bookmark misunderstand in IE5. window.gPopupDivStyle.visibility = gBsStyVisShow; setTimeout("BSSCPopup_Timeout();", 100); return false; } function BSSCSize(x, y) { this.x = x; this.y = y; } function BSSCGetContentSize(thisWindow, size) { if (!((gBsBrowser.ie4) || (gBsBrowser.ns4))) return; if (gbMac) { size.x = 300; size.y = 300; return; } // Resize the width until it is wide enough to handle the content // The trick is to start wide and determine when the scrollHeight changes // because then we know a scrollbar is necessary. We can then go back // to the next widest size (for no scrollbar) var ClientRate = gBsClientHeight / gBsClientWidth; var GoldenSize = new BSSCSize(0,0); GoldenSize.x = gBsClientWidth * gBMaxXOfParent; GoldenSize.y = gBsClientHeight *gBMaxYOfParent ; if (ClientRate > gBRateH_W) { GoldenSize.y = GoldenSize.x * gBRateH_W; } else { GoldenSize.x = GoldenSize.y / gBRateH_W; } // Try to using parent specified max x. var x = 0; var maxgoldx = GoldenSize.x; var maxx = gBsClientWidth * gBMaxXOfParent; // This double resize causes the document to re-render (and we need it to) thisWindow.moveTo(10000,10000); // this is used to fix the flash on IE4. thisWindow.resizeTo(1, 1); thisWindow.resizeTo(1, 1); thisWindow.resizeTo(maxgoldx, thisWindow.document.body.scrollHeight + gBscrollHeight); thisWindow.resizeTo(maxgoldx, thisWindow.document.body.scrollHeight + gBscrollHeight); var miny = thisWindow.document.body.scrollHeight + gBscrollHeight; if (miny > GoldenSize.y) // the popup does not fix in the parent wanted golden area. so try to expand itself as large as it can { thisWindow.resizeTo(maxx , thisWindow.document.body.scrollHeight + gBscrollHeight); thisWindow.resizeTo(maxx , thisWindow.document.body.scrollHeight + gBscrollHeight); miny = thisWindow.document.body.scrollHeight + gBscrollHeight; maxy = gBsClientHeight * gBMaxYOfParent; if (miny > maxy) { // the popup must have a scroll, OK let it be. miny = maxy; size.x = maxx; size.y = maxy; } else { // popup still can fit in the parent area by someway. now we choose the same h/w rate as parent. size.y = miny; // downsize from maxx , now I try to using binary divide. x = maxx; deltax = -maxx/2; //j = 0; while (true) { x = x + deltax; thisWindow.resizeTo(x, miny); thisWindow.resizeTo(x, miny); diffy = thisWindow.document.body.scrollHeight + gBscrollHeight - x * ClientRate; if (diffy > gBpermitYDelta ) // it is higher than wanted, so x need to be wide a little bitter deltax = Math.abs(deltax) /2; else if (diffy < -gBpermitYDelta) // it is shorter than wanted, so x need to be narrow a little bitter deltax = -Math.abs(deltax) /2; else // the y is close enough to wanted. break; if (Math.abs(deltax) < gBpermitXDelta) // the next change is too slight and it can be ignore. break; //j ++; } size.x = thisWindow.document.body.scrollWidth; //+ gBscrollWidth; size.y = thisWindow.document.body.scrollHeight;// + gBscrollHeight; thisWindow.document.body.scroll = 'no'; // At this time we do not want to show scroll any more. so it will looks better a little. // Handle absurd cases just in case IE flakes // if (size.y < 100) { // size.y = 100; // } } } else { // downsize from maxgoldx , now I try to using binary divide. x = maxgoldx; deltax = -maxgoldx/2; //i = 0; while (true) { x = x + deltax; thisWindow.resizeTo(x, miny); thisWindow.resizeTo(x, miny); diffy = thisWindow.document.body.scrollHeight + gBscrollHeight - x * gBRateH_W; if (diffy > gBpermitYDelta ) // it is higher than wanted, so x need to be wide a little bitter deltax = Math.abs(deltax) /2; else if (diffy < -gBpermitYDelta) // it is shorter than wanted, so x need to be narrow a little bitter deltax = -Math.abs(deltax) /2; else // the y is close enough to wanted. break; if (Math.abs(deltax) < gBpermitXDelta) // the next change is too slight and it can be ignore. break; //i ++; } size.x = thisWindow.document.body.scrollWidth ;//+ gBscrollWidth; size.y = thisWindow.document.body.scrollHeight ;//+ gBscrollHeight; thisWindow.document.body.scroll = 'no'; // At this time we do not want to show scroll any more. so it will looks better a little. } if ((gbIE4) && (!gbIE5)) { size.x = size.x + 16; //reserve a width for scrollbar (IE 4.0 only) } thisWindow.resizeTo(size.x, size.y); thisWindow.resizeTo(size.x, size.y); return; } function BSSCPopupParentClicked() { BSSCPopupClicked(); return; } function BSSCPopupClicked() { if (!window.gbPopupTimeoutExpired) { return false; } if (gPopupIFrame.window.gbInPopupMenu) { return false; } // Give the user a message about javascript calls through objects. if ((gPopupIFrame.window.event != null) && (gPopupIFrame.window.event.srcElement != null) && (gPopupIFrame.window.event.srcElement.tagName == "A") && (gPopupIFrame.window.event.srcElement.href.indexOf("javascript:") == 0) && (gPopupIFrame.window.event.srcElement.href.indexOf(".") != -1)) { gPopupIFrame.window.event.cancelBubble = true; alert('Hyperlinks to objects do not work in popups.'); return false; } if (gPopupIFrame.document) { gPopupIFrame.document.body.onclick = null; } document.onclick = null; document.onmousedown = null; // Simply hide the popup gPopupDivStyle.visibility = gBsStyVisHide; gPopupIFrame.location.href = gbBlankPageForIFrame; return true; } //trace the mouse over's position for hotspot function BSPSPopupOnMouseOver(event) { if (gBsBrowser.ie4) { window.gnPopupClickX = event.clientX + document.body.scrollLeft; window.gnPopupClickY = event.clientY + document.body.scrollTop; window.gnPopupScreenClickX = event.screenX; window.gnPopupScreenClickY = event.screenY; } else if (gBsBrowser.ns4) { window.gnPopupClickX = event.pageX; window.gnPopupClickY = event.pageY; } } function BSSCHidePopupWindow() { if (window.gPopupWindow != null) { if (gBsBrowser.ns4) { if ((typeof window.gPopupWindow != "undefined") && (!window.gPopupWindow.closed)) { window.gPopupWindow.close(); window.gPopupWindow = null; } } } return; } var gbPopupMenuTimeoutExpired = false; var gbInPopupMenu = false; var gbPopupMenuTopicList = null; ////////////////////////////////////////////////////////////////////////////////////////// // // Popup Menu code // ////////////////////////////////////////////////////////////////////////////////////////// function _WritePopupMenuLayer() { if (gbNav4) { //Do not try to write ininle styles for NS! NS can not handle it and will not stop downloading the html page... document.write("
"); } else { document.write(""); if (gbIE4) { document.write(""); } } } //Define variable arguments as: strTitle, strUrl function PopupMenuTopicEntry() { this.strTitle = PopupMenuTopicEntry.arguments[0]; this.strURL = PopupMenuTopicEntry.arguments[1]; } // If the topic list is set, it is an array of TopicEntry objects (defined in WebHelp3.js) function PopupMenu_SetTopicList(aPopupTopicArray) { gbPopupMenuTopicList = aPopupTopicArray; } //Seek for the bsscright frame function _SeekFrameByName( cRoot, strName ) { if( cRoot == null ) return null; if( cRoot.frames == null ) return null; if( cRoot.frames[strName] != null ) return cRoot.frames[strName]; for (var i=0; i"); wndPopupLinks.document.write(""); var strParaLine = ""; for (var i = 0; i < (argLen - 2) / 2; i++) { strParaLine = ""; strParaLine += "
"); wndPopupLinks.document.close(); window.gbInPopupMenu = true; if (!gbIE) { wndPopupLinks.focus(); } return false; } // Make sure we have reasonable arguments var argLen = fn_arguments.length; if (argLen < 3) { return false; } // Check to see if we only have one target var strTarget = ""; if (((argLen < 5) && ((isNaN(fn_arguments[2])) || (gbPopupMenuTopicList == null))) || ((argLen < 4) && ((!isNaN(fn_arguments[2])) && (gbPopupMenuTopicList != null)))) { // Get the place that we will be putting the topic into var targetDoc = null; if (fn_arguments[1] == '') { targetDoc = window.document; } else { targetDoc = _GetFrameByName( parent, fn_arguments[1] ); if (targetDoc == null) { targetDoc = window.document; } //if (gbIE4) { // targetDoc = eval("top.document.frames['" + fn_arguments[1] + "']"); // } else if (gbNav4) { // targetDoc = eval("window.top." + fn_arguments[1] + ".document"); //} strTarget = "TARGET='" + fn_arguments[1] + "'"; } if (isNaN(fn_arguments[2]) || (gbPopupMenuTopicList == null)) { targetDoc.location.href = fn_arguments[3]; } else { targetDoc.location.href = gbPopupMenuTopicList[fn_arguments[2]].strURL; } return false; } var strMenu = ""; if (gbNav4) { strMenu = ''; } else { strMenu = '
'; } else { strMenu += '' + gbPopupMenuTopicList[fn_arguments[i]].strTitle + ''; } strMenu += ''; if (isNaN(fn_arguments[i]) || (gbPopupMenuTopicList == null)) { i += 2; } else { i += 1; } } strMenu += "
"; if (gbMac) { // totally hack. because ie5 in mac need something. is one of them. mac is mad. strMenu +="
"; } var layerPopup = null; var stylePopup = null; var nEventX = 0; var nEventY = 0; var nWindowWidth = 0; if (gbIE4) { layerPopup = document.all["PopupMenu"]; layerPopup.innerHTML = strMenu; stylePopup = layerPopup.style; _BSPSGetClientSize(); // Get the position of the item causing the event (relative to its parent) //if (gbMac) { if (true) { nEventX = window.event.clientX; nEventY = window.event.clientY; } else { //??? YJ: Can not remember why we calculate envent position by following code... //but it is wrong in a case like: CENTER->P->TABLE: //the offset positions of TABLE, P and CENTER are same (same offsetTop,offsetLeft) //so we get triple times of offset of x and y as we expect... nEventX = window.event.srcElement.offsetLeft - document.body.scrollLeft; nEventY = window.event.srcElement.offsetTop - document.body.scrollTop; // Get the location of the parent var nParentLocX = 0; var nParentLocY = 0; var ParentItem = window.event.srcElement.offsetParent; while (ParentItem != null) { if (ParentItem.offsetLeft) { nParentLocX += ParentItem.offsetLeft; nParentLocY += ParentItem.offsetTop; } ParentItem = ParentItem.parentElement; } // Adjust the location of the item using the location of the parent(s) nEventX += nParentLocX; nEventY += nParentLocY; } if (nEventY + layerPopup.scrollHeight + 10 < gBsClientHeight) { nEventY += document.body.scrollTop + 10; } else { nEventY = (document.body.scrollTop + gBsClientHeight) - layerPopup.scrollHeight - 20; } stylePopup.top = nEventY; if (nEventX + layerPopup.scrollWidth + 20 > gBsClientWidth) { if (gBsClientWidth - layerPopup.scrollWidth < 5) { stylePopup.left = 5; } else { stylePopup.left = gBsClientWidth - layerPopup.scrollWidth - 5; } } else { stylePopup.left = nEventX + document.body.scrollLeft + 20; } stylePopup.visibility = "visible"; document.onclick = PopupMenu_HandleClick; } else if (gbNav4) { layerPopup = document.layers.PopupMenu; layerPopup.visibility = "hide"; stylePopup = layerPopup.document; stylePopup.write(strMenu); stylePopup.close(); var e = fn_arguments[0]; nEventX = e.pageX; nEventY = e.pageY; _BSPSGetClientSize(); if (nEventY + layerPopup.clip.height + 20 < window.pageYOffset + gBsClientHeight) { nEventY += 20; } else { nEventY = gBsClientHeight + window.pageYOffset- layerPopup.clip.height - 20; } layerPopup.top = nEventY; if (nEventX + layerPopup.clip.width + 20 > gBsClientWidth + window.pageXOffset) { if (gBsClientWidth + window.pageXOffset - layerPopup.clip.width < 20) { nEventX = 5; } else { nEventX = gBsClientWidth + window.pageXOffset - layerPopup.clip.width - 20; } } else { nEventX += 20; } layerPopup.left = nEventX; layerPopup.visibility = "show"; // window.captureEvents(Event.CLICK | Event.MOUSEDOWN); window.captureEvents(Event.MOUSEDOWN); // window.onclick = PopupMenu_HandleClick; window.onmousedown = PopupMenu_HandleClick; } window.gbInPopupMenu = true; window.gbPopupMenuTimeoutExpired = false; setTimeout("PopupMenu_Timeout();", 100); return false; } function PopupMenu_Timeout() { window.gbPopupMenuTimeoutExpired = true; } function PopupMenu_Over(e) { if (gbIE4) { e.srcElement.className = "PopupOver"; } else if (gbNav4) { // this.bgColor = "red"; // e.target.document.className = "PopupOver"; } return; } function PopupMenu_Out(e) { if (gbIE4) { e.srcElement.className = "PopupNotOver"; } else if (gbNav4) { this.bgColor = "#f0f0f0"; } return; } function PopupMenu_HandleClick(e) { if (!window.gbPopupMenuTimeoutExpired) { return; } window.gbInPopupMenu = false; if (gbNav4) { // window.releaseEvents(Event.CLICK); window.releaseEvents(Event.MOUSEDOWN); } var layerPopup = null; var stylePopup = null; if (gbIE4) { layerPopup = document.all["PopupMenu"]; stylePopup = layerPopup.style; stylePopup.visibility = "hidden"; } else if (gbNav4) { layerPopup = document.layers.PopupMenu; layerPopup.visibility = "hide"; } return; } // This function should be deleted when all old projects are cleaned up function BSPSWritePopupFrameForIE4() { return false; } ///////////////////////////////////////////////////////////////////// function BSSCPopup_ClickMac() { if ((!DHTMLPopupSupport()) && (gbIE4)) { var bClickOnAnchor = false; var el; if ((window.event != null) && (window.event.srcElement != null)) { el = window.event.srcElement; while (el != null) { if ((el.tagName == "A") || (el.tagName == "AREA")) { bClickOnAnchor = true; break; } if (el.tagName == "BODY") { break; } el = el.parentElement; } } if (BSSCPopup_IsPopup()) { if (!bClickOnAnchor) { parent.window.gPopupWindow = null; self.close(); } } else { bClosePopupWindow = true; if ((bClickOnAnchor) && (el.href) && (el.href.indexOf("javascript:BSSCPopup") != -1)) { bClosePopupWindow = false; } if (bClosePopupWindow) { if (window.gPopupWindow != null) { var strParam = "titlebar=no,toolbar=no,status=no,location=no,menubar=no,resizable=yes,scrollbars=yes,height=300,width=400"; window.gPopupWindow = window.open("", gstrPopupSecondWindowName,strParam); window.gPopupWindow.close(); window.gPopupWindow = null; } } } } } ////////////////////////////////////////////////////////////////////// _BSPSGetBrowserInfo(); function _BSSCOnLoad() { if (!gbIE4 && !gbNav4) return; // Make everything visible in navigator if (gbNav4) { // Make some special effects items visible for (var iLayer = 0; iLayer < document.layers.length; iLayer++) { document.layers[iLayer].visibility = gBsStyVisShow; document.layers[iLayer].left = 0; } } // Remove the NavBar if necessary RemoveNavBar(); // Don't continue without IE4 if (gbIE4) { HHActivateComponents(); doStaticEffects(); startAnimationSet(0); } } function _BSSCOnUnload() { } function _BSSCOnClick() { if (!gbIE4) return; BSSCPopup_ClickMac(); startNextAnimationSet(); } function _BSSCOnError(message) { if(-1 != message.indexOf("denied") || -1 != message.indexOf("Object required")) return true; } function ResizeBasedonRate(thisWindow, size, rate, maxx, maxy) { x = maxx; y = maxy; deltax = -maxx/2; while (true) { x = x + deltax; thisWindow.resizeTo(x, y); thisWindow.resizeTo(x, y); diffy = thisWindow.document.body.scrollHeight + gBscrollHeight - x * rate; if (diffy > gBpermitYDelta ) // it is higher than wanted, so x need to be wide a little bitter deltax = Math.abs(deltax) /2; else if (diffy < -permitYDelta) // it is shorter than wanted, so x need to be narrow a little bitter deltax = -Math.abs(deltax) /2; else // the y is close enough to wanted. break; if (Math.abs(deltax) < gBpermitXDelta) // the next change is too slight and it can be ignore. break; //j ++; } size.x = thisWindow.document.body.scrollWidth; //+ gBscrollWidth; size.y = thisWindow.document.body.scrollHeight;// + gBscrollHeight; thisWindow.document.body.scroll = 'no'; // At this time we do not want to show scroll any more. so it will looks better a little. } //////////BSSCDHTML Section Embedded Code////////// var s_strAgent = navigator.userAgent.toLowerCase(); var s_nVer = parseInt(navigator.appVersion); var s_bIE = (s_strAgent.indexOf('msie') != -1); var s_bNS = (s_strAgent.indexOf('mozilla') != -1) && ((s_strAgent.indexOf('spoofer') == -1) && (s_strAgent.indexOf('compatible') == -1)); var s_bOpera = (s_strAgent.indexOf('opera') != -1); var s_bIE3Before = ((s_bIE) && (s_nVer <= 2)); var s_bNS3Before = ((s_bNS) && (s_nVer <= 3)); var s_bNS2 = ((s_bNS) && (s_nVer <= 2)); var s_bNS3 = ((s_bNS) && (s_nVer == 3)); var s_bIE300301 = ((s_bIE) && (s_nVer == 2) && ((s_strAgent.indexOf("3.00") != -1)||(s_strAgent.indexOf("3.0a") != -1)||(s_strAgent.indexOf("3.0b")!=-1)||(s_strAgent.indexOf("3.01")!=-1))); var s_bIE302 = ((s_bIE) && (s_nVer == 2) && (s_strAgent.indexOf("3.02") != -1)); function HasExtJs() { if (s_bIE3Before) { return false;} if (s_bNS3Before) { return false;} if (typeof (_BSSCOnLoad) == "undefined"){ return false; } return true; } function BSSCOnLoad() { if (HasExtJs()) { _BSSCOnLoad(); } } function BSSCOnUnload() { if (HasExtJs()) { _BSSCOnUnload(); } } function BSSCOnClick() { if (HasExtJs()) { _BSSCOnClick(); } } function BSSCOnError(message) { if (HasExtJs()) { return _BSSCOnError(message); } } function WritePopupMenuLayer() { if (HasExtJs()) {_WritePopupMenuLayer();} } function BSSCCreatePopupDiv() { if (HasExtJs()) {_BSSCCreatePopupDiv(); } } function BSSCPopup(strURL) { if (HasExtJs()) { _BSSCPopup(strURL); }else{ //Create a temporary window first to ensure the real popup comes up on top var wndTemp = null; if (!s_bNS3) { wndTemp = window.open("", "temp", "titlebar=no,toolbar=no,status=no,location=no,menubar=no,resizable=yes,scrollbars=yes,height=3,width=4"); } // Create the real popup window var wndPopup = window.open(strURL, "BSSCPopup", "titlebar=no,toolbar=no,status=no,location=no,menubar=no,resizable=yes,scrollbars=yes,height=300,width=400"); // Close the temporary if (!s_bNS3) { wndTemp.close(); } else { wndPopup.focus(); } } } var gbWndTemp = null, gbWndPopupLinks = null; var gbstrParaTotal = ""; function PopupMenu_Invoke() { if (HasExtJs()) { return _PopupMenu_Invoke(PopupMenu_Invoke.arguments); } if (s_bNS3Before || s_bIE3Before ) { var argLen = PopupMenu_Invoke.arguments.length; if (argLen < 5) { window.document.location.href = PopupMenu_Invoke.arguments[3]; return false; } gbWndTemp = null; gbWndPopupLinks = null; gbstrParatotal = ""; for (var i = 0; i < (argLen - 2) / 2; i++) { var strParaLine = ""; if (s_bNS2 || s_bOpera){ strParaLine += "
" strParaLine += PopupMenu_Invoke.arguments[2 * i + 2]; strParaLine += ""; } else { strParaLine += ""); if (s_bNS2 || s_bOpera) { gbWndPopupLinks.document.write(""); } else { //YJ: IE301,302 and NS3.x works fine gbWndPopupLinks.document.write("<"); gbWndPopupLinks.document.write("script>"); gbWndPopupLinks.document.write("function gotoUrl(aUrl) {opener.window.location=aUrl; close();}"); gbWndPopupLinks.document.write("<"); gbWndPopupLinks.document.write("/script>"); } gbWndPopupLinks.document.write(""); gbWndPopupLinks.document.write(gbstrParaTotal); gbWndPopupLinks.document.write(""); gbWndPopupLinks.document.close(); // Close the temporary if (!s_bNS3 && gbWndTemp != null) { gbWndTemp.close(); }else { gbWndPopupLinks.focus(); } return true; } return false; } onload = BSSCOnLoad; document.onclick = BSSCOnClick; onunload = BSSCOnUnload; onerror = BSSCOnError;doc/get_max_level.htm0000644000175000017500000000440210237176654013627 0ustar renerene get_max_level

get_max_level

Returns the deepest Branch-and-bound level of the last solution.

int get_max_level(lprec *lp);

Return Value

get_max_level returns the deepest Branch-and-bound level of the last solution.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_max_level function returns the deepest Branch-and-bound level of the last solution.
Is only applicable if the model contains integer variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int max_level;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  max_level = get_max_level(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLIget_total_nodes, get_total_iter

doc/IDE.htm0000644000175000017500000001006711247320750011407 0ustar renerene LPSolve IDE

LPSolve IDE

The LPSolve IDE (Integrated Development Interface) is a very user friendly Windows interface to the lpsolve API. All functionality of lpsolve can be accessed via a graphical and very user friendly application.

Many thanks to Henri Gourvest for making this nice interface to lpsolve and making it available to the community.

Here is a list of some of the features of the IDE:

  • Everything is graphical and mouse controled
  • Enter your lp model in all supported formats and even via an XLI interface (See External Language Interfaces)
  • Convert your lp model from any supported format to another supported format and even via an XLI interface (See External Language Interfaces)
  • Very user friendly editor to enter/change the model with syntax highlight.
  • Syntax checking of the model
  • Solve the model
  • See the results in grids
  • Control every possible lpsolve option (tolerances, presolve, scaling, ...)
  • View the matrix in grids
  • Export model to HTML, RTF, LaTeX output
  • Export matrix to CSV, HTML, RTF output
  • Export results to CSV, HTML, RTF output
  • Show statistics about the model.
  • ...

Here are some screen shorts:

Source

Results

Matrix

Options


Installation

Download the setup lp_solve_5.5.0.15_IDE_Setup.exe and run the setup, that is all.
Note that it needs the lpsolve dll (lpsolve55.dll) to do its job. For your convenience, a dll is provided with this archive, but it is not guaranteed to be the most recent one. To get the most recent lpsolve dll, extract if from the lp_solve_5.5.0.15_dev.zip archive and put it in the folder where you installed the IDE files in. Also note that the IDE also puts some messages on the console. This may be changed in the future. When started from a command prompt, the messages are shown in this screen, when started from Windows, a console screen will also be created. If you are looking for a message not shown in the IDE, maybe it is shown on the console window...

Usage

The IDE is very easy to use and doesn't need much explanations. When you start it, you get an editor window where a model file must be entered. By default this in the lp format. Initially, you will see the following:
/* Objective function */
min: ;

/* Variable bounds */
As an example, clear this and enter the following:
max: 143 x + 60 y;

120 x + 210 y <= 15000;
110 x + 30 y <= 4000;
x + y <= 75;
Now press the F9 button or click the green arrow (Solve) in the toolbar to solve this model. In the result tab you see the result of this model. Note that this is the model presented in Formulation of an lp problem in lpsolve. The model is formulated in the lp format. See lp-format for a description of it.
doc/get_orig_index.htm0000644000175000017500000000655010351321242013766 0ustar renerene get_orig_index

get_orig_index

Returns the original row/column where a constraint/variable was before presolve.

int get_orig_index(lprec *lp, int lp_index);

Return Value

get_orig_index returns the original row/column where a constraint/variable was before presolve.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

lp_index

constraint or column number. If lp_index is between 1 and get_Nrows then the index is a constraint (row) number. If lp_index is between 1+get_Nrows and get_Nrows + get_Ncolumns then the index is a column number.

Remarks

The get_orig_index function returns the original row/column where a constraint/variable was before presolve.
Note that the number of constraints (get_Nrows) and columns (get_Ncolumns) can change when a presolve is done or when negative variables are split in a positive and a negative part. get_orig_index returns the original position of the constraint/variable. If lp_index is not a legal index, the return value is 0.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int index;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  index = get_orig_index(lp, 1); /* Will return 1 */

  set_presolve(lp, PRESOLVE_COLS);
  solve(lp);

  index = get_orig_index(lp, 1); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_lp_index, get_Ncolumns, get_Norig_columns, get_Nrows, get_Norig_rows, get_Lrows, get_lp_index

doc/mps-format.htm0000644000175000017500000005146011244011372013067 0ustar renerene MPS file format

MPS file format

Fixed MPS format

The main things to know about fixed MPS format are that it is column oriented
(as opposed to entering the model as equations), and everything
(variables, rows, etc.) gets a name.

MPS is an old format, so it is set up as though you were using punch
cards. Fields start in column 2, 5, 15, 25, 40 and 50.
Sections of an MPS file are marked by so-called header cards,
which are distinguished by their starting in column 1. Although it is
typical to use upper-case throughout the file (like I said, MPS has
long historical roots), many MPS-readers will accept mixed-case for
anything except the header cards, and some allow mixed-case anywhere.
The names that you choose for the individual entities (constraints or
variables) are not important to the solver; you should pick names that
are meaningful to you, or will be easy for a post-processing code to
read.

Here is a little sample model written in MPS format (explained in more
detail below):

NAME          TESTPROB
ROWS
 N  COST
 L  LIM1
 G  LIM2
 E  MYEQN
COLUMNS
    XONE      COST                 1   LIM1                 1
    XONE      LIM2                 1
    YTWO      COST                 4   LIM1                 1
    YTWO      MYEQN               -1
    ZTHREE    COST                 9   LIM2                 1
    ZTHREE    MYEQN                1
RHS
    RHS1      LIM1                 5   LIM2                10
    RHS1      MYEQN                7
BOUNDS
 UP BND1      XONE                 4
 LO BND1      YTWO                -1
 UP BND1      YTWO                 1
ENDATA

For comparison, here is the same model written out in lp-format:

min: +XONE +4 YTWO +9 ZTHREE;
LIM1: +XONE +YTWO <= 5;
LIM2: +XONE +ZTHREE >= 10;
MYEQN: -YTWO +ZTHREE = 7;
XONE <= 4;
YTWO >= -1;
YTWO <= 1;

Strangely, there is nothing in MPS format that specifies the direction
of optimisation.  And there really is no standard "default" direction;
some LP codes will maximize if you don't specify otherwise, others will
minimize, and still others put safety first and have no default and
require you to specify it somewhere in a control program or by a
calling parameter. lp_solve uses minimization as default. This can be
changed do maximization by calling set_maxim or set_sense after reading
the file or by using option -max on the lp_solve command line program.
If you have a model formulated for minimization and the code you are
using insists on maximization (or vice versa), it may be easy to convert:
just multiply all the coefficients in your objective function by (-1).
The optimal value of the objective function will then be the negative of
the true value, but the values of the variables themselves will be correct.

Any line with an asterisk (*) in Column 1 is treated as a comment.

The eight character names used to specify variables, constraints and
other entities are fixed format. Names are not automatically justified,
so blanks are treated just like other characters. For example "ROW1    "
is not the same as " ROW1   ". (Note that some optimisers do not permit
blanks in names.) No case conversion is performed, so "row1    " is
different from "ROW1    ".

Floating point numbers may be specified in free format within the 12
character field (including embedded blanks). The following list describes
the possible ways of writing a number.

Mantissa:

        + or -      optional sign character (no sign indicates a positive number)

        digits      optional integer part of the mantissa

        .           optional decimal point (if not present, a decimal point will
                    be assumed after the mantissa digit)

        digits      optional fraction part of the mantissa -the mantissa must
                    contain at least one digit

Exponent (optional):

        D or E      exponent leader

        + or -      optional exponent sign

        digits      exponent digits

Numbers with an absolute value greater than 1010 or less than 10-10 are rejected.

The NAME card can have anything you want, starting in column 15.  The
ROWS section defines the names of all the constraints; entries in
column 2 or 3 are E for equality rows, L for less-than ( <= ) rows, G
for greater-than ( >= ) rows, and N for non-constraining rows (the
first of which would be interpreted as the objective function).  The
order of the rows named in this section is unimportant.

The largest part of the file is in the COLUMNS section, which is the
place where the entries of the A-matrix are put. All entries for a given
column must be placed consecutively, although within a column the
order of the entries (rows) is irrelevant. Rows not mentioned for a
column are implied to have a coefficient of zero.

The RHS section allows one or more right-hand-side vectors to be
defined; most people don't bother having more than one.  In the above
example, the name of the RHS vector is RHS1, and has non-zero values
in all 3 of the constraint rows of the problem.  Rows not mentioned in
an RHS vector would be assumed to have a right-hand-side of zero.
Note that the objective may also have a constant. This can also be
specified in this section by using the object name as constraint name
and then specifying the constant. Note that there are 2 interpretations
of this constant. Some solvers see this as the constant that would be
really in the RHS and when brought into the objective (LHS), it is negated.
Other solvers, as lp_solve does, use the specified value in the MPS file
as the value for the objective and don't negate it.

The optional BOUNDS section lets you put lower and upper bounds on
individual variables (no * wild cards, unfortunately), instead of
having to define extra rows in the matrix.  All the bounds that have
a given name in column 5 are taken together as a set.  Variables not
mentioned in a given BOUNDS set are taken to be non-negative (lower
bound zero, no upper bound).  A bound of type UP means an upper bound
is applied to the variable.  A bound of type LO means a lower bound is
applied.  A bound type of FX ("fixed") means that the variable has
upper and lower bounds equal to a single value.  A bound type of FR
("free") means the variable has neither lower nor upper bounds.

There is another optional section called RANGES that I won't go into
here. The final card must be ENDATA, and yes, it is spelled funny.

==========================================================================

MPS input format was originally introduced by IBM to express linear
and integer programs in a standard way.  The format is a fixed column
format, so care must be taken that all information is placed in the
correct columns as described below.

The following is not intended as a complete description of MPS format,
but only as a brief introduction.  For more information, the reader is
directed to:

  "Advanced Linear Programming," by Bruce A. Murtagh
  "Computer Solutions of Linear Programs," by J.L. Nazareth


It may be useful to look at an example MPS file while reading this
MPS information.


The following template is a guide for the use of MPS format:

---------------------------------------------------------------------
Field:    1           2          3         4         5         6
Columns:  2-3        5-12      15-22     25-36     40-47     50-61

          NAME   problem name

          ROWS

           type     name

          COLUMNS
                   column       row       value     row      value
                    name        name                name
          RHS
                    rhs         row       value     row      value
                    name        name                name
          RANGES
                    range       row       value     row      value
                    name        name                name
          BOUNDS

           type     bound       column    value
                    name        name

          SOS
           type     CaseName    SOSName   SOSpriority
                    CaseName    VarName1  VarWeight1
                    CaseName    VarName2  VarWeight2

                    CaseName    VarNameN  VarWeightN

          ENDATA
---------------------------------------------------------------------

NOTES:

A. In the ROWS section, each row of the constraint matrix must have a
   row type and a row name specified.  The code for indicating row type
   is as follows:

                     type      meaning
                     ---------------------------
                      E    equality
                      L    less than or equal
                      G    greater than or equal
                      N    objective
                      N    no restriction

B. In the COLUMNS section, the names of the variables are defined along
   with the coefficients of the objective and all the nonzero constraint
   matrix elements.  It is not necessary to specify columns for slack or
   surplus variables as this is taken care of automatically.

C. The RHS section contains information for the right-hand side of the problem.

D. The RANGES section is for constraints of the form:  h <= constraint <= u .
   The range of the constraint is  r = u - h .  The value of r is specified
   in the RANGES section, and the value of u or h is specified in the RHS
   section.  If b is the value entered in the RHS section, and r is the
   value entered in the RANGES section, then u and h are thus defined:

        row type       sign of r       h          u
        ----------------------------------------------
           G            + or -         b        b + |r|
           L            + or -       b - |r|      b
           E              +            b        b + |r|
           E              -          b - |r|      b


E. In the BOUNDS section, bounds on the variables are specified.  When
   bounds are not indicated, the default bounds ( 0 <= x < infinity )
   are assumed.  The code for indicating bound type is as follows:

                    type            meaning
                   ---------------------------------------------------
                     LO    lower bound        b <= x (< +inf)
                     UP    upper bound        (0 <=) x <= b
                     FX    fixed variable     x = b
                     FR    free variable      -inf < x < +inf
                     MI    lower bound -inf   -inf < x (<= 0)
                     PL    upper bound +inf   (0 <=) x < +inf
                     BV    binary variable    x = 0 or 1
                     LI    integer variable   b <= x (< +inf)
                     UI    integer variable   (0 <=) x <= b
                     SC    semi-cont variable x = 0 or l <= x <= b
                           l is the lower bound on the variable
                           If none set then defaults to 1

F. Sections RANGES and BOUNDS are optional as are the fields 5 and 6.
   Everything else is required.  In regards to fields 5 and 6, consider
   the following 2 constraints:

                       const1:  2x + 3y <= 6
                       const2:  5x + 8y <= 20

   Two ways to enter the variable x in the COLUMNS section are:

     (Field:  2    3           4            5         6  )
   1.         x  const1       2.0         const2     5.0

   2.         x  const1       2.0
              x  const2       5.0

G. A mixed integer program requires the specification of which variables
   are required to be integer.  Markers are used to indicate the start
   and end of a group of integer variables.  The start marker has its
   name in field 2, 'MARKER' in field 3, and 'INTORG' in field 5.  The
   end marker has its name in field 2, 'MARKER' in field 3, and 'INTEND'
   in field 5.  These markers are placed in the COLUMNS section.
   When there are BOUNDS on the variables, then these are used as lower
   and upper bound of these integer variables and there is no confusion
   possible. Even a lower bound of 0 is already enough. In that case, if
   there is no upper bound, infinite is used.
   However there is an interpretation problem if there are no bounds at
   all on these variables. Some solvers then use 0 as lower bound and 1
   as upper bound. So the variables are treated as binary variables.
   That is the original IBM interpretation.
   Other solvers, like lp_solve, use the default bounds on variables in
   that case. That is 0 as lower bound and infinite as upper bound.
   When lp_solve writes an MPS file, it will write the default lower
   bound of 0 if there are no lower/upper bounds set on the variable. As
   such, there is no confusion.
   However when lp_solve reads an MPS file and there are no bounds on
   variables between INTORG/INTEND, it interpretes the variables as
   integer and not binary as some other solvers do. That could result
   in another solution than expected.

H. A specially ordered set of degree N is a collection of variables where
   at most N variables may be non-zero.  The non-zero variables must be
   contiguous (neighbours) sorted by the ascending value of their respective
   unique weights.  In lp_solve, specially ordered sets may be of any
   cardinal type 1, 2, and higher, and may be overlapping.  The number of
   variables in the set must be equal to, or exceed the cardinal SOS order.

   Below is a representation of a SOS in an MPS file, where each SOS is
   defined in its own SOS section, which should follow the BOUNDS section.

   0        1         2         3         4
   1234567890123456789012345678901234567890
   SOS
    Sx CaseName  SOSName.  SOSpriority.
       CaseName  VarName1  VarWeight1..
       CaseName  VarName2  VarWeight2..

       CaseName  VarNameN  VarWeightN..

   x at the second line, position 3, defines is the order of the SOS.
   Due to limitations in the MPS format, N is restricted to the 1..9 range.
   Each SOS should be given a unique name, SOSName. lp_solve does not
   currently use case names for SOS'es and the CaseName could be any non-empty
   value.  The SOSpriority value determines the order in which multiple SOS'es
   are analysed in lp_solve.
   See also Interpolation with GAMS.

Example:
NAME SOS2test ROWS N obj L c1 L c2 E c3 COLUMNS x1 obj -1 c1 -1 x1 c2 1 x2 obj -2 c1 1 x2 c2 -3 c3 1 x3 obj -3 c1 1 x3 c2 1 x4 obj -1 c1 10 x4 c3 -3.5 x5 obj 0 RHS rhs c1 30 c2 30 BOUNDS UP BOUND x1 40 LI BOUND x4 2 UI BOUND x4 3 SOS S2 SET SOS2 10 SET x1 10000 SET x2 20000 SET x4 40000 SET x5 50000 ENDATA

Free MPS format

The free format is very similar to the fixed MPS format, but it is less restrictive e.g. it allows longer names. Also some implementations allow more than 12 positions to specify the values. The fields do not have fixed column positions as in the fixed MPS format. They may be written anywhere except column 1, with each field separated from the next by one or more blanks. However, they must appear in the same sequence as in fixed format. In the rows and bounds sections, the codes can be lower and upper case and at any starting position. Repeated column names are sometimes skipped and spaces are put there instead. The Fortran D exponent is allowed in the values.

There is one important limitation compared to the fixed MPS format: names may not contain blanks.

Note that the free MPS parser cannot read all fixed MPS formats correctly. Spaces in the names or names starting with spaces will give problems. It is not sure that an error will be given in that case. If the format complies to the free MPS format then it won't... So if you know that a model is in fixed MPS format, use it and not the free format. It is advised to first try the fixed format and only if it doesn't work, use the free format.

Also note that there is no real standard for the free format. Each implementer has its own implementation and interpretation of the free format ... Some allow one space in the name, some require that names must take at least 8 positions (and thus extended with spaces). Some allow to have more than 6 fields on a line. lp_solve only reads the first 6 fields and ignores the rest.

lp_solve tries to handle all possible free formats. The only real limitation is that there may be no blanks in names (also no leading blanks) and only 6 fields per line may be used. When lp_solve writes an mps file in free format, it will be the same as for fixed format, except if names are longer than 8 characters. In that case all data is shifted to the right.

OBJSENSE

Several solvers have added a 'standard' to the free MPS format to allow to specify the objective direction. This via the new optional section OBJSENSE. Below this section, there may be one line that specifies the objective direction. This in field 1 of this line via the following possible keywords: MAXIMIZE, MAX, MINIMIZE, MIN. If the section is not specified, then lp_solve assumes minimization, just like the fixed MPS format.
For example:

OBJSENSE
 MAX

This section should be before the ROWS section.
For example:

NAME          TESTPROB
OBJSENSE
 MAX
ROWS
 N  COST
 L  LIM1
 G  LIM2
 E  MYEQN
COLUMNS
    XONE      COST                 1   LIM1                 1
    XONE      LIM2                 1
    YTWO      COST                 4   LIM1                 1
    YTWO      MYEQN               -1
    ZTHREE    COST                 9   LIM2                 1
    ZTHREE    MYEQN                1
RHS
    RHS1      LIM1                 5   LIM2                10
    RHS1      MYEQN                7
BOUNDS
 UP BND1      XONE                 4
 LO BND1      YTWO                -1
 UP BND1      YTWO                 1
ENDATA

The lp_solve free MPS reader recognises and interprets all possible OBJSENSE direction values. When a free MPS file is created, the OBJSENSE section will only be written when the direction is maximization. This because minimization is by default assumed and to stay as compatible as possible with other solvers.

OBJNAME

Several solvers have added a 'standard' to the free MPS format to allow to specify the objective row. By default the first "N" row defined in the ROWS section becomes a problem's objective; a different objective may be specified in the optional OBJNAME section, which contains exactly one data line that names the objective in field 1.
For example:

OBJNAME
 obj2

This section should be before the ROWS section.
For example:

NAME          TESTPROB
OBJNAME
 PROFIT
ROWS
 N  COST
 N  PROFIT
 L  LIM1
 G  LIM2
 E  MYEQN
COLUMNS
    XONE      COST                -1   PROFIT               1
    XONE      LIM1                 1   LIM2                 1
    YTWO      COST                -4   PROFIT               4
    YTWO      LIM1                 1   MYEQN               -1
    ZTHREE    COST                -9   PROFIT               9
    ZTHREE    LIM2                 1   MYEQN                1
RHS
    RHS1      LIM1                 5   LIM2                10
    RHS1      MYEQN                7
BOUNDS
 UP BND1      XONE                 4
 LO BND1      YTWO                -1
 UP BND1      YTWO                 1
ENDATA

The lp_solve free MPS reader recognises and interprets this OBJNAME section and uses the objective name specified here. Other "N" cards in the ROWS section are then ignored. Note that if there is no OBJNAME section that, just like in the fixed MPS format, the first "N" card from the rows section is then taken and all other "N" cards are ignored. When a free MPS file is created, the OBJNAME section will never be created since lp_solve always only has one objective function in memory.

doc/get_scaling.htm0000644000175000017500000001505110246721710013262 0ustar renerene get_scaling

get_scaling

Specifies which scaling algorithm is used.

int get_scaling(lprec *lp);

Return Value

get_scaling returns which scaling algorithm is used. Can by any of the following values:

SCALE_NONE (0) No scaling
SCALE_EXTREME (1) Scale to convergence using largest absolute value
SCALE_RANGE (2) Scale based on the simple numerical range
SCALE_MEAN (3) Numerical range-based scaling
SCALE_GEOMETRIC (4) Geometric scaling
SCALE_CURTISREID (7) Curtis-reid scaling

Additionally, the value can be OR-ed with any combination of one of the following values:

SCALE_QUADRATIC (8)  
SCALE_LOGARITHMIC (16) Scale to convergence using logarithmic mean of all values
SCALE_USERWEIGHT (31) User can specify scalars
SCALE_POWER2 (32) also do Power scaling
SCALE_EQUILIBRATE (64) Make sure that no scaled number is above 1
SCALE_INTEGERS (128) also scaling integer variables
SCALE_DYNUPDATE (256) dynamic update
SCALE_ROWSONLY (512) scale only rows
SCALE_COLSONLY (1024) scale only columns

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_scaling function returns which scaling algorithm is used. This can influence numerical stability considerably. It is advisable to always use some sort of scaling.
set_scaling must be called before solve is called.
SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC, SCALE_CURTISREID are the possible scaling algorithms. SCALE_QUADRATIC, SCALE_LOGARITHMIC, SCALE_USERWEIGHT, SCALE_POWER2, SCALE_EQUILIBRATE, SCALE_INTEGERS are possible additional scaling parameters.
SCALE_POWER2 results in creating a scalar of power 2. May improve stability.
SCALE_INTEGERS results also in scaling Integer columns. Default they are not scaled.
SCALE_DYNUPDATE is new from version 5.1.1.0
It has always been so that scaling is done only once on the original model. If a solve is done again (most probably after changing some data in the model), the scaling factors aren't computed again. The scalars of the original model are used. This is not always good, especially if the data has changed considerably. One way to solve this was/is call unscale before a next solve. In that case, scale factors are recomputed.
From version 5.1.1.0 on, there is another way to make sure that scaling factors are recomputed and this is by settings SCALE_DYNUPDATE. In that case, the scaling factors are recomputed also when a restart is done. Note that they are then always recalculated with each solve, even when no change was made to the model, or a change that doesn't influence the scaling factors like changing the RHS (Right Hand Side) values or the bounds/ranges. This can influence performance. It is up to you to decide if scaling factors must be recomputed or not for a new solve, but by default it still isn't so. It is possible to set/unset this flag at each next solve and it is even allowed to choose a new scaling algorithm between each solve. Note that the scaling done by the SCALE_DYNUPDATE is incremental and the resulting scalarsare typically different from scalars recomputed from scratch.
The default is SCALE_GEOMETRIC + SCALE_EQUILIBRATE + SCALE_INTEGERS (196).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int scalemode;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  scalemode = get_scaling(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_scaling, set_scalelimit, get_scalelimit, is_integerscaling, is_scalemode, is_scaletype

doc/xli_MPS.htm0000644000175000017500000001203711235654147012327 0ustar renerene MPS XLI (xli_MPS)

MPS XLI (xli_MPS)

lp_solve supports the MPS format natively via API calls read_mps, read_freemps, read_MPS, read_freeMPS, write_mps, write_freemps, write_MPS, write_freeMPS, MPS_writefileex, read_basis, write_basis

This accoring to the following MPS format

Two issues are addressed in above document:

Objective constant

The objective can have a constant. This optional constant is specified in the RHS section. There are 2 interpretations of this constant. Some solvers see this as the constant that would be really in the RHS and when brought into the objective (LHS), it is negated. Other solvers, as lp_solve natively does, use the specified value in the MPS file as the value for the objective and don't negate it.
This XLI allows lp_solve to interprete the constant as the other solvers do, ie negate it.
This via the option -negobjconst

Integer/binary variables

A mixed integer program requires the specification of which variables are required to be integer. Markers are used to indicate the start and end of a group of integer variables. The start marker has its name in field 2, 'MARKER' in field 3, and 'INTORG' in field 5. The end marker has its name in field 2, 'MARKER' in field 3, and 'INTEND' in field 5. These markers are placed in the COLUMNS section. When there are BOUNDS on the variables, then these are used as lower and upper bound of these integer variables and there is no confusion possible. Even a lower bound of 0 is already enough. In that case, if there is no upper bound, infinite is used. However there is an interpretation problem if there are no bounds at all on these variables. Some solvers then use 0 as lower bound and 1 as upper bound. So the variables are treated as binary variables. That is the original IBM interpretation. Other solvers, like lp_solve by default, use the default bounds on variables in that case. That is 0 as lower bound and infinite as upper bound. When lp_solve writes an MPS file, it will write the default lower bound of 0 if there are no lower/upper bounds set on the variable. As such, there is no confusion. However when lp_solve reads an MPS file and there are no bounds on variables between INTORG/INTEND, by default it interpretes the variables as integer and not binary as some other solvers do. That could result in another solution than expected.
This XLI allows lp_solve to interprete these integer variables as binary as in the original ibm specification.
This via the option -ibm

Free format

This XLI also supports the free format via the option -free

Basis

read_basis and write_basis allow to read and write a basis in MPS format as described in MPS bas file format. This XLI also allows to read and write a basis in this format. This via the option -bas. This can be combined with option -free to read/write in a free format.

Reading and writing the basis with this XLI is a bit awkward. This because these operations must be done at a different moment than reading and writing of a model file.

Reading the basis must be done after reading the model, but before solve. The read routine of the XLI cannot be used for reading the basis because reading creates a new lp structure. Therefore, the write function of the XLI is (mis)used. With the lp_solve command line program, this can be done as follows:

lp_solve lpfile -wxli xli_MPS.dll basfile -wxliopt "-free"

Writing the basis must be done after solve. Therefore, the write function of the XLI is again used, but now with the results parameter on TRUE as if the results of a model must be written. This is also a bit of a misuse of the XLI, but it must be done to be sure that it is done after solve. With the lp_solve command line program, this can be done as follows:

lp_solve lpfile -wxlisol xli_MPS.dll basfile -wxlisolopt "-free"

Options summary

  -free          Read/write in free format.
  -ibm           Interprete integer variables as in the original ibm specifications
  -negobjconst   Negate the objective constant.
  -bas           Read/write a basis file
doc/Intro.htm0000644000175000017500000002320011236130435012067 0ustar renerene Introduction

Introduction to lp_solve 5.5.0.15

What is lp_solve and what is it not? The simple answer is, lp_solve is a Mixed Integer Linear Programming (MILP) solver.

And what is Linear Programming? See "What is Linear Programming?" and "Oh, and we also want to solve it as an integer program." for a brief description. Also see Formulation of an lp problem in lpsolve.

lp_solve is a free (see LGPL for the GNU lesser general public license) linear (integer) programming solver based on the revised simplex method and the Branch-and-bound method for the integers.
It contains full source, examples and manuals.
lp_solve solves pure linear, (mixed) integer/binary, semi-continuous and special ordered sets (SOS) models. Note the word linear. This means that equations must be of the first order. 5 * x - 3 * y is an example. However x * y is not linear and cannot be handled by lp_solve. Both the objective function and the constraints have this restriction. Also see Ratios.
Via the Branch-and-bound algorithm, it can handle integer variables (see integer variables), semi-continuous variables (see semi-continuous variables) and Special Ordered Sets (see Special Ordered Sets (SOS)).
lp_solve has no limit on model size and accepts standard both lp or mps input files, but even that can be extended. Note however that some models could give lp_solve a hard time and will even fail to solve. The larger the model the likely the chance for that. But even commercial solvers have problems with that.
It can also be called as a library from different languages like C, VB, .NET, Delphi, Excel, Java, ...
It can also be called from AMPL, MATLAB, O-Matrix, Scilab, Octave, R via a driver program. lp_solve is written in ANSI C and can be compiled on many different platforms like linux and WINDOWS.

lp_solve has its own community via the Yahoo group http://groups.yahoo.com/group/lp_solve/. There you can find the latest sources, executables for the common platforms, examples, manuals and a message board where people can share their thoughts on lp_solve.

lp_solve was originally developed by Michel Berkelaar at Eindhoven University of Technology. The work of Jeroen Dirks made the transition from the basic version 1.5 to the full version 2.0 possible. He contributed the procedural interface, a built-in MPS reader, and many fixes and enhancements to the code. At that point there was also a Java port of lp_solve 2.0. This was not a Java native interface (JNI) to the C library, but rather a translation of the algorithm (ver 2.0) from C into Java. It was also very limited This meant that it did not keep up with lp_solve as it evolved. Starting at version 3.0, lp_solve is released under the LGPL license. Before the code could only be used for non-commercial purposes. Many other people also contributed to lp_solve, but there was no track of them. Sorry if you are not mentioned. Development was stagnated for some time at version 3.2, but now it is again alive and well via the new developers Kjell Eikland and Peter Notebaert. But also other people help to improve the product. For example the new Java interface to lp_solve was made by Juergen Ebert. It is a JNI interface that supports the full functionality of lp_solve. He did a great job. We encourage other people to participate in the development of lp_solve.
First a version 4 was introduced that had already several enhancements and improvements and now with version 5 this enhancement continues resulting is faster solving times, more stability and able to solver larger models and new functionality. See Changes from version 4 to version 5.1 for the changes done to version 5 and Changes from version 5.1 to version 5.5 for the changes done to version 5.5.

Basically, lp_solve is a library, a set of routines, called the API that can be called from almost any programming language to solve MILP problems. There are several ways to pass the data to the library:

  • Via the API
  • Via input files
  • Via an IDE

Via the API

The API is a set of routines that can be called from a programming language to build the model in memory, solve it and return the results. There are many API routines to perform many possible tasks and set several options. See lp_solve API reference for an overview.

Via input files

Standard, lp_solve supports several input files types. The common known MPS format (see mps-format) is supported by most solvers, but it is not very readable for humans. Another format is the lp format (see lp-format) that is more readable. lp_solve has the unique ability to use user-written routines to input the model (see External Language Interface). See read_mps, read_freemps, read_MPS, read_freeMPS and read_lp, read_LP for the API calls to read the model from file.

There is also a driver program called lp_solve that uses the API to provide a command line application to solve models. See lp_solve for its usage. With this program you don't have to know anything of API or computer programming languages. You can just provide your model via file to the program and it will solve the model and give you the result.

Via an IDE

Thanks to Henri Gourvest, there is now also an IDE program called LPSolve IDE that uses the API to provide a Windows application to solve models. See LPSolve IDE for its usage. With this program you don't have to know anything of API or computer programming languages. You can just provide your model to the program and it will solve the model and give you the result.

As already stated, lp_solve can be called from many programming language. Among them are C, C++, Pascal, Delphi, Java, VB, C#, VB.NET, Excel. But let this list not be a limitation. Any programming language capable of calling external libraries (DLLs under Windows, Shared libraries (.so) under Unix/Linux) can call lp_solve.

Here is a list of some key features of lp_solve:

  • Mixed Integer Linear Programming (MILP) solver
  • Basically no limit on model size
  • It is free and with sources
  • Supports Integer variables, Semi-continuous variables and Special Ordered Sets
  • Can read model from MPS, LP or user written format
  • Models can be build in-memory without the use of files
  • Has a powerful API interface
  • Easy callable from other programming languages
  • Advanced pricing using Devex and Steepest Edge for both primal and dual simplexes
  • Provides different scaling methods to make the model more numerical stable
  • Has presolve capabilities to tighten constraints/make the model smaller and faster to solve
  • Has a base crashing routine to determine a starting point
  • Allows restart after making changes to the model. Solve continues from the last found solution
  • Possible to select desired combinations of primal and dual phases 1 and 2
  • Possible to set several solver parameters like tolerances
  • Alternative (and faster) inverse/re-factorisation libraries are provided for. See Basis Factorization Packages
  • Alternative model readers and writers possible via the XLI implementation. See External Language Interfaces
  • Has the possibility to convert one model format to another format
  • Provides post-optimal sensitivity analysis. See Sensitivity
  • ...
doc/set_timeout.htm0000644000175000017500000000565410237176664013370 0ustar renerene set_timeout

set_timeout

Set a timeout.

void set_timeout(lprec *lp, long sectimeout);

Return Value

set_timeout has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

sectimeout

The number of seconds after which a timeout occurs. If zero, then no timeout will occur.

Remarks

The set_timeout function sets a timeout in seconds. The solve and lag_solve functions may not last longer than this time or the routines return with a timeout. The default timeout is 0, resulting in no timeout.
If a timout occurs, but there was already an integer solution found (that is possibly not the best), then solve will return SUBOPTIMAL. If there was no integer solution found yet or there are no integers or the solvers is still in the first phase where a REAL optimal solution is searched for, then solve will return TIMEOUT.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_timeout(lp, 600); /* sets a timeout of 600 seconds (10 minutes) */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_timeout, time_elapsed, solve, lag_solve

doc/set_maxpivot.htm0000644000175000017500000000507510247425536013542 0ustar renerene set_maxpivot

set_maxpivot

Sets the maximum number of pivots between a re-inversion of the matrix.

void set_maxpivot(lprec *lp, int max_num_inv);

Return Value

set_maxpivot has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

max_num_inv

The maximum number of pivots between a re-inversion of the matrix.

Remarks

The set_maxpivot function sets the maximum number of pivots between a re-inversion of the matrix.
For stability reasons, lp_solve re-inverts the matrix on regular times. max_num_inv determines how frequently this inversion is done. This can influence numerical stability. However, the more often this is done, the slower the solver becomes.
The default is 250 for the LUSOL bfp and 42 for the other BFPs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_maxpivot(lp, 10);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_maxpivot

doc/Python.htm0000644000175000017500000035651011244025430012267 0ustar renerene Using lpsolve from Python

Using lpsolve from Python

Python?

Python is an interpreted, interactive, object-oriented programming language. It is often compared to Tcl, Perl, Scheme or Java.

Python combines remarkable power with very clear syntax. It has modules, classes, exceptions, very high level dynamic data types, and dynamic typing. There are interfaces to many system calls and libraries, as well as to various windowing systems (X11, Motif, Tk, Mac, MFC, wxWidgets). New built-in modules are easily written in C or C++. Python is also usable as an extension language for applications that need a programmable interface.

The Python implementation is portable: it runs on many brands of UNIX, on Windows, OS/2, Mac, Amiga, and many other platforms.

Some of Python's notable features:

  • Python uses an elegant syntax for readable programs.
  • Python is an agile language that makes it easy to get your program working. This makes Python an ideal language for prototype development and other ad-hoc programming tasks, without compromising maintainability.
  • A variety of basic data types are available: numbers (floating point, complex, and unlimited-length long integers), strings (both ASCII and Unicode), lists, dictionaries.
  • Python supports object-oriented programming with classes and multiple inheritance.
  • Code can be grouped into modules and packages.
  • The language supports raising and catching exceptions, resulting in cleaner error handling.
  • Data types are strongly and dynamically typed. Mixing incompatible types (e.g. attempting to add a string and a number) causes an exception to be raised.
  • Python contains advanced programming features such as generators and list comprehensions.
  • Automatic garbage collection frees you from the hassles of memory management.
  • The large standard library supports many common programming tasks such as connecting to web servers, regular expressions, and file handling.
  • Python's interactive mode makes it easy to test short snippets of code. There's also a bundled development environment called IDLE.
  • The Python interpreter is easily extended by adding new modules implemented in a compiled language such as C or C++.
  • The interpreter can also be embedded into an application to provide a programmable interface.
  • Python runs on many different computers and operating systems: Windows, MacOS, many brands of Unix, OS/2, ...

We will not discuss the specifics of Python here but instead refer the reader to the Python website. Also see Dive Into Python - Python from novice to pro

Python and lpsolve

lpsolve is callable from Python via an extension or module. As such, it looks like lpsolve is fully integrated with Python. Matrices can directly be transferred between Python and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for Python (especially for matrix support). So you have full control to the complete lpsolve functionality via the lpsolve Python driver. If you find that this involves too much work to solve an lp model then you can also work via higher-level script files that can make things a lot easier. See further in this article.

Python is ideally suited to handle linear programming problems. These are problems in which you have a quantity, depending linearly on several variables, that you want to maximize or minimize subject to several constraints that are expressed as linear inequalities in the same variables.If the number of variables and the number of constraints are small, then there are numerous mathematical techniques for solving a linear programming problem. Indeed these techniques are often taught in high school or university level courses in finite mathematics.But sometimes these numbers are high, or even if low, the constants in the linear inequalities or the object expression for the quantity to be optimised may be numerically complicated in which case a software package like Python is required to effect a solution.

Installation

To make this possible, a driver program is needed: lpsolve55.pyd/lpsolve55.so. This driver must be put in a directory known to Python and Python can call the lpsolve solver.

This driver calls lpsolve via the lpsolve shared library (lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux) (archive lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). This has the advantage that the lpsolve driver doesn't have to be recompiled when an update of lpsolve is provided. The shared library must be somewhere in the Windows path.

So note the difference between the Python lpsolve driver that is called lpsolve and the lpsolve library that implements the API that is called lpsolve55.

There are also some Python script files (.py) as a quick start.

See Install the lpsolve driver for the installation of these files.

To test if everything is installed correctly, enter the following in the Python command window.

>>> from lpsolve55 import *
>>> lpsolve()

If it gives the following, then everything is ok:

lpsolve Python Interface version 5.5.0.6
using lpsolve version 5.5.0.15

Usage: [ret1, ret2, ...] = lpsolve('functionname', arg1, arg2, ...)

If you get the following:

This application has failed to start because lpsolve55.dll was not found.
Re-installing the application may fix this problem.

Or (Unix/Linux):

liblpsolve55.so: cannot open shared object file: No such file or directory.

Then Python can find the lpsolve driver program, but the driver program cannot find the lpsolve library that contains the lpsolve implementation. This library is called lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux.
Under Windows, the lpsolve55.dll file must be in a directory that in the PATH environment variable. This path can be shown via the following command in Python: !PATH
It is common to place this in the WINDOWS\system32 folder.

Under Unix/Linux, the liblpsolve55.so shared library must be either in the directories /lib or /usr/lib or in a directory specified by the LD_LIBRARY_PATH environment variable.

Solve an lp model from Python via lpsolve

In the following text, >>> before the Python commands is the Python prompt. Only the text after >>> must be entered.

To call an lpsolve function, the following syntax must be used:

>>> [ret1, ret2, ...] = lpsolve('functionname', arg1, arg2, ...)

The return values are optional and depend on the function called. functionname must always be enclosed between single quotes to make it alphanumerical and it is case sensitive. The number and type of arguments depend on the function called. Some functions even have a variable number of arguments and a different behaviour occurs depending on the type of the argument. functionname can be (almost) any of the lpsolve API routines (see lp_solve API reference) plus some extra Python specific functions. Most of the lpsolve API routines use or return an lprec structure. To make things more robust in Python, this structure is replaced by a handle or the model name. The lprec structures are maintained internally by the lpsolve driver. The handle is an incrementing number starting from 0. Starting from driver version 5.5.0.2, it is also possible to use the model name instead of the handle. This can of course only be done if a name is given to the model. This is done via lpsolve routine set_lp_name or by specifying the model name in routine read_lp. See Using model name instead of handle.

Almost all callable functions can be found in the lp_solve API reference. Some are exactly as described in the reference guide, others have a slightly different syntax to make maximum use of the Python functionality. For example make_lp is used identical as described. But get_variables is slightly different. In the API reference, this function has two arguments. The first the lp handle and the second the resulting variables and this array must already be dimensioned. When lpsolve is used from Python, nothing must be dimensioned in advance. The lpsolve driver takes care of dimensioning all return variables and they are always returned as return value of the call to lpsolve. Never as argument to the routine. This can be a single value as for get_objective or a matrix or vector as in get_variables. In this case, get_variables returns a 4x1 matrix (vector) with the result of the 4 variables of the lp model.

Note that you can get a usage of lpsolve, its arguments and the constants that it defines by entering the following in Python:

>>> import lpsolve55
>>> help(lpsolve55)
Help on module lpsolve55:

NAME
    lpsolve55

FILE
    c:\python24\lib\site-packages\lpsolve55.pyd

CLASSES
    exceptions.Exception
        lpsolve.error

    class error(exceptions.Exception)
     |  Methods inherited from exceptions.Exception:
     |
     |  __getitem__(...)
     |
     |  __init__(...)
     |
     |  __str__(...)

FUNCTIONS
    lpsolve(...)
        lpsolve('functionname', arg1, arg2, ...) ->  execute lpsolve functionname with args

DATA
    ANTIDEGEN_BOUNDFLIP = 512
    ANTIDEGEN_COLUMNCHECK = 2
    ANTIDEGEN_DURINGBB = 128
    ANTIDEGEN_DYNAMIC = 64
    ANTIDEGEN_FIXEDVARS = 1
    ANTIDEGEN_INFEASIBLE = 32
    ANTIDEGEN_LOSTFEAS = 16
    ANTIDEGEN_NONE = 0
    ANTIDEGEN_NUMFAILURE = 8
    ANTIDEGEN_RHSPERTURB = 256
    ANTIDEGEN_STALLING = 4
    BRANCH_AUTOMATIC = 2
    BRANCH_DEFAULT = 3
    BRANCH_CEILING = 0
    BRANCH_FLOOR = 1
    CRASH_LEASTDEGENERATE = 3
    CRASH_MOSTFEASIBLE = 2
    CRASH_NONE = 0
    CRITICAL = 1
    DEGENERATE = 4
    DETAILED = 5
    EQ = 3
    FEASFOUND = 12
    FR = 0
    FULL = 6
    GE = 2
    IMPORTANT = 3
    IMPROVE_BBSIMPLEX = 8
    IMPROVE_DUALFEAS = 2
    IMPROVE_NONE = 0
    IMPROVE_SOLUTION = 1
    IMPROVE_THETAGAP = 4
    INFEASIBLE = 2
    Infinite = 1e+030
    LE = 1
    MSG_LPFEASIBLE = 8
    MSG_LPOPTIMAL = 16
    MSG_MILPBETTER = 512
    MSG_MILPEQUAL = 256
    MSG_MILPFEASIBLE = 128
    MSG_PRESOLVE = 1
    NEUTRAL = 0
    NODE_AUTOORDER = 8192
    NODE_BRANCHREVERSEMODE = 16
    NODE_BREADTHFIRSTMODE = 4096
    NODE_DEPTHFIRSTMODE = 128
    NODE_DYNAMICMODE = 1024
    NODE_FIRSTSELECT = 0
    NODE_FRACTIONSELECT = 3
    NODE_GAPSELECT = 1
    NODE_GREEDYMODE = 32
    NODE_GUBMODE = 512
    NODE_PSEUDOCOSTMODE = 64
    NODE_PSEUDOCOSTSELECT = 4
    NODE_PSEUDONONINTSELECT = 5
    NODE_PSEUDORATIOSELECT = 6
    NODE_RANDOMIZEMODE = 256
    NODE_RANGESELECT = 2
    NODE_RCOSTFIXING = 16384
    NODE_RESTARTMODE = 2048
    NODE_STRONGINIT = 32768
    NODE_USERSELECT = 7
    NODE_WEIGHTREVERSEMODE = 8
    NOFEASFOUND = 13
    NOMEMORY = -2
    NORMAL = 4
    NUMFAILURE = 5
    OPTIMAL = 0
    PRESOLVED = 9
    PRESOLVE_BOUNDS = 262144
    PRESOLVE_COLDOMINATE = 16384
    PRESOLVE_COLFIXDUAL = 131072
    PRESOLVE_COLS = 2
    PRESOLVE_DUALS = 524288
    PRESOLVE_ELIMEQ2 = 256
    PRESOLVE_IMPLIEDFREE = 512
    PRESOLVE_IMPLIEDSLK = 65536
    PRESOLVE_KNAPSACK = 128
    PRESOLVE_LINDEP = 4
    PRESOLVE_MERGEROWS = 32768
    PRESOLVE_NONE = 0
    PRESOLVE_PROBEFIX = 2048
    PRESOLVE_PROBEREDUCE = 4096
    PRESOLVE_REDUCEGCD = 1024
    PRESOLVE_REDUCEMIP = 64
    PRESOLVE_ROWDOMINATE = 8192
    PRESOLVE_ROWS = 1
    PRESOLVE_SENSDUALS = 1048576
    PRESOLVE_SOS = 32
    PRICER_DANTZIG = 1
    PRICER_DEVEX = 2
    PRICER_FIRSTINDEX = 0
    PRICER_STEEPESTEDGE = 3
    PRICE_ADAPTIVE = 32
    PRICE_AUTOPARTIAL = 256
    PRICE_HARRISTWOPASS = 4096
    PRICE_LOOPALTERNATE = 2048
    PRICE_LOOPLEFT = 1024
    PRICE_MULTIPLE = 8
    PRICE_PARTIAL = 16
    PRICE_PRIMALFALLBACK = 4
    PRICE_RANDOMIZE = 128
    PRICE_TRUENORMINIT = 16384
    PROCBREAK = 11
    PROCFAIL = 10
    SCALE_COLSONLY = 1024
    SCALE_CURTISREID = 7
    SCALE_DYNUPDATE = 256
    SCALE_EQUILIBRATE = 64
    SCALE_EXTREME = 1
    SCALE_GEOMETRIC = 4
    SCALE_INTEGERS = 128
    SCALE_LOGARITHMIC = 16
    SCALE_MEAN = 3
    SCALE_NONE = 0
    SCALE_POWER2 = 32
    SCALE_QUADRATIC = 8
    SCALE_RANGE = 2
    SCALE_ROWSONLY = 512
    SCALE_USERWEIGHT = 31
    SEVERE = 2
    SIMPLEX_DUAL_DUAL = 10
    SIMPLEX_DUAL_PRIMAL = 6
    SIMPLEX_PRIMAL_DUAL = 9
    SIMPLEX_PRIMAL_PRIMAL = 5
    SUBOPTIMAL = 1
    TIMEOUT = 7
    UNBOUNDED = 3
    USERABORT = 6
Also see Using string constants for an alternative.

An example

(Note that you can execute this example by entering command per command as shown below or by executing script example1. This will execute example1.py.)

>>> from lpsolve55 import *
>>> lp = lpsolve('make_lp', 0, 4)
>>> lpsolve('set_verbose', lp, IMPORTANT)
>>> ret = lpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1])
>>> ret = lpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], GE, 92.3)
>>> ret = lpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], LE, 14.8)
>>> ret = lpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], GE, 4)
>>> ret = lpsolve('set_lowbo', lp, 1, 28.6)
>>> ret = lpsolve('set_lowbo', lp, 4, 18)
>>> ret = lpsolve('set_upbo', lp, 4, 48.98)
>>> ret = lpsolve('set_col_name', lp, 1, 'COLONE')
>>> ret = lpsolve('set_col_name', lp, 2, 'COLTWO')
>>> ret = lpsolve('set_col_name', lp, 3, 'COLTHREE')
>>> ret = lpsolve('set_col_name', lp, 4, 'COLFOUR')
>>> ret = lpsolve('set_row_name', lp, 1, 'THISROW')
>>> ret = lpsolve('set_row_name', lp, 2, 'THATROW')
>>> ret = lpsolve('set_row_name', lp, 3, 'LASTROW')
>>> ret = lpsolve('write_lp', lp, 'a.lp')
>>> print lpsolve('get_mat', lp, 1, 2)
78.26
>>> lpsolve('solve', lp)
0L
>>> print lpsolve('get_objective', lp)
31.7827586207
>>> print lpsolve('get_variables', lp)[0]
[28.600000000000001, 0.0, 0.0, 31.827586206896552]
>>> print lpsolve('get_constraints', lp)[0]
[92.299999999999997, 6.863999999999999, 391.2928275862069]

Note that there are commands that return an answer. If they do and their result is not stored in a variable, then it is echoed on screen. If assigned to a variable then the value is not echoed. For example:

>>> obj = lpsolve('get_objective', lp)

The result in then not shown on screen. But the contents of the variable can be printed:

>>> print obj
31.7827586207

Or even:

>>> obj
31.782758620689656

Note that get_variables and get_constraints return two results: The result vector and a status. If only the vector is needed, then [0] can be used as in the example. Or the result can be stored in an extra variables:

>>> [x, ret] = lpsolve('get_variables', lp)

Variable x will contain the result vector and ret the return status of the call.

Note that if this is stored only in one variable that you get the following:

>>> x = lpsolve('get_variables', lp)
>>> print x
[[28.600000000000001, 0.0, 0.0, 31.827586206896552], 1L]

Don't forget to free the handle and its associated memory when you are done:

>>> lpsolve('delete_lp', lp)

Note that there is another way to access the lpsolve library. It is more object oriented, but requires more typing:

>>> import lpsolve55
>>> lp = lpsolve55.lpsolve('make_lp', 0, 4)
>>> lpsolve55.lpsolve('set_verbose', lp, lpsolve55.IMPORTANT)
.
.
.
>>> lpsolve55.lpsolve('delete_lp', lp)

This technique will not be used in this description because the lpsolve library is not really object oriented structured. But if you prefer it, there is nothing that should stop you. The only difference is that you have to put lpsolve55. before every lpsolve function and constant.

Using model name instead of handle

From driver version 5.5.0.2, it is possible to use the model name instead of the handle. From the moment the model has a name, you can use this name instead of the handle. This is best shown by an example. Above example would look like this:
>>> from lpsolve55 import *
>>> lp = lpsolve('make_lp', 0, 4)
>>> ret = lpsolve('set_lp_name', lp, 'mymodel')
>>> lpsolve('set_verbose', 'mymodel', IMPORTANT)
>>> ret = lpsolve('set_obj_fn', 'mymodel', [1, 3, 6.24, 0.1])
>>> ret = lpsolve('add_constraint', 'mymodel', [0, 78.26, 0, 2.9], GE, 92.3)
>>> ret = lpsolve('add_constraint', 'mymodel', [0.24, 0, 11.31, 0], LE, 14.8)
>>> ret = lpsolve('add_constraint', 'mymodel', [12.68, 0, 0.08, 0.9], GE, 4)
>>> ret = lpsolve('set_lowbo', 'mymodel', 1, 28.6)
>>> ret = lpsolve('set_lowbo', 'mymodel', 4, 18)
>>> ret = lpsolve('set_upbo', 'mymodel', 4, 48.98)
>>> ret = lpsolve('set_col_name', 'mymodel', 1, 'COLONE')
>>> ret = lpsolve('set_col_name', 'mymodel', 2, 'COLTWO')
>>> ret = lpsolve('set_col_name', 'mymodel', 3, 'COLTHREE')
>>> ret = lpsolve('set_col_name', 'mymodel', 4, 'COLFOUR')
>>> ret = lpsolve('set_row_name', 'mymodel', 1, 'THISROW')
>>> ret = lpsolve('set_row_name', 'mymodel', 2, 'THATROW')
>>> ret = lpsolve('set_row_name', 'mymodel', 3, 'LASTROW')
>>> ret = lpsolve('write_lp', 'mymodel', 'a.lp')
>>> print lpsolve('get_mat', 'mymodel', 1, 2)
78.26
>>> lpsolve('solve', 'mymodel')
0L
>>> print lpsolve('get_objective', 'mymodel')
31.7827586207
>>> print lpsolve('get_variables', 'mymodel')[0]
[28.600000000000001, 0.0, 0.0, 31.827586206896552]
>>> print lpsolve('get_constraints', 'mymodel')[0]
[92.299999999999997, 6.863999999999999, 391.2928275862069]

So everywhere a handle is needed, you can also use the model name. You can even mix the two methods. There is also a specific Python routine to get the handle from the model name: get_handle.
For example:

>>> lp = lpsolve('get_handle', 'mymodel')
>>> print lp
0

Don't forget to free the handle and its associated memory when you are done:

>>> lpsolve('delete_lp', 'mymodel')

In the next part of this documentation, the handle is used. But if you name the model, the name could thus also be used.

Matrices

lpsolve uses Python lists to represent matrices (and vectors). Note that lpsolve can only work with real numbers, not complex numbers. For example:
>>> lpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 1, 14.8)

[0.24, 0, 11.31, 0] is a list type variable.

Most of the time, variables are used to provide the data:

>>> lpsolve('add_constraint', lp, a1, 1, 14.8)

Where a1 is a variable of type list. Sometimes a two-dimensional matrix is used:

>>> lpsolve('set_mat', lp, [[1, 2, 3], [4, 5, 6]])

[1, 2, 3] is the first row and [4, 5, 6] is the second row.

The lpsolve driver sees all provided matrices as sparse matrices. lpsolve uses sparse matrices internally and data can be provided sparse via the ex routines. For example add_constraintex. The lpsolve driver always uses the ex routines to provide the data to lpsolve. Even if you call from Python the routine names that would require a dense matrix (for example add_constraint), the lpsolve driver will always call the sparse version of the routine (for example add_constraintex). This results in the most performing behaviour. Matrices with too few or too much elements gives an 'invalid vector.' error.

An important final note. Several lp_solve API routines accept a vector where the first element (element 0) is not used. Other lp_solve API calls do use the first element. In the Python interface, there is never an unused element in the matrices. So if the lp_solve API specifies that the first element is not used, then this element is not in the Python matrix.

Maximum usage of matrices with lpsolve

Because Python has the list possibility to represent vectors, all lpsolve API routines that need a column or row number to get/set information for that column/row are extended in the lpsolve Python driver to also work with vectors. For example set_int in the API can only set the integer status for one column. If the status for several integer variables must be set, then set_int must be called multiple times. The lpsolve Python driver however also allows specifying a vector to set the integer status of all variables at once. The API call is: return = lpsolve('set_int', lp, column, must_be_int). The matrix version of this call is: return = lpsolve('set_int', lp, [must_be_int]). The API call to return the integer status of a variable is: return = lpsolve('is_int', lp, column). The matrix version of this call is: [is_int] = lpsolve('is_int', lp)
Also note the get_mat and set_mat routines. In Python these are extended to return/set the complete constraint matrix. See following example.

Above example can thus also be done as follows:
(Note that you can execute this example by entering command per command as shown below or by executing script example2. This will execute example2.py.)

>>> lp = lpsolve('make_lp', 0, 4)
>>> lpsolve('set_verbose', lp, IMPORTANT)
>>> ret = lpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1])
>>> ret = lpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], GE, 92.3)
>>> ret = lpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], LE, 14.8)
>>> ret = lpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], GE, 4)
>>> ret = lpsolve('set_lowbo', lp, [28.6, 0, 0, 18])
>>> ret = lpsolve('set_upbo', lp, [Infinite, Infinite, Infinite, 48.98])
>>> ret = lpsolve('set_col_name', lp, ['COLONE', 'COLTWO', 'COLTHREE', 'COLFOUR'])
>>> ret = lpsolve('set_row_name', lp, ['THISROW', 'THATROW', 'LASTROW'])
>>> ret = lpsolve('write_lp', lp, 'a.lp')
>>> print lpsolve('get_mat', lp)[0]
[[0.0, 78.26, 0.0, 2.9], [0.24, 0.0, 11.31, 0.0], [12.68, 0.0, 0.08, 0.9]]
>>> lpsolve('solve', lp)
0L
>>> print lpsolve('get_objective', lp)
31.7827586207
>>> print lpsolve('get_variables', lp)[0]
[28.600000000000001, 0.0, 0.0, 31.827586206896552]
>>> print lpsolve('get_constraints', lp)[0]
[92.299999999999997, 6.8639999999999999, 391.29282758620695]

Note the usage of Infinite in set_upbo. This stands for 'infinity'. Meaning an infinite upper bound. It is also possible to use -Infinite to express minus infinity. This can for example be used to create a free variable. Infinite is a constant defined by the lpsolve library.

To show the full power of the matrices, let's now do some matrix calculations to check the solution. It works further on above example. Note that Python doesn't support matrix calculations on lists. However, there are several numerical packages that can do this. The list type variables must be converted to the matrix types of these packages. A common known package for this is Numeric. It is not installed by default but can be easily installed. See http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=1351. There are newer packages like SciPy: http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=6222. See http://numeric.scipy.org/ for a brief overview. This documentation works with Numeric to do the math calculations.

>>> from Numeric import *
>>> A = array(lpsolve('get_mat', lp)[0])
>>> A
array([[  0.  ,  78.26,   0.  ,   2.9 ],
       [  0.24,   0.  ,  11.31,   0.  ],
       [ 12.68,   0.  ,   0.08,   0.9 ]])
>>> X = array(lpsolve('get_variables', lp)[0])
>>> X
array([ 28.6       ,   0.        ,   0.        ,  31.82758621])
>>> B = matrixmultiply(A, X)
>>> B
array([  92.3       ,    6.864     ,  391.29282759])

We even don't have to explicitly convert the lists to matrices:

>>> from Numeric import *
>>> a = lpsolve('get_mat', lp)[0]
>>> a
[[0.0, 78.26, 0.0, 2.9], [0.24, 0.0, 11.31, 0.0], [12.681, 0.0, 0.018, 0.9]]
>>> x = lpsolve('get_variables', lp)[0]
>>> x
[28.600000000000001, 0.0, 0.0, 31.827586206896552]
>>> B = matrixmultiply(a, x)
>>> B
array([  92.3       ,    6.864     ,  391.29282759])

matrixmultiply returns not a list, but a Numeric array object. If the result is needed again in a list, then this can be easily done:

>>> b = list(B)
>>> b
[92.299999999999997, 6.8639999999999999, 391.29282758620695]

So what we have done here is calculate the values of the constraints (RHS) by multiplying the constraint matrix with the solution vector. Now take a look at the values of the constraints that lpsolve has found:

>>> lpsolve('get_constraints', lp)[0]
[92.299999999999997, 6.8639999999999999, 391.29282758620695]

Exactly the same as the calculated B vector, as expected.

Also the value of the objective can be calculated in a same way:

>>> c = lpsolve('get_obj_fn', lp)[0]
>>> x = lpsolve('get_variables', lp)[0]
>>> obj = matrixmultiply(c, x)
>>> obj
31.782758620689656

So what we have done here is calculate the value of the objective by multiplying the objective vector with the solution vector. Now take a look at the value of the objective that lpsolve has found:

>>> lpsolve('get_objective', lp)
31.782758620689656

Again exactly the same as the calculated obj value, as expected.

Using string constants

From driver version 5.5.0.15 on, it is possible to use string constants everywhere an lp_solve constant is needed or returned. This is best shown by an example. In the above code we had:
>>> lp=lpsolve('make_lp', 0, 4);
>>> lpsolve('set_verbose', lp, IMPORTANT);
>>> ret = lpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], GE, 92.3);
>>> ret = lpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], LE, 14.8);
>>> lpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], GE, 4);

Note the 3rd parameter on set_verbose and the 4th on add_constraint. These are lp_solve constants. One can define all the possible constants in Python as is done in the Python driver and then use them in the calls, but that has several disadvantages. First there stays the possibility to provide a constant that is not intended for that particular call. Another issue is that calls that return a constant are still returning it numerical.

Both issues can now be handled by string constants. The above code can be done as following with string constants:

>>> lp=lpsolve('make_lp', 0, 4);
>>> lpsolve('set_verbose', lp, 'IMPORTANT');
>>> ret = lpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 'GE', 92.3);
>>> ret = lpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 'LE', 14.8);
>>> ret = lpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 'GE', 4);

This is not only more readable, there is much lesser chance that mistakes are being made. The calling routine knows which constants are possible and only allows these. So unknown constants or constants that are intended for other calls are not accepted. For example:

>>> lpsolve('set_verbose', lp, 'blabla');

Traceback (most recent call last):
  File "", line 1, in 
    lpsolve('set_verbose', lp, 'blabla');
error: BLABLA: Unknown.

>>> lpsolve('set_verbose', lp, 'GE');

Traceback (most recent call last):
  File "", line 1, in 
    lpsolve('set_verbose', lp, 'GE');
error: GE: Not allowed here.

Note the difference between the two error messages. The first says that the constant is not known, the second that the constant cannot be used at that place.

Constants are case insensitive. Internally they are always translated to upper case. Also when returned they will always be in upper case.

The constant names are the ones as specified in the documentation of each API routine. There are only 3 exceptions, extensions actually. 'LE', 'GE' and 'EQ' in add_constraint and is_constr_type can also be '<', '<=', '>', '>=', '='. When returned however, 'GE', 'LE', 'EQ' will be used.

Also in the matrix version of calls, string constants are possible. For example:

>>> ret = lpsolve('set_constr_type', lp, ['LE', 'EQ', 'GE']);

Some constants can be a combination of multiple constants. For example set_scaling:

>>> lpsolve('set_scaling', lp, 3+128);

With the string version of constants this can be done as following:

>>> lpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_INTEGERS');

| is the OR operator used to combine multiple constants. There may optinally be spaces before and after the |.

Not all OR combinations are legal. For example in set_scaling, a choice must be made between SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC or SCALE_CURTISREID. They may not be combined with each other. This is also tested:

>>> lpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_RANGE');

Traceback (most recent call last):
  File "", line 1, in 
    lpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_RANGE');
error: SCALE_RANGE cannot be combined with SCALE_MEAN

Everywhere constants must be provided, numeric or string values may be provided. The routine automatically interpretes them.

Returning constants is a different story. The user must let lp_solve know how to return it. Numerical or as string. The default is numerical:

>>> lpsolve('get_scaling', lp)
131L

To let lp_solve return a constant as string, a call to a new function must be made: return_constants

>>> ret = lpsolve('return_constants', 1);

From now on, all returned constants are returned as string:

>>> lpsolve('get_scaling', lp)
'SCALE_MEAN|SCALE_INTEGERS'

Also when an array of constants is returned, they are returned as string when return_constants is set:

>>> lpsolve('get_constr_type', lp)
['LE', 'EQ', 'GE']

This for all routines until return_constants is again called with 0:

>>> ret = lpsolve('return_constants', 0);

The (new) current setting of return_constants is always returned by the call. Even when set:

>>> lpsolve('return_constants', 1)
1L

To get the value without setting it, don't provide the second argument:

>>> lpsolve('return_constants')
1L

In the next part of this documentation, return_constants is the default, 0, so all constants are returned numerical and provided constants are also numerical. This to keep the documentation as compatible as possible with older versions. But don't let you hold that back to use string constants in your code.

py-files

Python can execute a sequence of statements stored in diskfiles. Such files are called Python scripts and should have the file type of ".py" as the last part of their filename (extension).

You can put Python commands in them and execute them at any time. The Python script is executed either via the command python script.py. The script files contain plain ascii data.

The lpsolve Python distribution contains some example script to demonstrate this.

example1.py

Contains the commands as shown in the first example of this article.

example2.py

Contains the commands as shown in the second example of this article.

example3.py

Contains the commands of a practical example. See further in this article.

example4.py

Contains the commands of a practical example. See further in this article.

example5.py

Contains the commands of a practical example. See further in this article.

example6.py

Contains the commands of a practical example. See further in this article.

lp_solve.py

This script uses the API to create a higher-level function called lp_solve. This function accepts as arguments some matrices and options to create and solve an lp model. Type help(lp_solve) or just lp_solve() to see its usage:

 LP_SOLVE  Solves mixed integer linear programming problems.

   SYNOPSIS: [obj,x,duals] = lp_solve(f,a,b,e,vlb,vub,xint,scalemode,keep)

      solves the MILP problem

              max v = f'*x
                a*x <> b
                  vlb <= x <= vub
                  x(int) are integer

   ARGUMENTS: The first four arguments are required:

            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) = -1  ==> Less Than
                      e(i) =  0  ==> Equals
                      e(i) =  1  ==> Greater Than
          vlb: n vector of lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
         keep: Flag for keeping the lp problem after it's been solved.
               If omitted, the lp will be deleted when solved.

   OUTPUT: A nonempty output is returned if a solution is found:

          obj: Optimal value of the objective function.
            x: Optimal value of the decision variables.
        duals: solution of the dual problem.

Example of usage. To create and solve following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

>>> from lp_solve import *
>>> [obj, x, duals] = lp_solve([-1, 2], [[2, 1], [-4, 4]], [5, 5], [-1, -1], None, None, [1, 2])
>>> print obj
3.0
>>> print x
[1.0, 2.0]

lp_maker.py

This script is analog to the lp_solve script and also uses the API to create a higher-level function called lp_maker. This function accepts as arguments some matrices and options to create an lp model. Note that this scripts only creates a model and returns a handle. Type help(lp_maker) or just lp_maker() to see its usage:

   LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: Autoscale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Example of usage. To create following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

>>> from lp_maker import *
>>> lp = lp_maker([-1, 2], [[2, 1], [-4, 4]], [5, 5], [-1, -1], None, None, [1, 2])
>>> lp
0L

To solve the model and get the solution:

>>> lpsolve('solve', lp)
0L
>>> lpsolve('get_objective', lp)
3.0
>>> lpsolve('get_variables', lp)[0]
[1.0, 2.0]

Don't forget to free the handle and its associated memory when you are done:

>>> lpsolve('delete_lp', lp)

lpdemo.py

Contains several examples to build and solve lp models.

ex.py

Contains several examples to build and solve lp models. Also solves the lp_examples from the lp_solve distribution.

A practical example

We shall illustrate the method of linear programming by means of a simple example, giving a combination graphical/numerical solution, and then solve both a slightly as well as a substantially more complicated problem.

Suppose a farmer has 75 acres on which to plant two crops: wheat and barley. To produce these crops, it costs the farmer (for seed, fertilizer, etc.) $120 per acre for the wheat and $210 per acre for the barley.The farmer has $15000 available for expenses. But after the harvest, the farmer must store the crops while awaiting favourable market conditions. The farmer has storage space for 4000 bushels.Each acre yields an average of 110 bushels of wheat or 30 bushels of barley. If the net profit per bushel of wheat (after all expenses have been subtracted) is $1.30 and for barley is $2.00, how should the farmer plant the 75 acres to maximize profit?

We begin by formulating the problem mathematically. First we express the objective, that is the profit, and the constraints algebraically, then we graph them, and lastly we arrive at the solution by graphical inspection and a minor arithmetic calculation.

Let x denote the number of acres allotted to wheat and y the number of acres allotted to barley. Then the expression to be maximized, that is the profit, is clearly

P = (110)(1.30)x + (30)(2.00)y = 143x + 60y.

There are three constraint inequalities, specified by the limits on expenses, storage and acreage. They are respectively:

120x + 210y <= 15000
110x + 30y <= 4000
x + y <= 75

Strictly speaking there are two more constraint inequalities forced by the fact that the farmer cannot plant a negative number of acres, namely:

x >= 0,y >= 0.

Next we graph the regions specified by the constraints. The last two say that we only need to consider the first quadrant in the x-y plane. Here's a graph delineating the triangular region in the first quadrant determined by the first inequality.

Source

Now let's put in the other two constraint inequalities.

Source

The black area is the solution space that holds valid solutions. This means that any point in this area fulfils the constraints.

Now let's superimpose on top of this picture a contour plot of the objective function P.

Source

The lines give a picture of the objective function. All solutions that intersect with the black area are valid solutions, meaning that this result also fulfils the set constraints. The more the lines go to the right, the higher the objective value is. The optimal solution or best objective is a line that is still in the black area, but with an as large as possible value.

It seems apparent that the maximum value of P will occur on the level curve (that is, level line) that passes through the vertex of the polygon that lies near (22,53).
It is the intersection of x + y = 75 and 110*x + 30*y = 4000
This is a corner point of the diagram. This is not a coincidence. The simplex algorithm, which is used by lpsolve, starts from a theorem that the optimal solution is such a corner point.
In fact we can compute the result:

>>> from Numeric import *
>>> from LinearAlgebra import *
>>> x = matrixmultiply(inverse(array([[1, 1], [110, 30]])), array([75, 4000]))
>>> print x
[ 21.875  53.125]

The acreage that results in the maximum profit is 21.875 for wheat and 53.125 for barley. In that case the profit is:

>>> P = matrixmultiply(array([143, 60]), x)
>>> print P
6315.625

That is, $6315.625.

Note that these command are in script example3.py

Now, lp_solve comes into the picture to solve this linear programming problem more generally. After that we will use it to solve two more complicated problems involving more variables and constraints.

For this example, we use the higher-level script lp_maker to build the model and then some lp_solve API calls to retrieve the solution. Here is again the usage of lp_maker:

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: Autoscale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Now let's formulate this model with lp_solve:

>>> from lp_maker import *
>>> f = [143, 60]
>>> A = [[120, 210], [110, 30], [1, 1]]
>>> b = [15000, 4000, 75]
>>> lp = lp_maker(f, A, b, [-1, -1, -1], None, None, None, 1, 0)
>>> solvestat = lpsolve('solve', lp)
>>> obj = lpsolve('get_objective', lp)
>>> print obj
6315.625
>>> x = lpsolve('get_variables', lp)[0]
>>> print x
[21.874999999999993, 53.125000000000007]
>>> lpsolve('delete_lp', lp)

Note that these command are in script example4.py

With the higher-level script lp_maker, we provide all data to lp_solve. lp_solve returns a handle (lp) to the created model. Then the API call 'solve' is used to calculate the optimal solution of the model. The value of the objective function is retrieved via the API call 'get_objective' and the values of the variables are retrieved via the API call 'get_variables'. At last, the model is removed from memory via a call to 'delete_lp'. Don't forget this to free all memory allocated by lp_solve.

The solution is the same answer we obtained before. Note that the non-negativity constraints are accounted implicitly because variables are by default non-negative in lp_solve.

Well, we could have done this problem by hand (as shown in the introduction) because it is very small and it can be graphically presented.
Now suppose that the farmer is dealing with a third crop, say corn, and that the corresponding data is:

cost per acre$150.75
yield per acre125 bushels
profit per bushel$1.56

With three variables it is already a lot more difficult to show this model graphically. Adding more variables makes it even impossible because we can't imagine anymore how to represent this. We only have a practical understanding of 3 dimensions, but beyond that it is all very theoretical.

If we denote the number of acres allotted to corn by z, then the objective function becomes:

P = (110)(1.30)x + (30)(2.00)y+ (125)(1.56) = 143x + 60y + 195z

And the constraint inequalities are:

120x + 210y + 150.75z <= 15000
110x + 30y + 125z <= 4000
x + y + z <= 75
x >= 0,y >= 0, z >= 0

The problem is solved with lp_solve as follows:

>>> from lp_maker import *
>>> f = [143, 60, 195]
>>> A = [[120, 210, 150.75], [110, 30, 125], [1, 1, 1]]
>>> b = [15000, 4000, 75]
>>> lp = lp_maker(f, A, b, [-1, -1, -1], None, None, None, 1, 0)
>>> solvestat = lpsolve('solve', lp)
>>> obj = lpsolve('get_objective', lp)
>>> print obj
6986.84210526
>>> x = lpsolve('get_variables', lp)[0]
>>> print x
[0.0, 56.578947368421055, 18.421052631578945]
>>> lpsolve('delete_lp', lp)

Note that these command are in script example5.py

So the farmer should ditch the wheat and plant 56.5789 acres of barley and 18.4211 acres of corn.

There is no practical limit on the number of variables and constraints that Python can handle. Certainly none that the relatively unsophisticated user will encounter.Indeed, in many true applications of the technique of linear programming, one needs to deal with many variables and constraints.The solution of such a problem by hand is not feasible, and software like Python is crucial to success.For example, in the farming problem with which we have been working, one could have more crops than two or three. Think agribusiness instead of family farmer.And one could have constraints that arise from other things beside expenses, storage and acreage limitations. For example:

  • Availability of seed.This might lead to constraint inequalities like xj < k.
  • Personal preferences. Thus the farmer's spouse might have a preference for one variety over another and insist on a corresponding planting, or something similar with a collection of crops; thus constraint inequalities like xi < xj or x1 + x2 > x3.
  • Government subsidies. It may take a moment's reflection on the reader's part, but this could lead to inequalities like xj > k.

Below is a sequence of commands that solves exactly such a problem. You should be able to recognize the objective expression and the constraints from the data that is entered. But as an aid, you might answer the following questions:

  • How many crops are under consideration?
  • What are the corresponding expenses? How much is available for expenses?
  • What are the yields in each case? What is the storage capacity?
  • How many acres are available?
  • What crops are constrained by seed limitations? To what extent?
  • What about preferences?
  • What are the minimum acreages for each crop?
>>> from lpsolve55 import *
>>> from lp_maker import *
>>> f = [110*1.3, 30*2.0, 125*1.56, 75*1.8, 95*.95, 100*2.25, 50*1.35]
>>> A = [[120, 210, 150.75, 115, 186, 140, 85], [110, 30, 125, 75, 95, 100, 50], [1, 1, 1, 1, 1, 1, 1],
         [1, -1, 0, 0, 0, 0, 0], [0, 0, 1, 0, -2, 0, 0], [0, 0, 0, -1, 0, -1, 1]]
>>> b = [55000, 40000, 400, 0, 0, 0]
>>> lp = lp_maker(f, A, b, [-1, -1, -1, -1, -1, -1], [10, 10, 10, 10, 20, 20, 20],
                           [100, Infinite, 50, Infinite, Infinite, 250, Infinite], None, 1, 0)
>>> solvestat = lpsolve('solve', lp)
>>> obj = lpsolve('get_objective', lp)
>>> print obj
75398.0434783
>>> x = lpsolve('get_variables', lp)[0]
>>> print x
[10.0, 10.0, 40.0, 45.652173913043455, 20.0, 250.0, 20.0]
>>> lpsolve('delete_lp', lp)

Note that these command are in script example6.py

Note that we have used in this formulation the vlb and vub arguments of lp_maker. This to set lower and upper bounds on variables. This could have been done via extra constraints, but it is more performant to set bounds on variables. Also note that Infinity is used for variables that have no upper limit.

Note that despite the complexity of the problem, lp_solve solves it almost instantaneously. It seems the farmer should bet the farm on crop number 6.We strongly suggest you alter the expense and/or the storage limit in the problem and see what effect that has on the answer.

Another, more theoretical, example

Suppose we want to solve the following linear program using Python:

max 4x1 + 2x2 + x3
s. t. 2x1 + x2 <= 1
x1 + 2x3 <= 2
x1 + x2 + x3 = 1
x1 >= 0
x1 <= 1
x2 >= 0
x2 <= 1
x3 >= 0
x3 <= 2

Convert the LP into Python format we get:

f = [4, 2, 1]
A = [[2, 1, 0], [1, 0, 2], [1, 1, 1]]
b = [1, 2, 1]

Note that constraints on single variables are not put in the constraint matrix. lp_solve can set bounds on individual variables and this is more performant than creating additional constraints. These bounds are:

l = [ 0, 0, 0]
u = [ 1, 1, 2]

Now lets enter this in Python:

>>> f = [4, 2, 1]
>>> A = [[2, 1, 0], [1, 0, 2], [1, 1, 1]]
>>> b = [1, 2, 1]
>>> l = [ 0, 0, 0]
>>> u = [ 1, 1, 2]

Now solve the linear program using Python: Type the commands

>>> from lpsolve55 import *
>>> from lp_maker import *
>>> lp = lp_maker(f, A, b, [-1, -1, -1], l, u, None, 1, 0)
>>> solvestat = lpsolve('solve', lp)
>>> obj = lpsolve('get_objective', lp)
>>> print obj
2.5
>>> x = lpsolve('get_variables', lp)[0]
>>> print x
[0.5, 0.0, 0.5]
>>> lpsolve('delete_lp', lp)

What to do when some of the variables are missing ?
For example, suppose there are no lower bounds on the variables. In this case define l to be the empty set using the Python command:

>>> l = None

This has the same effect as before, because lp_solve has as default lower bound for variables 0.

But what if you want that variables may also become negative?
Then you can use -Infinite as lower bounds:

>>> l = [-Infinite, -Infinite, -Infinite]

Solve this and you get a different result:

>>> lp = lp_maker(f, A, b, [-1, -1, -1], l, u, None, 1, 0)
>>> solvestat = lpsolve('solve', lp)
>>> obj = lpsolve('get_objective', lp)
>>> print obj
2.66666666667
>>> x = lpsolve('get_variables', lp)[0]
>>> print x
[0.66666666666666674, -0.33333333333333348, 0.66666666666666674]
>>> lpsolve('delete_lp', lp)

Overview of API routines

Note that everwhere where lp is used as argument that this can be a handle (lp) or the models name.

  • add_column, add_columnex
    • return = lpsolve('add_column', lp, [column])
    • return = lpsolve('add_columnex', lp, [column])
    • Both have the same interface from add_column but act as add_columnex
  • add_constraint, add_constraintex
    • return = lpsolve('add_constraint', lp, [row], constr_type, rh)
    • return = lpsolve('add_constraintex', lp, [row], constr_type, rh)
    • Both have the same interface from add_constraint but act as add_constraintex
  • add_SOS
    • return = lpsolve('add_SOS', lp, name, sostype, priority, [sosvars], [weights])
    • The count argument in the API documentation is not needed in Python since the number of elements is derived from the size of the sosvars and weights matrices. These must have the same size.
  • column_in_lp
    • return = lpsolve('column_in_lp', lp, [column])
    • No special considerations.
  • copy_lp
    • lp_handle = lpsolve('copy_lp', lp)
    • No special considerations.
  • default_basis
    • lpsolve('default_basis', lp)
    • No special considerations.
  • del_column
    • return = lpsolve('del_column', lp, column)
    • No special considerations.
  • del_constraint
    • return = lpsolve('del_constraint', lp, del_row)
    • No special considerations.
  • delete_lp
    • lpsolve('delete_lp', lp)
    • No special considerations.
  • free_lp
    • lpsolve('free_lp', lp)
    • lp is not changed as in the lpsolve API since it is a read_only input parameter. So it acts the same as delete_lp.
  • get_anti_degen
    • return = lpsolve('get_anti_degen', lp)
    • No special considerations.
  • get_basis
    • [bascolumn] = lpsolve('get_basis', lp {, nonbasic})
    • The bascolumn argument in the API documentation is here the return value. The nonbasic argument is optional in Python. If not provided, then 0 is used.
  • get_basiscrash
    • return = lpsolve('get_basiscrash', lp)
    • No special considerations.
  • get_bb_depthlimit
    • return = lpsolve('get_bb_depthlimit', lp)
    • No special considerations.
  • get_bb_floorfirst
    • return = lpsolve('get_bb_floorfirst', lp)
    • No special considerations.
  • get_bb_rule
    • return = lpsolve('get_bb_rule', lp)
    • No special considerations.
  • get_bounds_tighter
    • return = lpsolve('get_bounds_tighter', lp)
    • No special considerations.
  • get_break_at_value
    • return = lpsolve('get_break_at_value', lp)
    • No special considerations.
  • get_col_name
    • name = lpsolve('get_col_name', lp, column)
    • [names] = lpsolve('get_col_name', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • get_column get_columnex
    • [column, return] = lpsolve('get_column', lp, col_nr)
    • [column, return] = lpsolve('get_columnex', lp, col_nr)
    • The column argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_constr_type
    • return = lpsolve('get_constr_type', lp, row)
    • [constr_type] = lpsolve('get_constr_type', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • get_constr_value
    • return = lpsolve('get_constr_value', lp, row {, primsolution})
    • The primsolution argument is optional. If not provided, then the solution of last solve is used.
  • get_constraints
    • [constr, return] = lpsolve('get_constraints', lp)
    • The constr argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_dual_solution
    • [duals, return] = lpsolve('get_dual_solution', lp)
    • The duals argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In Python, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_epsb
    • return = lpsolve('get_epsb', lp)
    • No special considerations.
  • get_epsd
    • return = lpsolve('get_epsd', lp)
    • No special considerations.
  • get_epsel
    • return = lpsolve('get_epsel', lp)
    • No special considerations.
  • get_epsint
    • return = lpsolve('get_epsint', lp)
    • No special considerations.
  • get_epsperturb
    • return = lpsolve('get_epsperturb', lp)
    • No special considerations.
  • get_epspivot
    • return = lpsolve('get_epspivot', lp)
    • No special considerations.
  • get_improve
    • return = lpsolve('get_improve', lp)
    • No special considerations.
  • get_infinite
    • return = lpsolve('get_infinite', lp)
    • No special considerations.
  • get_lowbo
    • return = lpsolve('get_lowbo', lp, column)
    • [return] = lpsolve('get_lowbo', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • get_lp_index
    • return = lpsolve('get_lp_index', lp, orig_index)
    • No special considerations.
  • get_lp_name
    • name = lpsolve('get_lp_name', lp)
    • No special considerations.
  • get_mat
    • value = lpsolve('get_mat', lp, row, col)
    • [matrix, return] = lpsolve('get_mat', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix in the first return value. The return code of the call is the second return value.
  • get_max_level
    • return = lpsolve('get_max_level', lp)
    • No special considerations.
  • get_maxpivot
    • return = lpsolve('get_maxpivot', lp)
    • No special considerations.
  • get_mip_gap
    • return = lpsolve('get_mip_gap', lp, absolute)
    • No special considerations.
  • get_nameindex
    • return = lpsolve('get_nameindex', lp, name, isrow)
    • No special considerations.
  • get_Ncolumns
    • return = lpsolve('get_Ncolumns', lp)
    • No special considerations.
  • get_negrange
    • return = lpsolve('get_negrange', lp)
    • No special considerations.
  • get_nonzeros
    • return = lpsolve('get_nonzeros', lp)
    • No special considerations.
  • get_Norig_columns
    • return = lpsolve('get_Norig_columns', lp)
    • No special considerations.
  • get_Norig_rows
    • return = lpsolve('get_Norig_rows', lp)
    • No special considerations.
  • get_Nrows
    • return = lpsolve('get_Nrows', lp)
    • No special considerations.
  • get_obj_bound
    • return = lpsolve('get_obj_bound', lp)
    • No special considerations.
  • get_objective
    • return = lpsolve('get_objective', lp)
    • No special considerations.
  • get_orig_index
    • return = lpsolve('get_orig_index', lp, lp_index)
    • No special considerations.
  • get_origcol_name
    • name = lpsolve('get_origcol_name', lp, column)
    • [names] = lpsolve('get_origcol_name', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • get_origrow_name
    • name = lpsolve('get_origrow_name', lp, row)
    • [names] = lpsolve('get_origrow_name', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • get_pivoting
    • return = lpsolve('get_pivoting', lp)
    • No special considerations.
  • get_presolve
    • return = lpsolve('get_presolve', lp)
    • No special considerations.
  • get_presolveloops
    • return = lpsolve('get_presolveloops', lp)
    • No special considerations.
  • get_primal_solution
    • [pv, return] = lpsolve('get_primal_solution', lp)
    • The pv argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_print_sol
    • return = lpsolve('get_print_sol', lp)
    • No special considerations.
  • get_ptr_constraints
    • Not implemented.
  • get_ptr_dualsolution
    • Not implemented.
  • get_ptr_primal_solution
    • Not implemented.
  • get_ptr_sensitivity_obj, get_ptr_sensitivity_objex
    • Not implemented.
  • get_ptr_sensitivity_rhs
    • Not implemented.
  • get_ptr_variables
    • Not implemented.
  • get_rh
    • return = lpsolve('get_rh', lp, row)
    • [rh] = lpsolve('get_rh', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • get_rh_range
    • return = lpsolve('get_rh_range', lp, row)
    • [rh_ranges] = lpsolve('get_rh_range', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • get_row get_rowex
    • [row, return] = lpsolve('get_row', lp, row_nr)
    • [row, return] = lpsolve('get_rowex', lp, row_nr)
    • The row argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In Python, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_row_name
    • name = lpsolve('get_row_name', lp, row)
    • [names] = lpsolve('get_row_name', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • get_scalelimit
    • return = lpsolve('get_scalelimit', lp)
    • No special considerations.
  • get_scaling
    • return = lpsolve('get_scaling', lp)
    • No special considerations.
  • get_sensitivity_obj, get_sensitivity_objex
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = lpsolve('get_sensitivity_obj', lp)
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = lpsolve('get_sensitivity_objex', lp)
    • The objfrom, objtill, objfromvalue, objtillvalue arguments in the API documentation are here the return values. Note that Python allows the return of fewer variables. For example if only objfrom and objtill are needed then the call can be [objfrom, objtill] = lpsolve('get_sensitivity_obj', lp). The unrequested values are even not calculated.
    • Since the API routine doesn't calculate the objtillvalue value at this time, Python always returns a zero vector for this.
    • The return code of the call is the last value.
    • get_sensitivity_obj and get_sensitivity_objex are both implemented, but have the same functionality.
  • get_sensitivity_rhs, get_sensitivity_rhsex
    • [duals, dualsfrom, dualstill, return] = lpsolve('get_sensitivity_rhs', lp)
    • [duals, dualsfrom, dualstill, return] = lpsolve('get_sensitivity_rhsex', lp)
    • The duals, dualsfrom, dualstill arguments in the API documentation are here the return values. Note that Python allows the return of fewer variables. For example if only duals is needed then the call can be [duals] = lpsolve('get_sensitivity_rhs', lp). The unrequested values are even not calculated.
    • The return code of the call is the last value.
    • get_sensitivity_rhs and get_sensitivity_rhsex are both implemented, but have the same functionality.
  • get_simplextype
    • return = lpsolve('get_simplextype', lp)
    • No special considerations.
  • get_solutioncount
    • return = lpsolve('get_solutioncount', lp)
    • No special considerations.
  • get_solutionlimit
    • return = lpsolve('get_solutionlimit', lp)
    • No special considerations.
  • get_status
    • return = lpsolve('get_status', lp)
    • No special considerations.
  • get_statustext
    • return = lpsolve('get_statustext', lp, statuscode)
    • No special considerations.
  • get_timeout
    • return = lpsolve('get_timeout', lp)
    • No special considerations.
  • get_total_iter
    • return = lpsolve('get_total_iter', lp)
    • No special considerations.
  • get_total_nodes
    • return = lpsolve('get_total_nodes', lp)
    • No special considerations.
  • get_upbo
    • return = lpsolve('get_upbo', lp, column)
    • [upbo] = lpsolve('get_upbo', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • get_var_branch
    • return = lpsolve('get_var_branch', lp, column)
    • [var_branch] = lpsolve('get_var_branch', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • get_var_dualresult
    • return = lpsolve('get_var_dualresult', lp, index)
    • No special considerations.
  • get_var_primalresult
    • return = lpsolve('get_var_primalresult', lp, index)
    • No special considerations.
  • get_var_priority
    • return = lpsolve('get_var_priority', lp, column)
    • [var_priority] = lpsolve('get_var_priority', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • get_variables
    • [var, return] = lpsolve('get_variables', lp)
    • The var argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_verbose
    • return = lpsolve('get_verbose', lp)
    • No special considerations.
  • get_working_objective
    • return = lpsolve('get_working_objective', lp)
    • No special considerations.
  • guess_basis
    • [basisvector, return] = lpsolve('guess_basis', lp, [guessvector])
    • In the API, element 0 of guessvector is not used and values start from element 1. In Python, there is no unused element in the matrix.
    • In the API, element 0 of basisvector is not used and values start from element 1. In Python, there is no unused element in the matrix.
  • has_BFP
    • return = lpsolve('has_BFP', lp)
    • No special considerations.
  • has_XLI
    • return = lpsolve('has_XLI', lp)
    • No special considerations.
  • is_add_rowmode
    • return = lpsolve('is_add_rowmode', lp)
    • No special considerations.
  • is_anti_degen
    • return = lpsolve('is_anti_degen', lp, testmask)
    • No special considerations.
  • is_binary
    • return = lpsolve('is_binary', lp, column)
    • [binary] = lpsolve('is_binary', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • is_break_at_first
    • return = lpsolve('is_break_at_first', lp)
    • No special considerations.
  • is_constr_type
    • return = lpsolve('is_constr_type', lp, row, mask)
    • No special considerations.
  • is_debug
    • return = lpsolve('is_debug', lp)
    • No special considerations.
  • is_feasible
    • return = lpsolve('is_feasible', lp, [values] {, threshold})
    • The threshold argument is optional. When not provided, the value of get_epsint will be taken.
  • is_free is_unbounded
    • return = lpsolve('is_free', lp, column)
    • return = lpsolve('is_unbounded', lp, column)
    • [free] = lpsolve('is_free', lp)
    • [free] = lpsolve('is_unbounded', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • is_infinite
    • return = lpsolve('is_infinite', lp, value)
    • No special considerations.
  • is_int
    • return = lpsolve('is_int', lp, column)
    • [int] = lpsolve('is_int', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • is_integerscaling
    • return = lpsolve('is_integerscaling', lp)
    • No special considerations.
  • is_maxim
    • return = lpsolve('is_maxim', lp)
    • No special considerations.
  • is_nativeBFP
    • return = lpsolve('is_nativeBFP', lp)
    • No special considerations.
  • is_nativeXLI
    • return = lpsolve('is_nativeXLI', lp)
    • No special considerations.
  • is_negative
    • return = lpsolve('is_negative', lp, column)
    • [negative] = lpsolve('is_negative', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • is_piv_mode
    • return = lpsolve('is_piv_mode', lp, testmask)
    • No special considerations.
  • is_piv_rule
    • return = lpsolve('is_piv_rule', lp, rule)
    • No special considerations.
  • is_presolve
    • return = lpsolve('is_presolve', lp, testmask)
    • No special considerations.
  • is_scalemode
    • return = lpsolve('is_scalemode', lp, testmask)
    • No special considerations.
  • is_scaletype
    • return = lpsolve('is_scaletype', lp, scaletype)
    • No special considerations.
  • is_semicont
    • return = lpsolve('is_semicont', lp, column)
    • [semicont] = lpsolve('is_semicont', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • is_SOS_var
    • return = lpsolve('is_SOS_var', lp, column)
    • [SOS_var] = lpsolve('is_SOS_var', lp)
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Python matrix.
  • is_trace
    • return = lpsolve('is_trace', lp)
    • No special considerations.
  • is_use_names
    • return = lpsolve('is_use_names', lp, isrow)
    • No special considerations.
  • lp_solve_version
    • versionstring = lpsolve('lp_solve_version')
    • The lpsolve API routine returns the version information in 4 provided argument variables while the Python version returns the information as a string in the format major.minor.release.build
  • make_lp
    • lp_handle = lpsolve('make_lp', rows, columns)
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
  • print_constraints
    • lpsolve('print_constraints', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Python (Windows) this means that the output is not shown.
    • The same information can also be obtained via lpsolve('get_constraints', lp). This shows the result on screen.
  • print_debugdump
    • return = lpsolve('print_debugdump', lp, filename)
    • No special considerations.
  • print_duals
    • lpsolve('print_duals', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Python (Windows) this means that the output is not shown.
    • The same information can be obtained via lpsolve('get_dual_solution', lp). This shows the result on screen.
  • print_lp
    • lpsolve('print_lp', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Python (Windows) this means that the output is not shown.
  • print_objective
    • lpsolve('print_objective', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Python (Windows) this means that the output is not shown.
    • The same information can be obtained via lpsolve('get_objective', lp). This shows the result on screen.
  • print_scales
    • lpsolve('print_scales', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Python (Windows) this means that the output is not shown.
  • print_solution
    • lpsolve('print_solution', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Python (Windows) this means that the output is not shown.
    • The same information can also be obtained via lpsolve('get_variables', lp). This shows the result on screen.
  • print_str
    • lpsolve('print_str', lp, str)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Python (Windows) this means that the output is not shown.
  • print_tableau
    • lpsolve('print_tableau', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Python (Windows) this means that the output is not shown.
  • put_abortfunc
    • Not implemented.
  • put_logfunc
    • Not implemented.
    • However, the lpsolve driver sets a log function to redirect the output of lpsolve from stdout (which is not visible in Windows Python) to the command window of Python. As such, all reported output can be seen in Python. How much output is seen is controlled by the verbose level that can be defined by set_verbose or can be specified in the read_ routines.
  • put_msgfunc
    • Not implemented.
  • read_basis
    • [ret, info] = lpsolve('read_basis', lp, filename)
    • No special considerations.
  • read_freemps, read_freeMPS
    • lp_handle = lpsolve('read_freemps', filename {, options})
    • lp_handle = lpsolve('read_freeMPS', filename {, options})
    • In the lpsolve API, read_freemps needs a FILE handle. In Python it needs the filename and thus acts the same as read_freeMPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_lp, read_LP
    • lp_handle = lpsolve('read_lp', filename {, verbose {, lp_name}})
    • lp_handle = lpsolve('read_LP', filename {, verbose {, lp_name}})
    • In the lpsolve API, read_lp needs a FILE handle. In Python it needs the filename and thus acts the same as read_LP.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not provided then NORMAL is used.
    • lp_name is optional. If not provided then no name is given to the model ('').
  • read_mps, read_MPS
    • lp_handle = lpsolve('read_mps', filename {, options})
    • lp_handle = lpsolve('read_MPS', filename {, options})
    • In the lpsolve API, read_mps needs a FILE handle. In Python it needs the filename and thus acts the same as read_MPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_params
    • return = lpsolve('read_params', lp, filename {, options })
    • options is optional.
  • read_XLI
    • lp_handle = lpsolve('read_XLI', xliname, modelname {, dataname {, options {, verbose}}}
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • dataname is optional. When not provided, '' (NULL) is taken. '' is taken as NULL.
    • options is optional. When not provided, '' is taken.
    • verbose is optional. If not specified, then NORMAL is used.
  • reset_basis
  • set_basisvar
    • lpsolve('set_basisvar', lp, basisPos, enteringCol)
    • No special considerations.
  • set_add_rowmode
    • return = lpsolve('set_add_rowmode', lp, turnon)
    • No special considerations.
  • set_anti_degen
    • lpsolve('set_anti_degen', lp, anti_degen)
    • No special considerations.
  • set_basis
    • return = lpsolve('set_basis', lp, [bascolumn], nonbasic)
    • In the API, element 0 of bascolumn is not used and values start from element 1. In Python, there is no unused element in the matrix.
  • set_basiscrash
    • lpsolve('set_basiscrash', lp, mode)
    • No special considerations.
  • set_bb_depthlimit
    • lpsolve('set_bb_depthlimit', lp, bb_maxlevel)
    • No special considerations.
  • set_bb_floorfirst
    • lpsolve('set_bb_floorfirst', lp, bb_floorfirst)
    • No special considerations.
  • set_bb_rule
    • lpsolve('set_bb_rule', lp, bb_rule)
    • No special considerations.
  • set_BFP
    • return = lpsolve('set_BFP', lp, filename)
    • No special considerations.
  • set_binary
    • return = lpsolve('set_binary', lp, column, must_be_bin)
    • return = lpsolve('set_binary', lp, [must_be_bin])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds
    • return = lpsolve('set_bounds', lp, column, lower, upper)
    • return = lpsolve('set_bounds', lp, [lower], [upper])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds_tighter
    • lpsolve('set_bounds_tighter', lp, tighten)
    • No special considerations.
  • set_break_at_first
    • lpsolve('set_break_at_first', lp, break_at_first)
    • No special considerations.
  • set_break_at_value
    • lpsolve('set_break_at_value', lp, break_at_value)
    • No special considerations.
  • set_col_name
    • return = lpsolve('set_col_name', lp, column, name)
    • return = lpsolve('set_col_name', lp, [names])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_column, set_columnex
    • return = lpsolve('set_column', lp, col_no, [column])
    • return = lpsolve('set_columnex', lp, col_no, [column])
    • Both have the same interface from set_column but act as set_columnex
  • set_constr_type
    • return = lpsolve('set_constr_type', lp, row, con_type)
    • return = lpsolve('set_constr_type', lp, [con_type])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_debug
    • lpsolve('set_debug', lp, debug)
    • No special considerations.
  • set_epsb
    • lpsolve('set_epsb', lp, epsb)
    • No special considerations.
  • set_epsd
    • lpsolve('set_epsd', lp, epsd)
    • No special considerations.
  • set_epsel
    • lpsolve('set_epsel', lp, epsel)
    • No special considerations.
  • set_epsint
    • lpsolve('set_epsint', lp, epsint)
    • No special considerations.
  • set_epslevel
    • lpsolve('set_epslevel', lp, epslevel)
    • No special considerations.
  • set_epsperturb
    • lpsolve('set_epsperturb', lp, epsperturb)
    • No special considerations.
  • set_epspivot
    • lpsolve('set_epspivot', lp, epspivot)
    • No special considerations.
  • set_free set_unbounded
    • return = lpsolve('set_free', lp, column)
    • return = lpsolve('set_unbounded', lp, column)
    • No special considerations.
  • set_improve
    • lpsolve('set_improve', lp, improve)
    • No special considerations.
  • set_infinite
    • lpsolve('set_infinite', lp, infinite)
    • No special considerations.
  • set_int
    • return = lpsolve('set_int', lp, column, must_be_int)
    • return = lpsolve('set_int', lp, [must_be_int])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lowbo
    • return = lpsolve('set_lowbo', lp, column, value)
    • return = lpsolve('set_lowbo', lp, [values])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lp_name
    • return = lpsolve('set_lp_name', lp, name)
    • In Python, when you name a model, this name can be used everywhere where lp is specified. This to access the model via the name instead of via a handle.
  • set_mat
    • return = lpsolve('set_mat', lp, row, column, value)
    • return = lpsolve('set_mat', lp, [matrix])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows to set the whole matrix (all rows/columns) at once. This is the most performant way to provide the constraint matrix. Consider using a Python sparse matrix for maximum performance and least memory usage. The matrix must be two-dimensional.
  • set_maxim
    • lpsolve('set_maxim', lp)
    • No special considerations.
  • set_maxpivot
    • lpsolve('set_maxpivot', max_num_inv)
    • No special considerations.
  • set_minim
    • lpsolve('set_minim', lp)
    • No special considerations.
  • set_mip_gap
    • lpsolve('set_mip_gap', lp, absolute, mip_gap)
    • No special considerations.
  • set_negrange
    • lpsolve('set_negrange', negrange)
    • No special considerations.
  • set_obj
    • return = lpsolve('set_obj', lp, column, value)
    • return = lpsolve('set_obj', lp, [values])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables. It is then the same as set_obj_fn
  • set_obj_bound
    • lpsolve('set_obj_bound', lp, obj_bound)
    • No special considerations.
  • set_obj_fn, set_obj_fnex
    • return = lpsolve('set_obj_fn', lp, [row])
    • return = lpsolve('set_obj_fnex', lp, [row])
    • Both have the same interface from set_obj_fn but act as set_obj_fnex
    • In the API, element 0 is not used and values start from element 1. In Python, there is no unused element in the matrix.
  • set_outputfile
    • return = lpsolve('set_outputfile', lp, filename)
    • In the API description it says that setting filename to NULL results in writing output back to stdout. In Python under Windows, output to stdout it not shown. However it results in closing the file. Use '' to have the effect of NULL.
  • set_outputstream
    • Not implemented.
  • set_pivoting
    • lpsolve('set_pivoting', lp, pivoting)
    • No special considerations.
  • set_preferdual
    • lpsolve('set_preferdual', lp, dodual)
    • No special considerations.
  • set_presolve
    • lpsolve('set_presolve', lp, do_presolve {, maxloops})
    • The maxloops argument is optional in Python. If not provided, then infinite is used.
  • set_print_sol
    • lpsolve('set_print_sol', lp, print_sol)
    • No special considerations.
  • set_rh
    • return = lpsolve('set_rh', lp, row, value)
    • return = lpsolve('set_rh', lp, [values])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows. Note that in this case, the value of row 0 is not specified in the matrix.
  • set_rh_range
    • return = lpsolve('set_rh_range', lp, row, deltavalue)
    • return = lpsolve('set_rh_range', lp, [deltavalues])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_rh_vec
    • lpsolve('set_rh_vec', lp, [rh])
    • In the API, element 0 is not used and values start from element 1. In Python, there is no unused element in the matrix.
  • set_row, set_rowex
    • return = lpsolve('set_row', lp, row_no, [row])
    • return = lpsolve('set_rowex', lp, row_no, [row])
    • Both have the same interface from set_row but act as set_rowex
    • In the API, element 0 is not used and values start from element 1. In Python, there is no unused element in the matrix.
  • set_row_name
    • return = lpsolve('set_row_name', lp, row, name)
    • return = lpsolve('set_row_name', lp, [names])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_scalelimit
    • lpsolve('set_scalelimit', lp, scalelimit)
    • No special considerations.
  • set_scaling
    • lpsolve('set_scaling', lp, scalemode)
    • No special considerations.
  • set_semicont
    • return = lpsolve('set_semicont', lp, column, must_be_sc)
    • return = lpsolve('set_semicont', lp, [must_be_sc])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_sense
    • lpsolve('set_sense', lp, maximize)
    • No special considerations.
  • set_simplextype
    • lpsolve('set_simplextype', lp, simplextype)
    • No special considerations.
  • set_solutionlimit
    • lpsolve('set_solutionlimit', lp, simplextype)
    • No special considerations.
  • set_timeout
    • lpsolve('set_timeout', lp, sectimeout)
    • No special considerations.
  • set_trace
    • lpsolve('set_trace', lp, trace)
    • No special considerations.
  • set_upbo
    • return = lpsolve('set_upbo', lp, column, value)
    • return = lpsolve('set_upbo', lp, [values])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_use_names
    • lpsolve('set_use_names', lp, isrow, use_names)
    • No special considerations.
  • set_var_branch
    • return = lpsolve('set_var_branch', lp, column, branch_mode)
    • return = lpsolve('set_var_branch', lp, [branch_mode])
    • In Python, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_weights
    • return = lpsolve('set_var_weights', lp, [weights])
    • No special considerations.
  • set_verbose
    • lpsolve('set_verbose', lp, verbose)
    • No special considerations.
  • set_XLI
    • return = lpsolve('set_XLI', lp, filename)
    • No special considerations.
  • solve
    • result = lpsolve('solve', lp)
    • No special considerations.
  • str_add_column
    • Not implemented.
  • str_add_constraint
    • Not implemented.
  • str_set_obj_fn
    • Not implemented.
  • str_set_rh_vec
    • Not implemented.
  • time_elapsed
    • return = lpsolve('time_elapsed', lp)
    • No special considerations.
  • unscale
    • lpsolve('unscale', lp)
    • No special considerations.
  • write_basis
    • lpsolve('write_basis', lp, filename)
    • No special considerations.
  • write_freemps, write_freeMPS
    • return = lpsolve('write_freemps', lp, filename)
    • return = lpsolve('write_freeMPS', lp, filename)
    • In the lpsolve API, write_freeMPS needs a FILE handle. In Python it needs the filename and thus acts the same as write_freemps.
  • write_lp, write_LP
    • return = lpsolve('write_lp', lp, filename)
    • return = lpsolve('write_LP', lp, filename)
    • In the lpsolve API, write_LP needs a FILE handle. In Python it needs the filename and thus acts the same as write_lp.
  • write_mps, write_MPS
    • return = lpsolve('write_mps', lp, filename)
    • return = lpsolve('write_MPS', lp, filename)
    • In the lpsolve API, write_MPS needs a FILE handle. In Python it needs the filename and thus acts the same as write_mps.
    • No special considerations.
  • write_XLI
    • return = lpsolve('write_XLI', lp, filename {, options {, results}})
    • No special considerations.

Extra Python routines

These routines are not part of the lpsolve API, but are added for backwards compatibility. Most of them exist in the lpsolve API with another name.

  • [names] = lpsolve('get_col_names', lp)
    • The same as get_col_name. Implemented for backwards compatibility.
  • [constr_type] = lpsolve('get_constr_types', lp)
    • The same as get_constr_type. Implemented for backwards compatibility.
  • [int] = lpsolve('get_int', lp)
    • The same as is_int. Implemented for backwards compatibility.
  • return = lpsolve('get_no_cols', lp)
    • The same as get_Ncolumns. Implemented for backwards compatibility.
  • return = lpsolve('get_no_rows', lp)
    • The same as get_Nrows. Implemented for backwards compatibility.
  • name = lpsolve('get_objective_name', lp)
    • The same as get_row_name with row=0. Implemented for backwards compatibility.
  • [row_vec, return] = lpsolve('get_obj_fn', lp)
    [row_vec, return] = lpsolve('get_obj_fun', lp)
    • The same as get_row with row 0. Implemented for backwards compatibility.
  • name = lpsolve('get_problem_name', lp)
    • The same as get_lp_name. Implemented for backwards compatibility.
  • [costs] = lpsolve('get_reduced_costs', lp)
    • The same as get_dual_solution. Implemented for backwards compatibility.
  • [names] = lpsolve('get_row_names', lp)
    • The same as get_row_name. Implemented for backwards compatibility.
  • [obj, x, duals, return] = lpsolve('get_solution', lp)
    • Returns the value of the objective function, the values of the variables and the duals. Implemented for backwards compatibility.
    • The return code of the call is the last value.
  • value = lpsolve('mat_elm', lp)
    • The same as get_mat. Implemented for backwards compatibility.
  • [handle_vec] = lpsolve('print_handle')
    • Returns a vector with open handles. Can be handy to see which handles aren't closed yet with delete_lp or free_lp.
  • lp_handle = lpsolve('read_lp_file', filename {, verbose {, lp_name}})
    • The same as read_LP. Implemented for backwards compatibility.
  • lp_handle = lpsolve('get_handle', lp_name)
    • Get the handle for this model from the models name. If an unknown model name is given (or already deleted), -1 is returned.
  • return_constants = lpsolve('return_constants'[, return_constants])
    • Returns the setting of return_constants and optionally sets its value.

Compile the lpsolve driver

The lpsolve Python driver is called lpsolve55.pyd (windows) and lpsolve55.so (Unix).
This driver is an interface to the lpsolve55.dll (windows) and liblpsolve55.so (Unix) lpsolve shared library that contains the implementation of lp_solve. lpsolve55.dll/liblpsolve55.so is distributed with the lp_solve package (archive lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). The lpsolve Python driver is just a wrapper between Python and lp_solve to translate the input/output to/from Python and the lp_solve library.

The lpsolve Python driver is written in C. To compile this code a C compiler is needed. Under Unix, this is the standard C compiler (cc/gcc) and under windows it is the Microsoft compiler from Visual Studio .NET. or the mingw gcc compiler This compiler must be called from Python. To make the compilation process easier, a Python script can be used: setup.py (setup64.py for 64 bit OS)
Under Unix, make sure you have enough rights. Possibly you must be logged in as a root user.
To compile and install the package, just enter the following in a command prompt/shell:

python setup.py install
or
python setup64.py install

and everything is done.

Under Windows, the Microsoft visual C compiler is needed by default.
Unfortunately apparently there is a test that the version must be exactly the same as the one where Python itself is build with.
However it is also possible to compile with the mingw gcc compiler. For this, create (or edit) the file C:\Python25\Lib\distutils\distutils.cfg:

[build]
compiler=mingw32

The python folder can of course be different.
Now run the python setup.py install command again.

Note that liblpsolve55.a may not exist in directory ../../lpsolve55/bin/win32. Delete it or temporary rename it such that lpsolve55.dll is used.

To create a distribution package, enter:

python setup.py bdist

Under Windows, use:

python setup.py bdist_wininst

Install the lpsolve driver

Under Linux, the distributable packages is called lpsolve55-5.5.0.6.linux-i686.tar.gz
The contents must be expanded to the appropriate directory.

Under Windows, there is an installer that installs the Python lpsolve driver and the supporting scripts lp_maker.py and lp_solve.py. Just run lpsolve55-5.5.0.6.win32-py2.4.exe (this installer is in archive lp_solve_5.5_Python_exe.zip).

On other platforms, the lpsolve driver must be compiled as described in the previous section: Compile the lpsolve driver

Don't forget that lpsolve55.dll (Windows) or liblpsolve55.so (Unix/Linux) is also needed for this (In archive lp_solve_5.5.0.15_dev.zip).

See also Using lpsolve from MATLAB, Using lpsolve from O-Matrix, Using lpsolve from Sysquake, Using lpsolve from Scilab, Using lpsolve from Octave, Using lpsolve from FreeMat, Using lpsolve from Euler, Using lpsolve from PHP, Using lpsolve from Sage, Using lpsolve from R

doc/IDE/0000755000175000017500000000000010762557070010701 5ustar renerenedoc/IDE/IDE1.gif0000644000175000017500000007010711247323477012060 0ustar renereneGIF87aw,! !&&&!(1101!J! Z1 Z18B1$sixr!y!AJAJQZY{aZB!J 1B81R(9Z8JRA!{a!HGHBIRBQZRQBVUVRQcZYsZiscYJcYRdbdeissiswrt (0!&!01(10!410181EB0B8B8BIBIBYBUZIZSBaReRqRiRiRykigq{yZVkYkc{iki{i{q$$3399DDss1{cx{cccss{{Khxai!q!A)I1Q9yqIJQJSTacycy{uwaJqckƊ֌!111ֆs֮RֶsBBRRcs猌眖眜Ɯք瘦画ޭȥ޼Ƶ޵ǔ׽޽Ƽݬޖޞƾަƾ瞌瞔쫜鶭ƶDŽǔϵτ܄ǽץƸXF=0qۻ*\ȰÇ#JHŋ3jȱǏ CIɓ(S\2Q5P͗͛8sɳϟ@ JѣH*]ʴӧPJJիXjӜ5KٳhӪ]˶۷p3Qɛݻx˷߿ LÈ+^̸ǐ#KL˘3k 87ΠCMӨS^ͺk}M۸sͻ Nȓ+_μУKN{νËOӫ}˟Oǿ(h& 6F(Vhfv h~"h(,0ƈ/db8㍜;)d?(8 @PF 2ViXf\v饄bΘdid aj)tzß (i衈&袌6裐F*餔Vj饘f馜v駠*ꨤh&0ETꡱ%Jkz'g&ZĒC& {BFˬ:[춈n+z{(&kmv,~z9L:Y#lNIpNp+,SÈ֊(tkJ*/KFmNJK28|r/CD\4ڻ)PG-5+q7+0<09iqbųs1@)r7~< AЂtjԠ=BAC "&zذ [9YMoJ3L'hF;GQuaM([; tv#HuG(cYv=_˰lbKXv,^"}_ +R_#͂E-c#ZѮ,eY6mmKҒv-fK.VukK:ЍtKZͮvV{BbO)WWt=FIrO ]|+tVJR%.m<ػ&p |;'_M#S&/ ×p}J(N1Wb /0eL8.'@ XHN2$;KL*[Xβ$/`L2;fN6p398:xγ9AYπ4L@΃rlF;ѐ'MJ[Ҙδ7EsӠGMRԨN5=VհgMZӚ>w^MbNf;ЎMj[ζn{AuMrNvnxyη~]{O;/8!N[ϸ7n9t=y<"?Krg-wý=i|5ˍkߜЇNtj{<׾yϓ7K'vԏraO彾:Inut;=EN]}`̓ek]f9ۿ ug}n;^>:Ծwwqs+~U:#g:#or#߼;?z'N/zГ3k@?YF `F P EH@lp l0ehy lٖn ȑjWwQ%Ʀ"$ssk,k+F`AJٍ  JW6>Dpvel lol9ؑ& ĆƗ~ɒ"&ɘ)1 A` ᘏɌkR ܰ k陿 6X ĆcОcll)¦{fytl)l'IG9ɜ&ʸkR0ېڠ )l0Wky<`Z;\б\:֚:Z*lWj*CzȤ<(rکQ;Rxb : (kh`Ʀ ٰ@ t:   lYYU@IPC0vK V:zpBjڲ2k4z]i,sIɋxs tcuiyhƤL~{/& kI@BpA;P<ȍ\ſKj[qG_kbj<<͸ћfyImn@B=D]F}BJ'xP՟kL]VpN-Z^`b=d]f}I}j<O}I)b\=t}]mx |Tւm#P Ձ=o+n؃p=ٞ}؋-o}vP 3 @ֆٚ [SۿM)ǹ"Wu͎)mmϯ}ܽl  ׆ۺ  ]{}M`eݺ)f,ܐݟp 1 }ޝW ܺޗ$1),r >ޜ~<) ŀ\')ޥ3p0n{}n1~˾䏾F]PPu "/5>=uEoP'%O&_5_P*o500 ' * g36*VDNM.`_46&'&/r7?)-.y߉tn/j5  14p_(_WkROުn_鄻o'O,oPl{_r$޺S޹`h?jP?_>bG4(p%KNe NmܘOE6Dؐ Ò'>K1eΤYM9uOA%ZQIT)x*Wc~ M+sS!?ۃ- 0w“pB +B 3pC;t6hAK,ʺC1KpFs1ӣQ=E%X 5´+"w2UJ,rK.K0sL24L4TsM/ J8 ŨTlN^trO,FO>TAi\PΚ`sRJ+RL3t2SP[Ӻ4UnRUuUV[uUXcU=YkV\5W^{mP_JN5XdUv+1XhISZlv[n[pw\r5\tEzu]x㕗KPF^|w_|G] Pw` 6ݪjva#x؝b3֘RqZp韷>瀠u:ˮqW}z^}y~`fPԫJ (&p^@P/ac+Ac`=X1z~HhBP~}_ ]BP5qCDsh N{d_G 6eELD(} +o3bE0ȸCXF>k\Fdrp`f J.ױ D;R4c/ yH\$" FF2Td%-yILfRd'=IPR$e)E9Frq<$6/ 1b@=ωK(JP eBЃFThE-zQfThG=Qp LzeH)ZVpR:;wRTXiz'Pozԛ# =hBԇ"4RiUzUfU[E? BU, A֕UϘ@kTwJP:}a>iTjȯ'\ "vUelcXFle-{YV4aS=T@^y6_%DzVJldm{[V]'[W'DR ]RZ>jc T{Z۽nrKV%oyu K']-#^Mjw׵.1_}J5o |`n|19^'ЍtO^BfwE X#&qM|bX+fq]bX3qmwTp̫ @AD45 ,T;AKA?&@ A>&*A. B |d4+žJCB-d@2A.C7TCCr3˰;q|"3D C |BB)C+E0AB*Ec< ,OQDTcĝжz-K,DDM4^\DǃW$- EX7OE ;+3/:SF4ƉbN|'gT@+FfF Yo4p=z3S#H3|ŋtGD1H",wHKH|Ē,GH KxyHSAjI,AHBF$ȠD@K2I|¯Č Ft԰ ˮ"Eʆ/a|zɡpE1\VUCICɛ\Ƶde4D ,H)3ʑCJۺJsK/Jt<]`eL`v ` ? N]12Xm]>,_aTKba*_+b\?G+N(b@`bf ^``9.ͺF7v '!M=mbcBN- cA `:cFFdD6/N.d3&c:NMGNG>JcEdJadv"XTAF2BRNeIn0νTa\]d_J>ₛ8{ CSM93V^u룄6^N.=l#l5]MlŶkGelu0Flʖ6Z[MՎhTP~Y66Mm\(j35@m"~k>f &0,y ᦺR,GHLT[nͻ&`mLI PMP3ȓ$PPzĺ{mFo.fo.7.`ޮNJ p̰J^ɖtn9]6DpŬ,] /Ԃnn8O⸛e E\/wTUGV'WuBYZ[S^?_`dbb"^?pKv[v?g4cvGt\lhheZSTt;ZC5ntsFR_Vf]؆٪|}Y`%Y 1x]+w|w6tAuWb=-;Vx8 xoUZ[pµx"dz:zVgXwV ZyvxwOx5_Dw^xHU/-Kׅz{yը7tQ{/{?{O{_{o{{{{{{7{olpVOz `x_Xy >zk[Yw'|=yUXeZ;t~p,yyǧW }ݰ/ͣA:ZX Vڃ }Q6ӯgt5~ Vk׉@wĹd=@u_w/&,h B2l!Ĉ'Rh"ƌ1+Ȑ"G,i$ʔ*Wl(z@i<6g!y/-j(ҤJ2m#J%H*֬ZrbǏNǒ-2&O5qUfЭAҭk.޼cVCS]x¯3nbX'IS-[o}J3ТG+` D=DzgӮ52w^֙YZ.n8r%|p⃱Y;qڍ{;x3$óo~/K!סlE{gyف\(%VR"^jh !-}]A7]b"-b$ Dvx-\$G"HAdK=8Xs9gYj%A0>$ը`[e$eA4dRH&EI ()M>d}\ :(\y|j7o7x'gv@tJrt&H*E %x:+thC79ZMjЃx wdjƆlʦZXkq6zy-x[9 @!lIFk!*7)G|2ky[Ѱizj(]ذv0)0B , )F䮞-EZ \Q{ZuP*;c,rҟŌnzƛv{Oiyoա-M)qH691V8ͪ;6s~WRDx]7:6^nD?l9Acc1^9]3z>{17蜟;WgDO#:A8žKO7ndbo}Eo~8)?R? ]>s~}߯9 0w`(@ D (/% Vy~FQĞ7KPp Ұ !wP-XCِ;!HC#KTxD&oK#, _™OrYb`4'χ$cD)>{Hl F5h4GQ8.02/odz]cGEG#݈FHIaXIqr:d7GMF %8FdY Y)l l>d$XDMҒm_$xLR%1752",JU%zѼg=;s)LSe9D ଠ:v`.Ch0Ubl ~T4ڔJM$t6U4^C zd?&=)JSҕ.})Lc*Ӕ>,4U8q >H%*ԡV?UINJN%KP*թ"ĨO5IR7J6^mS-oGձu VH:Ƈl͚h}k ugZ7µѲ\*Xy7I} *r`P+-E>˿>t#mh%"ٯRv}2[r^cΘslDzFd^m a ۨ6.n9D=mGZ!ƽ*rK徕 <+M]P9>NQt/7ׂ%' E{ϓ499_tx"}jxV^ռ,.iGaVfcÿ!.y6tI9̇<ةɄ)T +433]#')&ep ^wӇ#$KBS7HuSKr?n?4'̽u&%8_Yc.[V3/k$b)beD/ټ:[YrcLy$ִ9f.tΈ5ph8 ]7쯀ӘGu9X]Sݖg(J'8 fI^G `)vox17H=WwPmn־Эn+ٷhu \7Iɢ{8#.S/j]mKkWzt,Ixpv GnvC浪O=Yn%7 ;tLvɵt}R:ӧkY/9׻~ruӞ2T Gپ;]Mwzw}sǻem!?x}[j>5WC k.wﻹnt/]G z':eNj=wdh᳈ u{tZ)O!o}ͷ=I_?Ga~H;[⓿P(C֋G}~DMy+bXב]յYezօ~` Ʌa$[^ >ưUk` ŤYzLgO!!P ^` Bc`&j<\zNIxVT`QaF!ab DaYu!A - 1!aTuቴa"^ i$BG:ގ !abF#B*b+ja-N +Z.bϹ"S V(b(U) bja^3*"/b,>'.,Bf/ڡ5bqz\W%,Z,22";.-ʣ2c>5R0^S1::z:n+b>ҢB"d-*$>U8#>n 5cBcd4 ld"`#q;F"/ "N+BcJc*c"&_5fK`GΒG]E`JNROZO˄ɨ$P%c%+%ebDŽM@eHZYV2΁\ S eЈ%Jeᜥ^FZ.R٢, t%ɵ| |] YN^Nfc%!%fI\f̲Ѐ`>&T%Pj~efj `vPgiFed%InE,2"QoLfBDp8NV9"VaqfΦg pfn& W#7f`xg xMk~k#tG`G c&u"ƌ朔fv2PgL.FxgBgrPgݛhb\'b'R$އ̤;b4xc~#.K%$'k-(xcFjZw6$?b=f#;Rw 'J^B,/bFOs!4nʊ)lz*hmX7:%*ii`D)zN)xUi (ni4ќCNd#pb=fcK2i;:"ViOU6*RT)mXL2*$DjjBrѕNj M(j *Kh䡪toVcjFLUl\,N.ǾDzȆ^,ɚPʪY˾O,UҬNO,.O mmN*-18Ӣ쵎n-v~-؆؎-ٖٞ-ڦڮ-۶۾mצk IN m^ZR*&M-Pߒs+.^k". !JnnJzaf#v.~..rnǕx(Lb^a nb !FD o(.an!Ƿ(2/1:F o`jhG5hƩp~4nv.:J"%/%¨ڇ~Ljp$0+\rn癣/I;0H[KR G0 pZ6jpp0 G 0/00pư0 /M p ;0 k?,/c'J1o"oq o~݄IJ nVqqPˆjwJ0 OZVV!3Zj#g[$$S2^2e rr'!r(grmrr1*(' )r#r,*+S-1.rr0,L-#3x(2'(11o.4Q0OV3Z0f!W2rz"9k93: :.8s1m^:X@-;;/Zo"$Dj6]39ŝcIjyZk(UGm$:*)"Lvcctk+u=YuEZ6'F$,;sk"/icOxaYd{;;w;vmg;Qph뇼)F*[(hao{>wP#Z*y+<VoҺB%j{ggz͚U{T<_<:#sg=b|$C o=[8e"EtՃU8nxzAw+ͻ,k}EۻcQ=X}{LT~P~ ~+$ŧEn8{@~*gIkוc9]y>}>ķMWSҽz>>|~<@:S_>Zq_UC|;zu ?>i<6zOzat϶w/(ósiփSy $8aB 6t%ΫXѢBRG 1%Ǒ&YNTRG!\8]Lu'uۇ}f}~وw? {'N.z6ܓ^ͦ>)ftſ?߫~t3џwg?z_-_u#?,&k5 )2=s  ~ЂAuv TaQ.HBR̄CVXC9LW _7C8}@TD\tH۔HA&:*VW EuOEHF7ˌCcqFnG? ƲMs$N8>< *7EJ#ɔMҍ%1HMR`$@IFQ1)Jb+̒ópi1]f[%`L iŬ1L-37D 4{&MQӉ֤6'01Mg)As[O(C "w UC1к^"6'oh42 ƣ턨HYjJ+=]KQ'j*:O/S5 ,rsWU 5EYUɕԫ-*WN//niZWΕdu=^kN Y~%!`G&؜ݕZk,Ŏs, ٤M`e3هmk@/抴4PK>Ӱ |-b6aQm_ZV]o ff[]^vrp1MK/y[_Rsk_r*~G70f\020% H v׆9Y7qH\b֞81ΊbG2ֱ`h-ߘdqX3̿ټ9SA21dYe/a\f3iVf7Slyg;yr{Qu(- ]hCщVhG?ґ)]iK_ӌgYeI]jSթVYjWֱi]k[ׯ;-,Y]lcVlg?і]mkKmo]nsVt_m"_ico Wbp08N,z7{VqمI^1vYr=(Q]^sC9rs\9ʮ۲[IWBҩ^u6~ 5uYOvN],xq^w{=y; N'Wʧ=yx|Ez7W$Oy[/iyӾpy{ԯ[^y=O>|/?W~}K_W<.|_e϶s#ڿO}>ӟ|4Oo\(/O/?2pCP9aSPW[U^PpkCe{oGr4v0 [p 33, P P ǰoRNP א P-[q)z?Mc1aC*/3Q7;?CQGK[ ^Qgюna!a5$WWqQ!t1}1wXQV?S&by1c1NZq 'NQ!Un T` 1PtV!3R#L@ ,&+rf7R%WE:RfBa` QQ%w'#$oR{(6ֱ M2'/2%*2-$Q*+*"e),R()Q'-'*--+.{2.ݑ./2/1ÞJ sJ_')lc21B,H#2!6S3/O:4Y0ESF.Ă4s55E531mVs2Ks,bs-s155_34(36K3`38S5YsF@73kENvn+U<9a7:s<]3>c=a>sFn9S??s; 49<_6~S<379?tEM6s7AtNtFeA3:kt6E5c8 b*533GtA=5T9BmAT)XCIH?J/FݢD3{S7_tI?u4<4\")22TE۴BqT7T=qLITAS1H{NtC7CTO5PIWIKEPi35tKN@{Nas?9GtDuT=etP4TW?a2ٔBKkVN44TE4ZTHCT@]u?O5J=S!uQW5uYuQZY95ܔZ'UZtXZ3YAuLURXZEXL{REVUV];>[>a]QPu\YW1`!ZY1bs[[U`/aP67U[UUS5O[ Wtf_=cteC_Z 6ZSA`qh9cYaE6Ad]14Y3cf#6h=vS'6ickPQVNUŶc5V!}LS7]]6:V\4LUjoon45pL5XT4ŕGqsFIGW۔dpFWXttdj۳p}Zw6up#pE+wJE7_60ARixwSZyxrOwy^/ۤ{z2{wBW||iu|W=Qi&i57A!baÃ{6ge)~)rDwqaԇK)v/5^U^}raD8UYN]7uK7-vQ8iU54_sUtXin{sSgUe-M5TXjUHkZEflRgkvhxYQ58t}Y#jP_urXW/kYr717[L;5l/0u6ovM%6sQ@􊻵ouY`eY_3[isIy#?bCYc֐CEeVcy+َ3Yd9Nmys?eXvd9/ϔY1֔?X?oauMُs=s~5ء6#yz%t;qkwXu7X[ZXpMJa3׸o67SwkTTI?T{x{7wtcV.㖄XQWy'ڭ嚮z:1)R!^TD -;mzr%7DIEv WxDL,%3Zn@5ɇ2ϊ+Uw%UjOY\Zr[XDx^X_g8rEmKX5JxDcuUݻ؀8w[S~m9q{7uciצ%1{)eV/zǹL#?yV]YVْx ڷAzgA7\甒ZYIkٛS5Ȯ?uٲ':56[dCdW f“<ʏVWYv#@-{9i)8kQr{ɷ՗ɳ9vUǫʱZӵ;zۙiɥͭo9s}^QTsXW׹p~;|y4[ނUIS=@YMXۨSum|j =ԹQ]7eٹ]H1K#͝Wi&NsM93ҥL:} 5ԩTZ:֭u;zY.ZxԪ=+lHtD#ޙw/ƾ nɒi.WpQ +Y`-_T|3e|8pӨIf׈-kYɚX{ <]r5lرeM:d[yog˛?>}Z+ZϩU|~H`8 {]}sf5_[ tfaba[fb"H" `|E[c2Hc6ވo'2H[HdFdJ.Ԏ܊kIL^eZne:bQt/zfjf#:Hqgz0%) diԆQ}8"b蘢(5uJzU^$yY㦾 )z(j{ *di6j~[^AFۮ5Ԥ#i߰;-*MZ]SJx6[wJTU~ĪX>tBBq]n"KN>AŻovRmoB*{0cskΊmqȤN۬fɫ5n|, Xˆ.vma2(kƲ=+m2ЇJ+gRBgtFdki! >̯m/57-睶owmݓlx6E波I$om'.G9][6HGJX }'\ƺ䬇]:2okm3:z]3ǎ[ׯh脖^%Bߟp{.ٶs.|_yS>=]}[x%.x5Oۿgl-Ft~9M#\Bm/ L:yC z4O:r6Pß M"^_e9M\!Έv*1k8>1®jyȬHMqg fW#3 aAYƬ16uG=r5]zǼXm CDTb:% <ջQ+gSj+C5\r@&-tKcG+_Ct4eJsԴJ4yf~Pæ7 p)ڄU/ljts,'/Kvs' 6.Ӟ?Y |2l"Q2P~@ @S)nv.9 ji:PC EFQTzEgχtlj Ɠњ*LIx)Qfi2%)v8.~gZ(U2#t;@+ʭHRyˍ; %9&ɲ 03eUQjRծ8NN7SrU@^1f|IO'9jZ Y+ DuxE&Q՝Y"4rajV,ڞ$BR~Mi@@L,"n-*Piؼ&׸mmJ~yؓKtZӊ4 ߖ]KYE9, 7o wpkZ6ya٧e4gXDVǹO?1}׼'b!ͭbs\* e{^e>њ۰;bX"b y8S4U^F!u1Jkn/toL7.S>,7eG^98M:sYdN[+ʥul6h$5^Ug1R듌,0I~TV~KM;Ҷ.e}Ș;& i驅h{5{s&LOfqyݍn;ٔn=plƼ'i{{ ?coE  mFT?Nk8܃ >[M/'3^|D/щ_|ZD-#RSԏޥW'R/s],C9Rceھp駄hA[ 5Wu@,Vv ;^oֈ"ޫ$dO~/KwϱmJԓ>٘&40欰MS&JXwijd򞕛J.>aw_hgI 4._nݦFqv~%_9CWc@~DTedBx}tge^eG4@Z&m kYf|6D_Q=8]2~=ghdIWE\l`âbG17+>m#71evn}WBS/8I?ӁJQφ _L;c7-f8g{F9Q$6Hy=&VceAuvJ^&b`g>v]ȄwH?(x]vh66h=X}SHdCH\|chG6H]xt~r5cdž$')JӖiӗHX#Fjyek&jY&ld|vv>TjAvuEml1sG9jj8HsWPP?hPZҀhttOL1BuRՎX*Honܖ}8ۘIF00 qIY0 yXp(I%ɍ(ng/ @ 3Аɒ'Q=ɑ (\J#hvx Ք+!S7g+)gQy8[&H]y3Guy姖 b 6\jFaycQC;DxmE9Oztڒ Y1f?-Gl[ZefȢI &VH奘VduZ)gZDٵZ{JaZJ8:(4hXXIJxksz̈^јfjlǧiͶkT:L&LjʪŊ:':?)M#Ȭ|ƔA*LcTuӪ˚7:*犮DYMzJZMj:KDxOZuS1RUaRM1§XHLy gX$] CVyFDK8V %{4fjyGv ղIet^CٜΖ}|4}$kHY|ٹlęY٢+yF 蜪i`:dZyC'ED82+f8z^_hK]YgꖃSxKC oۮ}}88P9kz MĘ J-Vap˯XY\[|`l&&1Igo|#blpLu\Ji$S|v}Px'~Lȅr<ȋ|\0 ɐƔڱə  i ǗɥlS* Q,b|ʳLM30e ˀ9˿T l̳ll0\$˃Lۼj|͕,|ͣ,vly,ɼ BLfΨe  Ol  -Mm !-#M%m'),n,-3My*9;=? A-CMB5.xHHPSMUmWY[> OԞGMg[!]mo q-s'`t"L[Q= 0ؕt؋؍؏ Z= wa"`20ֆm00 =щ٫ڭگ ۬*pxz`&`mm=30 =3p-Ѫ $=۝Mɕ}yZ  V-]ޣPRpހ)+ 05 0=?c ǝǶ٭OQ0eT [ݶAa.c` }}/׾q.s WMnsz. :N.sm^!~'L.烎陮>Ԗ =en~7]jKMdQ빮h .Nnǎɮ.N- mLB .Nn/Oo _m:.6?!/#O%o')+-/1/3O5o79;=?>/O< IKMOQ/SOUoWY[]_a/cOK?E|moq/sOuow{}/O|{/Oo{A/?ovl/Oo/Oŏɯoj/Ooirwa}ޯu)n< DPB hp`A VcC=*|HcČ/V\Jy(?SL5my:=ٓɒ-YD4IMTU.ujTbK ZEUkSeVĒ*2mlZuޥ3{ ] ?,Ulb ;5Un6G+yk+r3ZВ3wFZUA,jϞ&J;gxm ގ<-4eŭ_M> -ݔ'o,-|A]xrO?u[/?@z'z-@l;ϣkOB?"<6 DVO/,1>41FA{QƆ(3Q&G,%? ıTt<2H+5Ԏh;ÛJp  R cˤȖGޤC4 V$QM?cLP@'F2 ?cM; + +(דSO|S<5%M,kSJW]P/od4cVYm 5uWvK_51MhV]ŕY[E6 VAWzPZy[V]\Jն\ue]w߅7^y祷^{7_}_8`&`F8afa/'b/8c7c?9dG&dOF9eWfe_9fM.tfo9gwg:h&fbF:ifi:j}yj:kkk&lF;mVm߆;n^';o,o/~_?ߜG@_ѧ6 ؿ Ѐ̠"D+(B2 KhB Z0#̟@8̡w@ H"HƑ&:Q [HqL|KbYw\hE}wHȇ0zkc1>pP}:SșnB 4! 'HЏ= !Bޏ1l%9". 7̤(#I,gIZ%Pm!,I9 ^2ax4 ,49:8FҹtsT7IyӞg=O}3?w4Bυ6t(B#jЁ Tu>P>G#QRԣ'HҖ0LgJӚ8ͩN]:rPʂݐc OԢ1@ժA*8Xzg=8̤e(<-Oԭ+=(G'ZҴlkEIP֕{=:ה.TmDVԯbIؼuͬf7z:UnUO@*0DKZ3Ajmmwˌs,kC94 DV*WQe\KO&5K:׹#U'sX-,rFW҅oeӪ]aQL`S!D{ |N_Ϻ=ew8mN \kwp]^;~o'|;񐏼waYwm~w~]<? 7='ֻ蕿Wuc~kG{xVօ?pU|XȁG~#8xX{؄2|}hWX'腉r>'Ghvvr mq(xX1(،s8X֘ڸnsqy׍8X8+g긎؎ 8X V r8(y(oI)؍!p-p{|7fDw44` (0# qlmV @ 2y 0 6YXo`oǐ Ion7oKoyI9QIo}viЕ^`b9dYfy4ogٖni) .F @ FIop o0 Y YICE9y1oSo!zl& ]9Yyi o Y 0ol wYpМ9oK9oPi o?٘vIT FiHyVH)9oU)'Wyonٟ94 Y9I9oU0ְ ۠  o9 [0epepoIə91 )|hoɔioOɔ){#y9iH*J * V Jp  @ v X@dЦdV Џ&֢ oS)4*~5ڧoMo?oEzN:9P`pZ@o  0 o ;nf7`jzo_on0v ox:ozj|ڙ)L9RB}p}lQٚZIC5Mjʎ :Zoʥtگ6 `:`GbJ % ouɚoZ*JJYoAJɉrr8voʮ0*T搜  Pz 0 {p H@ /P VF=7F%^oYf)6:2ZF;ʶz`zg{k}˭e⺚j+TF 8刊lPK@;؀ {` 3I s[WF@\_pcof[hkojt n9v|(}s|l;-\92`[s > o@ F P`oY@ @ ((-0>p%  _dK Z㩶o NɼGȋ7'Uiy ׻tUo0 o p$poXпs.>n  9Kûu gx*ۺ]Vtnp0o@`íp=L@P+@ħк(R 99żUl rƎ'xջɊX[o|ʁxG'o1lwplz`u0v8] 9pPmɼ;o\q́w\}y\G'Ψ<e

&)n7q=v}z"N a* fh  2 ;~2k.֬hr.(9'0{1PPO~*^v~P-00 l`Y*h>,' lp)B>hI봞z^IoK{">n!>캾 qiG)^ y] 10 PNfNnr~~0M^|^_ 쯉qϞ @1@! k^y* llﰉ>^rE^砎:onu.Hn]4N2/#<9ZE @`2@/1:*n>L.`%TsT?TB~^]HMTiW//LE1 ( +Z4zmnۀ?T2_)o?T(/[KnʏoZ_B4Ń'#B8sp* p%0"E/^(G,#YI)UdK1eΤYM9uOAm #Wh=E9\%N5GN7zdWYYWlY`;<=k]ѪKYKNfTyX]9~qqؐN$+,B@`+(b:+"fkرeϦ]6NI&])Vn*b{eغv0ٵox"qď.t[;O,rPƱDn J$cnT@TpAt"g7z{/"j*-#@1<Q"hE3EN"X2 M<1)ɪMI_~VH[lJ/2B,rK.܌'2ɴPȉj898fM>Ӽ9=S :` 6ZQ\\)4+RL3tS)1?=7?KtRTJOV[N0b%oSSR24 &x7I[RNUvYfuvO? QClEcUnSJQ[m E̓*b8a@#Udw^z뵗h˜L_x` 6`Wv;-Aa# 'bwc;|A4a$3dSVye[vdcekfsyg{gzh6hVziW.+t%Yajzkk{l6l~zdKNm{nn{Sm|p 7pW|f{ddr+r3|s;sC}tK7tSW}u[wuc}vkvq\ZWq~x7x}w}{7w~Oz~{_wQ}G~}w}no%_{/|ϻ_%P d ԧ"i,KՒAW]#$a MZ;`EwdX,:܋nxB QC|Q z@KdbD(FQK D\QSb=,~QF4b1c|bF8ƑF6t|ZC^͏8XCV Rdd#GǨ/qSdiȵJ0} ? Ntd)MyAp)?XHNbZ#&hH\ɕe/})7UJis%ob^z,]RӤ&ׂiDz yD uRoe&IN4uNlcg=yϝLyu\!+͓x3:Nd7:DhE-zQ{GI6"D1zRT]64r6QӐԦ8i9VSUi0b CJ߻TFUSjUzUfU[jWUE]RZVVSkek[Ug]qWU{k_zU%,^[X&ְelaXFV;+]JflgYφmgE(YԦ֗-egzliX6moW W׺֮e,iXU`O[F]p1\ͭ^5]zt7Ůt{ R׬r}xvj_s_OsepWMxW.p7`/H};L.X n\bfq_W!ޯiXJ 1wSXCj80^Gd ~U_"gY˅32Zeo70F}3wf8߭ugLS>n|?q&t6jw1lf 6,z0\CgZaCt{Oo6~s7}jT_H5`[WH7MumUգݵ^K _&v O׮^]gfӦV{ۖ^mow}nsVwnw߮vok [6'9l}{gxõπwx] qD 6Z\Ǹ6qV[S1YN|3Gmcȏ)^yzNs 9snj˳&G]C_XщgmR-sG!_5w]:o-r_{ vr*yٽ\Z&cK|OxWbKNG^&=u~[fzЧW}]8[}i{}?B^ï[Nz#౱}dV2_[S|==Phy<cɍg_'cKg:C5,2\C7$639C4|C<8C> =@=A DBDC,mCET5+$0,̾EDCID~DKjDM~kd@OőDROO\>O=Om=+P<M[P<}P8ЬІЯЉ GP@QzDQTQ%}ѨQ:љQ9ъQm8 RR"D=R4R%7&mMLR('bR+B,K)R S1-u.]25L2]uR76S6=PSxS<-4=8S?}3@ ԇSBA=!KTE8CmgdTH0IT TKGTTN MOT UQ=MR-UdDNdEABb\YdIdJF1JdOdddP>eTNe{eR^SVeYeZRBWVXe_e`V>B]>(^fe^ffa!.Kxkfflfnfofpdnfr.gs։gKں挸wgyosg|HgZg|jx~xflFh.h^hh{ghrg\䎀gh~mmhkh^iev@nAj֊؈q)!(i9OfPXhS jjD~ikh ikc!0i iik[&BZk.eBNlŶޚo+^lɞljlW̖ly쬁dm.m>mNm^mV-RS+b4ڮL\ mmmnn.n`܆6^t@nw@ ZmnNnnmn&+&Znk-&oF/f6 nomo)FSyX"nEoXX/FVpnpK 7p X-_PBa._+'g" . q& S$Or%~Qrr+0gr/2r(6gyÑs Jsn =: sŻj2s9C:A@/?:/{vkP,JwtB< ;9@TTtӋSUt=tukFLF'Ms ZR'[O[X/\?; ;j׻VV]Ycu!:v#A?\jva$cB쀡OtW}Na_takw}_xQtW/t@'f$lxw` Hi_Lwv89?fovxvBtuwSzyVr6$_@ogm_zw~oy{/z\#y?`~zW@@ WzKg'vbz\? f z{IG?q 8 x 7Yzg{z%Xkj!zH 8"%߂e5 zo%zTxmx#9#=)Yhׄwd!$QJ9%UZye|BUy-Fd3b9&ey&i9+vid셹uy'y'mr1)#|z(*(~t͙hॕjgz, { M**PٸwBj~6YaoRښt_Ef۵C]eݲ8ZݥN}+ 调*&}4U]Uk,ڋkAqb+oR+u;R%&q=5X`h)_'/\L\"eırZA5RLZq<|0%\¤Rh|YSJG$Tǜ`[uJR۪ڮLnK1ovռ}$j'Ґ0Be=xNլU6=n9R+uy^T>ppo.יt|}m7讋0lnp⣂iÞ~z`iKz$l |ZNFTl+[_>&VMŜW[qpDe?`LggU.ka]JY(ˬvEv^˺yѻ\&9=ɂ]lj%PTt-[!n0kj.jI/s@)˵zvֶlE_ݞк]s( Z'rVw.L"Z˂ ! |F[a[]bXTwC^v.F%̯R"C?lJȜۢv0Ʋ!אS{dyR*k2O)sƴr83*PEأ~j!hf=-=Jx3(F:*ъ4-=kʫ9&tqV%SU'e5c-k:Zg]zMs-aז&6w$i]٣463)d gPB[=$N:|ô$^lU93u]" u,&jJ\53uzwӠ.W+:Vyn&yIz*Xtr*@Xlayܔ.fk_mX icзR]K.|gBuPꨥğ[EQO2%(N0x֝Oj[ӽ6;kFWWBwt͖ЕFup2?x/Os{衃~%k [ģ={#cF~Qq=+f7795㐱LdFLb잗d+XǷSgZL)}͕ɬxUU{ɏД_OmrCQ ՓL$6FN^`U n Zv  +} `~ _ށڇ0`-!\Yt BԅĜ ` O zHܑQ Xae `-Xoy ^5! ƛ@؅Z-_:MWSe(a݄Digޖ4]ݡ\eZ] їEiaAMɗ)B] ] ٔ""t_VT& !]H]bĖ&f!pJ"m!UPTb" \)&265r1cإ\_!TDmai!`y1>E#=^6 cٱS~BXczIU}evPtHAI!b(bsyoEK3Zc,6RT>(&$)mؿcЕDOO;QGfiG↭zJB=u!2ثeMV#A֜!D66m˽ՃeΥ$Qa+b1 cv O $QV1c#e aMm8Q&$:=dv _¡JbJbfd&DY b &g%J~sޟi rӶ1gD n'>i1"U#wyvz'{'|"{'}''MgXrڧ*dT'p'!@E x|}Y&rZ ԃb$P%EIQoyh0cсF"t ( FTFƼX]Z )Iҡsb+%c& \uWFx$Ɲb]].je%2&n\I,YJQi恓gYY }ܕfia"7])K)L:N_%W5!p%%]VzjCNUVj._q)E&nt?έ&(n`HƙbόQQ6B%4.'n*ң$>+W%SMMҥqSYYFn#ZNecF)7kp(V(píu$ݡv݄qkޟ>]Q#~ Rqݿދe$ N'멪:",Y.Oˎ\% (X(lul}ј=:PemOji(q$&Xm"ln-ւgjن&Ya۴•*bcobKզ߯\E988\Zy Li~8ZCJ.7P:~.&e)qn~YC7n7nҭ..'>J.*(f.'n//t&o//.n &BoίeEZpR+Ih.^/(TBICJ#)Wlk6p;!iGhJ _ gpfNb0fT5-f_6B \YKPނVhV m2 pZ2~,\v}K3N"j4%]:$rh&!Z"+Qp\%P ͆}⩂V+0pkp.XMs9evkD%Aek?n'SBޗTّ^jT$Ħ@J_0W(ƑKj,EM3_*9dm0ϋBs +R3!5c7vXE x(Lpb[;fu]]CXfvY`av[96l'FdBe_vV&ℂY;TKw8:vt<|vh &nC=<`sxK&6aӀahn2)"s*swwQ~!ZT(S.{{+#6|`+2̉hqw?Kb%1Uh49f+*\e^n0$O-k-MT(w97t^'8͆CN^V,WlwNd 錭i[%aFrA9L8tbA[yIr;䗢Kc9*-?rV̌ni7,94V:սC{"+9 @dC#e&3wy#iv5z| CQ 攺!?"O7i3 Dk2aϩa^j;c<69pɣAp\sByk=l&Y{e~ɮVٓt|t"M_bxgYuu Ukݾ-o"+֚>j!~dkB2Eb{l//slv|`ԖGZȿ|<6߼<}|==vc0kO: pҷOs#5~aԓi=:0||/U}f}:~׉<̚*^.k7T$}|=4eDc| Si.ĿTθZIxķ0r@fUjL1Bxx*yL/ӟ 6c{{ :9?>Oy*k4*W;=S:|j铡:ط8Jo-::dn= .a.xD= 4xaB 6tbD/ͳ#8pݸqһzY( ez)SHrbLg.)f4yBgœ?{Qwt:P)T@iReHTjOA:1VTXˢmVZMo^{_? l@ˏD+ AP@P 9L«RnC q,mLB@ 2@$ēc 2li,k.02tH0l1%μO<=@4|7<1)׫H%I-L5T;CL't42H9=TU]V]@uSFUzWuݕ^}@ceQEkSRs f}hbCVSnpY/mMv}^v=uӟyELOey!pa b$cu2%-TbWX&=t!M>cP}9mp3P`y[8碍>Sw9_Z}xhꪭSME:dY쾺Zkg~Fڐzݸޛo禛k 8C%[n5BOM?&\]emuߝ}?_y-s5'IwO~F?_?vY/ޢ赥9w1g X@ T@>)XA ^`'?Q)W?Z; YB1 iXC:h7ǁp1 s$p Kb X""P9XE+^Y58`y8O8xp(H@5EyG?Y<#Ce$1N`: D1JHO~(IyAiziC@ t\\H 9[̥(ryZG'KYLcTf)KQ{dW`J<._js2YNs`= {A3{Ҝ^=gJdrH7OӟJЁ hGƩN>2ݘBч8k0HIZRe('(4bR LiZSԆieȠo}%IUjROndQ,dS^YjwO34%YiUZVU\ZWB=z`[U'/͌u!,< {\f9YrI'hI[ZӞUjYZ׾li[[ձ{<[^rUr&ѕt[]^v]~x[^Uz^|[ָ s_d \Sx=P`?)\a _9a!I\b)VYbk2i\H-%ycA\d#IVd'?Q\e+ڲe1e1\f3iV3q\g8yֳg?} gAщVhGYpRz|hJ_И47i6[ӡ3E]jSՃJRjRzүe=kF֊uyk_/zw=l?zFvlfϖ0h6,h G>mnۙ Ŝmv;N ol{63gn{O}{ Wx]#| O3n1./7-m"5-^pyg.G7^i7<)~r޹|G>y7>c|5n|5'W_x;_п_i۾_GoNpRO -"do NR-mm<N: 6.%nkPCXܔ0脐 9pp U 0 L ǐ  P א PPQ Y#Q'+/3Qp7?CQGKO%S[_cQgAqksQw{oπhQQQǑQבQ R  !R!!!"#R"'!;doc/IDE/IDE4.gif0000644000175000017500000007155111247323703012057 0ustar renereneGIF87aw,! !&&&!(1101181989!J! Z1 Z18B1$sixr!y!AJY{aZB!J 1B81R(9Z8JRA!{a!BABJIJBIXBQZRQBUUVRQcZYsZiscYJcYRdbdeissiswrt (0!&!01(10!410181EB0B8B8BIBIBYBUZIZSBaYhZqRqRiRiRykicqix{yZVkYkc{iki{i{q$$3399DDss1)k{scx{cccss{ai!q!A)I1Q9yqIJQJSTacycy{uwaJqckƊ֌!111ֆs֮RֶsBBRRcs猌眖眜ƛ͜ք瘦画ޭȥݼƵ޵ǔ׽޽ƻڬޖޞƾަƾ瞌瞔쫜箥維ᄉƶDŽǔϵτ܄ǽץXF=@0q\*\ȰÇ#JHŋ3jȱǏ CIɓ(S\Ra: \2͛8sɳϟ@ JѣH*]ʴӧPJJիXjݹ [ÊKٳhӪ]˶۷PKݻx˷_` LÈ+Koǐ#KLz3k̹1MӨSװcF[O۸sͻ Nȓ+_μУKNإJä{Ovӓ jć˟(޵w!@d'h& 6M:VhVI nhc(≞o!4H%<@)dM#ΑH&HӄmE2)N;d\v;˘dIhf7 n 'dftީrgvg9yΙ'F*I碈::~R:i 碊Byjwb꫰*무j뭸eNa&c&,$09̴ X,R{ֳ'Ц辙z饬;*oJ˫Λn*;7/+WlgLv.'ɂC,8K..#Ă߆;n=k *4Hk M{2=J[u s^k,dmٯ:ll-32| 1쀫z3Ό32(O pXO ) {)B\р [j^4/LNG5m'|s<'7vR=8[cb+~/~_?ߜG@_ѧ6 ؿ Ѐ̠"D+(B2 KhB Z0#̟@8̡w@ H"Hȡ&:q [HErL|KbYx\hE}xH؇0zk1>pP}:SșnB 4! 'HЏ= !Bޏ1l%9". 7̤(#I,gIZ%m!,Љ9 ^0G̜ ӌȃ4? 359:8F ҹtsT7IyӞg=O}3?w4Bυ6t(B#jЁ Tu>P>G#QRԣ'HҖ0LgJӚ8ͩN]:rPʂݔc OԢ2@ժAj8Xzg=8̤e(<-Oԭ+=(G'ZҴlkEIP֕{=:ה.TmDVԯbIؼuͬf7zB:Ăoeҁ`jڨ6miM@,ȭp{emY9'FVrhtJ*ӕkv}ixVw.\R^}.uk^7lZË_~=u7:^N`*Ý2qOuPEawZ8(Gd%Wc Ku`1K"HNA&` <Xβ,?鄱;-A2JN6oLgaB ʳxoYπV)OЈNhO@u+J#Ȗδ7YY GMPAtWS g N@Ӹεw^i=LbNf;ЎMj[ζn{6MrNv6zη~NO;'N[ϸ76zm GN(OWgN8Ϲwx'샟{x>g</[>Op+x5.z|~gO/wϋ]o;o´rz>v_>?|G}_w}﷾}_㷽~~G~7|cg}X}7}Wz۷whW* ~xhqW~v؀~ ٧} '}Ǘ~7ǂ6؀ׂ؃>3x2H~C8h8'&x9!QhYwx b8dHB(v4xiappTqx5{1(uCPeXgWG\Ȉ#}8 8L(T~h槉}H}؉(|X{؊e('XXtmW*qNj''ryH%WG̈s،XF֘ڸ8{؍86x䘎긎s(s8qXH`o)G؏Hr)Gcg qz7x yot@"I&r *  m0o` p Г\XFr9I)Gv#& f o^0 dYfyhjlٖnIVctYm 'i)o59qNPm No0o`I @GyoٙKɔzx~Q7oayoEyٛVyYyɐ  Y&K&?0E0goo)ٔoYƕr6V9ZIY` ڛʹ؜Vxpp ۠ 0 ڹo0\o=CpP.ZǞ鞣I 7SfS Pz Q oU@ ۠ڠ Po0Zo'z=+o@tJ_ p2oo469Yʣj?GgrǤNZڠj OzXZ I^oڰP Pv ֦pV^^gcЧ9ٚYo:ښ⇌xw7w劅6 Z40T@J:o񐪪ڪcZ|0[|o0VЫp$6B]P]ƧaGi('|J7pXzI8;j`گ٠ P P  `H`?=pk<^P^|ڶo ۞)ۣo;*sۨ?ʲ}ו ^Wf*ڳФ@ˎlڰpo P J Vo\@\XpJ`D0rk׶|(kYv*'Njxs-cI2`ˏtE kpP M+* PoYP P (P(->p,  _ k ʬ";p%{U9N87'\ ٟ.+ ,u00;Upo@ [pҀ $oX0t.> ,u q^:Nt,&yr.vKNL7C Y-no . P _ns]r.]Iyқsr nR^-w'\^>ݐ{9 30 bmns0r^^u~CBhRn~Jv v뻮ǹ m[~).+sҾ.߸E L j襞4뷉z^޳n.'~ʅ >ݸ P4`B >n>nh>ΛNo]DP~oz~J|X~nNX.@`2P$?1Pmvr>1OMLnLTs"TACϼdW?TRϮ[T4P  _*Oow)mBU?C>?B%iEbTȎz]UZCE2dDwNN^ɑp J"EJ%z!E$YI)UdK1eΤYM9ua 7T谐 !Sȸt)ƍvԚjJ'F$P8ze Ы:V+֭oV\z]w<`)ߋ\OawV便fP{תp,ȟUfkرeϦM3ѢF~適?@+i\-ʍjvd[p3W_ŏyկKXp*G̾|v;V:ʈ 4@TpAʨrrj7¦ o /PD -C4/DP무BaTqsF /K4"LI&ѻGK6&*_ZAB s qG1otL4TsM6,Qg9):=O@$ UtQ!ϳ$0HkrRJzhNsSaQR5MTSUuUV[Up:3V;$DKuK*1R`wF+5&/q*8x".L\v[n[`uV:kU^\@Ev^z-*b8aA>wSx` 6x5q$Τa#xb+bxc;XzC>K6Vye[f9aYcUg^kfsyg{gYdhVzivizjjz`VgA.zl6lV{mvm{nv;no|p 7pċ[fNq#|r+r^|\k3}tK7tSg{s;qaW}vkvsWi}oЃ~xu7xW^=޿v/!髧zs{^v_~|7?>mτ.?~ן=°1:4z/~@F^ 0D3@1P|$a Mh> w CV@P'aH>xD"THj'$bil!b$\$=BqE,YE01^"H+QkdE8nxG`ͶHcB$?NzA.7[dp0b ~p^3\5&[@QotW\᩽]n@%~C|!q')'Coߐ((o<6 NzHGapizn{VWGIzt/˱^uo8a^v7|p{Ζg(50o60R߽9/~[ N}n9^o=Sw+/{||G8Mkz_= -Z݆I|$GU}}]a_;w2׾*{ϟs`ޒ #O 7~2KD[˸sL 1{,@y@K[@ 4 \ 9tVCD (`L],aL,8E;ı[?[] +(4dD3,Fg$n3dFps+˫;F<]A@D'GAE*Zr|C4CUu4TCiGj3RDR$FW\HDŽ$' D~DƃDEO„Zv\{HFkA)cɎIULStȡ۱I%zBlbH_|4AJQ\dIqč¯FJ$3K440yûA!KG,4LYKJğKK~J9?Ɍ7+TƼHˣ̛̔LΤG2>d˘&ͷ#D,,L ьAEMM&a;̓@ԔȚl<4cA`4LNL ALJI|MڄZ#?NO=R$EP4U'0MR&\Nm+QyRdR~Y'*]S SM'uP(%\eS;x%6m#7m#D\ y]ӲiJ«TITJTKT!}S*GՎ*K-US L+-,eKtAmL/4MR)u#DUPE%F+R,(:Ub-VcT껷U!O}TPmcVHV R@DjCBke=N9-[re?^)r+VkWy p-N8=z`PVTWcW]V--=9JWYW(rWXuefv V*+XSXQQlS_b":FBٸib/%}>1Z2١U%ǃ]̄%`+E+XzLMVu=ZZ][@Dc[5@XLOʊ%Vl{e[ĝں|zH\ ϫ̬mԏ%Yj%]Í\u߼J5^)v͜-\]ϳ$c6\ O aa~_bS!"#V$ac&'^(#+.-)b0^1_VEc 5670ݢ:b'c?F=b$MzIdJd:GNd_Z&cCKc5E-ڥ=&e0eDG+gI^4TVeeeueA* YFZfGdiD]$I9DDf]d3acqKXfgC&hFiej;ACm>?nov"IȂAX 6stuLH.eD|œÕgYN-FtfRtP\i @,dhv㘆K]KETiHLj΋ed)k h= l!H.HjJƮd>Cgɮffᗤk[e|Ce.kNVfp8 oeͶ雮޸Ƌ/_d^-]eL,9ppoe놔'f,qFF$lGv6 og>qn|qgJII}s)/n9riq6cHnzxrgŎgI8IzL+†D.68'7s?$/q*q~ʠHJ7F|mlFy t u~̮!1sH~siJjo uǾd׆m1W?.inez14rNvqu%3kv.pZ\MnutIA_mT,}i~L||wR7Elj@l_5)?.ItlNw ?|gFUurVx'Cur vj^?DtsdfkDxx&W,d&^_?=y DvofzlxDzQkgozE?oYpVzoIyxa\p_Z;W6ʹӤEknyc&DV{bnŸ~VvWqwo'!mm&;coyΗẋ}ȗ;2ICYeWG4t^7{|nyHw~r7R"w/46[?moG'MowM?_s7y~& m~kzG>C#JtX"ƌ7r#Q}LhE$)R,)%Ę.gHN:u'О 9(ѣH2 ԨP4)&֬Z^صްb ًUgJm+u+ܸr^}Z$F'È;_-lXnȑwm/`'X/Ȅ7Ya7smTiPMMzSQ>vܳ_ˆ%[VƵ.emHěN9' :v%2輢VNӠ(j)HS ! J Y*ɍȖ){+:\&j('{"gJ*贐NjiV[v-lݩjЉZ!t:ݛ:ۗ_~hm.+u6('YkJm^6m;nYzeoM}<ݱnB]3[9 oC@YZM;qK?u$wjr[M.GZ o34ds la\]tq&tno  w~.7:>;~߄+8;[8(7\_Sz3Aby[f]u0k*Sq~{AtZ;޸c ?<|噗5y>%2}sVzͲk ,:7oTF3Eli}A҃\ϠʢIqe/f?JD  Viޫ4 Q9ˬBLA> b{cjjӄ'4)y֦yMUQU >MT"ę'RoEM>2kCll&Tz#@BBc] AzNV W߳T3jL:ubxjHGxNߎ_-('n":D;s)^s){aOx+N'_@v BvwVa1 Tݾ>w/;YKCdlf޼$%cδBɕ{my?> P2o-cy"2!!"~R?w!#긑ڧ ߵAar౎}g޹x!S%%v萟Zqr `eՉfuW!e4!M5"'b.&)vb]`ꜙq0F fu\c:3!6"V .z#b$><-Q? נc/9#AbU".Y\a_,b=Q!2S3A#?ZQcI^ס_]V_Y)Nd7cѝӯcTHޓAzHT-"1b2UК,OUP!&A`ZJZ<*e'cR%%B%HW Thd$+NWX^ZUYJeZ Z^z^\j$dy__UH _a``Za^UM)!݊9~IEf^feY-N;2dMQ`E$Nud%mvXFOҟq'r&r_ffZ[E&2e&w Br]`$ JgCᰐ=&Pwn5"I{wr^g@`gJ`C6lq|0fevngsQ5 vaBcm!Zhxf;fpjrV~8py"zW攐~{jz$e6Bnpaa㍦ t#rN%/"6j$dކOfnb lt Ձcc&aR̓Nod$"e_n.J#vܠȚBlPvҞ._<*E aߗڥfCFdu*j[V>ݧieQe]$kOjQ5i*~g"# kׄ)q':%Q# `kkЧnd9$fk\e&6þzQk(cUiHF,MlU꼊+] cmcݨR,ql^yTb]jJog&my~N>,l)fzɺz(}->dnFԾ跂5ϹK"9ZPZZ\E-mš Dl헵lR+:2YV.~IWF:*h ,^%*n>.9%^V]nQڒH-=30vqQ`bJz^ ܆2IC'8w2,73O01[\JSnU5bd͵7uv]4Rtfy5fcE~LbOn\waV?Vg±VvƊ55X"ut[WXc4d?:Tqֹ-Kin!眕mTsNio wj?343)mرԺ;(n/sPoQJ.A~"Q1' V.urԹI02^'3"7G6U+/w0boWxc/>!)j3]7A*c_:c837:zlƶCxBx fs" @ֲ_97x37׳C-?w\'p#˸<߷6>v+5ߦ9B6v|yXwzF*8(ㆁc4tXW(u;Ro[v1R"t?rYF:/']f9g$;z( /'{*oleS{yIp!cF-5ﰿy//M[h6d,9sk:7782y>:DLگį{ hŃ׮ɇٴ<ůŧ=]!H[~F>wM?:f7kG+04f>z75bv~hL}z2{%Dz 4xaB 6tbD)VHoE9Vdca#I$92d !$(˂2 4(A9mhzHާy@TOR}NQcU(QF5"UʐiKTJ5TUg޴ o^{lʐ'G<)!Y8„b;v|_+]ڔUʢźgܹ1_|3EhAߵ|UҸunxpIÐ7mzt >8{aڪG^[ZnnoKK]j=.s6k#_%#ror c--,՛.j,*|-B0\k390iQ ],dzkJ$%$c*z"?ْ.LNK/D24q5-R9¦$:kړ>3G?=t&m–s,FJ-L5ݔN=T<B ]JR/2OT]=TWjt)mtNRYu3< ->uR΂sd5YZmh%:5UYSU4jW,V[oea}V*7\"=Cp'R/7tu]WvXXy#?5Zxa@^/ءa ]Jvz4cHYE@9͍9y8B^>גS& Qs b>8\z#9U8hJhތ_]:@hlDKR>_LţH𱾯Lee^P87rT-ozA7.Wjl=}yQ?v1%>%.yRL2m/puoF4}ӧ7{Ys_tw+ܴ=|5COɎvĊX$-s>[f=|a&5s\")FI[ܖ.HmAg֎̅mYҦB,U{ -rPsiw9VwXo\␁}i_CWY_h}SQic!8Y X:z- \.v^tbX к5=:-74v6֪:͌cհ#e2TT@&2{ٶI1% 2Y=~nm\bdTUE3o-7 LT91lƦ[J hGCX$qxlπ#i^C7ld +7tw]M3~qAm,؟\:im>I S}6gk7lbJס5?a'ylp3n*D`k_{3~M_+۝y6PSw{Ht g)q;0br%mEi&jQ}%$/+i7z9.yN[0_g|nj?d?D l͝kA*uW>;L>qn2;4}O/zatUxݞahu?O=Q^3|߈_ KYcv y{+ꀗ;=[t<#ksi_Mԫz[zGc}Bc^;?Q^N|sɾk7<=|oWR]n5W~T_PoVlPM#0SM+/30M>BKpFSP W_ZgJksnP{Pv  P] P :o P lय Ќ.  ӰP E  ߐ0?P0"F Q#Q'+/3Q7;?CQGKOW"ZQg#^Q/sQ iPQQEaVv!mPQǑӑQqQ R q !R!!! "+"/#3R#/"q#CR$G$K$# c"O%_&cR&1%Y2Ub&sR'w'{j%'}()2'&R)R**)I(*,R,*KbA-֒-.R..+/R/2Rp,M2*r00s./11/$"-ݲ020ے-933S3?3/S14O522nC0169s4a362i6R6ղ4S78_r5h218 9-93:S9Sa9*;;-/ю<":<:3=9:;A;>>,'-;ѳ=?=S@S>>TAg2s:3*(BB+0BA?DC/.NESTEWE[4EESt>EFkF W20bG{EGaFoHHYDDIEHTJo4I]KTKKKJTLTA4/>MTMהMMNMctm4 OTTPYPMQUQQQR#UR'R+R/S3US7S;S?TCUTGTKTOUSUUWT+ UV0V UbuVs5 OjNpUWUyWOX;PZ}YWuX]USY\gZ2[u[mXU]ap\ղ\ZN/[^I]Y\U^6`5ZS`a?] `"^a3)V@bbuZ5dZN .BWUZodkRvhBa`vdg6]mh.e`%fVai-_Udeij,juj6G cl+kk_^mUll͵lknŶWUk)jV 6nVaX/ovk_ Wqupm[g0lrrr$sqcqV[$.ct$sA!T}JWȆFu,^uӬJ&vS rWl7^pcxm:iv[oof2q~bs}ev~D ªbbW?gwZBtp" u㦜v zxl#*׆K{8JR0H籸w."| XSkD}9wnɵn=qKӲ4kxy7}!T} y)UʈTgw+׆ExFXZwgX嫆wܴu{8o87+uׄwKwvwةn|}?7q'o@ +XĬn&{#g"}|'؎ww{is؆A[׃Jwx5Fwlx' //x7~Vj)J!Swi8kxoؐqTkKٍߣد0ryK8wNuU_3fg L x~,ݸXy}{b97טw.UyZזaJ!ٝ;z홟C\bCW2/yWױWY9՗MC9:9~|˕UYz5Aڀ:uI7?$dCݘk:uIl %Êz)Mz:ګs؉Zzza`Xww׸⢺ѷW9[!eũVp #.j5׳b WoW$G G9oDyWk/^mc۶wۗprIۑ|tV;;y{W?Y_֛3:[:h;Y2X7 {uQ5yPJڥwڡCJ[Oڹ;{/|w9@OܺXg[緉ڈp:zW7,({7{uX_|{K<8l 5<۹5ْEz <11}&CĖػ[y >{ؔ[ɠ<_[j{ʏM:x8];(ۘٗ#=u|{|'[|u·)#=C<2y\<̓ _gZ ܘw?]{ԍ;թX ]'| kI{|y=wW]*]ոy,Z,O+G\é:^]\zg8]Z ^#ު]'ēYZZ y>_jUZ wsA su\-ekx;\ y>}FWC~s~{=ꯞa>w捣u%'{ٶQvԷ屗ca<>+c,˅LY^F"b^mol _?H:?z:A Y8{w9I:Wu[Wnyi??MP?%p)] ]AZY;@` :|:DHbB2xѢĆEVܸ"Ň&;.eʕ.?,Iȕ%sfM#5V<*4ҥL:} 5*MsYJ\Uad+[V@E,0ʶq{fTeݹ,dԤ_t{ݩm[ #^޽hQ-TÝ;:9gjЬ-'eY'ͩE.#i{ իXrZd2Wqlٸw̫bֵ{^S-C~[Ѱ'v?{z˻nM{w_n߱Wv_p>a G\V!r9tl7߀ v冠J fB ~c#3zHX)'"kvgI)MtIe^*EU^\Xcm0ugmqZgd͹"gyyy':ddGnɝE6Zhm1*}j i1M W*ק訣:)jn(_ʫawaVia.lRv2'^\·mqǕaimˮ2Ȯ}k-ڋo96w.Lp3Jz pS]j z"tjNdD|;^$c&uZ&E[ 8ƮH]_C%\PK.a WYQro]KYvr(^ `H-y 0sHU%3e<22[u$SP}-$7xXˢFl\8F V:aϫZ1Dl3cΗ?5ؚM_D0RG7nZs;by,ы\(q˽WSk_TƿL0Z]J/6`5xk/k_Z 3ðI᳿!1ly+ʋM.~"v $L帋/n?b•7f!UK;O϶SްW :QI(%CӲw oO|C{ާQ׼$;CɠP@GP%2TC\)Fwn1JS2VTo#J">+b^ƞ!9YhsQ*wD,FNc/‡VpZN|&T6.Z&o_>4E&6|<9rp }Dg^}R^kj‹z}P^-R}lBl,eU3϶elݮ!}^fj\j_;fU}s fMqk stE_ޮNnn*.0ģ[<)2޽]LygwvGfȞj;ۭ޵maXmx8OZz9r,}Gv2\}eC7Ԋ|`^zwۙ/qIfQB?f{K~9G75m|WHw_xqiqvv:2dx'gI84KdYn}'[VFIm.\35t'6 i HEDuXzd"dbe9xlvnfbEG*xxijh$HH!5'k$~05 q( qp䴆|FS}ej'Xf&`gio]`FjXheZa<.Ɔ~U>Fxc4^H9`drT p%nm'*{Q*g=]ף^B_fo&*m&K=8=.ʸV~1w usz4\HWcBTȋDw] Bp߀ o3tu@ r6u)2u6)NaYaPްА*Su%iIdgΒW5iّ6xA)7В/96M.WGɓ2,W+; = D?sRc#`&3mfxYY5[SXt%H3gye)*8aW&vvBǖHjR|=U76fbxB#c\P"yH(^b2Yq8wTM]IAo$V@Bo|{|[tzu7|H|Ly[bwmɈczDC+G]g{#l<{clIyWUhice/CXg5lgJ)?fFEBؙמ~8:ub$e:Yd h^@c m(ifm(ƠHZx%W8)H{nbøH=gd"I>ȄWXbWa|o_GWjz^/"aJȆOCE7U 쵤j$9ZxBˆ[ݶ ٥hEs;xGc fj?jzIlz$Lx|oW~hxOXoJj}|inʛ6_H%ȎkȫJLo3z* HU j@A:1*Z-J*:z?#ɭખ(i0L\\hޔ4 m =0 {@ڭ[1Xʔ+#;5;{~$/1 +*[,{p?eVȗ" |=UJ3бPqӪ9ZghYu_~Ј/Kx5m cK;RuVxsM\ z9+5;b8 `ضDJ7O盽'WʖvZl2sj_nkY*̩Cmincˉr9;ʮմO˔qgqŞU%9 xJ*y@VzgZYԃһE);x4X{[s犡T F6)huj#RqX2|<˼6zKڿV~3{FɕAgK~g6[hdīL:b]6ʷdk]+7(ld:f`s; ܤM2aJ#e<ꥊxK[P:Ju<܉$Tnaڵ'GsDmdSWjmo8ͷTی@{J¹U&KZrW;GۈX{ 0hxtՄfl(T0|օeV1}Mή pCV%lzdK~ʙ՟٥oHЋUfSa4PsNx.$ [q^ā>~n艮qˎn [hr+nꢞ4.Y>\nM Zo6)Onn Hn׎ٮ.Nn.N2*No bMkVa.#O%o')+-/1/3O5o79;=?&#@OQ/SOUoWY[I&CO&[jjo f!sOuowy{N/O4Vi߰1 U!}o_).B p 40 Qy2>P/04p /Ooˏ_a?>ͯOoOMoكPB >QD-^ĘQF=~RH%MDRJz>uLzhĉzT(PA}p5b7U^j\knDVZmݾW\u7ҋ4͜}ihPEv8sS̅FVdʔÅ2p={>`hҥMFZju]ɗl9yY^q׽xGyz쩮~vC^'_|'}`}O{׃$8<- $@vt0j'ػi\_"Ⱦod BY0~?a8AЈa=H#:n:,"xB#p$W'C"9J0Xa&qr<4`lLj>7o2d ?q!KhFFZ{88Iə#r\V#ޑXۣB+n`PHn2|%DAeJ^Г|%!s9R#XKC\$ gi5fVs]+8Elkd2goWe21WFoRf9 7KΣT_gGӑ"FIP`BQ V h,WE>EnsiPO^j”.BjLkUժWjVUlM57_kX:VլgEkZպVխok\:Wծwk^Wկmk;XְElbX6ֱld*XVֲlf5YvֳM,eA;ZҖִEmjUˊmleN;[ֶumu[ַe0\׸Enr\6׹υnt;]V׺nv]v׻ox;^׼Es;doc/IDE/IDE2.gif0000644000175000017500000005026611247323602012053 0ustar renereneGIF87aw,! !&&&!(1212!J-&T1$sixr!y!EJAJQZY{aZB!J 1B81R(9Z8JRA!{a!FEFBIXBQZRQBUUVRQcZYsZiscYJcYRdbdeissiswrt (0!&!01(10!410181EB0B8B8BIBIBYBUZIZSBaYhZqRqRnkicqix{yZVkYkc{iki{i{q$$3399DDss)9k{scx{i{BGVhxam!A)I1Q9yqIJQJSTacycy{uwaJqckƊ֌!111ֆs֮RֶsBBRRcs猌眖眜ƛ͜ք瘦画ޭȥݼƵ޵ǔ׽޽ƻڬޖޞƾަƾ瞌瞔쫜箥維ᄉƶDŽǔϵτ܄ǽץXF9@ q]*\ȰÇ#JHŋ3jȱǏ CIɓ(S\R! 0` 8sɳϟ@ JѣH*]ʴӧPJJիXjʵ^1IJٳhӪ]˶۷pʕzNs˷߿ w؂+^̸ǐ#6|BtϿ r\$ PރF(Vhf6.($(.N,pdΌ4h4fG@@)dDH&L6PZD:TiXfie:J7`ɥp̙hhr˜tIxgE։ ~ (tg蟂2h.h>:颉(*I覘z::jV 覚"zk+k&u:Ae^s:e%)dh9s̸ǘ-N!Dt@g*k",j[0KW,[,0_¬* $l(2F򷸴|e -<|P "D'[A ֣ད4lqTG2|+մVrYeugoݱ/ tmx߀7|3C)s$A,W[ϢJ#PKmם6v髦q hc 饽.0W+<Ƕb+?g[+~[ 1OL䓻~5h3 v0Dx&8Aj4`%HVp`% ,5zPS!IB06!Q 0:D x*!$7&:PH*ZX̢E):apmAhE41xG G91j_1>xB_=6?)NE!}Cꐈ'$82)JZ0 "r0 ;D!/sJT򖦌 k.L2f:N(NkE4t 6X :tC Ԥ=)G3QjGEZҙԥ5=iL5R48PJԢHMRԦ:P%aXj C'sUͪXjֳǨZת^խHJct@ngC"5(K!JR6iJw ؟Vt]N/*SNVmEӐ”MeRV6-C7 FlgKֶN@ǡ*ָ* ^Enw[6`\`etq׆kCZA IK͊WS%obիPnQ[׼9(yKZ,x;WE0k+gSΰ7a?!DE pGgm fLcfksifT. vH~,Sa&'yNm:'[Xβ;yp0EL0wH6?g%:x޲Z>6MB jG 3ыt:]Odbδ7Lgm^ Mj=ԨrSV0fMZִ6C+k\׺%<b_f;ЎMmdζn{MrNvMoy4η~Nܾ77;'N[ϸ7{ GN(OW07,o2Ϲw@ЇN/;PԧN[GW{`N[]L7pk#Tx>Y./剟N[ ;.S< 5> ?9a.z|}ǼgO;\\S'}/ʑw;7;{<|?z;'_<~s|~}XHt }7ǀ 'h77xg}!؀WW++$x284r hH~X,z')ȁG?yw7~FEJWN85\؅85uԧ{9g}>XrOZ؆W+؄ehGqK؃Xv؇txqV腄Xx{`tudGxPȆ~wX\} Dɵ4H,r,0,'@ wB 9P|,qȥsEȈm MHm9웻ɛmyr3sImy;p@rO=rQ-P]>@Ks[MyM=Sra rcMV-re}j=iqoqq-g-ml}8z-yׂ=؄qZ7Y،؎}q؈=ٍؘْMْ}ٚڢ֜؞ؠ=ڪ[\ړmsڬ=۴=صۼ-ۖ=ڒ0]}ȝʽ=ܽܳw-ێ- K ]y ۟p=]}ٽv] }  P0  v]`UWt'>t݀P (.v xgBWKt2qq}*sߠ ^p / })]m|9s5~&Wws;> h Q+asLTxO=.x .0.s~}yg+^] . n~^6 r~O7n*i.)9(^+y9i)* ." gP >ntN^SJ~ }^ߞGS+/֑02 1`j>(!(>0.Nw>^݉[;y9o+ P P )&_nbho.Y'B/D?qC<D_^opL}N{P5 /af_e*kos V^S[\X5(?@WUȯbU>@/ΟU_ȿگ_P? @  ܮXP  .4hP<%NXE5nG!E$YI)Udc0r1c!(3f0ip~ zOI](ӦLP*yt" orڔUR&ͺѥ"ͥ3Rd͖WmRI v4.%r+Nʇ& @?tgСE&]iaڤY&9Y%9mśާy*m;,MN`oVoZ>}KuT:&{N'Z^sgYND7JGtC`5s"֣5Kd0;χ?}l fveCӦv}mͮ mfK^Ak'[6w=_ 6p=jZq?gM7ȡ)g(Ԍ`-wGnt!Mir01f8@N:]^Ķ }KG\˃+J4Džr7OqⲢF'.䑎a'򤇝Kv 2e@1_#v}Q{!p#]t?rw&hQl; Mg|3f&ӻsN{Xl爆_Q z݉q<ϑ;^}/A;Q'~L3z_g_>Fg7%~_g~_q?bKv?z(@<@L@\@l@|@\@@ @@ ?ȫ8<; @,Ay8A,\ A@Bzc2A A@BɃ LB%4\BlB't@$B*\$#A#B-tA <@.4/t*,B64A(D@C'|C/%B3Bz6C Cz$D%:\B=\DU݃<@Dd@C4$C CFr=DDRJ$C 0DV"PԿ5$EYT@L,D;TZ9lE^ġWTCEa<@S$E[T^\TCa\<;DcDfrDhBDCEl@qXI94I,9J웬,̛\K ʮ,PJ\kә¹DPKNKT5K!KLҜL:ѥMMMMN!NߜMm),O@OA TBTC-ԋӺSEmnbTGUTITDTKTWQ,TMMTTPUUR=2UT]UQUV}UqUXUZUU\UU^ՅԼ8`-VUcMVAVemaVgVˁViȡVkVVmVo WWq-׻!WsMVUWw]Vv}WzexeOW}QWt X~Tb-X]}mXWwXUWXsXWXoXVYk-YVMYg]YUV}YcYVY^YUYZYU ZVZEU=ZRMZUmZM}ZTZIZuTZEZSZ8 [eS-[1=[mR]m[Q[ [mP[[O[[у\\ĥN]W`lO}X}Ý\n\-v\}m\-M,]}LM\]]T5MWם]]J]Ol]%Jޟ,^IM^\^H}^^G^z^EG^m^eF ^_mE=_OL_eDm_=|_5C*_eNM-~U-`<`?^``tSm` F: `` 8 `w`5aQaOT~a6aV3-aV6Fa!0".bR b$#^kb'>0(bb*/+bSb-f[.b0[1-c3[4N]c6[7~c9&K|:cu=~,dBS:>4dE*Fn"LdHFNId|dKf)LPdNNOddQ~P.$eTn%U^I=eWVeEeZTXee]>^^ee`n^af-fc^dNf]ff^g~ffi^jffl._mffo^_pggr_s>gMgu_vng\ygez{V}g}N`~gg~`yぎ|>IhnZhhh`hh.ah.?cĊ>^ iani~iai&i%`F#KifjjF>jxUIkVnkbkFm}kݼ`kDklkvd>HlV^kȎLlNɾllͶl^W3>mzImՖnmδl~ҎَVۦݾ;^ϒ5{m>>mV'm羢ndnNn2nnoo.o>oNofn-mVҶ/oooooV.Q;35?g3_p p p p p66O4ĭq/q? Bqoqq/7qqa/q r!.)!Or%_r&"'nr)r*G'7#*r.r2 $r2/s3078sc3s8sIsI7?s=s>G :P3|7"7|GR6b|׿ȗ|w||,>̏z7(ʟpc |~}R|X@W}|pI_7\7mB~{O8O>?|o+?6|Џ}^|ˇpҧow|WoS=Ikp *\p!ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:wDPhaʼn !JX ϨRRj*֬ZrGA-z4B}z,ܸrҭk.޼z];QIUv/Ċ3n1}|vN13ТG.r2YC%-gӲ5FmcĹン﫨-Ⱥ׆c|syzGlZ9t}qsx,GӃEx_wa߄մ!z&5^QIbI~GV硸BRef`GtcKLJNN䊸XaDE`\f)ie#)e>&EQ8抵"z(2*xaHނ0#Yh*Uj)XXߥ`h(cfJ#{~'"xv)f%ʢJy"1j{:V.eFg0}H%Wne|ګem*, S Z.먈.f*+{뼨R.ʋk*=R+`Bj-nk 0'fgn;Kp@r9/|ɢLEtUGCs:3:#y yrAl.|uz7Z볹 eR]roy߷D8olae gN8sg937Ƭ]HޭԎt۹a.~/=Q+ok3oϴw&(O 9***fD; 5˹([dִ=T7Vl (u0=,B.\EO09_JG-kMM>a!$8֏vx6N|()'~HG6%,"(1q#GL_ׇe|#(GǜQ[N=~t)nQ#"E!)IRqbj-qMt'-)Jra$yƫtV %]Z3Y0S\V7px) 5IkR R+eZ~gAlM[i@&Zh0)8eF3gJInĞYrbE=`1H\ש k0|/g~ѥ Є TDitzӔ(z,6 | VTCTIQK}~i /_dz.rY57ڸtU{6ib؝ICS{F/m:%.q9;]NƦ87֡v)>*pS3ޤj5{ 67u=xo|:AVAYUe[ kX˂Ƭ??M4uo#NA{XX5#SGgBֹ`krw_t]o +/-W&5b\ك6Y /(SDԿ]%<{U mo=?Վ{ſ|";e<g/38N AIX>.(z"%6$,er3 7{TZ^ܴf>e4nq9ӹΞ~̛,+}MH2j>s-c ƅvn=x{Bnol<]{"Om~½Uz=_p5oU '%}kx/خAGxqM궝-e~sr~@rm]-mbOՂޯ!I8}}Z{$pE՚qXҗ6a͛umXd7guGJEm^GVӕ}m5#9_u9PEZ v`  Op !L&.H !>!.F[5Z zB a*1_ؘRmlZ!#ma)!h3 ~NH HI6EK"Q`[b1i͐]b^ ٍΥlu`eګYv5^ULIU܇ x.URkZ+چaX,t!oE E^1N$&] Qޕ^ ңU>b62mcݔ`/KUuW$ D1&V%dN&e !?aen&gZf7`fbg&iJd&joji`cvkbzEmV-`TԠՁX)cRnZmf]Br绔#0$pd xWr& ƞelURss!vb ׆ [o]w"I`.iAgx,fa ̊I ]_&^egWvmK9\`=MYn\ bЅJeD%fG&h5_dtJFΎgI}gOyR!X|zr]'\jr(|jUMuL.)ym|'\I'}Nޱ\Ɲ^yOb'DVյq#QCVU)qꅝbW|<\;e4&)EҍNzf=+)pF VEQ㤺dDZi2šZA +jFƨj$m2Mk-$؞mkPPB$>bd\jP$c3uQciƦML!TNg_^a2bLfݰ2,J%<:*I-b" [qi#bZ(Ğ!쁘-]Z[b&"VRcj]R Qy~by6kN-f-?j-؆^\ؖnٞڮmThJlƦ:%-iqbX`.5g--VZ曰J=M=Ӧg|F.9-6>'(bF䶞n~+]֨6.uM *lTEc)ֳU,H1.WMݘܻQ(b"Xthn \Z[v^&\讒bݵaT.,_KB).37s?A?otAOtH PE>C74t7ƚ}#0~PZBB WܩQh&0FWr1*kWC:.0OF*{SÜTy('^1Cv8:嵔uvS.PF/sQWo5+8f&p>o50f,ɔXj34l{''5z `OzH;nB;j4A=v;;F ĀO'` SwF&x7oR@X;:3i{y淇z'7|+'[Y RWS7~59esl|+<)ז-;/|=8v~pϩryQo 8K}8-qܔgJrgZ<#v~Ez^d?k;[iG.7By;}z X \!Ĉ'6X"B 6cF!#n,1EI<%K)9T9fN;yhP}w\ntަzzuWsă&ARG22TMgx͵8 [Vo]5 - -Jo)Vᾍx-Yl朑 ,BYvPF*eԮ[f;Xרb.~ܠ_n?-㋛OO}1tګG_s_ɽ-SVqџW;z=RZ;K$ˎ" [bې=iyz')pjv7em5‘}6Hي6oKQXԊ*2< Ē. 0 qOME'j1J`8<ē$dr*5r+)<D]FeOmC1@{B|N=PE5R3t5 jQ]}XeVJ&3tW `bUIJ565X:lmh}l?QU}mFOH;?52^^ KvnO]8gY\Lzt8Ocߞ60*S NV`eu-Xȥ1[0NtCb-k2ŔYCRkk>R:驯ͪ2D =5>%Q[YKog`4U^]L%qpwי{O]rW;yrKvD{<[R?On_g<@rthtU2r1gX>4a!yabW@UxCG sh.WC ;ԢG;Hp{:qCzD7Pi\ G 9 P6-Yhjr> 2lQSv " PdxIy%{q_a81 WԈ)6GK_K@Lj"#`lSI]FєfIw"Ji}89jǬ%7or9t"sd|.Obg1u n BPh,:}F9J(_;;ZRZSi=0'RNUka7V,JWd` [X 3\?>u ءΕf9VS%E;[ZӚ]zZ׾ְll"R̶YUXVJ%ph"Ur\Rѕt[]^v]~x[^Uz^v{6ZDj_ \` V`?׵Q[U*}G* I\b)VYb1i\c9ycX0IE rIVBc'?Q\e+_Yid Y%-m2s6.O5G,n2\g;yr\1Qy@ 8hs~9iOԡ<`f˂y33:Dy$@S)/C9GSD;T6D1E/19E!#{r 23 SrB+)r$Do48+T$s@#Hͳ8ْ"OE1GJu2KcrKSSJ4%TLJKSLQ2MKLt_TNB[MwMLOU4P8 PQUQQQR#UR'R+R/S3US7S;S?TCUTGTKuRŠdLUUWU[U_VcUVgVkVoW1U%W{WXUXXX5VwYYYZUZXZ[U[[[mZU\Ǖ\\]Uŀ]]^U^^^_U___`V`` `aVaaab#_b+b/c3Vc7c;c?dCVdGdKdOeSVeWe[e_fcVfg8;doc/lp_solveAPIreference.htm0000644000175000017500000007360611127442503015050 0ustar renerene lp_solve API reference

lp_solve API reference

Alfabetical index

add_column, add_columnex, str_add_column
add_constraint, add_constraintex, str_add_constraint
add_lag_con, str_add_lag_con
add_SOS
column_in_lp
copy_lp
default_basis
del_column
del_constraint
delete_lp
dualize_lp
free_lp
get_anti_degen
get_basis
get_basiscrash
get_bb_depthlimit
get_bb_floorfirst
get_bb_rule
get_bounds_tighter
get_break_at_value
get_col_name, get_origcol_name
get_column, get_columnex
get_constr_type
get_constr_value
get_constraints, get_ptr_constraints
get_epsb
get_epsd
get_epsel
get_epsint
get_epsperturb
get_epspivot
get_improve
get_infinite
get_lambda, get_ptr_lambda, get_lambda, get_ptr_lambda
get_lowbo
get_lp_index
get_lp_name
get_Lrows
get_mat
get_max_level, get_max_level
get_maxpivot
get_mip_gap
get_Ncolumns
get_nameindex
get_negrange
get_nonzeros
get_Norig_columns
get_Norig_rows
get_Nrows
get_obj_bound
get_objective
get_orig_index
get_pivoting
get_presolve
get_presolveloops
get_primal_solution, get_ptr_primal_solution, get_var_primalresult
get_print_sol
get_rh
get_rh_range
get_row, get_rowex
get_row_name, get_origrow_name
get_scalelimit
get_scaling
get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex
get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult
get_simplextype
get_solutioncount
get_solutionlimit
get_status
get_statustext
get_timeout
get_total_iter
get_total_nodes
get_upbo
get_var_branch
get_var_priority, get_var_priority
get_variables, get_ptr_variables
get_verbose
get_working_objective
guess_basis
has_BFP
has_XLI
is_add_rowmode
is_anti_degen
is_binary
is_break_at_first
is_constr_type
is_debug
is_feasible
is_unbounded
is_infinite
is_int
is_integerscaling
is_lag_trace
is_maxim
is_nativeBFP
is_nativeXLI
is_negative
is_obj_in_basis
is_piv_mode
is_piv_rule
is_presolve
is_scalemode
is_scaletype
is_semicont
is_SOS_var
is_trace
is_use_names
lag_solve
lp_solve_version
make_lp
print_constraints
print_debugdump
print_duals
print_lp
print_objective
print_scales
print_solution
print_str
print_tableau
put_abortfunc
put_bb_branchfunc
put_bb_nodefunc
put_logfunc
put_msgfunc
read_basis
read_lp, read_LP
read_mps, read_freemps, read_MPS, read_freeMPS
read_params
read_XLI
reset_basis
reset_params
resize_lp
set_add_rowmode
set_anti_degen, get_anti_degen
set_basis
set_basiscrash
set_basisvar
set_bb_depthlimit
set_bb_floorfirst
set_bb_rule
set_BFP
set_XLI
set_binary
set_bounds
set_bounds_tighter
set_break_at_first
set_break_at_value
set_column, set_columnex
set_col_name
set_constr_type
set_debug
set_epsb
set_epsd
set_epsel
set_epsint
set_epsperturb
set_epspivot
set_epslevel
set_unbounded
set_improve
set_infinite
set_int
set_lag_trace
set_lowbo
set_lp_name
set_mat
set_maxim
set_maxpivot
set_minim
set_mip_gap
set_negrange
set_obj_bound
set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj
set_obj_in_basis
set_outputstream, set_outputfile
set_pivoting
set_preferdual
set_presolve
set_print_sol
set_rh
set_rh_range
set_rh_vec, str_set_rh_vec
set_row, set_rowex
set_row_name
set_scalelimit
set_scaling
set_semicont
set_sense
set_simplextype
set_solutionlimit
set_timeout
set_trace
set_upbo
set_use_names
set_var_branch
set_var_weights
set_verbose
solve
time_elapsed
unscale
write_basis
write_lp, write_LP, write_lpex
write_mps, write_freemps, write_MPS, write_freeMPS, MPS_writefileex
write_params
write_XLI

Functional index

Create/destroy model

copy_lp
make_lp
read_lp, read_LP
read_mps, read_freemps, read_MPS, read_freeMPS
read_XLI
delete_lp
free_lp

Build model

add_column, add_columnex, str_add_column, set_column, set_columnex, get_column, get_columnex
add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex
add_lag_con, str_add_lag_con
add_SOS, is_SOS_var
del_column
del_constraint, get_row, get_rowex
get_nameindex
is_infinite
is_negative
resize_lp
set_add_rowmode, is_add_rowmode
set_binary, is_binary
set_bounds
set_bounds_tighter, get_bounds_tighter
set_col_name, get_col_name, get_origcol_name
set_constr_type, get_constr_type, is_constr_type
set_unbounded, is_unbounded
set_infinite, get_infinite
set_int, is_int
set_lowbo, get_lowbo
set_lp_name, get_lp_name
set_mat, get_mat
set_obj_bound, get_obj_bound
set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj
set_rh, get_rh
set_rh_range, get_rh_range
set_rh_vec, str_set_rh_vec
set_row_name, get_row_name, get_origrow_name
set_semicont, is_semicont
set_upbo, get_upbo
set_var_branch, get_var_branch
set_var_weights

Solver settings

default_basis
read_basis
reset_basis
write_basis
guess_basis
read_params, write_params
reset_params
set_anti_degen, is_anti_degen
set_basis, get_basis
set_basiscrash, get_basiscrash
set_bb_depthlimit, get_bb_depthlimit
set_bb_floorfirst, get_bb_floorfirst
set_bb_rule, get_bb_rule
set_BFP, has_BFP, is_nativeBFP
set_break_at_first, is_break_at_first
set_break_at_value, get_break_at_value
set_epsb, get_epsb
set_epsd, get_epsd
set_epsel, get_epsel
set_epsint, get_epsint
set_epsperturb, get_epsperturb
set_epspivot, get_epspivot
set_epslevel
set_improve, get_improve
set_maxim, is_maxim
set_maxpivot, get_maxpivot
set_minim
set_mip_gap, get_mip_gap
set_negrange, get_negrange
set_obj_in_basis, is_obj_in_basis
set_pivoting, get_pivoting, is_piv_mode, is_piv_rule
set_preferdual
set_presolve, get_presolve, get_presolveloops, is_presolve
set_scalelimit, get_scalelimit
set_scaling, get_scaling, is_integerscaling, is_scalemode, is_scaletype
set_sense
set_simplextype, get_simplextype
set_solutionlimit, get_solutionlimit
set_timeout, get_timeout
set_use_names, is_use_names
unscale

Callback routines

put_abortfunc
put_bb_branchfunc
put_bb_nodefunc
put_logfunc
put_msgfunc

Solve

solve
lag_solve

Solution

get_constraints, get_ptr_constraints
get_constr_value get_objective
get_primal_solution, get_ptr_primal_solution, get_var_primalresult
get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex
get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult
get_solutioncount
get_total_iter
get_total_nodes
get_variables, get_ptr_variables
get_working_objective
is_feasible

Debug/print settings

set_debug, is_debug
set_lag_trace, is_lag_trace
set_outputstream, set_outputfile
set_print_sol, get_print_sol
set_trace, is_trace
set_verbose, get_verbose

Debug/print

print_constraints
print_debugdump
print_duals
print_lp
print_objective
print_scales
print_solution
print_str
print_tableau

Write model to file

write_lp, write_LP, write_lpex
write_mps, write_freemps, write_MPS, write_freeMPS, MPS_writefileex
write_XLI, set_XLI, has_XLI, is_nativeXLI

Miscellaneous routines

column_in_lp
dualize_lp
get_lp_index
get_Lrows
get_Ncolumns
get_nonzeros
get_Norig_columns
get_Norig_rows
get_Nrows
get_orig_index
get_statustext
get_statustext
lp_solve_version
set_basisvar
time_elapsed
doc/set_add_rowmode.htm0000644000175000017500000001064610237176660014157 0ustar renerene set_add_rowmode

set_add_rowmode

Specifies which add routine performs best. add_column, add_columnex, str_add_column or add_constraint, add_constraintex, str_add_constraint

unsigned char set_add_rowmode(lprec *lp, unsigned char turnon);

Return Value

set_add_rowmode return TRUE if changed from mode and FALSE if this mode was already set.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

turnon

TRUE or FALSE. If FALSE, then add_column, add_columnex, str_add_column performs best. If TRUE, then add_constraint, add_constraintex, str_add_constraint performs best.

Remarks

Default, this is FALSE, meaning that add_column, add_columnex, str_add_column performs best. If the model is build via add_constraint, add_constraintex, str_add_constraint calls, then these routines will be much faster if this routine is called with turnon set on TRUE. This is also called row entry mode. The speed improvement is spectacular, especially for bigger models, so it is advisable to call this routine to set the mode. Normally a model is build either column by column or row by row.
Note that there are several restrictions with this mode:
Only use this function after a make_lp call. Not when the model is read from file. Also, if this function is used, first add the objective function via set_obj_fn, set_obj_fnex, str_set_obj_fn and after that add the constraints via add_constraint, add_constraintex, str_add_constraint. Don't call other API functions while in row entry mode. No other data matrix access is allowed while in row entry mode. After adding the contraints, turn row entry mode back off. Once turned of, you cannot switch back to row entry mode. So in short:
- turn row entry mode on
- set the objective function
- create the constraints
- turn row entry mode off

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 10);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_add_rowmode(lp, TRUE);
  /* first! set the objective function */

  /* now add the constraints */
  set_add_rowmode(lp, FALSE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_add_rowmode, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, add_column, add_columnex, str_add_column, set_column, set_columnex, add_constraint, add_constraintex, str_add_constraint

doc/O-Matrix2.jpg0000644000175000017500000011735210251410040012507 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?^Z׌a~ھy4K-:ܮX]'NmiC D?>$YA"JF=6ܬ,$ 6L8?) 12>|C3ᮃ^.^'^m3ՖMKJҼZ&ou?QD6:ޫkioc:۷c{- Aox0׉ [O/|m!IUz)Fa'.Wd<g/Q> Mψ%KKY{H>&I/؉E(1Ss/;\ͽ?K08_R<-S7;2f3 |C<Լan ëqcXxj843Ƭtye\O?j>=1~ˋ&k__g_|C7_7?a ލC|AO?!V{xXPp7Y{Ù~gnegIpMpfUO4կ3ڮ +ڭW§ P*]\䔳EGӧsҥ`qq..NPa\XjU>TB>'[ioZ''ğ?_?|[KQx_~|,~ ƵĶ=wTԼ[ е?zׄ?νnzekXa#<- S/5υl7oǟ?)}6Jhk;o >!xş tږ@мAqwiz%u5[>ѿ6O|G㏀~<|׼i;|'gXkg x׾.iq^12Y.6|R8EM(| ?-_G4O Y-}7 zxρ2|"k/??x9z>eOǿm?{ƾ&o<5⫯Z:_"/O VZ- kV>e~l-kYʹ׺ΛUy c\&Xr9iĹ^qy>sKȲx8,22~;0؉,TQe%O#8GAk/E'[O7߀0xk?h~˚_'Q_~)x[_xDIt-3Wk+ W[}KzW>*跶(oK9n4Ux;&rg/0'CNhVSPRjs<e٤NAk/E'[n-h˿QN? bzeo+%3ioZ_j??mҏ쌽̣/eg۽X ?J_˵N|O?#n_Z?#n_Z?Y)c(  ?f#y~/5o ֟G5o ֟_5g? 0m~O<S7kOE7kOEQҏ|6@}C?q?Y_}) Gr5" Gr5"~Y(GG>_Bp>,y/>AhAk,t~yg/F _PPObk6iߊ|QO$v^olo&^"|?dιVz>zֿhZƩce?Kv?u]ե޷WkqȰ>3xZTF¬mO1<ppp q䧐ee9VN(0X)b25JT湶*yS1U})NtA'peYe }\oʽ\Lhj¤a0r{_9M.hRqj\}#4iloxG'?l"A  㞀5O1#iuoۛf-ρlLD_$`N=7ĝ{R KϾB  =_힩wq< ଄F8 ~[Tx8CU׆%~hE9*qSNIg깿[QSXۜi{\?^6rqf['{W__ď>%+_0VEuu|=7:ÿx2W-|Yq kk^H LԵ OR~.i<7߶_o$lUb2?b q_(']fal"u;IY?0 `6rH __&_-#=|oĉ>|!guZMT> |.W_Fnm4Kk=&(exΎa,/ y3rn c#W+93OOOĔhQxJRJ+bNOc*bq0 gxi:ΰ} sBA:eַyTӍE 4/9ҙ!%\}SRReݎ'w%>z|=7V%Y閖?"{-CL5 9!g|ܽs2@l3Gt؎GKr R+qy1pmü1β4N Mc|Bcz߇Iq\CB1ų\$o LmmeX# 㧍ӎZn%zU"*)WG0t75Y?ت}8jORPs(g<=m;_moۃVj~,'ԗ6$ ^_杨 s6a Y+f {j `%Cprd#%} x["gp&_Xsq̸+p4#N&Ce*K 5)ҥ gxif9WeY~[0ѩ 6J|)ƜjN\$j1?l?ah?:~>/!X]ýoSqEico:O[bHI/7|77g[K;g?Ow4-x-S񿁼;+[E6-+iwviOj}_^1OnO7 xz߄?|uM/č_Xl6e:]1_h %VwW_~[Qdc6d$cFv#xX *,rrZ\u2ԝ10ЖFz;cr^?J3, l."c2lg*E[,XXܷ8#)ԥ,Z3x.+ (yw[o ~Z^(fDo{{:+m[liއizmNGGޗhھap/lo|Shv>9~_|4¿ [_xU|euC>xό|}Ꮘ_]o> ~:];Pռ}yGjfs! lvOF'Oӓ :Tp2.pF#f3;3jazI{6+3:a01o |/\:ḎRx:NKphd:,CQ~Wڊo'_W?*_(4o ᷀~YC;šZYY:OX)yךjZlfK O;' Gqw'j^7hQw0vׅ V}{!T? _ 1ES4g8*B qk G\L?峎iR8+'ȱm>KOfЌ3L ΖYgQ(bs,CO\I( F+qY .sBQQfxjt9ҥO/WLe:VOǟ*|M/P @7>|ŠE|D?i> FCGng^k+w?~߷OÿE>b/;u ? ?$f|Oտ4ks/ _ KZg>>aA4f|CtWP2YTJjEeZy6_ 1ES4g8* xw"q<ϲ >D9,N#,b~~OVWO(Kº1eOs}$sL5d2qؘNJV)ju5ey۝Ztt,> 2/5nٓվ:Gڿ UA^xR~⇍<3<i>,.U߉㨼O^kmJ?|(+طu{G|0|#tO#N^{J7O =|^xxM+v~ƪnDgC}cipUǿB0X f<3fV_<aL:2l.kO5}Gʜ=VH*ϤfyV{6 2l೼|djeؼV?-R|Tv&/sqb+Ú2G ?aofφI.oQ3~:Q*?QF?~Ɵ_|l_{?HOx)'ż7gab1saF+VUÖ G УR)')|xU 8)-8,YNaV|v+R\N+WRUQiB(~,G"yG|F?~Ɵ_|lGC}}]4½:P*>[%$o O_E(X(¿u(O uU?cO/6}.^qmKIf=>Ƕ7QQ3~:Q*?QF?~Ɵ_|lB]4½:P*?z}7?m ???o??O5_cipTW 1ES5Å8.}|[eLs^ ?4_p_Hw.~.?~jEOWC W 1ES5ÅWMѫ t8ot y?߄꟧q=SUF?~ƿp7!T|oGMѫ t8ot y?߄꟧q=SUF?~ƿp7!T|oGMѫ t8ot y?߄꟧q=SUF?~ƿp7!T|oGMѫ t8ot y?߄꟧q=SUF?~ƿp7!T|oGMѫ t8ot y?߄꟧q=SUF?~ƿp7!T|oGMѫ t8ot y?߄꟧q=SUF?~ƿp7!T|oGMѫ t8ot y?߄OՏ(!Iczҡa5_(ߊ=E'qLu?ࣿUc/~9_KߣJ¯m_5GS ~[~_w# C{Ewc/qo?vSLĿD7P_~0??oM~:Q*QG?^rGMѧ ty?_pK(y/|?oM7O_&wO( ߎ_(u?ࣿUc/~9&Gk:t< /8%<_7O_&F/_wc/q:Q*Q}i:f_O?__/F/_`?Hxټo1/ GM9U#ya1K+4v_S ;E_18|2>*gƟثNcnb?ŏz΍Zcx/xc~֬eZ׉t}[A,SӮݣ?3J_}br\ŋ3- >y]:쯇4׶~oiO_ |o'WOkq|<<_߇rg?]:IVeQ4'MkXKeg5cw/:U]@Hp0` NDF*0dO TsF^,ʍX$¼lx{4 -#GßV_^oϦx橧jw,fލuV avs<[Ǐ؇D?G_ 9o!c3x$M?QtT|9xge} +YU8AQ:·~jeSʼcbܟ#&sf|#=a^_Nj0UvbeJtr֍n/ \? prc3<e 7T-G K ^ҕHԩe^`߳WOxk?kǎx_I'/ 𶏡ZO>,Y}RK6Kakic?q=}e񄮟G١W?oq<iEIHg~c4o$/XCy?x@-\Kggxc^;3^]P׶Q$Z7 ọVI45XD#qi?TmJF_7QD9ψJoZIS nXw*J}>JvJ.HMtw؂i#d2b[x. 42`ӸWڇ1yI.ϨMqog6^&ac1c;mӤv}9o[ZeʐF8/VZk=h/؊ Y.%ѥ񶇨.!x.[FVOrKg`<'7 ZŠTէ|Y^:YOhƽTN5*\ׇ'joO O5ujЭNON<Ҵ&S#j,- am NA߀[FH}=#~Ƶ]#x*&=tۿh~dx4EU!5P]yqyK?1|$\8s .J;.|;MRkҭO|qN8fqGcX2Mʎ'QiRJ9+(_0oB~;q_еJoH_>O Ev (?F ( ( ( ( ( a7|eOAO ?cgO|U|fp/ !3>x!| ?i}xu_ zo_? -j_>%u|h~6]>!|0'R]|#d'=o~ o~˾)go*5N+oS7_ :,;}G ~ >~+|9tg%> ywؐ|H /?ׇnx/?wek_ ~x~#G/ڇu?/|Bû_߷S??h|2ӿd▏៎M;㿈?mg[ ~iޙWL.).e1m?NWu ]W>їQƾ6  = ĿiC^mk~>o_W{}g\wxxmksxJIN_S&D7?q/,|4/|+мS~߳Lj>/^4MOᾕ-c^@_Qs|d֤?g_|.V?Oj n]/ WvZt˿gχ|7>+x{izYŏ>'xW )|9xsW-k/:|h?}㟏_egW9yO¿OI+O|/׎>xfO5}gW+F>"k9 O]\-f(>)xOG{$6U㯆z~Go^Ÿx)ֵo|>57>#a oĀ)*}?NWo3:gM *Wߴo|x~?獼1wofN<ėj;~x?Q@/߂?iK#i4 ?[>$?u<|=#wn>%`-jF~?ן D!OŞ,ǿ~[h 4 Ioំ?~ '-A7I?Ş ?h ~"j&8ܿ a?M>8Z{}Þ+O&/RoD?Xxc  h+'qe?75(?,{s6牼~'tk3үbD&~~x o^дO|Ty=?euM;$׾|3Ï8f(~xϊm {Ǿ y?o|??o']L|.E:|o<;9[|2\ˡ~6~?k 3q,|H' xx#ǯ~ ?퉩,xOi쯤}sܚ?u J_"6xPƯ9y{iZ~ j~9PK%[?ï(~.6|.'Ggo/ϏAu/ і>H4#kF?xx"~^"_MOw_~ҟ7'gᧈ!x^h,'oً|'"ž1~%|OR.?x(K?Fk~ x? @@;W)=?d/ $a+ߎj -Ge?'>53;mm3RjRYx3/~& ?0? /cJ-/C?_ݟ?0W*N‚>>xP?w׆|7g+;WtSw:e߀_|] nþş=^ӴWGW Hb? u QijL~xKk ~|M?fo?SNn6?rMw컮gEQEQEQEQEQEQEQEQEQE_sWqCE7q$U?>Wr7:`?Lx;/ k-ᕱHFl4]m?G5gҿjyO0__=~Ε W7gW$q_,ݜ@QE (QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_s_(*~? _ɺxd\q,Y|1n8Kş +h_*9 1|+?/? MWxz׉=/ŚǺg] Q]GV6>nDZu|x?^P#◈<_x_O_t%Yѿn.;Xk sI3_s[m^Ks'Szŏ R/^//xs<;iѿ|]KH _Jд BƧ閾m_?|#)~_ 'h'"X>)OA?8/٣7/ǿ|:G}xs2_S $~ўA'?R/Ŗu T~Þ:kUt?YkΝos $W{= eI,?2?g_x?mؿV_>?xI׋5O|⧊ :V}mCf~Wt=.YNu*kl((((((((((((((((((((((((?JYQK8U?q7E<&3o~\e?6Lq7_C5`8zsM) GI&ㄿY8,ω 5Wx/O?sR& <]-G_oGab/|"Ŭ|jY|7;o?fgG?0)O>NN~f/}<3ߧW' ;S!߲<5CvBx/u⟇~ $ǞGÏ! 2_gv>;?8x~?jG]C~E/><'|>+|UQҥu4KD:׆m 7jFߧ(((((((((((((((((((((((J?q|~?nxx3Mׄg$s'?j3ci?|sg:W1_?I E_=~Ε W9gW$q_,ݜ@QE (WR7_?Izoo_kKƿ"~@>)|:7f;㿇7" 4C3]ҵ=e)g6O`>xU=Wi_MoxǎٯZi>1g9|%>%.F-Ï|5|Aᛍ#Y KGgm?t|j/,<xGYڿ0i5վ"-K5=n}2~)x?Gw^: //Sºg???x'IׄO࿊|UciZuZ״?Y]h6v_Mlڍ{QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE)WAf?JYQ_ɺh[\k^p]_m'?og:ki8|p=?hgҿ'~,Y|1n8Kş (?E 77_G ?nool??(~,WUx _ ŞGÞ*🊼9k7|C4-^Tѵ.Q.`U?_,6 ? Ž!|[oHnx#׈?3+H7 GQ?l_wß*kkd@~O}įW?1~ ;#WW?m߃}7 |U_ڃ__-NKϋO?xVKt\ 624xWT?Ɩ+1f(d~˟;G _x⏋t?cO9~|@Ӳ𿇴o9🈴sHω_f{C?u-;S2x^ugúONZ^? gA;_|׊5xuMcm{~xGVe~Ծ?λywVhj6^*K<'?| />+k ׼-yk⻛~Ϟ>ol5}woŏ| |R)/^(g/xs,Y|1n8Kş (?E 77_G ?nool??((((mo+SP~0|w_Ro {?^nN״Uh~?c\/x&PW S'{xB Y,whg#f\-_M ~W/9ً iG:ΕS^/e0j٣czOƿsGtA 75#wGD|kf_@K+iW5/Nfc_>:gk߈~|%?:;4~_I.|hᖯ?&kak|Ytl4ڇxJ)gko{Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@8U>>9|q|~?nxx3Mׄg$s'qqͧ6u`9z+ U_JoH_>O7%b|A?n*Ϳًo_\~Ծ |:a$7o|-4o__'/X௎&x\ޓO~ҟw9Po߳߂,/_hV~Wl5/Cu}:;tF"|[ ]OG5o\`C:??ؗK!Ꮙj/ÏZoO IxF=x _p > ??:qWS텣z;ZfMCx{ׁ[|Y|Y_߶ o>4xzΝ? ¾#gMc&ψt{#^^Y6]iڦum}cs=Jo8?cι5wGe֓ ~?Ǟ4g??g[Ɵ> ~7>OXyCC)ٯ XWCN1<'uxWRW¿|CxfXҴ^yq]ji[M}i/- IEPEPEPEPEPEP^?;о)| i3oG~?^.𞥤xHZ~oS4˯6 |?yo|)}2^v ƵOŸ?%}SODgC#kʺc6x/yB|?#i?/m9oŏw|R)/g/x;]=KH_Uе?B>i^mlw}O+Ӵ_߿V}g Ѽ7h_Ï bqӞ|Y*?g°_־1ž 4]xMXu}S{k?/> ^{x[?me`?EPEPEPEPEPEPEPEPEPEPEPEPEPEPEP~?oG~ G)VtYg xIO7gƟO0__=~Ε Wɂ*Ytbϥ7/?Vb ~'g(OBAGv>~ۛ[}((((((((~,WUx _ ŞGÞ*🊼9k7|C4-^Tѵ.Q.`U {?7" nhӿXjOY߷]/xKAvGO~)O?~vos g?ঞX:~6~ _߇Ax2-o˫x;Y)|ijƓ{Gsk+&?*O' <+_?4 txY>5ΝM:KF^j~4O7%bQ_~ۛ[}77@ EPEPEPEPEPEPEPEPEPEPEP?ࣟww>~-,>;h'Rߴo[hZ5 ßiq Lk 0]~ _y+|8h&|A.W^=ƶ:mo ~׋uO xV-~qRZ_Wc &_+ׂ|9?BGGx^xᎍ/ q][xqb Esg|{_ &<O,w|'#<+=:X3H׼?zwZv][_Xm[EeWWuU)wڏভ7w GaCg^.O^5?EQEQEQEQEQEQEQEQEQEQEQEWwP+/'OxiigMSvGOQJ/ > W>UQWA?x^*ώ ox/ xzΣxO^mx>!l}gghΗykz0E*sk-gL __[)6~/xw,G|Hψge._~EPEPEPEPEPEPEPEPEPEP~?oG~ G)VtYp_ K놏/gƿfɂ*Ytb6L?qW_CN)!|Yc ?p?gWY*)W+_2+⟏/BxGw%_k=?e/>/7dt?R7RoşxG`?gx> Y]~- 9? |*')W?ΥH~l}???lG54Đo٫wgAk_K+ğ~0_|d_п uO}t߅Vw>| ӾPa>)x]/ƿZ%~0~L_|Mx#Ş.;?Afi=>˦iVQAmbQEQEQEQEQEQEQEQEQEQEQEQEQE/T? N7[g=_]en3/º|+yPռmx⥳ kw 'x@/ z((((((((((*89R+7>ٟ] X_$ύ U_<m'/gJ+SBef+Qɸ/ + A~ؗ㷇~ۛ[}(((((((((((((";_M(_>*)Q_xڏ<{^|X-Z]xx.Ú_ğ x7&Wtm&JOxPxOŞ|34Oп|AχT--u0<|MgQEQEQEQEQEQEQEQEQE_s[gtQ8U?q7E&3k ğYYu`9z+ U_JoH_>O7%bQ_~ۛ[}77@ EPEPEPEPEPEPEPEPEPEPEPEPEPEPy >~/|?g[Lj/uEWZӵM-|G?7:&xMӵO&NJlڗ|*x~x^wӵ}9縱/hZxO:vI|)F&iv_\&4am x<%uЮΏ7[C( ( ( ( ( ( ( ( (?q|~?n?JTk?Q_ɺhZq|kVn]_m'/gJ+i?|sg:W1_қRş+1_?`M سvqEW'_?twfkAGv>EQEQEQEQEQEQEQEQEQEQEQEQEQEW|'㿁|k[/7Ruo[wG:7_G4?PtOG?u=>Y(߷O?ڃ~3tϏz7è;GcGi.~3->'|[_E|[ܿt_j7Zρ5F|U/xsŚXj?sXl/'u/:㻿TuŎៅ"o+ox~_^> sg.σ;((((((((*89R8E<&3o YqY?6L?qW_C`9z+sM) GI&ㄿY8+P:;PQsݳaϵ_?twfhh((((((((((((((+o*O4VO_'OJYV& |?=ZFO=Z']k/~5;zu %oh߲Oh_?k[_j/]cឬ|N|=xCǚW2|Bt'ş = C Z ¾=|u_xƞ ox;>tWŞmx{sykt=SFt˭;TӮng)[(((((((*89R+7^ٞ] xo#ˌ͏ U_<m'/gJ+SBef+Qɸ/ (?/W- OG汧vڟm+¿-ψ3Eso ំ*m~ go#?j[ox\U[[WL'ğ^?ⶁo'?|7A'ǭc{:;PQsݳaϵ>1~.uu?_' |/О-c/ ?iof/ :Aac~5Wj:~A'o_Z>*|+Su?:>i~ 5;}fK5:QWQH&&Z( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (?o .?/쏬~şG;~~O~oa_ >7tM3nauAsiV xi> ]kzEo,|Y/{iiim>U~$cO Ʃj__h?*||M_xfiNWмAjz|Y?O'YmĚ6{Q@Q@Q@Q@Q@Q@Q@8U?r54R?O_h?xOf{Ow<2-8eƟfGɂ*Ytb6L?qW_CN})!|Yc ?p?gxGڿ_^D3GYx_ÚF{[|EA㍗~ X|27_ |M#^ >!-[xOW\~~o&Y|tI~G,i싏7M SkHSzwυ߁E;࿇Co?W' ;S!߲<5CvBx/u⟇~ $ǞGÏ! 2_gv>;?8x~? )_ٯ :xP?a3x[x/"Kqa_j7u׊~=6'_Ǿ ]_ŏx/~*O2> ?/@OK)4]_o ٚ>Mguoii~Zz}픳JWNGOUּ?=QEQEQEQEQEQE?j_Š_9R+7^ٞ] X_#ύ U_<m'/gJ+SBef+Qɸ/ (+~l~W((ٿg Z( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (?4 ~_Ʊ|f nx>kQx#|9G<ZF~!xNK^' |6_C= _*7o?¿_?k[_if|N|=xCzFH2=е[ş = g\W( ( ( ( ( (?q|~?n?J?Ɗx8/Mׄg%uG?_jsi?|sg:W1_?I& 8gҿ'~,Y|1n8Kş (?E 77_G ?nool??(((((((((((((((((wo*V4;㧇OJYV*D& |?=&Y¿Z'{׌5xŚu WN᯿a&aScx ~_>xS-?oB|As!|GH=B[qbx_QEQEQEQEQE)UAfO9~>'~ g xIO/gƿfɂ*Ytbo6Lq7_C5N})!|Yc ?p?gQE~~G ?nool?~l-Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@I(ڷG^ ;x;j3 W־3izC߆:7|G2/NJ|Cmumň^ƿ% 0|?o/^&4OH Úo<#cxO&/34 Aqcymsg}oyktGþ,t[¾2𮭬Sz6gT~uؿ5z~?k Sχf?U:5x~&x/uS|+j:%Χxך?u??*8~N#>~֞ gNK/z[ý2x _ƿ +_ iOOhֺuƝA>4 \êj5xIOj,mF¶zkڽ/ƿ 8~ў:Ax'cNNV_~ ּu?6:ƫ 4+}T4m:QWNyo!  (ـ~ο((/9R(*8 u? ?}?,ZO0__=~Ε Wɂ*Ytbϥ7/?Vb ~'g(OB(?~~ؿl/mO|4k>x_ 9c>jAjchΣ>:Nu_a G{"_>a G?~}_X?,@ jŗ k[ ?/MqG@YE& O o2 $i—W,Y[ L)?/ c\Q1QI+??MqG@YE&?/i7e4⿿((W?.|(+C_Y_<9'LJ< ? ӿ*C_o 6C|'YGß>N'o?i¬~0i 7WSo#7O*?/Mq^?S JxWP?:O.'x࿊|UciZu״?Y]h6v_MlڍkS4M[KI4Q ',l~_ֿ|?2-(XKG)rf4mWc k _e4Mq_ _o+??/i7P1QI((WQ@@YE& c\WEOcG?| m+?} |BӼ[J[j; LVk={? ¾&׎^_|gŞ1?c;Þ|9\!7C~6zF H5gTӴ: h%j|j?e/~ |VX~oߋ^W~;w lhW/>[|\b|"[DxwK߰ǎ~ x/GO|C?t[3œ%4ؖ>:~4/]~:ǂS?/eώ>о)||?E[,xs=ƝA?5?w?V//^*ϋOtÿ/woxa'_?o;?p_ k3 kuoZOKƿ +xNu ! 4-sTѭ$n4UaMq_?)?.?#?Mi݌KV GhLo4M'7I4 ?',l~п_𨼏?2§t7-(W?5@@YE& c\WEe4Mq_O WUx ~ ѼYO?|9 Úxg:?g> е{;=SFt]GKmmn`)W^c_)ne]g?PO>-~ ^wu8hw▝?)?<%';Ś? t{_á\z~+ Q@?d)'iFzgq&Ǜ=FO~~~ўf?੺ͳV¿i~,F·͎:Ŏ?d)'iFzgq&Ǜ=FO~~~ўf?੺ͳV¿i~,F·͎:Ŏ~׀~~2>9Gg_FtxKg$^11|]#'xǶP|c3bxƞ |YP ?x^#nu!<y u{SYuK˭GTnogY[T ?V‹i+T *U o"_[G?'og-z ~,M oO2#?7ß cP Gjgo5=CSoong( ( ( ( ~߲~5im ,_^7} aM~!xwÚw|U Wt?>#gOoho>_[3+pC110?fw?a??dh4E𧭿"vqԇba??di?0#lI]:4Ep!/?+¾јIZ?0?fF֏OWY/, 7L?+pO?810?fW_<+0?WG~δM>_Ed|)"nqԇba_$C/F6N֏O[+%śOVkL?+pJ1Q_'FI]:ҏ<+1M>Ohg_En 2Q_7FI]:Ra??diĚ}"fSU;8C|A:O+0?WG~δ rO_FҏO_Y/, |A[79CYca?̇$C'F6N֏O[+%śOVkL?+pC110?f }i+:?0?f#Jҏ?_9/, |A[?;8C|A9O+đu# sF`$nh3E4'sCwEWÓ6`$i0?fw?Ě}"fS[Va[?79?gTW|90?7WÓ6a%t?GI/o>_[?!=mR?Ψ# sFa'sGF6N֏?_9/, |A[?;8C|A:_'lCOß3;Z_&H"_YoYEn1?+~ј:90͓uHd|)o-_?;9?:_'lCOß3;Z?M>_Ed|)[?;8C|C10?fw?a??dh4E_Yo濤"vqԃba??dh~ј:i+$śOFf#D8>hΨ# sFa'sGF6N֏OWY', 70!>_ GuEOß3;Z?0?fW_M>_Ed|*_#Ck?+¾јIZ_+lC?O_Y/, |C??W\Ψ# sFa'sGF6N֏O['%śOVh?+pGgqH<gTW90͓u# sFa'sGI/o>_[!>_ GuEOß3;Z?0?fw?ę"fSUE~1o9RYswi /$g$xcO :j ~|!hVBDX}%YK2if?ῇ\?Pca|r,4a0?iZR_*,N5cCĜO]zg82KEWWWNjSԢ(ϰ ( ( ( ( ( ( ( ( ( ( ( ( (#T^ aUQE<}&X3x3`QE,~QEQEQEQEQEQEQEQEQEQEQEQEdoc/set_lp_name.htm0000644000175000017500000000434410237176664013310 0ustar renerene set_lp_name

set_lp_name

Set the name of the lp.

unsigned char set_lp_name(lprec *lp, char *lpname);

Return Value

set_lp_name returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

lpname

The name for the lp.

Remarks

The set_lp_name sets the name of the lp.
Giving the lp a name is optional. The default name is "Unnamed".

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_lp_name(lp, "test");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_lp_name

doc/is_semicont.htm0000644000175000017500000000507010237176660013327 0ustar renerene is_semicont

is_semicont

Gets the type of the variable. semi-continuous or not.

unsigned char is_semicont(lprec *lp, int column);

Return Value

is_semicont returns TRUE (1) if the variable is set as semi-continuous, FALSE (0) otherwise.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be checked. It must be between 1 and the number of columns in the lp.

Remarks

The is_semicont function returns if a variable must be semi-continuous or not. Default a variable is not semi-continuous. See semi-continuous variables for a description about semi-continuous variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char sc;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  sc = is_semicont(lp, 1); /* will return 0 since the variable is not set as semi-continuous at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_semicont

doc/print_constraints.htm0000644000175000017500000000601410237215326014566 0ustar renerene print_constraints

print_constraints

Prints the values of the constraints of the lp.

void print_constraints(lprec *lp, int columns);

Return Value

print_constraints has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

columns

Number of columns to print solution.

Remarks

The print_constraints function prints the values of the constraints of the lp. This can only be done after a successful solve.
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_constraints(lp, 1);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_constraints, get_constr_value, print_lp, print_objective, print_solution, print_duals, print_scales, print_tableau, print_str, set_outputstream, set_outputfile, print_debugdump

doc/Semi-ContinuousVariables_files/0000755000175000017500000000000010762557071016355 5ustar renerenedoc/Semi-ContinuousVariables_files/img00340.gif0000644000175000017500000000430207755240700020202 0ustar renereneGIF89a!,H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ ,È{0cK22˘?.gMzaҨS YάEM96ےc{ݽ-pƓZsK}uկkO}wݿ~yϫ~{_}'Mh d&ȟjmZ RjFnUhSMu8ڇ *܈%؄nR"z$6V㌊h#蘏<\p@ Ӑi$KH(5iܓP$erTV ҕe%G\:ܘd&lidukЛ)'Btjgݞ|m _*P*:A:j3Jz%Zj z*:J$* ٺ%x%Z*{b2;NBl) V&Ur[-lNjnXn;&adi 0u +++5 q/{i r<{ %׉Ϯ.eNIsDޜGrE<@64Ev4IS4N38--uY}5֙i5׵QMd^LjvIe"-ܾM`_v]qWD'];8t_]BK\yoţVWqg-::\mN{Kh;^;[ ?<5g;7ԉѿű[ˏ=8yw6'Zr |d09I(FT$'BMjgdOYT򕰌,gIZ̥.w^d\(72ʩGD'8Fͬ+C=1T4OcV2,CB3m9րr~\';g"Ow&VEM1GE ՇyJR,0z>)ԙJ(Y2hF4GR`c% Avepդ::=r24M 3R]+d~ T4C9*LNtOERBEuWeOV2Um<_m(r*ҖE<ֶ$ ;doc/Semi-ContinuousVariables_files/bsscdhtm.js0000644000175000017500000021432307755240700020523 0ustar renerene//////////BSSCDHTML Section 1////////// // RoboHELP Dynamic HTML Effects Script // Copyright 1998-2000 eHelp Corporation. All rights reserved. // Version=3.72 // Warning: Do not modify this file. It is generated by RoboHELP and changes will be overwritten. //{{HH_SYMBOL_SECTION var HH_ChmFilename = ""; var HH_WindowName = ""; var HH_GlossaryFont = ""; var HH_Glossary = ""; var HH_Avenue = ""; var HH_ActiveX = false; //}}HH_SYMBOL_SECTION var gbNav4 = false; var gbIE4 = false; var gbIE = false; var gbIE5 = false; var gbIE55 = false; var gAgent = navigator.userAgent.toLowerCase(); var gbMac = (gAgent.indexOf("mac") != -1); var gbWindows = ((gAgent.indexOf("win") != -1) || (gAgent.indexOf("16bit") != -1)); var error_count = 0; gbIE = (navigator.appName.indexOf("Microsoft") != -1); if (parseInt(navigator.appVersion) >= 4) { gbNav4 = (navigator.appName == "Netscape"); gbIE4 = (navigator.appName.indexOf("Microsoft") != -1); if (gbIE4) { if (gAgent.indexOf("msie 5.0") != -1) { gbIE5 = true; } if (gAgent.indexOf("msie 5.5") != -1) { // curently IE 5.5 has some buggy stuff. we need do some remedy to our code. gbIE55 = true; } } } function HHActivateComponents() { if (HH_ActiveX && (HH_ChmFilename != "") && ((self == top) || (self == top.frames[0]))) { var objBody = document.all.tags("BODY")[0]; if( typeof(objBody) == "object" ) { objBody.insertAdjacentHTML("beforeEnd", ''); if (HHComponentActivator.object) { HHComponentActivator.Activate(HH_ChmFilename, HH_WindowName, HH_GlossaryFont, HH_Glossary, HH_Avenue); } } } } var gAmc = new Array(); var BSSCSequenceIndex = 0; function animationContext(el, progressAnimation, finishAnimiation, animationDuration, animationPeriod) { this.el = el; this.progressAnimation = progressAnimation; this.finishAnimiation = finishAnimiation; this.animationDuration = parseFloat(animationDuration); this.animationPeriod = animationPeriod; this.animationStartTime = (new Date()).getTime(); this.continueAnimation = true; } function progressFade(ndx) { if( typeof( gAmc[ndx].el.filters.alpha ) != "object" ) return; percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0){ percent = 1.0; gAmc[ndx].continueAnimation = false; } gAmc[ndx].el.filters.alpha.opacity = gAmc[ndx].initialOpacity*(1.0-percent) + gAmc[ndx].finalOpacity*percent; } function finishFade(ndx) { if( typeof( gAmc[ndx].el.filters.alpha ) == "object" ) gAmc[ndx].el.filters.alpha.opacity = parseInt(gAmc[ndx].finalOpacity); } function progressTranslation(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } gAmc[ndx].el.style.pixelLeft = gAmc[ndx].startX*(1.0-percent) + gAmc[ndx].finalX*percent; gAmc[ndx].el.style.pixelTop = gAmc[ndx].startY*(1.0-percent) + gAmc[ndx].finalY*percent; } function progressSpiral(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } rf = 1.0 - percent t = percent * 2.0*Math.PI rx = Math.max(Math.abs(gAmc[ndx].el.initLeft), 200) ry = Math.max(Math.abs(gAmc[ndx].el.initTop), 200) gAmc[ndx].el.style.pixelLeft = Math.ceil(-rf*Math.cos(t)*rx) gAmc[ndx].el.style.pixelTop = Math.ceil(-rf*Math.sin(t)*ry) gAmc[ndx].el.style.visibility="visible" } function progressElasticFromRight(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } rf=Math.exp(-percent*7) t = percent * 1.5*Math.PI rx =Math.abs(gAmc[ndx].el.initLeft) gAmc[ndx].el.style.pixelLeft = rf*Math.cos(t)*rx gAmc[ndx].el.style.pixelTop = 0 gAmc[ndx].el.style.visibility="visible" } function progressElasticFromBottom(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } rf=Math.exp(-percent*7) t = percent * 1.5*Math.PI rx =Math.abs(gAmc[ndx].el.initTop) gAmc[ndx].el.style.pixelLeft = 0 gAmc[ndx].el.style.pixelTop = rf*Math.cos(t)*rx gAmc[ndx].el.style.visibility="visible" } function progressZoomIn(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1; gAmc[ndx].continueAnimation = false; } for (var index=0; index= 1.0) { finishZoom(ndx); } } function progressZoomOut(ndx) { percent = ((new Date()).getTime() - gAmc[ndx].animationStartTime)/gAmc[ndx].animationDuration; if (percent > 1.0) { percent = 1.0; gAmc[ndx].continueAnimation = false; } for (var index=0; index= 1.0) { finishZoom(ndx); } } function finishTranslation(ndx) { gAmc[ndx].el.style.pixelLeft = parseInt(gAmc[ndx].finalX); gAmc[ndx].el.style.pixelTop = parseInt(gAmc[ndx].finalY); } function finishZoom(ndx) { for (i=0; i BSSCSequenceIndex && (!bFound || objectOrder < minBSSCSequenceIndexFound)) { minBSSCSequenceIndexFound = objectOrder; bFound = true; } } } if (bFound) { BSSCSequenceIndex = minBSSCSequenceIndexFound; bStarted = startAnimationSet(BSSCSequenceIndex); } } function getOffsetFromTopOfBrowser(el) { if (null == el.offsetParent) return el.offsetTop; else return el.offsetTop + getOffsetFromTopOfBrowser(el.offsetParent); } function startAnimationSet(ndx) { var m = 0; bStarted = false; // Find document elements with "BSSCAnimationType" attribute divElements = document.all.tags("DIV"); for (var index = 0; index < divElements.length; index++) { el = divElements[index]; animationType = el.getAttribute("BSSCAnimationType", false); if(null != animationType) { framePeriod = el.getAttribute("BSSCFramePeriod", false); frameCount = el.getAttribute("BSSCFrameCount", false); sequenceIndex = el.getAttribute("BSSCObjectOrder", false); // Stop any currently running RevealTrans filters if ("RevealTrans" == animationType && parseInt(sequenceIndex) == ndx-1 && gbWindows) el.filters.RevealTrans.stop(); // Filter on ndx if (0 == ndx && null == sequenceIndex || ndx == parseInt(sequenceIndex)) { if ("FlyInFromRight" == animationType) { animationDuration = el.getAttribute("BSSCDuration", false); if (null == animationDuration) animationDuration = 1000; // default to 1s gAmc[m] = new animationContext(el, progressTranslation, finishTranslation, animationDuration, 10); gAmc[m].startX = document.body.clientWidth + document.body.scrollLeft; gAmc[m].startY = 0; gAmc[m].finalX = 0; gAmc[m].finalY = 0; animationPump(m++); bStarted = true; } if ("FlyOutToRight" == animationType) { animationDuration = el.getAttribute("BSSCDuration", false); if (null == animationDuration) animationDuration = 1000; // default to 1s gAmc[m] = new animationContext(el, progressTranslation, finishTranslation, animationDuration, 10); gAmc[m].startX = 0; gAmc[m].startY = 0; gAmc[m].finalX = document.body.clientWidth + document.body.scrollWidth; gAmc[m].finalY = 0; animationPump(m++); bStarted = true; } if ("FlyInFromLeft" == animationType) { animationDuration = el.getAttribute("BSSCDuration", false); if (null == animationDuration) animationDuration = 1000; // default to 1s for (childIndex=0; childIndex 0) && (document.images[0].src.indexOf('bsscnav1.gif') != -1)) { document.links[0].href = "javascript:void(null);"; } } } return; } ////////////////////////////////////////////////////////////////////////////////////////////// // // Begin DHTML Popup Functions // ////////////////////////////////////////////////////////////////////////////////////////////// //variables used to isolate the browser type var gBsDoc = null; var gBsSty = null; var gBsHtm = null; var gBsStyVisShow = null; var gBsStyVisHide = null; var gBsClientWidth = 640; var gBsClientHeight = 480; var gBsBrowser = null; // here is the varible for judge popup windows size. these parameter is for IE5.0, it may need adjust for others. var gBRateH_W = 0.618; // 1.618 Golden cut. var gBMaxXOfParent = 0.8; var gBMaxYOfParent = 0.8; var gBscrollHeight = 16; var gBscrollWidth = 16; var gBpermitXDelta = 3; var gBpermitYDelta = 3; //the browser information itself function _BSPSBrowserItself() { var agent = navigator.userAgent.toLowerCase(); this.major = parseInt(navigator.appVersion); this.minor = parseFloat(navigator.appVersion); this.ns = ((agent.indexOf('mozilla') != -1) && ((agent.indexOf('spoofer') == -1) && (agent.indexOf('compatible') == -1))); this.ns2 = ((this.ns) && (this.major == 2)); this.ns3 = ((this.ns) && (this.major == 3)); this.ns4 = ((this.ns) && (this.major >= 4)); this.ie = (agent.indexOf("msie") != -1); this.ie3 = ((this.ie) && (this.major == 2)); this.ie4 = ((this.ie) && (this.major >= 4)); this.op3 = (agent.indexOf("opera") != -1); if (this.ns4) { gBsDoc = "document"; gBsSty = ""; gBsHtm = ".document"; gBsStyVisShow = "show"; gBsStyVisHide = "hide"; } else if (this.ie4) { gBsDoc = "document.all"; gBsSty = ".style"; gBsHtm = ""; gBsStyVisShow = "visible"; gBsStyVisHide = "hidden"; } } //Here is the browser type function _BSPSGetBrowserInfo() { gBsBrowser = new _BSPSBrowserItself(); } //Get client size info function _BSPSGetClientSize() { if (gBsBrowser.ns4) { gBsClientWidth = innerWidth; gBsClientHeight = innerHeight; } else if (gBsBrowser.ie4) { gBsClientWidth = document.body.clientWidth; gBsClientHeight = document.body.clientHeight; } } var gstrPopupID = 'BSSCPopup'; var gstrPopupShadowID = 'BSSCPopupShadow'; var gstrPopupTopicID = 'BSSCPopupTopic'; var gstrPopupIFrameID = 'BSSCPopupIFrame'; var gstrPopupIFrameName = 'BSSCPopupIFrameName'; var gstrPopupSecondWindowName = 'BSSCPopup'; var gPopupDiv = null; var gPopupDivStyle = null; var gPopupShadow = null; var gPopupTopic = null; var gPopupIFrame = null; var gPopupIFrameStyle = null; var gPopupWindow = null; var gnPopupClickX = 0; var gnPopupClickY = 0; var gnPopupScreenClickX = 0; var gnPopupScreenClickY = 0; var gbPopupTimeoutExpired = false; var gbScriptName = "EHELP_DHTM"; var gbPathofJS = ""; if (gbIE4) { var aScripts = document.scripts; var aScript = null; var i = 0; for (i = 0; i < aScripts.length ; i ++ ) { if (aScripts[i].name == gbScriptName) { aScript = aScripts[i]; break; } } if (aScript != null) { var nPathPos = 0; var strCurrentSrc = ""; strCurrentSrc = aScript.src; var nPathPos1 = strCurrentSrc.lastIndexOf("\\"); var nPathPos2 = strCurrentSrc.lastIndexOf("/"); if (nPathPos1 > nPathPos2) nPathPos = nPathPos1 + 1; else nPathPos = nPathPos2 + 1; gbPathofJS = strCurrentSrc.substring(0, nPathPos); } } // Replace point - Used by SingleSource // var gbBlankPageForIFrame = gbPathofJS + "_blank.htm"; var gbBlankPageForIFrame = "about:blank"; if (BSSCPopup_IsPopup()) { document.write(""); } function DHTMLPopupSupport() { if ((gbIE4) && (!gbMac)) { return true; } return false; } function BSSCPopup_IsPopup() { if (DHTMLPopupSupport() && (this.name == gstrPopupIFrameName)) { return true; } else if ((gbNav4 || gbIE4) && (this.name == gstrPopupID)) { return true; } else { return false; } } function _BSSCCreatePopupDiv() { if (gPopupDiv == null) { if (DHTMLPopupSupport()) { document.write(""); var tempColl = document.all.tags("DIV"); for (var iDiv = 0; iDiv < tempColl.length; iDiv++) { if (tempColl(iDiv).id == gstrPopupID) { gPopupDiv = tempColl(iDiv); } if (tempColl(iDiv).id == gstrPopupShadowID) { gPopupShadow = tempColl(iDiv); } if (tempColl(iDiv).id == gstrPopupTopicID) { gPopupTopic = tempColl(iDiv); } } gPopupIFrame = eval("gPopupDiv.document.frames['" + gstrPopupIFrameName + "']"); gPopupDivStyle = eval("gPopupDiv" + gBsSty); gPopupIFrameStyle = eval(gBsDoc + "['" + gstrPopupIFrameName + "']" + gBsSty); } } } function BSSCPopup_Timeout() { if ((gPopupIFrame.document.readyState == "complete") && (gPopupIFrame.document.body != null) && (gPopupIFrame.location.href.indexOf(gbBlankPageForIFrame) == -1)) { BSSCPopup_TimeoutReal(); } else { setTimeout("BSSCPopup_Timeout()", 100); } } function BSSCPopup_TimeoutReal() { window.gbPopupTimeoutExpired = true; if (gPopupIFrame.document) { BSSCPopup_ChangeTargettoParent(gPopupIFrame.document); gPopupIFrame.document.body.onclick = BSSCPopupClicked; } document.onmousedown = BSSCPopupParentClicked; } function BSSCPopup_ChangeTargettoParent(tagsObject) { var collA = tagsObject.all.tags("A"); var j = 0; if (collA != null) { for (j = 0; j < collA.length; j ++ ) { collA[j].target = "_parent"; } } } function BSPSPopupTopicWinHelp(strURL) { _BSSCPopup(strURL); return; } function _BSSCPopup(strURL) { if (DHTMLPopupSupport()) { // If we are already in a popup, replace the contents if (BSSCPopup_IsPopup()) { location.href = strURL; parent.window.gbPopupTimeoutExpired = false; if (gbMac) { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 400); } else { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 100); } } else { // Load the requested URL into the IFRAME gPopupIFrame.location.href = strURL; window.gbPopupTimeoutExpired = false; if (gbMac) { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 400); } else { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 100); } } } else { _BSSCPopup2(strURL); } return; } function _BSSCPopup2(strURL) { if (window.name == gstrPopupSecondWindowName) { window.location = strURL; } else { BSSCHidePopupWindow(); var nX = 0; var nY = 0; var nHeight = 300; var nWidth = 400; _BSPSGetClientSize(); if (gBsBrowser.ns4) { nX = window.screenX + (window.outerWidth - window.innerWidth) + window.gnPopupClickX; nY = window.screenY + (window.outerHeight - window.innerHeight) + window.gnPopupClickY; if (nY + nHeight + 40 > screen.availHeight) { nY = screen.availHeight - nHeight - 40; } if (nX + nWidth + 40 > screen.availWidth) { nX = screen.availWidth - nWidth - 40; } } else { nX = window.gnPopupScreenClickX; nY = window.gnPopupScreenClickY; } // Launch a separate window var strParam = "titlebar=no,toolbar=no,status=no,location=no,menubar=no,resizable=yes,scrollbars=yes"; if (gBsBrowser.ns) { strParam += ",OuterHeight=" + nHeight + ",OuterWidth=" + nWidth; strParam += ",screenX=" + nX + ",screenY=" + nY; strParam += ",dependent=yes"; } else { strParam += ",height=" + nHeight + ",width=" + nWidth; strParam += ",left=" + nX + ",top=" + nY; } window.gPopupWindow = window.open(strURL, gstrPopupSecondWindowName, strParam); if (gBsBrowser.ns4) { window.gPopupWindow.captureEvents(Event.CLICK | Event.BLUE); window.gPopupWindow.onclick = NonIEPopup_HandleClick; window.gPopupWindow.onblur = NonIEPopup_HandleBlur; } else if (gBsBrowser.ie4) { window.gPopupWindow.focus(); } } return; } function NonIEPopup_HandleBlur(e) { window.gPopupWindow.focus(); } function NonIEPopup_HandleClick(e) { // Because navigator will give the event to the handler before the hyperlink, let's // first route the event to see if we are clicking on a Popup menu in a popup. document.routeEvent(e); // If a popup menu is active then don't do anything with the click if (window.gPopupWindow.gbInPopupMenu) { window.gPopupWindow.captureEvents(Event.CLICK); window.gPopupWindow.onclick = NonIEPopup_HandleClick; return false; } // Close the popup window if (e.target.href != null) { window.location.href = e.target.href; if (e.target.href.indexOf("BSSCPopup") == -1) { this.close(); } } else { this.close(); } return false; } function BSSCPopup_AfterLoad(strURL) { if (typeof(window.gPopupIFrame.document) == "unknown") { _BSSCPopup2(strURL); return; } if ((window.gPopupIFrame.document.readyState == "complete") && (window.gPopupIFrame.document.body != null) && (window.gPopupIFrame.location.href.indexOf(gbBlankPageForIFrame) == -1)) { BSSCPopup_ResizeAfterLoad(strURL); } else { setTimeout("BSSCPopup_AfterLoad('" + strURL + "')", 200); } } function BSSCPopup_ResizeAfterLoad(strURL) { window.gPopupDivStyle.visibility = gBsStyVisHide; // Determine the width and height for the window //var size = new BSSCSize(0, 0); //BSSCGetContentSize(window.gPopupIFrame, size); //var nWidth = size.x; //var nHeight = size.y; _BSPSGetClientSize(); var size = new BSSCSize(0, 0); BSSCGetContentSize(window.gPopupIFrame, size); // Determine the width and height for the window var nWidth = size.x; var nHeight = size.y; window.gPopupDivStyle.width = nWidth; window.gPopupDivStyle.height = nHeight; // Determine the position of the window var nClickX = window.gnPopupClickX; var nClickY = window.gnPopupClickY; var nTop = 0; var nLeft = 0; if (nClickY + nHeight + 20 < gBsClientHeight + document.body.scrollTop) { nTop = nClickY + 10; } else { nTop = (document.body.scrollTop + gBsClientHeight) - nHeight - 20; } if (nClickX + nWidth < gBsClientWidth + document.body.scrollLeft) { nLeft = nClickX; } else { nLeft = (document.body.scrollLeft + gBsClientWidth) - nWidth - 8; } if (nTop < document.body.scrollTop ) nTop = document.body.scrollTop + 1; if (nLeft< document.body.scrollLeft) nLeft = document.body.scrollLeft + 1; window.gPopupDivStyle.left = nLeft; window.gPopupDivStyle.top = nTop; // Set the location of the background blocks window.gPopupShadow.style.left = 6; window.gPopupShadow.style.top = 6; if (gbIE55) { window.gPopupShadow.style.left = 4; window.gPopupShadow.style.top = 4; } window.gPopupShadow.style.width = nWidth; window.gPopupShadow.style.height = nHeight; window.gPopupTopic.style.width = nWidth; window.gPopupTopic.style.height = nHeight; if (gbIE55) { window.gPopupShadow.style.width = nWidth + 2; window.gPopupShadow.style.height = nHeight + 2; window.gPopupTopic.style.width = nWidth + 2; window.gPopupTopic.style.height = nHeight + 2; } if (gbMac) { // Total hack on the iMac to get the IFrame to position properly window.gPopupIFrameStyle.pixelLeft = 100; window.gPopupIFrameStyle.pixelLeft = 0; // Explicitly call BSSCOnLoad because the Mac doesn't seem to do it window.gPopupIFrame.window.BSSCOnLoad(); } //var nOriWidth = window.gPopupIFrameStyle.width window.gPopupIFrameStyle.width = nWidth; window.gPopupIFrameStyle.height = nHeight; if (gbIE55) { window.gPopupIFrameStyle.top = 0; window.gPopupIFrameStyle.left = 0; } gPopupIFrame.location.href = strURL; // reload again, this will fix the bookmark misunderstand in IE5. window.gPopupDivStyle.visibility = gBsStyVisShow; setTimeout("BSSCPopup_Timeout();", 100); return false; } function BSSCSize(x, y) { this.x = x; this.y = y; } function BSSCGetContentSize(thisWindow, size) { if (!((gBsBrowser.ie4) || (gBsBrowser.ns4))) return; if (gbMac) { size.x = 300; size.y = 300; return; } // Resize the width until it is wide enough to handle the content // The trick is to start wide and determine when the scrollHeight changes // because then we know a scrollbar is necessary. We can then go back // to the next widest size (for no scrollbar) var ClientRate = gBsClientHeight / gBsClientWidth; var GoldenSize = new BSSCSize(0,0); GoldenSize.x = gBsClientWidth * gBMaxXOfParent; GoldenSize.y = gBsClientHeight *gBMaxYOfParent ; if (ClientRate > gBRateH_W) { GoldenSize.y = GoldenSize.x * gBRateH_W; } else { GoldenSize.x = GoldenSize.y / gBRateH_W; } // Try to using parent specified max x. var x = 0; var maxgoldx = GoldenSize.x; var maxx = gBsClientWidth * gBMaxXOfParent; // This double resize causes the document to re-render (and we need it to) thisWindow.moveTo(10000,10000); // this is used to fix the flash on IE4. thisWindow.resizeTo(1, 1); thisWindow.resizeTo(1, 1); thisWindow.resizeTo(maxgoldx, thisWindow.document.body.scrollHeight + gBscrollHeight); thisWindow.resizeTo(maxgoldx, thisWindow.document.body.scrollHeight + gBscrollHeight); var miny = thisWindow.document.body.scrollHeight + gBscrollHeight; if (miny > GoldenSize.y) // the popup does not fix in the parent wanted golden area. so try to expand itself as large as it can { thisWindow.resizeTo(maxx , thisWindow.document.body.scrollHeight + gBscrollHeight); thisWindow.resizeTo(maxx , thisWindow.document.body.scrollHeight + gBscrollHeight); miny = thisWindow.document.body.scrollHeight + gBscrollHeight; maxy = gBsClientHeight * gBMaxYOfParent; if (miny > maxy) { // the popup must have a scroll, OK let it be. miny = maxy; size.x = maxx; size.y = maxy; } else { // popup still can fit in the parent area by someway. now we choose the same h/w rate as parent. size.y = miny; // downsize from maxx , now I try to using binary divide. x = maxx; deltax = -maxx/2; //j = 0; while (true) { x = x + deltax; thisWindow.resizeTo(x, miny); thisWindow.resizeTo(x, miny); diffy = thisWindow.document.body.scrollHeight + gBscrollHeight - x * ClientRate; if (diffy > gBpermitYDelta ) // it is higher than wanted, so x need to be wide a little bitter deltax = Math.abs(deltax) /2; else if (diffy < -gBpermitYDelta) // it is shorter than wanted, so x need to be narrow a little bitter deltax = -Math.abs(deltax) /2; else // the y is close enough to wanted. break; if (Math.abs(deltax) < gBpermitXDelta) // the next change is too slight and it can be ignore. break; //j ++; } size.x = thisWindow.document.body.scrollWidth; //+ gBscrollWidth; size.y = thisWindow.document.body.scrollHeight;// + gBscrollHeight; thisWindow.document.body.scroll = 'no'; // At this time we do not want to show scroll any more. so it will looks better a little. // Handle absurd cases just in case IE flakes // if (size.y < 100) { // size.y = 100; // } } } else { // downsize from maxgoldx , now I try to using binary divide. x = maxgoldx; deltax = -maxgoldx/2; //i = 0; while (true) { x = x + deltax; thisWindow.resizeTo(x, miny); thisWindow.resizeTo(x, miny); diffy = thisWindow.document.body.scrollHeight + gBscrollHeight - x * gBRateH_W; if (diffy > gBpermitYDelta ) // it is higher than wanted, so x need to be wide a little bitter deltax = Math.abs(deltax) /2; else if (diffy < -gBpermitYDelta) // it is shorter than wanted, so x need to be narrow a little bitter deltax = -Math.abs(deltax) /2; else // the y is close enough to wanted. break; if (Math.abs(deltax) < gBpermitXDelta) // the next change is too slight and it can be ignore. break; //i ++; } size.x = thisWindow.document.body.scrollWidth ;//+ gBscrollWidth; size.y = thisWindow.document.body.scrollHeight ;//+ gBscrollHeight; thisWindow.document.body.scroll = 'no'; // At this time we do not want to show scroll any more. so it will looks better a little. } if ((gbIE4) && (!gbIE5)) { size.x = size.x + 16; //reserve a width for scrollbar (IE 4.0 only) } thisWindow.resizeTo(size.x, size.y); thisWindow.resizeTo(size.x, size.y); return; } function BSSCPopupParentClicked() { BSSCPopupClicked(); return; } function BSSCPopupClicked() { if (!window.gbPopupTimeoutExpired) { return false; } if (gPopupIFrame.window.gbInPopupMenu) { return false; } // Give the user a message about javascript calls through objects. if ((gPopupIFrame.window.event != null) && (gPopupIFrame.window.event.srcElement != null) && (gPopupIFrame.window.event.srcElement.tagName == "A") && (gPopupIFrame.window.event.srcElement.href.indexOf("javascript:") == 0) && (gPopupIFrame.window.event.srcElement.href.indexOf(".") != -1)) { gPopupIFrame.window.event.cancelBubble = true; alert('Hyperlinks to objects do not work in popups.'); return false; } if (gPopupIFrame.document) { gPopupIFrame.document.body.onclick = null; } document.onclick = null; document.onmousedown = null; // Simply hide the popup gPopupDivStyle.visibility = gBsStyVisHide; gPopupIFrame.location.href = gbBlankPageForIFrame; return true; } //trace the mouse over's position for hotspot function BSPSPopupOnMouseOver(event) { if (gBsBrowser.ie4) { window.gnPopupClickX = event.clientX + document.body.scrollLeft; window.gnPopupClickY = event.clientY + document.body.scrollTop; window.gnPopupScreenClickX = event.screenX; window.gnPopupScreenClickY = event.screenY; } else if (gBsBrowser.ns4) { window.gnPopupClickX = event.pageX; window.gnPopupClickY = event.pageY; } } function BSSCHidePopupWindow() { if (window.gPopupWindow != null) { if (gBsBrowser.ns4) { if ((typeof window.gPopupWindow != "undefined") && (!window.gPopupWindow.closed)) { window.gPopupWindow.close(); window.gPopupWindow = null; } } } return; } var gbPopupMenuTimeoutExpired = false; var gbInPopupMenu = false; var gbPopupMenuTopicList = null; ////////////////////////////////////////////////////////////////////////////////////////// // // Popup Menu code // ////////////////////////////////////////////////////////////////////////////////////////// function _WritePopupMenuLayer() { if (gbNav4) { //Do not try to write ininle styles for NS! NS can not handle it and will not stop downloading the html page... document.write("
"); } else { document.write(""); if (gbIE4) { document.write(""); } } } //Define variable arguments as: strTitle, strUrl function PopupMenuTopicEntry() { this.strTitle = PopupMenuTopicEntry.arguments[0]; this.strURL = PopupMenuTopicEntry.arguments[1]; } // If the topic list is set, it is an array of TopicEntry objects (defined in WebHelp3.js) function PopupMenu_SetTopicList(aPopupTopicArray) { gbPopupMenuTopicList = aPopupTopicArray; } //Seek for the bsscright frame function _SeekFrameByName( cRoot, strName ) { if( cRoot == null ) return null; if( cRoot.frames == null ) return null; if( cRoot.frames[strName] != null ) return cRoot.frames[strName]; for (var i=0; i"); wndPopupLinks.document.write(""); var strParaLine = ""; for (var i = 0; i < (argLen - 2) / 2; i++) { strParaLine = ""; strParaLine += ""); wndPopupLinks.document.close(); window.gbInPopupMenu = true; if (!gbIE) { wndPopupLinks.focus(); } return false; } // Make sure we have reasonable arguments var argLen = fn_arguments.length; if (argLen < 3) { return false; } // Check to see if we only have one target var strTarget = ""; if (((argLen < 5) && ((isNaN(fn_arguments[2])) || (gbPopupMenuTopicList == null))) || ((argLen < 4) && ((!isNaN(fn_arguments[2])) && (gbPopupMenuTopicList != null)))) { // Get the place that we will be putting the topic into var targetDoc = null; if (fn_arguments[1] == '') { targetDoc = window.document; } else { targetDoc = _GetFrameByName( parent, fn_arguments[1] ); if (targetDoc == null) { targetDoc = window.document; } //if (gbIE4) { // targetDoc = eval("top.document.frames['" + fn_arguments[1] + "']"); // } else if (gbNav4) { // targetDoc = eval("window.top." + fn_arguments[1] + ".document"); //} strTarget = "TARGET='" + fn_arguments[1] + "'"; } if (isNaN(fn_arguments[2]) || (gbPopupMenuTopicList == null)) { targetDoc.location.href = fn_arguments[3]; } else { targetDoc.location.href = gbPopupMenuTopicList[fn_arguments[2]].strURL; } return false; } var strMenu = ""; if (gbNav4) { strMenu = ''; } else { strMenu = '
'; } else { strMenu += '' + gbPopupMenuTopicList[fn_arguments[i]].strTitle + ''; } strMenu += ''; if (isNaN(fn_arguments[i]) || (gbPopupMenuTopicList == null)) { i += 2; } else { i += 1; } } strMenu += "
"; if (gbMac) { // totally hack. because ie5 in mac need something. is one of them. mac is mad. strMenu +="
"; } var layerPopup = null; var stylePopup = null; var nEventX = 0; var nEventY = 0; var nWindowWidth = 0; if (gbIE4) { layerPopup = document.all["PopupMenu"]; layerPopup.innerHTML = strMenu; stylePopup = layerPopup.style; _BSPSGetClientSize(); // Get the position of the item causing the event (relative to its parent) //if (gbMac) { if (true) { nEventX = window.event.clientX; nEventY = window.event.clientY; } else { //??? YJ: Can not remember why we calculate envent position by following code... //but it is wrong in a case like: CENTER->P->TABLE: //the offset positions of TABLE, P and CENTER are same (same offsetTop,offsetLeft) //so we get triple times of offset of x and y as we expect... nEventX = window.event.srcElement.offsetLeft - document.body.scrollLeft; nEventY = window.event.srcElement.offsetTop - document.body.scrollTop; // Get the location of the parent var nParentLocX = 0; var nParentLocY = 0; var ParentItem = window.event.srcElement.offsetParent; while (ParentItem != null) { if (ParentItem.offsetLeft) { nParentLocX += ParentItem.offsetLeft; nParentLocY += ParentItem.offsetTop; } ParentItem = ParentItem.parentElement; } // Adjust the location of the item using the location of the parent(s) nEventX += nParentLocX; nEventY += nParentLocY; } if (nEventY + layerPopup.scrollHeight + 10 < gBsClientHeight) { nEventY += document.body.scrollTop + 10; } else { nEventY = (document.body.scrollTop + gBsClientHeight) - layerPopup.scrollHeight - 20; } stylePopup.top = nEventY; if (nEventX + layerPopup.scrollWidth + 20 > gBsClientWidth) { if (gBsClientWidth - layerPopup.scrollWidth < 5) { stylePopup.left = 5; } else { stylePopup.left = gBsClientWidth - layerPopup.scrollWidth - 5; } } else { stylePopup.left = nEventX + document.body.scrollLeft + 20; } stylePopup.visibility = "visible"; document.onclick = PopupMenu_HandleClick; } else if (gbNav4) { layerPopup = document.layers.PopupMenu; layerPopup.visibility = "hide"; stylePopup = layerPopup.document; stylePopup.write(strMenu); stylePopup.close(); var e = fn_arguments[0]; nEventX = e.pageX; nEventY = e.pageY; _BSPSGetClientSize(); if (nEventY + layerPopup.clip.height + 20 < window.pageYOffset + gBsClientHeight) { nEventY += 20; } else { nEventY = gBsClientHeight + window.pageYOffset- layerPopup.clip.height - 20; } layerPopup.top = nEventY; if (nEventX + layerPopup.clip.width + 20 > gBsClientWidth + window.pageXOffset) { if (gBsClientWidth + window.pageXOffset - layerPopup.clip.width < 20) { nEventX = 5; } else { nEventX = gBsClientWidth + window.pageXOffset - layerPopup.clip.width - 20; } } else { nEventX += 20; } layerPopup.left = nEventX; layerPopup.visibility = "show"; // window.captureEvents(Event.CLICK | Event.MOUSEDOWN); window.captureEvents(Event.MOUSEDOWN); // window.onclick = PopupMenu_HandleClick; window.onmousedown = PopupMenu_HandleClick; } window.gbInPopupMenu = true; window.gbPopupMenuTimeoutExpired = false; setTimeout("PopupMenu_Timeout();", 100); return false; } function PopupMenu_Timeout() { window.gbPopupMenuTimeoutExpired = true; } function PopupMenu_Over(e) { if (gbIE4) { e.srcElement.className = "PopupOver"; } else if (gbNav4) { // this.bgColor = "red"; // e.target.document.className = "PopupOver"; } return; } function PopupMenu_Out(e) { if (gbIE4) { e.srcElement.className = "PopupNotOver"; } else if (gbNav4) { this.bgColor = "#f0f0f0"; } return; } function PopupMenu_HandleClick(e) { if (!window.gbPopupMenuTimeoutExpired) { return; } window.gbInPopupMenu = false; if (gbNav4) { // window.releaseEvents(Event.CLICK); window.releaseEvents(Event.MOUSEDOWN); } var layerPopup = null; var stylePopup = null; if (gbIE4) { layerPopup = document.all["PopupMenu"]; stylePopup = layerPopup.style; stylePopup.visibility = "hidden"; } else if (gbNav4) { layerPopup = document.layers.PopupMenu; layerPopup.visibility = "hide"; } return; } // This function should be deleted when all old projects are cleaned up function BSPSWritePopupFrameForIE4() { return false; } ///////////////////////////////////////////////////////////////////// function BSSCPopup_ClickMac() { if ((!DHTMLPopupSupport()) && (gbIE4)) { var bClickOnAnchor = false; var el; if ((window.event != null) && (window.event.srcElement != null)) { el = window.event.srcElement; while (el != null) { if ((el.tagName == "A") || (el.tagName == "AREA")) { bClickOnAnchor = true; break; } if (el.tagName == "BODY") { break; } el = el.parentElement; } } if (BSSCPopup_IsPopup()) { if (!bClickOnAnchor) { parent.window.gPopupWindow = null; self.close(); } } else { bClosePopupWindow = true; if ((bClickOnAnchor) && (el.href) && (el.href.indexOf("javascript:BSSCPopup") != -1)) { bClosePopupWindow = false; } if (bClosePopupWindow) { if (window.gPopupWindow != null) { var strParam = "titlebar=no,toolbar=no,status=no,location=no,menubar=no,resizable=yes,scrollbars=yes,height=300,width=400"; window.gPopupWindow = window.open("", gstrPopupSecondWindowName,strParam); window.gPopupWindow.close(); window.gPopupWindow = null; } } } } } ////////////////////////////////////////////////////////////////////// _BSPSGetBrowserInfo(); function _BSSCOnLoad() { if (!gbIE4 && !gbNav4) return; // Make everything visible in navigator if (gbNav4) { // Make some special effects items visible for (var iLayer = 0; iLayer < document.layers.length; iLayer++) { document.layers[iLayer].visibility = gBsStyVisShow; document.layers[iLayer].left = 0; } } // Remove the NavBar if necessary RemoveNavBar(); // Don't continue without IE4 if (gbIE4) { HHActivateComponents(); doStaticEffects(); startAnimationSet(0); } } function _BSSCOnUnload() { } function _BSSCOnClick() { if (!gbIE4) return; BSSCPopup_ClickMac(); startNextAnimationSet(); } function _BSSCOnError(message) { if(-1 != message.indexOf("denied") || -1 != message.indexOf("Object required")) return true; } function ResizeBasedonRate(thisWindow, size, rate, maxx, maxy) { x = maxx; y = maxy; deltax = -maxx/2; while (true) { x = x + deltax; thisWindow.resizeTo(x, y); thisWindow.resizeTo(x, y); diffy = thisWindow.document.body.scrollHeight + gBscrollHeight - x * rate; if (diffy > gBpermitYDelta ) // it is higher than wanted, so x need to be wide a little bitter deltax = Math.abs(deltax) /2; else if (diffy < -permitYDelta) // it is shorter than wanted, so x need to be narrow a little bitter deltax = -Math.abs(deltax) /2; else // the y is close enough to wanted. break; if (Math.abs(deltax) < gBpermitXDelta) // the next change is too slight and it can be ignore. break; //j ++; } size.x = thisWindow.document.body.scrollWidth; //+ gBscrollWidth; size.y = thisWindow.document.body.scrollHeight;// + gBscrollHeight; thisWindow.document.body.scroll = 'no'; // At this time we do not want to show scroll any more. so it will looks better a little. } //////////BSSCDHTML Section Embedded Code////////// var s_strAgent = navigator.userAgent.toLowerCase(); var s_nVer = parseInt(navigator.appVersion); var s_bIE = (s_strAgent.indexOf('msie') != -1); var s_bNS = (s_strAgent.indexOf('mozilla') != -1) && ((s_strAgent.indexOf('spoofer') == -1) && (s_strAgent.indexOf('compatible') == -1)); var s_bOpera = (s_strAgent.indexOf('opera') != -1); var s_bIE3Before = ((s_bIE) && (s_nVer <= 2)); var s_bNS3Before = ((s_bNS) && (s_nVer <= 3)); var s_bNS2 = ((s_bNS) && (s_nVer <= 2)); var s_bNS3 = ((s_bNS) && (s_nVer == 3)); var s_bIE300301 = ((s_bIE) && (s_nVer == 2) && ((s_strAgent.indexOf("3.00") != -1)||(s_strAgent.indexOf("3.0a") != -1)||(s_strAgent.indexOf("3.0b")!=-1)||(s_strAgent.indexOf("3.01")!=-1))); var s_bIE302 = ((s_bIE) && (s_nVer == 2) && (s_strAgent.indexOf("3.02") != -1)); function HasExtJs() { if (s_bIE3Before) { return false;} if (s_bNS3Before) { return false;} if (typeof (_BSSCOnLoad) == "undefined"){ return false; } return true; } function BSSCOnLoad() { if (HasExtJs()) { _BSSCOnLoad(); } } function BSSCOnUnload() { if (HasExtJs()) { _BSSCOnUnload(); } } function BSSCOnClick() { if (HasExtJs()) { _BSSCOnClick(); } } function BSSCOnError(message) { if (HasExtJs()) { return _BSSCOnError(message); } } function WritePopupMenuLayer() { if (HasExtJs()) {_WritePopupMenuLayer();} } function BSSCCreatePopupDiv() { if (HasExtJs()) {_BSSCCreatePopupDiv(); } } function BSSCPopup(strURL) { if (HasExtJs()) { _BSSCPopup(strURL); }else{ //Create a temporary window first to ensure the real popup comes up on top var wndTemp = null; if (!s_bNS3) { wndTemp = window.open("", "temp", "titlebar=no,toolbar=no,status=no,location=no,menubar=no,resizable=yes,scrollbars=yes,height=3,width=4"); } // Create the real popup window var wndPopup = window.open(strURL, "BSSCPopup", "titlebar=no,toolbar=no,status=no,location=no,menubar=no,resizable=yes,scrollbars=yes,height=300,width=400"); // Close the temporary if (!s_bNS3) { wndTemp.close(); } else { wndPopup.focus(); } } } var gbWndTemp = null, gbWndPopupLinks = null; var gbstrParaTotal = ""; function PopupMenu_Invoke() { if (HasExtJs()) { return _PopupMenu_Invoke(PopupMenu_Invoke.arguments); } if (s_bNS3Before || s_bIE3Before ) { var argLen = PopupMenu_Invoke.arguments.length; if (argLen < 5) { window.document.location.href = PopupMenu_Invoke.arguments[3]; return false; } gbWndTemp = null; gbWndPopupLinks = null; gbstrParatotal = ""; for (var i = 0; i < (argLen - 2) / 2; i++) { var strParaLine = ""; if (s_bNS2 || s_bOpera){ strParaLine += "
" strParaLine += PopupMenu_Invoke.arguments[2 * i + 2]; strParaLine += ""; } else { strParaLine += ""); if (s_bNS2 || s_bOpera) { gbWndPopupLinks.document.write(""); } else { //YJ: IE301,302 and NS3.x works fine gbWndPopupLinks.document.write("<"); gbWndPopupLinks.document.write("script>"); gbWndPopupLinks.document.write("function gotoUrl(aUrl) {opener.window.location=aUrl; close();}"); gbWndPopupLinks.document.write("<"); gbWndPopupLinks.document.write("/script>"); } gbWndPopupLinks.document.write(""); gbWndPopupLinks.document.write(gbstrParaTotal); gbWndPopupLinks.document.write(""); gbWndPopupLinks.document.close(); // Close the temporary if (!s_bNS3 && gbWndTemp != null) { gbWndTemp.close(); }else { gbWndPopupLinks.focus(); } return true; } return false; } onload = BSSCOnLoad; document.onclick = BSSCOnClick; onunload = BSSCOnUnload; onerror = BSSCOnError;doc/get_mip_gap.htm0000644000175000017500000000644310237176654013276 0ustar renerene get_mip_gap

get_mip_gap

Returns the MIP gap value.

REAL get_mip_gap(lprec *lp, unsigned char absolute);

Return Value

get_mip_gap returns the MIP gap value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

absolute

If TRUE then the absolute MIP gap is returned, else the relative MIP gap.

Remarks

The get_mip_gap function returns the MIP gap that specifies a tolerance for the branch and bound algorithm. This tolerance is the difference between the best-found solution yet and the current solution. If the difference is smaller than this tolerance then the solution (and all the sub-solutions) is rejected. This can result in faster solving times, but results in a solution which is not the perfect solution. So be careful with this tolerance.
The default mip_gap value is 1e-11

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL mip_gap;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  mip_gap = get_mip_gap(lp, TRUE); /* Will return 1e-9 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_mip_gap, get_epsd, set_epsd, set_infinite, get_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb

doc/Java.htm0000644000175000017500000000415510762600214011665 0ustar renerene Using lpsolve from Java

Using lpsolve from Java

Java?

Java is a programming language originally developed by Sun Microsystems and released in 1995 as a core component of Sun's Java platform. The language derives much of its syntax from C and C++ but has a simpler object model and fewer low-level facilities. Java applications are typically compiled to bytecode which can run on any Java virtual machine (JVM) regardless of computer architecture.

The original and reference implementation Java compilers, virtual machines, and class libraries were developed by Sun from 1995. As of May 2007, in compliance with the specifications of the Java Community Process, Sun made available most of their Java technologies as free software under the GNU General Public License. Others have also developed alternative implementations of these Sun technologies, such as the GNU Compiler for Java and GNU Classpath.

Java and lpsolve

Java is an object oriented programming language. The lpsolve API is not object oriented. However there is a wrapper created by Juergen Ebert that is object oriented. All lpsolve API is available via this wrapper but in an object oriented way and in the case as used by Java. For example lpsolve API call make_lp is accessed as makeLP in Java. The general rule of renamed API names is that a name begins in lower case, each underscore is removed and the letter after the underscore is in upper case.
See C - Java function reference for the translation of calls.
An introduction of using lpsolve with Java is given in the document Using lp_solve 5.5 in Java programs
The Java object model is described in the document Java api

doc/get_epsperturb.htm0000644000175000017500000000514110237176654014047 0ustar renerene get_epsperturb

get_epsperturb

Returns the value that is used as perturbation scalar for degenerative problems.

REAL get_epsperturb(lprec *lp);

Return Value

get_epsperturb returns the perturbation scalar.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The default epsperturb value is 1e-5

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL epsperturb;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  epsperturb = get_epsperturb(lp); /* Returns 1e-5 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epsperturb, set_infinite, get_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_mip_gap, get_mip_gap

doc/add_constraint.htm0000644000175000017500000001623710351333542014005 0ustar renerene add_constraint, add_constraintex, str_add_constraint

add_constraint, add_constraintex, str_add_constraint

Add a constraint to the lp.

unsigned char add_constraint(lprec *lp, REAL *row, int constr_type, REAL rh);

unsigned char add_constraintex(lprec *lp, int count, REAL *row, int *colno, int constr_type, REAL rh);

unsigned char str_add_constraint(lprec *lp, char *row_string, int constr_type, REAL rh);

Return Value

add_constraint, add_constraintex and str_add_constraint return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

count

Number of elements in row and colno.

row

An array with 1+get_Ncolumns (count for add_constraintex, if colno is different from NULL) elements that contains the values of the row.

colno

A zero-based array with count elements that contains the column numbers of the row. However this variable can also be NULL. In that case element i in the variable row is column i and values start at element 1.

row_string

A string with column elements that contains the values of the row. Each element must be separated by space(s).

constr_type

The type of the constraint. Can by any of the following values:

LE (1) Less than or equal (<=)
EQ (3) Equal (=)
GE (2) Greater than or equal (>=)

rh

The value of the right hand side (RHS).

Remarks

The add_constraint, add_constraintex, str_add_constraint functions add a row to the model (at the end) and sets all values of the row at once.

Note that for add_constraint (and add_constraintex when colno is NULL) element 0 of the array is not considered (i.e. ignored). Column 1 is element 1, column 2 is element 2, ...

str_add_constraint should only be used in small or demo code since it is not performant and uses more memory.

add_constraintex has the possibility to specify only the non-zero elements. In that case colno specifies the column numbers of the non-zero elements. Both row and colno are then zero-based arrays. This will speed up building the model considerably if there are a lot of zero values. In most cases the matrix is sparse and has many zero value.
Note that add_constraintex behaves the same as add_constraint when colno is NULL.

Thus it is almost always better to use add_constraintex instead of add_constraint. add_constraintex is always at least as performant as add_constraint.

Note that it is advised to set the objective function (via set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj) before adding rows. This especially for larger models. This will be much more performant than adding the objective function afterwards.

Note that these routines will perform much better when set_add_rowmode is called before adding constraints.

Note that if you have to add many constraints, performance can be improved by a call to resize_lp.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL row[1+3];     /* must be 1 more than number of columns ! */
  REAL sparserow[2]; /* must be the number of non-zero values */
  int colno[2];

  /* Create a new LP model */
  lp = make_lp(0, 3);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_add_rowmode(lp, TRUE);

  row[1] = 1.0;
  row[2] = 0.0; /* also zero elements must be provided */
  row[3] = 2.0;
  add_constraint(lp, row, GE, 3.0); /* constructs the row: +v_1 +2 v_3 >= 3 */

  colno[0] = 1; sparserow[0] = 1.0; /* column 1 */
  colno[1] = 3; sparserow[1] = 2.0; /* column 3 */
  add_constraintex(lp, 2, sparserow, colno, GE, 3.0); /* constructs the row: +v_1 +2 v_3 >= 3 */

  set_add_rowmode(lp, FALSE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_row, set_rowex, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, set_add_rowmode, is_add_rowmode, resize_lp, get_constr_type, is_constr_type, del_constraint, add_column, add_columnex, str_add_column, set_column, set_columnex, get_column, get_columnex, get_row, get_rowex, get_mat

doc/set_mat.htm0000644000175000017500000000744410242131740012440 0ustar renerene set_mat

set_mat

Set a single element in the matrix.

unsigned char set_mat(lprec *lp, int row, int column, REAL value);

Return Value

set_mat returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

Row number of the matrix. Must be between 0 and number of rows in the lp. Row 0 is objective function.

column

Column number of the matrix. Must be between 1 and number of columns in the lp.

value

Value to be set for row row, column column.

Remarks

The set_mat function sets a value in the matrix. If there was already a value for this element, it is replaced and if there was no value, it is added.
This function is not efficient if many values are to be set. Consider to use add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, add_column, add_columnex, str_add_column, set_column, set_columnex.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(2, 3);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_mat(lp, 1, 2, 3.1415927);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_constraint, add_constraintex, str_add_constraint, set_row, set_rowex, set_obj_fn, set_obj_fnex, str_set_obj_fn, add_column, add_columnex, str_add_column, set_column, set_columnex, get_column, get_columnex, get_row, get_rowex, get_mat

doc/resize_lp.htm0000644000175000017500000000706710564146076013020 0ustar renerene resize_lp

resize_lp

Allocate memory for the specified size.

unsigned char resize_lp(lprec *lp, int rows, int columns);

Return Value

Returns TRUE if succeeded, FALSE if not.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

rows

Allocate memory for this amount of rows.

columns

Allocate memory for this amount of columns.

Remarks

The resize_lp function deletes the last rows/columns of the model if the new number of rows/columns is less than the number of rows/columns before the call.

However, the function does not add rows/columns to the model if the new number of rows/columns is larger. It does however changes internal memory allocations to the new specified sizes. This to make the add_constraint, add_constraintex, str_add_constraint and add_column, add_columnex, str_add_column routines faster. Without resize_lp, these functions have to reallocated memory at each call for the new dimensions. However if resize_lp is used, then memory reallocation must be done only once resulting in better performance. So if the number of rows/columns that will be added is known in advance, then performance can be improved by using this function.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 3);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /* 1000 constraints will be added, so allocate memory for it in advance to make things faster */
  resize_lp(lp, 1000, get_Ncolumns(lp));

  /* Now add the 1000 constraints */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also copy_lp, delete_lp, free_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_column, add_columnex, str_add_column, add_constraint, add_constraintex, str_add_constraint

doc/Build.htm0000644000175000017500000007035711236130334012050 0ustar renerene Calling the lpsolve API from your application

Calling the lpsolve API from your application

There are two ways to call the lpsolve API from an application:

  • Dynamically
  • Statically

Dynamically means that the lpsolve code is dynamically linked to your code. This means that it is linked to your program when the executable is started or even only when you make calls to the lpsolve library. The lpsolve library is then not linked with the executable and is provided in a separate file. Under Windows this is a dll (lpsolve55.dll), under Unix/Linux this is a shared library (liblpsolve55.so). You must distribute this separate library with your program to make it work. The library must be located on a place that can be found by the program. There are several advantages of this way of working. Almost all programming languages have a way to call dynamic libraries or even can only call libraries that way. One example is VB6. Another advantage is that it is easier to update the package. The program doesn't have to be recompiled/relinked. You only have to provide a new lpsolve library.

Statically means that the lpsolve code is statically linked to the code. This means that the program does not need extra files to be able to call lpsolve since the code is already contained in the executable. The executable will thus be larger. This can only be done if you have the source code of your program and you can recompile it and link it with the lpsolve code. Not all programming languages have the possibility to statically link code. For example VB6 does not have a way to do that. The advantage of this way of calling the lpsolve library is that you don't have to provide extra files with your executable since the library is already in the exe. The disadvantage is that you must recompile (or at least link) the program with the lpsolve code when an update of lpsolve is needed. There are two ways to link your application with lpsolve. The first way is add the needed lpsolve source code to the project and compile it together as one unit. This is most probably only possible when the code is also written in C/C++ (however not always since for example .NET allows to link for example C# code with C code). The disadvantage of this way of working is that you have to revise your project when you use a new version of lpsolve since there could be files added or removed in the lpsolve package. Also you may have to define some defines. A better way of working is making use of the lpsolve library. Under DOS/Windows this is called liblpsolve55.lib (liblpsolve55d.lib in debug mode), under Unix/Linux liblpsolve55.a. The advantages are that other languages (like Pascal) can also link with such a library, your project is not overloaded with the lpsolve source files and also not unimportant, the linker only takes the code from the library that you really use resulting in a smaller executable. One disadvantage is that you cannot debug and step trough the lpsolve code then, if you would want to do that.

So what method to choose to call lpsolve from your application?

  1. Dynamically link your application with lpsolve
    1. Implicit linking with the lpsolve dynamic library
    2. Explicit linking with the lpsolve dynamic library
  2. Statically link your application with lpsolve
    1. Implicit linking with the lpsolve static library
    2. Link your code with the lpsolve source code

Dynamically link your application with lpsolve

lpsolve is separated from the application. So there are two separate compilations. One of the application and one of the lpsolve library. Most people will not compile the lpsolve library themselves since it is provided for several popular platforms. The files are in lp_solve_5.5.0.15_dev.zip for Windows and lp_solve_5.5_dev.gz for Linux. Therefore it is first explained how to access the lpsolve library in your application. This depends on the OS and the calling language. The most common are described here.

There are two ways of linking a dynamic library to the application: Implicit and Explicit linking. It depends on the programming language which way of linking is supported. Some support only one of the two, some can do both ways.
Implicit linking with the lpsolve dynamic library

With Implicit Linking, the shared library file gets loaded into memory as soon as we execute the client program. If implicitly linked, the library is not removed from memory unless the application is terminated. However, if there are other applications in memory that are using the library, it is not removed from memory till the last of these applications is terminated.

If Implicit Linking is used, a link (or import) library must be provided to the linker to resolve the symbols. In the code, the function calls are made as if all symbols are available.

Explicit linking with the lpsolve dynamic library

If we want, we can defer the loading of the library till the time a call to the exported function in the library is not made. This is known as Explicit Linking. Explicit linking is more appropriate for interpreted languages such as Visual Basic, but it can also be used from C/C++ if we need to.

If Explicit Linking is used, the library is explicitly loaded in memory via a special API call and the routines are also explicitly called via API calls. It should be clear that Explicit linking requires more coding than Implicit linking, but it allows you do load the library only when you need it and even decide at runtime from which library to call the routines.

Some may see Implicit linking as 'early binding' and Explicit linking as 'late binding'. Although it is not exactly the same, the analogy is true. Just like 'early binding', with Implicit linking, the symbols are resolved and checked at compile (actually link) time. There is strong type checking and less chance to pass wrong arguments. Just like 'late binding', with Explicit linking, the symbols are resolved and checked at runtime. The type checking is loose and there is chance that wrong parameters are passed to the function with possible disastrous results. But with the flexibility to dynamically load and call functions.
For Windows, there is a good article explaining all this: DLLs for Beginners

WINDOWS: Call the lpsolve dll from C/C++

Microsoft Visual C/C++ and GNU gcc support both Implicit and Explicit linking. In both cases, some header files are also needed. They are included with the archive where the libraries are also in lp_solve_5.5.0.15_dev.zip and lp_solve_5.5_dev.gz. Only lp_lib.h must be included in your source code. The other header files are included by this master include file.

Implicit linking

In implicit linking, the linker matches the symbols of the library via a .lib file (the import library). Note the extension of the file. This is the same as for a static library. This may be confusing. There is a big difference between a static library and an import library. It is unfortunate that Microsoft has used the same extension for both. A static library contains code and it is statically linked to the executable. An import library only contains symbol definitions so that the linker can resolve the symbols. An import library will thus be much smaller in size than a static library. This file is provided with the lpsolve dll and is called lpsolve55.lib (both in archive lp_solve_5.5.0.15_dev.zip). It depends on the environment and the version how to do this. Via the link.exe command, this is done by just specifying the lpsolve55.lib file at the command line. Via the .NET environment, this can be done via: Project, Properties, Linker, Input, Additional Dependencies. Optionally it is possible to also specify a link path via Project, Properties, Linker, General, Additional Library Directories. In Visual studio 6, this can be done via: Project, Settings, Link, Category General, Object/library modules. Optionally it is possible to also specify a link path via Project, Settings, Link, Category Input, Additional library path.
After this is done, the lpsolve functions can be called just like the lpsolve functions are linked to the program.

Example:

#include <stdio.h>

#include "lp_lib.h"

main()
{
  lprec *lp;

  lp = make_lp(0,4);

  /* ... */

  delete_lp(lp);
}
Explicit linking

In explicit linking we don't use the .lib file. Instead we call the Win32 LoadLibrary( ) function, specifying the DLL's pathname as a parameter. The LoadLibrary( ) function returns an HINSTANCE parameter. This parameter is used in a call to the GetProcAddress( ) function to fetch the address of the function to be called. This address is a pointer to a function. Through this pointer the function is finally called. As can be seen in the following example, this requires some extra coding.

Example:

#include <stdio.h>

#include "lp_lib.h"

main()
{
  lprec *lp;
  HINSTANCE lpsolve;
  make_lp_func *_make_lp;
  delete_lp_func *_delete_lp;

  lpsolve = LoadLibrary("lpsolve55.dll");

  if (lpsolve == NULL) {
    printf("Unable to load lpsolve shared library\n");
    return(FALSE);
  }
  _make_lp = (make_lp_func *) GetProcAddress(lpsolve, "make_lp");
  _delete_lp = (delete_lp_func *) GetProcAddress(lpsolve, "delete_lp");

  lp = _make_lp(0,4);

  /* ... */

  _delete_lp(lp);

  FreeLibrary(lpsolve);
}

Note that the prototype definitions of the lpsolve functions (ex make_lp_func) are already defined in lp_lib.h. This same code also works with the Windows gnu gcc compiler. The only thing that must be done at compile time is defining the WIN32 macro. This will make sure that the calling convention will be __stdcall as required.

The C demo example (lp_solve_5.5_c.tar.gz) demonstrates both implicit and explicit linking.

The following batch/script files can be used to compile the demo's from the command line:

cvc6.bat Compile the demo with the Microsoft Visual C compiler. It generates demoi.exe, demoe.exe, demos.exe. These are Dynamic Implicit linked, Dynamic Explicit linked and Static linked versions of the same demo.
cgcc.bat Compile the demo with the GNU gcc compiler. It generates demoi.exe, demoe.exe, demos.exe. These are Dynamic Implicit linked, Dynamic Explicit linked and Static linked versions of the same demo. Also note that the lpsolve55.dll file must also be compiled with gcc for this to work.

The following VC.NET project files can be used to compile the demo's from the IDE:

DemoDynamicImplicit.sln, DemoDynamicImplicit.vcproj Generates a Dynamic Implicit linked exe.
DemoDynamicExplicit.sln, DemoDynamicExplicit.vcproj Generates a Dynamic Explicit linked exe.

WINDOWS: Call the lpsolve dll from VB (also VBS Excel, Word, Access)
These environments support only Explicit linking. However it is much easier than in C. Via a DECLARE statement, the API routines are declared and can immediately be called. The LoadLibrary/GetProcAddress API calls are done by VB and are invisible to you. To make things even easier, a class file is made to access the lpsolve library. It is called lpsolve55.cls. See the VB/Excel demos to see how it works (lp_solve_5.5_vb.zip, lp_solve_5.5_excel.zip).

WINDOWS: Call the lpsolve dll from VB.NET, C#

This is analogue as for VB. These environments probably also allow to use implicit linking, but this is not investigated. The demos use implicit linking. There is a class library made to call the lpsolve library. It is called lpsolve55.vb and lpsolve55.cs
See the demos for how it works (lp_solve_5.5_vb.net.zip and lp_solve_5.5_cs.net.zip).

LINUX/UNIX: Call the lpsolve shared library from C/C++
Not yet documented. See lp_solve_5.5_c.tar.gz

ccc Compile the demo under Linux/Unix. It generates demoi, demoe, demos. These are Dynamic Implicit linked, Dynamic Explicit linked and Static linked versions of the same demo.

Statically link your application with lpsolve

lpsolve is linked with the application. The application is most likely a C/C++ application. It must at least be a programming environment with a linker such that the lpsolve code can be linked with your code. Some header files are also needed. They are included with the archive where the libraries are also in lp_solve_5.5.0.15_dev.zip and lp_solve_5.5_dev.gz. Only lp_lib.h must be included in your source code. The other header files are included by this master include file.

There are two ways to link lpsolve statically with your application: Implicit linking with the lpsolve static library and link your code with the lpsolve source code.
Implicit linking with the lpsolve static library

The lpsolve code is in a library file. The files are in lp_solve_5.5.0.15_dev.zip for Windows and lp_solve_5.5_dev.gz for Linux. Under Windows with the Microsoft compiler, this is in a .lib file. Under Unix and under Windows with the cygwin gcc compiler, this is in a .a file. Note for the Microsoft compiler the extension of the file. This is the same as for a dynamic library with implicit linking. This may be confusing. There is a big difference between a static library and an import library. It is unfortunate that Microsoft has used the same extension for both. A static library contains code and it is statically linked to the executable. An import library only contains symbol definitions so that the linker can resolve the symbols. An import library will thus be much smaller in size than a static library.
The static library file is provided with the lpsolve distribution and is called liblpsolve55.lib (liblpsolve55d.lib for debugging) for the Microsoft compiler and liblpsolve55.a under Linux and with the cygwin gnu compiler under Windows. It depends on the environment and the version how to link the static library with your code. For Linux and with the cygwin gnu compiler, just specify the .a file to the compile command line:

cc pgr.c liblpsolve55.a

For the Microsoft visual C compiler it can be done as follows: Via the link.exe command this is done by just specifying the liblpsolve55.lib file at the command line. Via the .NET environment, this can be done via: Project, Properties, Linker, Input, Additional Dependencies. Optionally it is possible to also specify a link path via Project, Properties, Linker, General, Additional Library Directories. In Visual studio 6, this can be done via: Project, Settings, Link, Category General, Object/library modules. Optionally it is possible to also specify a link path via Project, Settings, Link, Category Input, Additional library path.
After this is done, the lpsolve functions can be called just like the lpsolve functions are linked to the program.

Example:

#include <stdio.h>

#include "lp_lib.h"

main()
{
  lprec *lp;

  lp = make_lp(0,4);

  /* ... */

  delete_lp(lp);
}

The C demo example (lp_solve_5.5_c.tar.gz) demonstrates static linking. The following batch/script files can be used to compile the demo's from the command line:

cvc6.bat Compile the demo with the Microsoft Visual C compiler. It generates demoi.exe, demoe.exe, demos.exe. These are Dynamic Implicit linked, Dynamic Explicit linked and Static linked versions of the same demo. Note that the static linked version is much larger than the dynamic linked versions.
cgcc.bat Compile the demo with the GNU gcc compiler. It generates demoi.exe, demoe.exe, demos.exe. These are Dynamic Implicit linked, Dynamic Explicit linked and Static linked versions of the same demo. Note that the static linked version is much larger than the dynamic linked versions. Also note that the lpsolve55.dll file must also be compiled with gcc for this to work.
ccc Compile the demo under Linux/Unix. It generates demoi, demoe, demos. These are Dynamic Implicit linked, Dynamic Explicit linked and Static linked versions of the same demo. Note that the static linked version is much larger than the dynamic linked versions.

The following VC.NET project files can be used to compile the demo from the IDE:

DemoStaticImplicit.sln, DemoStaticImplicit.vcproj Generates a Static linked exe.
Link your code with the lpsolve source code

The lpsolve source code is linked with your code. The lpsolve source code is contained in archive lp_solve_5.5_source.tar.gz. This is the most complex method and should only be used when the others don't work.

One note in advance. Your C/C++ compiler must know 64 bit integers. Most today compilers support this trough the data type long long. lp_solve uses a define LLONG for this. If your compiler doesn't support long long, but it supports 64 bit integers trough another name, then you can define LLONG to this type at the compiler command line. For example -DLLONG=int64. Also some older (versions of) compilers only support long long via an additional switch. For example previous gcc compilers need the switch -std=c99 at the gcc compile command to enable ISO C99. Without this switch a warning is given like "warning: ISO C90 does not support `long long'".

The following source files must at least be added to your project:

bfp/bfp_LUSOL/lp_LUSOL.c
bfp/bfp_LUSOL/LUSOL/lusol.c
colamd/colamd.c
ini.c
shared/commonlib.c
shared/mmio.c
shared/myblas.c
lp_crash.c
lp_Hash.c
lp_lib.c
lp_matrix.c
lp_MDO.c
lp_mipbb.c
lp_MPS.c
lp_params.c
lp_presolve.c
lp_price.c
lp_pricePSE.c
lp_report.c
lp_scale.c
lp_simplex.c
lp_SOS.c
lp_utils.c
lp_wlp.c

All header (.h) files from lpsolve must be accessible. Most compilers use the directive -Ipath with path the location to the header files. Note that the colamd, bfp and bfp/bfp_etaPFI directories also contain header files that must be included.

If you also need the lp parser to read an lp model (read_lp, read_LP) then you must also include the files lp_rlp.c and yacc_read.c and define the symbol PARSER_LP. Most compilers use the directive -DPARSER_LP to do that. If you forget to define this symbol then the linker will give a link error saying that the symbols read_lp, read_LP are already defined. Also define the symbol YY_NEVER_INTERACTIVE (-DYY_NEVER_INTERACTIVE). This to disable the interactive mode of the lex parser and remove the dependency on isatty() routine which not available in all environments.

Note that lp_rlp.c, lp_rlp.h may give you some warnings when they are compiled. This is 'normal'. These files are not human-written, but generated from yacc/bison/lex tools from the corresponding .y and .l files. These tools don't seem to care much in generating code that is fully Ansi compliant and without warnings. Normally they can be ignored.

Note that there are more .c files in the lpsolve directory. You don't have to (even may not) include these in your project also. This because there files are either automatically included by the other source files or are needed for other functionality.

With the Windows Microsoft compiler, the compilation command could be:

cl -Ic:\lp_solve_5.5 -Ic:\lp_solve_5.5\bfp -Ic:\lp_solve_5.5\bfp\bfp_etaPFI -Ic:\lp_solve_5.5\colamd /Zp8 -DWIN32 %src% -o MyExe.exe

With the Windows gnu compiler, the command could be:

gcc -Ic:\lp_solve_5.5 -DBFP_CALLMODEL=__stdcall %src% -o MyExe.exe

Under Unix/Linux, the command could be:

cc -I/lp_solve_5.5 -I/lp_solve_5.5/bfp -I/lp_solve_5.5/bfp/bfp_etaPFI -I/lp_solve_5.5/colamd $src -o MyExe.exe -lm -ldl

%src% / $src is an environment variable containing all source files (above lpsolve source files plus your sources). Note the /Zp8 option with the Windows c compiler. This is also important. It ensures 8-bit alignment. This is required when you make use of the BPF functionality (see Basis Factorization Packages) and the XLI functionality (see External Language Interfaces). It doesn't matter which calling convention is used. __cdecl or __stdcall or any other calling convention is ok, even if you make use of the BFP functionality. Note the -DBFP_CALLMODEL=__stdcall option with the non-Microsoft compiler. This is to define a macro for the BFP to make sure its routines are called via the __stdcall calling convention. This is required if you want to make use of the BFP functionality. If your compiler doesn't provide a way to specify the __stdcall calling convention, then you can drop this, but the BFP functionality will then probably not work (even crash). With the Microsoft compiler this option doesn't have to be specified because it is automatically set by the lpsolve header files via the WIN32 macro. Under Unix/Linux the -lm option must be added to link with the math library and the option -ldl is used to link with the shared library. Not all Unix systems have this functionality. In that case you can drop the -ldl option but then you have to add -DLoadInverseLib=0 -DLoadLanguageLib=0 in which case you will not be able to use the BFP functionality (see Basis Factorization Packages) and also not the XLI functionality (see External Language Interfaces).

The compiler commands to compile the package with also the lp (lpsolve and CPLEX) parser functionality:
With the Windows Microsoft compiler, the command could be:

cl -Ic:\lp_solve_5.5 -Ic:\lp_solve_5.5\bfp -Ic:\lp_solve_5.5\bfp\bfp_etaPFI -Ic:\lp_solve_5.5\colamd /Zp8 -DWIN32 -DYY_NEVER_INTERACTIVE -DPARSER_LP %src% -o MyExe.exe

With the Windows gnu compiler, the command could be:

gcc -Ic:\lp_solve_5.5 -Ic:\lp_solve_5.5\bfp -Ic:\lp_solve_5.5\bfp\bfp_etaPFI -Ic:\lp_solve_5.5\colamd -DBFP_CALLMODEL=__stdcall -DYY_NEVER_INTERACTIVE -DPARSER_LP %src% -o MyExe.exe

Under Unix/Linux, the command could be:

cc -I/lp_solve_5.5 -I/lp_solve_5.5/bfp -I/lp_solve_5.5/bfp/bfp_etaPFI -I/lp_solve_5.5/colamd -DYY_NEVER_INTERACTIVE -DPARSER_LP $src -o MyExe.exe -lm -ldl

And for Unix/Linux without the possibility to use the BFP and XLI functionality:

cc -I/lp_solve_5.5 -I/lp_solve_5.5/bfp -I/lp_solve_5.5/bfp/bfp_etaPFI -I/lp_solve_5.5/colamd -DYY_NEVER_INTERACTIVE -DPARSER_LP -DLoadInverseLib=0 -DLoadLanguageLib=0 $src -o MyExe.exe -lm

Note that I used here the command prompt commands to compile the sources. It is of course also possible to use the graphical interfaces with their project files to build it. The principle stays however the same.

In the lp_solve folder, there are also some batch/script files to build the lp_solve application. This may be a good start to begin. Note that lp_solve.c is here the application. It only contains this one source file. Or you could also look at the demo program in the demo directory. Here the application is demo.c

doc/XLI.htm0000644000175000017500000004305310474126144011445 0ustar renerene External Language Interface

External Language Interfaces

To facilitate the development of other model language interfaces, a quite simple "eXternal Language Interface" (XLI) has been defined, which allows lp_solve to be dynamically configured (at run-time) to use alternative means to read and write the MIP model or write a solution file in a specific format. lp_solve has several build-in interfaces to models: mps, lp. XLI allows implementing a custom reader and writer for other model layouts and a solution layout.
This feature again gives a unique flexibility and openness to the user and developer community that we have quite some expectations for.
If you write your own XLI, we would be glad if you would share your code with the lp_solve community. We are very interested in providing as many different XLIs as possible to the community.

Under Windows, an XLI is provided as DLL (xli_*.dll), under UNIX/LINUX as a dynamic linked library (libxli_*.so). These libraries are loaded/linked at runtime with lp_solve.

Under Unix/Linux it is standard that a library has the lib prefix and a .so postfix.
For example libxli_MathProg.so
Under Windows there is no prefix and the postfix is .dll
For example xli_MathProg.dll

To make the calling structure for XLIs uniform across different types of OS, lp_solve automatically adds the prefix and postfix if not provided. So for example under all platforms, the MathProg XLI may be referenced as xli_MathProg. It is advised to call the XLIs as such.

To locate the XLI on the file system, the following search order is used if no path is provided:

Windows
  1. Current directory.
  2. A semi-colon-separated (;) list of directories in the user's PATH environment variable.
Unix/Linux
  1. A colon-separated (:) list of directories in the user's LD_LIBRARY_PATH environment variable.
  2. The list of libraries specified in /etc/ld.so.cache (which is generated from /etc/ld.so.conf).
  3. /lib, followed by /usr/lib. Note the order here; this is the reverse of the order used by the old a.out loader. The old a.out loader, when loading a program, first searched /usr/lib, then /lib (see the man page ld.so(8)). This shouldn't normally matter, since a library should only be in one or the other directory (never both), and different libraries with the same name are a disaster waiting to happen.

Note again that this search path is only used if no path is specified for the XLI.

Using an XLI with the lp_solve stand-alone program

The lp_solve program provides a way to specify an XLI for reading a model, an XLI for writing the model and an XLI for writing the solution file. These can be different so that a model in one format can be converted to another format. It is still possible to both read and write the models with the build-in formats (mps, lp) and you can combine with the XLI.

Read a model

With the lp_solve program, to set the XLI to read the model, use the option
-rxli xliname filename

filename is the name (with optional path) of the model name to read. If no path is specified, the file is read from the current directory.

Depending on the XLI, an optional data file name can be provided. Use the option
-rxlidata datafilename

For example for the MathProg XLI, there is a possible optional datafilename containing the data. Note that this name may not start with a minus sign (-)

Depending on the XLI, options can be provided to change the behaviour of the routine. Use the option
-rxliopt "options"

So the following commands are valid for both Windows and Unix/Linux:

lp_solve -rxli xli_MathProg input.mod -rxlidata input.dat
lp_solve -rxli ./xli_MathProg input.mod -rxlidata input.dat

The latter makes sure that the XLI is searched in the current directory, especially for Unix/Linux.

Write a model

With the lp_solve program, to set the XLI to write the model, use the option
-wxli xliname filename

filename is the name (with optional path) of the model name to write. If no path is specified, the file is written in the current directory.

Depending on the XLI, options can be provided to change the behaviour of the routine. Use the option
-wxliopt "options"

So the following commands are valid for both Windows and Unix/Linux:

lp_solve input.lp -wxli xli_MathProg output.mod
lp_solve input.lp -wxli ./xli_MathProg output.mod

The latter makes sure that the XLI is searched in the current directory, especially for Unix/Linux.

Write a solution

With the lp_solve program, to set the XLI to write the solution, use the option
-wxlisol xliname filename

filename is the name (with optional path) of the solution name to write. If no path is specified, the file is written in the current directory.

Depending on the XLI, options can be provided to change the behaviour of the routine. Use the option
-wxlisolopt "options"

So the following commands are valid for both Windows and Unix/Linux:

lp_solve -rxli xli_DIMACS maxflow.net -wxlisol xli_DIMACS maxflow.sol
lp_solve -rxli ./xli_MathProg maxflow.net -wxlisol xli_DIMACS maxflow.sol

The latter makes sure that the XLI is searched in the current directory, especially for Unix/Linux.

Using an XLI from the lpsolve API

Read a model

The read_XLI reads a model via an XLI.
See the API call for its usage.

Write a model

To write a model, two API calls are needed:

First use set_XLI to set the XLI library
See the API call for its usage.

Then use write_XLI to write the model.
See the API call for its usage. Note that the last argument, results must FALSE.

Write a solution

To write a model, two API calls are needed:

First use set_XLI to set the XLI library
See the API call for its usage.

Then use write_XLI to write the model.
See the API call for its usage. Note that the last argument, results must TRUE.

Creating an XLI

This section is only for people who will create their own XLI because you have a model file type that is not supported by lp_solve. The developers would appreciate it if you would make this XLI public.

To create your own XLI, you have to create a DLL/shared library that implements the following routines:

char * XLI_CALLMODEL xli_name(void)

Return Value

xli_name must return a string describing the XLI library.

Parameters

None

MYBOOL XLI_CALLMODEL xli_readmodel(lprec *lp, char *model, char *data, char *options, int verbose);

Return Value

Must return TRUE or FALSE to indicate if successful (TRUE) or not (FALSE).

Parameters

lp

An initial lp structure created via make_lp(0, 0).

model

Filename to read the model from.

data

Optional data to read data from. For example used by the MathProg XLI.

options

Extra options that can be used by the reader.

verbose

The verbose level. Can be used to output more or less information while creating the model.

Remarks

This routine is called when the read_XLI API is called.
Via the provided lp variable all lpsolve API routines can be accessed to create the model.
Note that xli_readmodel already provides an lp structure. You must use this one to build the model. The lp structure is created via make_lp(0, 0). So it contains 0 rows and 0 columns.

MYBOOL XLI_CALLMODEL xli_writemodel(lprec *lp, char *filename, char *options, MYBOOL results);

Return Value

Must return TRUE or FALSE to indicate if successful (TRUE) or not (FALSE).

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

filename

The filename argument of write_XLI. Filename to write the model/solution to.

options

The options argument of write_XLI. Extra options that can be used by the writer.

results

The results argument of write_XLI. When FALSE, the XLI should create a model file and when TRUE is should create a solution file.

Remarks

This routine is called when the write_XLI API is called.
This routine must be used to write the model/solution. Via the provided lp variable all lpsolve API routines can be accessed to do the job.

lp_XLI1.c must be included at the beginning of the source file. This to include an extra routine xli_compatible needed by the lpsolve library to check the compatibility.

If you want to create XLIs yourself, make sure that under Windows, you use 8 byte alignments. This is needed for the XLIs to work correctly with the general distribution of lp_solve and also to make sharing XLIs as uncomplicated as possible. If not, it will likely crash. It doesn't matter which calling convention is used to compile the library. The XLI_CALLMODEL directive makes sure that the calling convention of the needed routines is always ok independent of the calling convention specified in the project.
Also under windows, a definition file must be added. If this is not done, it will not work. The definition file should have extension .def and contain the following:

EXPORTS
  xli_compatible           @1
  xli_name                 @2
  xli_readmodel            @3
  xli_writemodel           @4

The definition file must be added to the project. How to do this depends on the version.
For Visual Studio 6: Project, Add to Project, Files, Files of type: Definition files (.def) and choose the created .def file
For Visual Studio .NET: Project, Properties, Linker, Input, Module Definition file. There you enter the name (with optional path) of the .def file.

XLI prototype
/* Generic include libraries */
#include <malloc.h>
#include <string.h>
#include "lp_lib.h"
#ifdef FORTIFY
# include "lp_fortify.h"
#endif

/* Include routines common to language interface implementations */

#include "lp_XLI1.c"

char * XLI_CALLMODEL xli_name(void)
{
  return("XLI_xxx v1.0" );  /* return the name and version */
}

MYBOOL XLI_CALLMODEL xli_readmodel(lprec *lp, char *model, char *data, char *options, int verbose)
{
  MYBOOL status = FALSE;

  /* implement the code here to read the model */

  return(status); /* status says if the model could be read or not. TRUE is ok, FALSE is not ok */
}

MYBOOL XLI_CALLMODEL xli_writemodel(lprec *lp, char *filename, char *options, MYBOOL results)
{
  MYBOOL status = FALSE;

  /* implement the code here to write the model */

  return( status ); /* status says if the model could be written or not. TRUE is ok, FALSE is not ok */
}
Working example:
demo.c:
/*  Modularized external language interface module - w/interface for lp_solve v5.0+
   ----------------------------------------------------------------------------------
    Author:        Peter Notebaert
    Contact:       lpsolve@peno.be
    License terms: LGPL.

    Template used:
    Requires:

    Release notes:
    v1.0.0  28 June 2004        First implementation.

   ---------------------------------------------------------------------------------- */

/* Generic include libraries */
#include <malloc.h>
#include <string.h>
#include "lp_lib.h"

/* Include libraries for this language system */
#include <math.h>

#ifdef FORTIFY
# include "lp_fortify.h"
#endif

/* Include routines common to language interface implementations */
#include "lp_XLI1.c"

char * XLI_CALLMODEL xli_name(void)
{
  return( "xli_demo v1.0" );
}

MYBOOL XLI_CALLMODEL xli_readmodel(lprec *lp, char *model, char *data, char *options, int verbose)
{
  MYBOOL status = FALSE;
  REAL row[1+2]; /* must be 1 more then number of columns ! */

  lp->add_columnex(lp, 0, NULL, NULL); /* add empty column */
  lp->add_columnex(lp, 0, NULL, NULL); /* add empty column */
  lp->set_add_rowmode(lp, TRUE);
  row[1] = 1.0;
  row[2] = 2.0;
  lp->add_constraint(lp, row, GE, 3.0); /* constructs the row: +v_1 +2 v_2 >= 3 */
  lp->set_add_rowmode(lp, FALSE);
  status = TRUE;

  return(status);
}

MYBOOL XLI_CALLMODEL xli_writemodel(lprec *lp, char *filename, char *options, MYBOOL results)
{
  if (!results)
    return(lp->write_lp(lp, filename));
  else {
    lp->print_objective(lp);
    lp->print_solution(lp, 1);
    lp->print_constraints(lp, 1);
    return(TRUE);
  }
}
demo.def:
EXPORTS
  xli_compatible           @1
  xli_name                 @2
  xli_readmodel            @3
  xli_writemodel           @4

This example is not very practical. It is only useful for demonstration purposes. Let's assume that the name of this library is xli_demo.
xli_readmodel creates the model. It doesn't even read from a file in this example. xli_writemodel uses write_lp to write the model to filename and some print_* functions to print the solution.

This XLI can be called from lp_solve via the following syntax:

lp_solve -S0 -rxli xli_demo "" -wxli xli_demo output.txt -wxlisol xli_demo ""

An empty ("") filename is provided because it isn't used by this demo. This command will create a file output.txt with contents:

/* Objective function */
min: ;

/* Constraints */
+C1 +2 C2 >= 3;

Because we didn't provide the option -parse_only, the model is also solved. However the lp_solve option -S0 disables showing the results. Results are generated via the -wxlisol option:

Value of objective function: 0

Actual values of the variables:
C1                              3
C2                              0

Actual values of the constraints:
R1                              3
doc/get_solutioncount.htm0000644000175000017500000000501510237176656014603 0ustar renerene get_solutioncount

get_solutioncount

Returns the number of equal solutions.

int get_solutioncount(lprec *lp);

Return Value

get_solutioncount returns the number of equal solutions. This is only valid if there are integer, semi-continious or SOS variables in the model so that the branch-and-bound algoritm is used. This count gives the number of solutions with the same optimal objective value. If there is only one optimal solution, this value is 1.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_solutioncount function returns the number of equal solutions up to get_solutionlimit.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int solutioncount;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  solutioncount = get_solutioncount(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_solutionlimit, set_solutionlimit

doc/get_mat.htm0000644000175000017500000000620510242132000012404 0ustar renerene get_mat

get_mat

Get a single element from the matrix.

REAL get_mat(lprec *lp, int row, int column);

Return Value

get_mat returns the value of the element on row row, column column. If no value was set for this element, the function returns 0.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

Row number of the matrix. Must be between 0 and number of rows in the lp. Row 0 is objective function.

column

Column number of the matrix. Must be between 1 and number of columns in the lp.

Remarks

This function is not efficient if many values are to be retrieved. Consider to use get_row, get_rowex, get_column, get_columnex.
If row and/or column are outside the allowed range, the function returns 0.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL a;

  /* Create a new LP model */
  lp = make_lp(2, 3);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  a = get_mat(lp, 1, 2); /* will return 0 because this element isn't created */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_row, get_rowex, get_column, get_columnex, set_column, set_columnex, set_mat, set_row, set_rowex

doc/is_negative.htm0000644000175000017500000000546211127442437013312 0ustar renerene is_negative

is_negative

Returns if the variable is negative.

unsigned char is_negative(lprec *lp, int column);

Return Value

is_negative returns TRUE (1) if the variable is defined as negative, FALSE (0) otherwise.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be checked. It must be between 1 and the number of columns in the lp.

Remarks

The is_negative function returns if a variable is negative or not. Negative means a lower and upper bound that are both negative. Default a variable is not free because default it has a lower bound of 0 (and an upper bound of +infinity).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int negative;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  negative = is_negative(lp, 1); /* will return 0 since the variable is not set as negative at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_upbo, set_upbo, set_lowbo, get_lowbo, set_bounds, is_unbounded, set_unbounded

doc/get_rh_range.htm0000644000175000017500000000606310237176656013447 0ustar renerene get_rh_range

get_rh_range

Gets the range on a constraint.

REAL get_rh_range(lprec *lp, int row);

Return Value

get_rh_range returns the range set on the constraint specified by row.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row number of the constraint from which the range must be retrieved. It must be between 1 and the number of rows in the lp.

Remarks

The get_rh_range function gets the range on the constraint (row) identified by row.
Setting a range on a row is the way to go instead of adding an extra constraint (row) to the model. Setting a range doesn't increase the model size that means that the model stays smaller and will be solved faster.
If the row has a less than constraint then the range means setting a minimum on the constraint that is equal to the RHS value minus the range. If the row has a greater than constraint then the range means setting a maximum on the constraint that is equal to the RHS value plus the range.
Note that the range value is the difference value and not the absolute value.
If no range was set then get_rh_range returns a very big number, the value of get_infinite.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL a;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  a = get_rh_range(lp, 1);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_rh_range

doc/set_unbounded.htm0000644000175000017500000000561211127442637013652 0ustar renerene set_unbounded

set_unbounded

Sets if the variable is free.

unsigned char set_unbounded(lprec *lp, int column);

Return Value

set_unbounded returns TRUE (1) if the variable could be set as free, FALSE (0) otherwise.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable that must be set. It must be between 1 and the number of columns in the lp.

Remarks

The set_unbounded function sets if a variable is free or not. Free means a lower bound of -infinity and an upper bound of +infinity. Default a variable is not free because default it has a lower bound of 0 (and an upper bound of +infinity). See free variables for a description about free variables.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_unbounded(lp, 1); /* will return 0 since the variable is not set as free at this point */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_upbo, set_upbo, set_lowbo, get_lowbo, set_bounds, is_unbounded, is_negative

doc/get_lp_index.htm0000644000175000017500000000663610351321250013445 0ustar renerene get_lp_index

get_lp_index

Returns the index in the lp of the original row/column.

int get_lp_index(lprec *lp, int orig_index);

Return Value

get_lp_index returns the index in the lp of the original row/column.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

orig_index

Original constraint or column number. If orig_index is between 1 and get_Norig_rows then the index is a constraint (row) number. If orig_index is between 1+get_Norig_rows and get_Norig_rows + get_Norig_columns then the index is a column number.

Remarks

The get_lp_index function returns the index in the lp of the original row/column.
Note that the number of constraints (get_Nrows) and columns (get_Ncolumns) can change when a presolve is done or when negative variables are split in a positive and a negative part. get_lp_index returns the position of the constraint/variable in the lp. If orig_index is not a legal index or the constraint/column is deleted, the return value is 0.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int index;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  str_add_constraint(lp, "0 1", LE, 1.0);

  index = get_lp_index(lp, 1); /* Will return 1 */

  set_presolve(lp, PRESOLVE_COLS);
  solve(lp);

  index = get_lp_index(lp, 1); /* Will return 0 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_orig_index, get_Ncolumns, get_Norig_columns, get_Nrows, get_Norig_rows, get_Lrows, set_presolve

doc/write_mps.htm0000644000175000017500000001160110662057274013022 0ustar renerene write_mps, write_freemps, write_MPS, write_freeMPS, MPS_writefileex

write_mps, write_freemps, write_MPS, write_freeMPS, MPS_writefileex

Write an mps model.

unsigned char write_MPS(lprec *lp, FILE *stream);

unsigned char write_freeMPS(lprec *lp, FILE *stream);

unsigned char write_mps(lprec *lp, char *filename);

unsigned char write_freemps(lprec *lp, char *filename);

unsigned char MPS_writefileex(lprec *lp, int typeMPS, void *userhandle, (void *userhandle, char *buf) write_modeldata_routine);

Return Value

The routines return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
Note that row entry mode must be off, else this function also fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

stream

Pointer to FILE structure.

filename

Filename to write the mps model to.

typeMPS

type of the MPS file. Can be one of the following values:

MPSFIXED (1) Fixed MPS format
MPSFREE (2) Free MPS format

write_modeldata_routine

Routine to write the MPS model to. The routine has following definition:
typedef int (__WINAPI write_modeldata_func)(void *userhandle, char *buf);
userhandle is the second parameter passed to write_lp_ex
buf is a shrunk of data.

Remarks

The write_mps, write_freemps, write_MPS, write_freeMPS functions write the model to filename. write_MPS, write_freeMPS need a file pointer to an already opened file. write_mps, write_freemps accept the name of the file. The latter function will generally be more convenient. MPS_writefileex writes the model via a user defined routine.

When stream or filename are NULL, then output is written to output set by set_outputstream, set_outputfile. By default this is stdout.

The model in the file will be in mps-format. The write_free* routines write files in free MPS format. The other routines write files in fixed MPS format.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"
int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  write_mps(lp, "model.mps");

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, copy_lp,read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, read_lp, read_LP, write_lp, write_LP, write_lpex, read_lp, read_LP

doc/set_maxim.htm0000644000175000017500000000425210237176664013006 0ustar renerene set_maxim

set_maxim

Set objective function to maximize.

void set_maxim(lprec *lp);

Return Value

set_maxim has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The set_maxim function sets the objective direction to maximize. The default of lp_solve is to minimize, except for read_lp, read_LP where the default is to maximize.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_maxim(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_maxim, set_minim, set_sense

doc/set_scaling.htm0000644000175000017500000001515510246721776013317 0ustar renerene set_scaling

set_scaling

Specifies which scaling algorithm must be used.

void set_scaling(lprec *lp, int scalemode);

Return Value

set_scaling has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

scalemode

Specifies which scaling algorithm must be used. Can by any of the following values:

SCALE_NONE (0) No scaling
SCALE_EXTREME (1) Scale to convergence using largest absolute value
SCALE_RANGE (2) Scale based on the simple numerical range
SCALE_MEAN (3) Numerical range-based scaling
SCALE_GEOMETRIC (4) Geometric scaling
SCALE_CURTISREID (7) Curtis-reid scaling

Additionally, the value can be OR-ed with any combination of one of the following values:

SCALE_QUADRATIC (8)  
SCALE_LOGARITHMIC (16) Scale to convergence using logarithmic mean of all values
SCALE_USERWEIGHT (31) User can specify scalars
SCALE_POWER2 (32) also do Power scaling
SCALE_EQUILIBRATE (64) Make sure that no scaled number is above 1
SCALE_INTEGERS (128) also scaling integer variables
SCALE_DYNUPDATE (256) dynamic update
SCALE_ROWSONLY (512) scale only rows
SCALE_COLSONLY (1024) scale only columns

Remarks

The set_scaling function specifies which scaling algorithm must be used. This can influence numerical stability considerably. It is advisable to always use some sort of scaling.
set_scaling must be called before solve is called.
SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC, SCALE_CURTISREID are the possible scaling algorithms. SCALE_QUADRATIC, SCALE_LOGARITHMIC, SCALE_USERWEIGHT, SCALE_POWER2, SCALE_EQUILIBRATE, SCALE_INTEGERS are possible additional scaling parameters.
SCALE_POWER2 results in creating a scalar of power 2. May improve stability.
SCALE_INTEGERS results also in scaling Integer columns. Default they are not scaled.
SCALE_DYNUPDATE is new from version 5.1.1.0
It has always been so that scaling is done only once on the original model. If a solve is done again (most probably after changing some data in the model), the scaling factors aren't computed again. The scalars of the original model are used. This is not always good, especially if the data has changed considerably. One way to solve this was/is call unscale before a next solve. In that case, scale factors are recomputed.
From version 5.1.1.0 on, there is another way to make sure that scaling factors are recomputed and this is by settings SCALE_DYNUPDATE. In that case, the scaling factors are recomputed also when a restart is done. Note that they are then always recalculated with each solve, even when no change was made to the model, or a change that doesn't influence the scaling factors like changing the RHS (Right Hand Side) values or the bounds/ranges. This can influence performance. It is up to you to decide if scaling factors must be recomputed or not for a new solve, but by default it still isn't so. It is possible to set/unset this flag at each next solve and it is even allowed to choose a new scaling algorithm between each solve. Note that the scaling done by the SCALE_DYNUPDATE is incremental and the resulting scalarsare typically different from scalars recomputed from scratch.
The default is SCALE_GEOMETRIC + SCALE_EQUILIBRATE + SCALE_INTEGERS (196).

Also see scaling for a description about scaling.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_scaling(lp, CURTISREIDSCALE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_scaling, is_integerscaling, is_scalemode, is_scaletype

doc/is_nativeXLI.htm0000644000175000017500000000450310237176660013351 0ustar renerene is_nativeXLI

is_nativeXLI

Returns if a build-in External Language Interfaces (XLI) is available or not.

unsigned char is_nativeXLI(lprec *lp);

Return Value

is_nativeXLI returns TRUE if a build-in XLI is available, FALSE if not.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

At this moment, this routine always returns FALSE since no build-in XLI is available. See External Language Interfaces for a complete description on XLIs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char nativeXLI;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  nativeXLI = is_nativeXLI(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_XLI, has_XLI, set_XLI

doc/delete_lp.htm0000644000175000017500000000341210237177146012746 0ustar renerene delete_lp

delete_lp

Deletes an lprec structure.

void delete_lp(lprec *lp);

Return Value

None

Parameters

lp

lprec structure to delete.

Remarks

The delete_lp function frees all memory allocated to the lp structure. 

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /*
  .
  .
  .
  */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also free_lp, make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

doc/print_lp.htm0000644000175000017500000000537210237176420012641 0ustar renerene print_lp

print_lp

Prints the lp model.

void print_lp(lprec *lp);

Return Value

print_lp has no return value. Note that row entry mode must be off, else this function fails. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The print_lp function prints the lp model.
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  print_lp(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, print_objective, print_solution, print_constraints, print_duals, print_scales, print_tableau, print_str, set_outputstream, set_outputfile, print_debugdump

doc/get_var_priority.htm0000644000175000017500000000600210237176656014404 0ustar renerene get_var_priority

get_var_priority

Returns, for the specified variable, the priority the variable has in the branch-and-bound algorithm.

int get_var_priority(lprec *lp, int column);

Return Value

get_var_priority returns the priority of the variable.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable on which the priority must be returned. It must be between 1 and the number of columns in the lp. If it is not within this range, the return value is 0

Remarks

The get_var_priority function returns the priority the variable has in the branch-and-bound algorithm. This priority is determined by the weights set by set_var_weights. The default priorities are the column positions of the variables in the model.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL weights[2];
  int priority;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  weights[0] = 2;
  weights[1] = 1;

  set_var_weights(lp, weights);

  priority = get_var_priority(lp, 1); /* will return 2 */
  priority = get_var_priority(lp, 2); /* will return 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_var_weights, get_var_branch, set_var_branch, set_bb_floorfirst, get_bb_floorfirst

doc/put_bb_nodefunc.htm0000644000175000017500000000670410311113350014130 0ustar renerene put_bb_nodefunc

put_bb_nodefunc

Allows to set a user function that specifies which non-integer variable to select next to make integer in the B&B solve.

void put_bb_nodefunc(lprec *lp, lphandleint_intfunc newnode, void *bbnodehandle);

Return Value

put_bb_nodefunc has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

newnode

The node selection routine.

typedef int (__WINAPI lphandleint_intfunc)(lprec *lp, void *bb_nodehandle, int vartype);

The routine must return the node (column number) to make integer. vartype is at this moment always equal to BB_INT (1).
When 0 is returned then it indicates that all variables are integer.
When a negative value is returned, lp_solve will determine the next variable to make integer as if the routine is not set.
Note the __WINAPI attribute. This is important under Windows. It ensures __stdcall calling convention which is required.

bb_nodehandle

A parameter that will be provided to the node selection routine.

Remarks

Allows to set a user function that specifies which non-integer variable to select next to make integer in the B&B solve. Via this routine the user can implement his own rule to select the next non-integer variable to make integer. This overrules the setting of set_bb_rule.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int __WINAPI nodefunction(lprec *lp, void *bb_nodehandle, int vartype)
{
 int node = -1;

 /* determine node to make integer */

 return(node);
}

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  put_bb_nodefunc(lp, nodefunction, NULL);

  solve(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_bb_rule

doc/print_duals.htm0000644000175000017500000000615010237176420013331 0ustar renerene print_duals

print_duals

Prints the values of the duals of the lp.

void print_duals(lprec *lp);

Return Value

print_duals has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The print_duals function prints the values of the duals of the lp. This can only be done after a successful solve.
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_duals(lp, 1);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex, print_lp, print_objective, print_solution, print_constraints, print_scales, print_tableau, print_str, set_outputstream, set_outputfile, print_debugdump

doc/O-Matrix3.jpg0000644000175000017500000025033510251405314012517 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?S{_^σmO\-4]RJկm,c̼O w.aZZk]odl+H`;Mk=!< uۙWmaoُ+o4EpF>|/t'@׼akz4M_\7+ShZ?D:piO9t ;2 Ag<=T¿ _t+k~ ~i/Έ?|7ľ4߆ ~+N 8g32#ɣfF{Rr .|S%C Rѕ,E\cO&ב}|v g `j# UjIنi*l>7 S3:pem,.2r~!xMm= JpE_@yQg.񵻳,[6ky.;775 qS?>q_TWGEC|'kW>wa/^(JoiK?{O_<=~k>1%#_Iំ|7_ ~&HS0yN{s3 Ø<'LJⳬEn-&[P,wS18~m| *:x_ g\: L,.gW5Y,;UX ?[\`SZM*?.Ŭ ǿ1k?0'GOG_]㿋/hg|4Iu2|W_>9|ݯᅿ-G4=qy|we 3ѥ-y; T>>~|3?w/P^ |7Z&5k/5/<]c&WUSJaMaTx`Tja,.VETN6|1+ЇT|-9x\-B9~Y!Nsvԛx|Dy*D,MeB:Wba{^N|u>_O)?[7~0,>n!|"‘7y^3+}+ƹ?k]?V>x^b?x6x3Z<'+x#??c9O|cAg?:֫&MbTp<>e lq?g,n 򪲥W#8n1cJX\MIbЭ^'X\F&E+}k Re*tiVl:x^ya*RbO;Wba{^m*~"_o>2|L߈4_|%xύ~ º͵¿ -C_lSJEy!KOyNQCGg ;7%|ҴmV8cy 7zՒk~64]{Zg};W3^K|B6syvÄ,,g9f,$s &?+s7d9U/ s? |9,OY3,/ 9c CYVBף^18|>*ЯN(z.Ŭ ǿ1k?0DݣȗT_ Kxo[姩 Z /{C ?^YK<GR4v[>iVyi{C ?G.Ŭזyv"_E@ԿM//~>aϚ_տ}Zz.Ŭvx-g7^]IL?SOaiڍ?.|ewJt]տOˣ=Kg?bcw Z n"ɓoɓoKiPߘKERE__{|RvosԿvx-g7G.Ŭ+|?& Ou/v]>)t迻o_/O]) 1k6?2]^8^ɕ_g<|7Gԥ>i1}> i}:yz~>G Z LW?b׿mey>/#)Ϛ}?Oe~N^qCmC(j^ey}_nt}J_Osw`vӫ痧zo.ůPWπFJ}]gPu{IN{qNy}_nY _$C+~_=n>SR2G)b̋lLJj+`XpإkY>UZ[ Rcj?mF8Ԕg*sQq_\=Ùe N]:Y|F5PuV (ciAա*U[Kԧ7xZeohm{SԂXf/n OPG#Oெ!c_d-Zf/xOLA j> Э~*Zokk?~hV^‘ͮ]j~!Cѵ8l'f/dOSa; #?9=g_~ MW F% F?Q+ߐ0s԰?r|?(Mqq3Ǿ1Ckw7>|'KA: C<}ek?⹇^5ⱹ5^˳ `Xd=rl>UG&`x5:ؕQF9&t)%m"MM7P./̾*E+B{ɤM?C~Y?g_?fMn᷂!HsyWzX'MPPڋ=)溇MOfmBM+™DV󽾟}%0O̢ ]\,Lpg)p30+V#b0پ xybe<X S"4jaqsZ\3/0+.x,et0-.عGcE>^9pQR?9tpVSB)> /H%+v<^GS/ x7~$Ɲo5\hzχ%W6c>Qƾ&-t;ȬmຎHs<1?=@ _ַ/?۬DT$qq!"1.u>biZ\w? >-,:}QAmm_ b/f|En~͚th2x:FQyh.4/ x |=ieqFQpc<q4<3QY:k0fLbF>Sɸ"| V_s Nq̲ƴZxl*?; 1diE|:Xի~UA60|O'\L:ZZ|eԵ;vw!utkxt}G^Դj>t_nl<]mi-#5>"QO: |P:U x =|!𯊵o ˨:/'ֵ)?Q11P?\ =I.O_X1^UO_/ ìOyew,~#x/d|sc8#x{j5\ҡ8*쪭z5qv|Kkr)U1X_ 2| W4e ^oUf/S6U|]&hWֲԾ|N"ȼ?X!ÿe:^Ŀ|WU/;o+[#;O%.7>kVwxcX']H]_Cz@Z??@Z?θ;.<\)%8{ePU^]5afX~?3<Nx[;C9_c2ܖep8 ]#H?M o KDM o KDM} 2>C%@^a֞'Fqo湖?vaf8V7֫bTZs9J_/?G'/32\G P8k2-,a0iѣJ!̗#H?=" & /N#Vx{GK97_%V&'GOxL~?-/Ga?zE|A+mc|UI_Eh"hc|UI_Eh"h,ǭh=>wĬxB<yzK_K_rGa@Z??@Z??|>?qt'|4ϯ+9Џ^>2Ga1lsӚ_ߓ/*GLbQIN/<~|I-M/?+>:-<'1ZFQoɿN? W? 1)GCH _qES+Ǟ_M?Vu oɿZFWx"_T1^(DU>?E9XB87yJ׎#Ac7_ߓ@bS*+芣'G+Gy70ZxOH2xw#ѿ&9k=o9_ӏCH _qEQx"_Tb/+^:Џ Crz7rG-~M+qbQIN/?@bS*O!yTߛ%k_? 1ZFQoɿN? W? 1)GCH _qEQW#<wĭxB<'$<;_ߓ?7!G$/E8"bQIN/?|~r?qS~oGă!ſX1G`0瞝fj/c?ƿm)G<#x~|I6hwF/|3m{64= HڗU5mR}_ak TEI^M>tpk]ۧ}?F?hj/c?ƿ__ak GCH0R腧Y_yLu~#Z.?:r}?F?hj/c?ƿ__ak GCH0R腣'G&OC%k?`$Q_bODto6Qf)g_^ 🎴k5MG~*|ugXs^ 񧃼cmkY3WŞ Vͤk]A ?!h,ɯh~)xRXõa+@f eox|-έe ? J/x >1sK{[_xy|!+k[Z['jP[u w+,LT5]jH'/d s'[|@?<>-e><=zīei:Vb_Z$HƌE_(/'/WEP?t}V{ OI|#Pu+ ھk[K)!6dXO"~ WqvEq3:/Ǿ xQC&*4gbK )SJ8yaY |QͲ\|IG /IKҝlV7ZXJ1UqQʏ:qrUUk}xzW4FU= 5xG5 J~7n[F( <zrNKa_xcol(Y`YIbDVnrjo%~(Yӫ6ac0~$s:sij Ҧ7<†7 KBhU*- yiQ,DiŊ,],w _0J/K50ЫT5iTY{H{Ru?_Oߍ|#/ x3_ŏe<{|I֡ojo~п~!xĺzF h5q'W,kyq=RO|0>\n |Bfu5i!Bʏ,pHsiCgh?xSXAxgſ> ERuڲL+Y]C7WhmO/ G<^x1]8?~Η2]JQe[BEC^P̣H oWØ~-`8nlW RK <v/f/\W+I:x rep~*~}̣s=<y}c=J|1C O ،%~(RN>8ޕ9aԫp]X$- 46n鹌=YeL @dIk_+Y&_i\ #%-e>\j'Zzy6p,QG׶[\ʅ?Uc|U:K}8sx &|OAֿ<3i GTѰh6Wű6eTp~"3=eC+pʴ֡J}Gn&R)6k;0ɳl3W0:xaÕ)Ҟ&ƣ+rPrqN7I>(mtPW䏱z 8S|-?7c1'|0.JxyL< =G[}/TM[QBZ}n+l6kx, vaK.ʕjRx*j:U#N78MI¤!8-83_ 9V=*+pUh攓i84lvEFa?_+F+?0W^7{·W^ɻ/"[Tx+0?o7~$>x[Oѿh ~> w?Sz'g;]360k>x>(A_~)F3SS +Ywjo%;?O⟄> [ǞM~Ӗ^?_>&0?;<:>TſxOkŸg> g|Q_?=;}fmKxW|Q/,_|U6x^5{Cx1~0x׾𝧌~>~O xWTtc^{s_ះiwZ4z~_x?<._=|<=;AuFi//<+gZgştX)| #vٟHx ?oBм??o~η>vo_?/k6[ '9O/ٻ]Om,?n>~ |;EGxOjC π+GZw|luJƞ*/ <ƶ5?7rxgvn^:|9 Ht53ƿl*E㿈)xDM#^m#wTe;_'*[x][o f⟊~7|' ;׏ >%hO# Wu/W>)nj^}cZx⟀>=CKi ?fZ +o_'3?-?H: OK-/™2KoW׉>>0x||8?_>#BO|AǞuᏉ,M%Pƿ|-P` s6*5߉~!|I4 WEO=i>-3 "w~n^Of<7şs>6υ?* _4#߈_ !n}3fA|''>it{6~ѿxS7_h_&^σAȼ ?;3:xǾ&_~w"߄>|Kg߇_>&_E'%?Z>;<9j^u 6Kk:YOtΝ g=ψ/4 FΗyxǾ*Ӵ-:K7u4ֱK>!|U=Eu:yy}??go>8,S▅ G/e//|@?h_>4i ?OBtbj5 +ؠujO~/'Ǿ {xX1|i._C|85_ h_+M!^|:c㏉4?MO?H|lk|5/_؃e~7o|B?f+<㟎~o?|{/2z?nc٥i^}U;_< xo/}?_w |9_}&no=9ঞ +zk_d ~?l/A_|W~7z 5k 쩮j7;z?z{o^ x^''7| ¤5o#//|R>??> 3U(۾xſ ?o|9Gg>)w @Ӿ-x_a?>7Ryc⟍o|@/>%)co?v@?M׮|ex%υP|4|Y}_'ŏY~<-ş l_'<{xww[㟘?h(g?h~ _m5]g Oi~!x'ßq5߆)|>[06h&?_0xQm|"|A7ށ@?ѿWk8u/xg ? x_ `oy-xǚG?g\|+5x^&"xxKgmW?ك 0~џuOkU[~*Mٿ'~7|7>56Ih~Uq|~j6:Ɖ7|Blx>8)|:`?᤿igJ.Y=#r> j3t/g?hKi 3V_4^kS_o#ᗈuc?/>׾-^ ~m/x _)i-cÀ/߶?? ?i_ZfSk 4 YeW^OhO {ƫk v>{/^𦿩Dxo>n%<]K@_v炾)|~"ΟE?xOڿ|E '/DS_o4iLc~Ȗ;[KPh|M!O{/_㿆>#zo]c<5GAu|mOj >=otύ~ ||BbcO'?|?ߍ3|b# |h_t |MA= _xWľ/?<];UЏ|_E|Vi C!Gg^3/1zRO xG$s>6x㷌xrמ.'3?Z@<xs {R_;w<Ox^;A?, O[ |uٟúg_WxH0~j~;-5?^zҀy[~?h/5_?^!#|Exk}𞭣G{W<;_#wGM׵KѴm?n7Itx]?z7ό^|3Zς߳o0? |?K "oo\x_ׇf_K ~4sDi/_^#SiA˿)|-'Ək $_xKٓA4cƟo >,Ρ< Cï ;|soxžѵ?bϊzo|?~(h>? 4/Wšx/>*U᧊>|c',^2gg /<1|C|  yt?gU񯊼M]w@GAگGŚε/6h|?{\Ե㗄KTOxzڿ|gy|,i'69_'/?/'׼U߷ī߉7~ˤxC}dž4=GAˠx'45oY95>)|dc?W_|4Ek¿j坯5;/⿋|}5a|tk W.-O G_t |MA= _xWľ/?<];UЏ|_E|Vi C!Gg^3/1zRO xG$s>6x㷌xrמ.'3?Z@<xs {R_;w<Ox^;Ao=oſo~5MA_w&==;|YѼk/ǿ_@|?;JN#>%m'OiZEm]}?[σ}G#zl/Z'?~'A׈x>=f;->O<F'O/ٻ||]eOms^,T9?n犮_ $;GxĿi= zϏ|+=Gúwt6~=''o6ɿk 7t@{:|CxK_xKN|Gß޸lwi'/O__gؗg?-ce<-2?i[ xS^3K4xĺgCⷿ7ğ|K?>YvԿcYG tg~ ~غbM׾4?z㟍Ú:g-?O?|3+Kn ?Z¾%7!|!?Zڮ|M/Oj<k>5|=񏍾k:|iW1|")uiS O~1|lFSt kO|[!|R!{Ok>u"'G㯈^&t|@񦥮{Q@Q@Q@Q@Q@5~tQMI?l8 }@1wOp ~H³8GQ:O Q"?uǯi?_wz|^^ɻ/"[Tx+(((((((((((((((((((((((((I?l9+W_ )$h]~:Qd.?_sXb(3g_ z֓_5]Qgο'TkOOOt8Z7|d_ W/+|Xw ox4]>6|g_~ٖO_~xkRoī_x$I{Ꮛ>@~;_>?K2?gW/ ۟Md?w g x?x,6ǀ3h/gO~.Q{_h/>~?i߄_=go-'ߌ=_xŚ:ΥZߜ?h~A '>o6^I| ow0P|9h;_!/|S?_R?埳;M7?*?챩j>!4 ~֩ OO<[a.ׅuW¾ŏK!>  -TZjh"ѯ,Pi?D~2xK:>:|.3Bg.h}XcC~x|Wo [:Ÿ~)x/!/iZQ?.-:5jMҩUӧ)҆IToW mβNrH.,>"֜կ*TR<-*ө_* M.Ս~~~οNoT7ޏygDNS ߇|!KG loY|PO-jz~jw5_kZg/xJ4/x]5}]5{IWG4B OJ.'4'kkeWF[|!6]K ~$&u Otl~ψ. Ěo/'4}(ygDNS ~οNoT7޾ȴ?][hsZ[xNO _[5t{"𮪗w7K[Jaeř9< oh^ŝ|,*oAP,*oA}E|,*oAR?TwbOGo~vUxn y5>*<=k q~_iIl=\i٦?5!4'⟂tZ|5e6~U4? >_j>'Ӵ/g}'~ G3wa,s-lc~,>-xwzU 4ZϚPe 8TRjRJeJZ5a:Ua VyWqʇxe)F5h(գO`xjCf8*caF# Z,*oA}Ejy,*oA}E|'EgYt+߷d֧aϭ-াѡnVd]/#Zh]S{7 }2k:u#tVRM7 QFӵ-:o/cm,-Y HGՏeyaM5ce%լwu Ե%Vז5?xD5>PB}_K?~'鿱}@Q@Q@1O(~c )#?h]~9Qd.?_sXb(3g_ z֓_5]Qgο'TkOOOt8Z7|d_ x [xCφU;:^. ᑮ^! >s:|o*Si:xWKo|MC?sqg7|6Ӽ'I^?O<y`xNDA{??g߄z[W{H4{o?h珴0|Xɤ|F?gNGYK+x7>'.#?>xWgKnW߅jw_Zƿ>\mY\wS׈W'ѿ񾔶?<=?>&x~ cw|>^)λ#|9i^&𗉴'ľմwJ nq(qZe(.Qj4ijεXUhWN FЍJUTJUiJ)Ԅ' qn2M6"z'|PҴj]xS6oII/)?^|1qZ|Lv|ala|\o#񯂼3:<_jZ5 +P4BXе]w>)λ#|9i^&𗉴'ľմwJ n>6|)[xBOu[x>3mwIq(!M3ᶹP׷aV*Bʭ$~ފ֋umNMTxo.\NXT`I7,<8,1eTrx6gƯ <1ϳE{EP\|-x95|?ms vB&cqaxCm]м7Yk-(t t{}B_mY>aK=w^*na nPNj@6跌.'U+5 kދ㿇>t'f7VvxBGCѾ!:ƝֵlO]2h|OYiw:uh&3^O@Q@Q@S-/ |EN|%{RI ψ|gĵ>&v>oPzĭR~mV;x;*k]oO ]7ڴi^.{o YjEψ:{ZB?zo7k|_CyZuώ| T_K)~/|!NtvZh>!wxߴ7?i7cO'x[I f4?.~exV ;} J5mY}{ N2RFQ[O4#Ux-\?WyU3n`sX+r*̩Vr܋84VN^+д_[Z|K:nhkgkZ.MsNiwsuk4JFQc8IJ2JQZe+EiM;QVzU(WRtkQ SF98TVgN9pT$$h(faT-7NtCG,,]'UuM/RNԴ$,nYmn" $xݔݢ8UU*R SNTRN3$(J-QjILקRjpF'J*JuiԋJu)8q$eM60Mvzƙ'PNN>cxC.zwxSA7|{{_.Do~+z}RԴ;Yӵ XtVM4J ;RӯP[k+ieH. HfvS }czƳj6jZkZ$=k^_׀|K~4Cė\xO? g|[>1JxGUNOb%K^4yF"pZv)1O-Uyr*ᲆ:oS/sLTxRI8^St4z䘙{5d2U'9Oɺ9Nczɺ9Ncz((౟?+΃(Hl:/W_h?ßˏ,EV%?0W~W=I`o?֯6?yMQ_h'W>)v |KooE[/?߇eú'i ??[G 2ͲP,O٣Ҿ:i߳oa/>?oߊw?6ïx]^l^Þ.OOƉ?^/xN>?_'A_O&__b/k *LӴa7g{E|.U? _G?JoįI S !?~6gulu&jՖq|Þ!  '|_ .toS:6cz]{\Lִ{Eu}WntSK-,u . ,/Aƛ'1xoĺΈ5KA8!MG~#k/?~ [Z|T#zU8GN & Y/;USnOƦ&`V)rʟ^_:q)SUaz񴛛5q!M^1.H#Kz( ( ߊ ?bҵE|}# _&kx2Y [x o]Suk Vg ? xE]:58;I_ieFIp[$89Bqqm>|V6L6&S:s5h֣ZZ"hSЩN:uTZ'w>𧊼QW׋5=*5uwqw˥ZVvZxEoS*7>2:"CZdA#O53gt-2IZUtx-S^| sH'OMozS t7|S϶[oVwkFo  V^Ciix^ 4/jzՅ7ZJRt&ܥksJ|rUm9ZJIJ7Yee,M 4Cx:cgX|= &+S!B*TWSEW9Q@xC%j¿xVզ,uO1^$ϩxᇍejƭzy|%6{^I{SQoEWx[,u[߈.~U5ZG_ۦ?5H/ U- /|Oi4{QEQE`xBް(n=;P4]PAӵ]:a,Lַu;K:U橬h˨Y$>]jVCL5+;l2Oj.)LNZ=3qaA 6z.X[+i^{h}7z~h&kd4wO٬ >JkzPwJ{_Z˳[A=s7o)K=kJtu; ((-K@~G5.#m;t6T]oEj<:n㿈͢cτ42>&|2 -t KeOfOڳ[M/MπgO} <3~tJZs cɓʚqٵ+(SF[{x*Z\)Tx(|RkrqS҆\k˧fQ;ЩOrܮ[Gq5%>)&(X(+gM{_ױ$ux.m5+ح/l/, _5 ['u kzމW>+ aa1ta_^iM;I]4MJ3:q95)3dq,&eP' ZDg&Z' (ԥVRH­)¤#%x^"?e''g i_Z>W?|W߶K}h/G'uxXOm{3ϟ)%>.~K۳ sZ'<1Z W!Sv_i:I֒,* 7Z5#JlA,x+տ_:U~ $K_1Don ~ΟY#lqdBƯ#(ѫJ U+ׯRhѣ TZI(SJRIB\&HMm$mdնމ%?(4i'M۳x3/ i75? xOH<;ȯ|3j}6>??)gk+_?#gO?0OA 7ݟ#gŸ9}mx@5Os㟈~_amN-N=Oš~-X|h!|Hmb6/k[_go m wIҩ :ui5)ԧ'  qjQd(iV Q:5iU9SJ9)өN' %(N-J2ILrٷ׍lữ_<[$Q~?' j 3rxWÉ_ޏL|:¾' ;t m@<3ï^2M Jy-g>8Ng xÚZͲմ7ff\\izM/_/ SD4V[?֝?=#ZWw;߉:_kOx? Iu{m ǟa]¾ OѴ; |74.ФզQF>gҥF&*ԩx\&)S9ХxSaƕjRkp8P(Pl]Yʎ"*O*QS G3?Q_g>6wOW.?YxwP/UX<7_ ]Co[he1㻟^4S~ '٣lOƿsG? A 75]_ XD|kf/|?xiOu?R|%=7J7Mj.kVu5&?g,|}[U~"~6Zy^<xK?1͡]k~%t?ᵏi>Û/yfB8ǖ>gBjӕJRqIQs䇴\!reJή32ӡ:5kb`ԣWӣC Rh*`bpӫ2(OH(մ+_ҵ= ]4kDִ'Xk+mGJմFK=CL洿&m )OxKV|%QOP;iןiKۛk_'˙/%>=?x_<_\x_ ~,|Jֽ[B}Xhi^HO-='W5m2WмAjv:߇0oEPEP!]./7Nzx{oXZ/ j$6N|?K ڭP. /T֬ Դiq檳E5Mo4vv1waX]=^o_X[ hW![`_7O.ʏZncC pX4T|A[[qa2ZMuU{K[[k{+xn-&5xgIa'xљXb ( zoO|3]'Rݥj6wcwmsS'xWV3|<;^Z_/oYxOž м =׆&𽇆Z?MT*a:TU&)PRS֨գJrPU&Vԥ%ULtaI -1MFk᪾#0W(SxW0t" 'Bql(χ (>ɺ9Nczɺ9Ncz ( (?g )#?h]~9 )$h]~: +a({ -GI_ (3g_ z֓_5]Qgο'TkNOOt8Z7|d_ QE~^}W,,u VY|YUP^ 5&K-XMvS,&̒L%@?7E[/?߇}Cú'i ??[G 2Ͳ\ 'VKguAX4=BHㅵfw!t S6:Rִ Un ƷV$7Ϋ-O$p֗ZIވ;> b a_]§iT*T3ۧV4 Wy•H*~^,9U g.jUXT <)VVSVJn_Ge𞣢; 5>ǂm|?_62 k,/?A1xB]F!+('񆱡gvx{:_;~ߟcgOX>[Mo -M#?~wP ZG4go=CLln`͓Ͽizv_j xןx]'·*u7S7mKq Y:s5_W5ѿ Q~ޚuU|ϫx^doE𯆼UxoaO~]i6ϋ iڔuM2H?06kׅPWxs :=Mo]<_}o]P!|<5-KÇTEFS^%sWK⨎y <_m#z}+ƺWt }CJԴB]>"7PEPEPki5Vyb-R#YxBDV%ƣ}kgmK&#n~-}ފ4|xZP/ vT[Ojq->+wmӼ5ghEQEW|Ki|PЭ4RVuVׅ糱ÏXojm[i^~u|<9|%zjTӝU)\kuM4EFIJ-I&2cp_**+kMIJ)ԄN*ԧ:Ua:S|7 _!wτ_9_h~%w.-~^5sT-xN???wP;K}/ëgG<'/|Z'> |QmFRп[o_ &?񅦗oB%spU'FMћ¥:uI()T2 3l eKr8rag`x+q >s_ (,4a0f X:#~7q7E|,usgצ|,usgצQEQE3RIe_uE/3RGe~џsE?<\)d/+Qgο'Tk('ZO~qyφn Ⱦ_ _ğ:#d70iLj5WXg~3-Xׂt?x7Axþ o4m>U~ xBgw]_OBQc>Ckߌ쭢?|E|6?:U?w{gG¿<k6_G'fg+_^ S:?8~f [?_A:ʰIC$>x1|Q_*Iᯅ|]h;oڏ.h?*SމW<>~З5 .? ٕ~7?j#/OW#u?zg_ڪW ~ο9?k&փg$OۦI_O5fZ~w_>Ǿ߆_ "|3? (<|\m2~P/ ?j0J)<G  Xe`a$XE$r:EiFJiW.JjB9Z2NJp,]Z OfnxhK%0PCyԳZ[>U,f6s5J)B+K0ia^N/xXS*na^qV¯ep*"$wיov5G(M(;S7)|_mFɶwm>\ }:揻nx0Z58V*FM{J3vn<^aj*W:uS+ꘈU(b(s,VM{Zvr5¹3W9]g⯇Ǎ~h^.__ ~#Lkڍ]cv z.68T$7Uj#$%VJw}(ԧ㰵R79C#Ri`]XJSNu?iS-J1]π%>QRNTnhӼdN3^3(тQh^δ[ jBR[ -hT-WVXƥ9EQEAQEytiZ &ii&esGoZG'WyexNմj6{ZZ[Uռ3ƽxu;,AGº~i>Ucό}:_ޭk_)˨+Ң*]K?=(((#MeMJN}4^i>֯Ce,:Yt +]^MG7%?oY 7.oaqX^iTΥii 15/ 0\Z\\[ˑWR]IkI""}Zo#ƙ_=fƽb)Nԩ¤' )ө -c:sgM]?C*̫z(Xʆ.18LM ElVB嫇akV֊q'N:5# %_<cojd-𾵠YW|]=hwwx/Ǿ'5-S爼#^hj7|3y뺇?bO-cBz+;NִgĺNwZghZYè֋\6ncq=Z,>7)a123 j(bsMJN4g7(TxzG5Joc2'8dxoOD1Xs7:4cS0aia1jmWf*<~Y-,usgצ|,usgצw.QEQE3RGe~џsEXIgAF@'sT9qȾ-+Qgο'Tk('ZO~qy׆n Ⱦ(@ VY|YUW_(gY(S 4_hM,m'$. FX_6 B*(.*EV+PR*Q|.*l6"!?g^J|yn-zJ-4NJU[͉ڷeIeCX2JXU2f3F1"E2'PJsM% QKȻ]qԔ9"3G"23#+Y[NPWUl:#+O(e+rHΖxz8U(JL^3׹7y-E(i-v[>2㢊+,(+<~$үѧzt߉5W}Y%:*r-/YGk:#S\\YOiwiIgoIkMyKq}}z$֜֞2^1wBJgDc(ӭFO/~ݺUT]¼4,F,D9c&ΕS+NNe*Rm좊+ (??ʚ|?Vߵx@lWOS}{o<ף|Wymt=g$_G|4ᴾu];?c. ضOڃ>㻟xGGN+CŚ|}?<P>)xĞ)6gk:5-? xDYi]dž|Ma l7w Z8g! ‰uqko%ܖv$厑"No4}wGw|JTCUQrq:O$zue#(USa1_ژZet,.2ҍn\^Q3j.TΪcp4*eհE'PwO Wi?_ #7iUgkVK|AKŸ'|CS9.w~|;|) "8ekZG3KK%>1> Vm[Bx[G‹e+]I4ӳ4tzԫRN5hUZRRd.YI87i&QE#@(5=NwWQ|Ot]3IҴ[o6.e%eai7 , VզMW{u CW^!+o:u][Ok0ޑzcV7>#҆ a]iZϊ7GU-5_/owv>g袊(+\$4-f+{5]VOk7ZemZY #D^%iPj+WΌi󅦡ݘm|?}a-k?PҼAkz&\lj[F;=KFĺ-w:M$1Z՜χ/!Ocf4$#.|Mk^k^:e?nsS[g8n!涿:U톭sjWshQEQEW^+֯?g^'M5%h6#/jc |-<QEy_(gY/=[QegU@ EPEPV9 x.( ý2oΦRwE5RcjjU8ӫOOZ*SƖ+%(te FHLjI]^Ώ::3#WGRC+))2 3MGQkȡE(t[D4\-*z_Э 0|-Ib2\/%9›7X|Ҏ; vQᧈ˱xf)BNJVm{J=+>Yy8N2J(Š( vyCa7sqOO[\$זWi}cw wsgyk|kh4aE|h:^eSzvw}GShoxy5o#^eX -o,[[c{kiІ5 OKKք&IUiBuU#s*ugWFB|6+)Γ˱#OVS:u*/N+TܪSרUVХR|F'qhcG=ݥͥjQ| io!~FQEQExKh|M76v,0|9QЮK{KBRu朚WX<=xT vw6pݣm4sƗVSX[3Ϋqe{mqgw "Kk&Rhq֗^/ivA{.4촘Ou}qoi}VY5=?O<1F_iwkkm}cso{e{o ݝƳ[\B ,3D3+@,QEQEMw^Mw^QEQEC?XIgAFc?$W4WSs?PK"Naf8GQ:O Q"?uǯi?_z|^>ɻ/"[Tx+<ۋٿoφ&j`լO.XǾU$sx“jQJkտ_:Uj~ڕZ\){Zs(˒>xҝ%H_NN;'fۣ]Sw!7S{OOb|5][÷7V~ յԶ2Y_iz{]ӵ G|YףYgO;^Xy1[hԆ{mYAw,p隴LJ4ѣVj3D*R%'V x:yBR)a1b%hWzjyn&QJRTgZJr+W:tsUR *#'x\=EjjMΏr\siڍI&I$Q_K,p5_idw*ya0k^ uq߈A_ 7"&\;o>.k)b/P| >^~^>Ś %𮵧k< G[[?O~ntMOBVkw: T>&/34jsqcymsg}og^ е{=Gþ,t'^ VSz6MT9Ox ( +տ_:U~,,u+?kH%݈7+|)`Ӯ]7 |+j8Ŀ|k:eϋ|Y+~xR7Q\8SUXL>%RAt&ha10ZWĺX5ruxr7t}iJ.s%x7(c|JMgQ8KX#kX&Ե߉zghPk~ x dtyaqxZ ù:*US/ Zz5œ*X,9(g+ڻ^i2(B( V;dFGMC4m'xّE Z7G edP΍) b'c3˖66IIRQ4S?|yv-v7yWnc [nDY0h,*JRWCF*\U,.5SWBi05p&<ފQ9sY&\ڋmN*\񂊚h7\4nq}X1e*VHذ4ן֩R,*SNJƥ*gRz5"Rz*QJPF2ti5~;44z4QEŠ(=?÷V/j>zVil%MPծ. Dis<qcږ66W7w]O-խRAsmsJ,3*4r"Ȭu6&Yn [,ocDⳳW:Fg@im>("X[/88V(”hͨ0(ƌpn1R%8qRJ1rƬ5_L҃lք(*? $\ vҊm0X:F(0Š(/ $*R|f'G?N_<+y⫯ڟe?ik/|M{aKt-R9'|[_E|[ܿt_j7Zρ5F|U/xsŚzEP^aO >!,xCDyexNմj6{ZZ[Uռ3ƽx 5]O>5 k֡{|Du\:72^?hQw_q|Ncs㫙o |? ( (3m.\ҵ=TZfiz4h-η|y͂XvG "VO94ǠrںKM=eexfm"ёĚo:z״[_ir\@q[]Zy{;kеk8Z<=yPƫky Ě|,usgצ|,usgצQEQE3RGe~џsEXIgAF@'sT9qȺGQ:O Q"?uǯi?_z|^^ɻ/"[Tx?ŏ/_~# oׇ|eo `h_|#W> O&|# 6IϩmI׀e?|s٣?.ύ wxᮞeUպx~]ܟ; yUnxcĚ׃|Kn7^4h٭/>hw{K.n}kf`x`VtNZy-Q:4T,2hk ]{UBLFT)Nq*Y8X=ފR^ijU_Y}ᯈ5C[֥Jᯉog-7kO^/5x  UK0CJ5)7Q' ^){\.*'R4$*F3TJP%(6TOi&Z4QEHQEf)3;@2@S<*г,wQroqoR2o@0VHr: *A)"c8WEۺLc3,h"O07i iDQ,rxI 5׹:]zጇ-,YYNR-<shJ_XѩK^x\_Kٷ4^UQ*)Ώ::3#WGRC+))2 3Mp9ʝH qq'(2IQiEM5thj=S[5( (:oWzxOj)ݲ#*v:}:JY:|袊(+ݦjv?۾~ʞ$}c@}#P6^-о{'es]F;=?L48滿!w46VVs*X7 "o +>ţi?zg4 K w@OXtjU>$xŸw_- = ( (0gO! F]д.zcYev}ewq[:#\AVѮlu?KZR5vZ}L~j& Ÿ<"4ߌ>{__cEiJn*p m86W.N2O]S>J1jjj*\M'yPj'NZU'ڜߏBtOh?|5i^"爴?]4-BW5WPҵU渰N ?P{KIṶXeGmZ$ԯ*uf/~gi6eޟhѿgGO<A6_,񤖶zO,j7=ƙkoi|V%c:? ZWt{ CJԴB-s)嶵7 Q\|cj_#c-6]϶}>:!f߇=ԵO^Cǃ5R 񾁡wQEQE kdž۟ &/kR/'DM?n/ZNj[[H.`8u 6Yh-R5{K-B*9F!'IŸ2Ma 35~+M΄i>:Սv>('~:t gω x i/?u;>4ѵ ¾f?>&|)U7P/­Oq|){w/. ^ׂ#|[yk>!:x_>P~3 lhG߃6:|W?a^A Q<[i.ݝ՞ycYV5K+տ_:U~,,u|'/F/.,K.־'Vu9i43V_hͶ-#M%~_ 隝7ڭct).KM|3{:5]/uM:GSzS֗Kk=#Yh5dӵ_ھY^u;_}z3Yc0֨r4L^R(jө?xb%#9PO?9{:g{IʝH9}oςJ5ב[\myiyli,N,[UO%\\[ZjzNihz查^Ye*Ӆj3U)ԏ4%viu('%$^&:*F*R{5$ӌ$ '%$((?/? G w(.+ ÿ 쮣g_UQռyfguv:uŝ3Y)/^8oMSSSƅ^:񞻨zO ֵv\xwҤ4z$0|dm U*VY{uV&ZjO%i*ny,թRr(#Z_+oDQIZ-7^$( (rԤ8&9$EIRUYYYdEIx9+l>"]En Xi%KqĶzY֧Jѵ}ioä_j3ϥxjHEi޽Xr4WN,4qUh8WͿeZ(5%U )Ыg<=e Rgf ,%F#_R2o)ԖUJ+*x6N-Osmsesqgyo=ݤ]Z$60HOoq<2G,R*W]mo!iϋm )nn66Ѭ:ufi:vۘwJtkOZZ{gV\G4y]L=_v<7<#z^ WO*pXya+~NGW ]pҜ1T\cnzXqQ\W|Z>!x_O~ ׆f5#QH.,o-l4wywŞxW^յ xF|7]ߏ@_2~9gD/!]-KV:/f}Z]aVK_ mP'o]c犾MthOQ?j '?K?kOk&YyxWG?x:^mu[~3'%uo-Mލ'VUhVڍZsm+(:( O hj_ĺ(Yvu]j7zFB,4xR/Z~F? Bυ|5_ _jxgѼSO췖_:4m[HoiZ}O-忙][:?.|+:VsKiu]o>,Ӭn@]Ƶ[š*!:xEԼ袊 Y& ;M Y& ;M((!,ov?౟?+΃.hOd -?_sXb(3g_ z֓_5]Qgο'TkNOOt8Z7|d_ QE~^}W,,u VY|YUPQEnI'-@ԥS<[YK6`ڞ}mo/촽{T^a>j7:Vmko%h.` "{-GLl4SOӵ]:QӮl`L?4h`%L9V{=;Li-S[@> 4>O kO6|;FF\%vYЯ'%Nk))OF+z/<5o㟇_et? i'[ºխˏys6o" k%|i?Vƛ|1"yUnxoĚׄu/x~:R9};Tҵ]/QKִ=kKXuFl/Ii~}ol|,Հe3RmWjڤwqc^,>$$F-!AL񍦗ᧈ˱2Ԍ_Uՠ:Tfxrf'*qaδգ%Y'Z{ZE?8+3 ( HնO5IK7%Je6tai%v(&&CJ4:#QSաV)qexVփ,E NΕD9&$f;5٦M=SZZi{yʱ 1ȇ&!K208CV9 x.( ý2oΦRwE5YvGVGFdtu*Hee e RFk2a(r_HPLFYRu+G;%T,.*ЎaT~ ]89?:7k)s/+ZRmQ^YaEP]uz'`it~.7777ڼΧ[x,J$Zw[b÷"Xr5wNo4o&.`)){{[kY/ny yb~zTV&xlM7J$c:eu*X]|=DIף*G^-5<=heGwk>,Ӭn?#⟄Mi)x[G_IgG*,5_[>K.j|i.+D]WDMV x>%?|ceicCuaojz^Z>S>|9W_k]x|oxSLu__Dw~g>I״ZOм3:cxKź៉Ҵ?m+BҾ|UI¬=a4*dW(v@/K?~'鿱}_K?~'鿱}@Q@Q@3_tgG3RGe~џsE 'oTiȾGQ:O Q"?uǯi?_wz|^>ɻ/"[Tx^+WŞq7~*Vk~*_];U>x/XψO^?>%<3Hq/[W_ ?dw]_qú׏g|7GO >:~; [cC|/h>1__/ ?j_E~x?ऺoxo??n}')MCχOϋAkΣA`'?|LwD(7x m7A,,u((+wgr|x{ZeLNχtK-> ~ŧi,päAGiKj͕yiw67Skyeyk*Okwiu=ʹO ʉ$n_4pJYV"h囔naER\MIRph,tyQ^Q@u^~N{(,u=?SF/.|;[]^xv6WRuecYivwNU]cAfko+EcQSZ5cRi+iE(N-NQ%E4qjI٧tǏ4 Lֵ-Sj =sS?5 {K{M#Y WiZ]׎|!AӼuƋo\ S֧k]ǃ~7V(X(~lsŲv41 -GŅ6T5(&6F1Z&R Wps'NqFoQNtҚ&2M;-uGk4hs쎬UԐ@*A  j$obJ-wWinfjBqZje:jcc:v&iFL::N&҆; 8J2Uc18 L^!BNI+N6SKe+'xwJJQEQ^iaEP\蚄zA3,w+#[^iΙX\y2ArjmݔYZA5ݥp6cf7j!џaVEsCjko^ӯ'Vz]t]'}zFLQe}y#QuKHTf@' k]gI6 ҵK߿ ^ԫZcK*RPS:*/4ԩAօ;x'mUNy5!ռ?up=Ƌ).8%4oiH͍sω+aQ*r|Г9'Njӧ88&rbpXJ*MJtS5JUJoŸ6QECW? ~|o<}QǞ |O/s_5cOx! 4/)VĞ#v_|>!g?/|qY_w_>7ïfk'$^7ŞE ??fiŇ>˩WOmx<;7foHh_[i,ׇ̾+nwIOᶫk/x5;PgxڎC^<9?gе&_ kW9-+O|? PMwD!4cGt,5=+SO,xnmQVZտ|\߂Sx:IB}AxxxK:W|-Uw!Nƿ3֟/|do:|RPm{jThRRN- .WJcpO7&_URPiqʾkIFSԫ-Q\QE4+ CH>FW}yo:iz W9=O|9v:~^Q@?Fkٳǂ$z}ǎ,?Lu: 4}"K9Fix' ];xo|yWRd7}Zm#~Kn5h>$ļVVkvf=6;]{DӚDtA!((!,gt_?E'3RIe_uE?'srK%|?'0Ն(Io"?uǯi?_EFa?_+FgC͏|7w_E'/'/Wy=wSM3Þ+__~|ux% >>x+X_½T(eO[gߵ¿xBo 0jσE>u~xt%OQ_8/ ^]^O 2F~CE|T |j ⟏=G]˭Ex~=|_Z=ßas_ |O>,|d>|w#a?(gY=*K\Zڴ߷[~mhb੊[Cg6i=JRQ'h97J]%SJ4WJ(խR5JPyU$&v/*YiaY xh,3E WXY$]JQPi4M&wM=SMhZ&p9ʝH qq'(2IQiEM5tQE2B}cQ5}WI5 0M^Y]=j6Si[ڮsuj66W3&e)¬'J!RHJJu" q' 'BQn2RMdUN:kSj5:UiUjSN\*SNip[$(iwƏjuϋ<'mk+o%Oᅚ{!=Z}c5Գ>ogK.|=SwW7>?xzyZ^+k[mONI^Ru2D4Mkyj7l}厧kzu/FEk?e.Z䵒y-fOso:%kkWxw\4g<EUs7q9֓*%R}_ZkՍ:bTW;KJ4J**\UbXFp' 9¤#R0RJuik1,F#V'ufGvDM8[$޵j cg4Q]+TӧZ_/]Etk.l:? jgćO6>IԼ/\]Zg_-Iג 6Ɨmo7zg V=֥}~msZ蚞Zuiz^ꖗ\Iij6que}euv1EqmqHRsNgjƒº1U)䧉\eө <6/(&Rn/kYJNIkѢ+ (r;̎UԂ*@*չQ'Q*^CHc]"p;ojaT wvJY!d :0)$r!d7VDfGVFe>_Jl:5*eؾ_ig׌8T)KIG֡Rtζ0gqmFqOtn2JVN24ChiFLuy%pV6;`\l gFn1J9)QzJja5(3\diUQ\Q@Fx{_;ޘ ^\y6My|"kzDHbi}Z@tLMGNo&ȹ,HH.-nm[k+ia{;9༳{iWQOgol_)mWmmYJ5Y9/43^peZoJ:<OWX{H_DJ6rԋniO RJXup>2KUѺq.P^Q[Y#[VnyUV.|:uy5>EYeE˭_>xroI+wfOxsHW5WOt}cJ!N{-CO{KI涹Xetob/ >^O>Ś V^ < G[h3QSu;]]r{s *jR{~4[> ğ׍t!Wtjw|UZjoү~٦_Yogwor̜㻿 xGEV>vDeޅHoecxc}>m/Ğ->iz ox/xCLEc9Wl.yb#>.EYh9dcUW^YZ9q5V .UqqS^F׫9,g+(?य़n޾?य़n޾((I?lWAEs4Q_tg_O(?C9'aYgJ=I`(3g_ z֓_5'':^l~/G (/>+տ_:U~,,uTMGD"ٶ,mWk8m_=ŽVz}6& FK !\種X|Gm'7mMEumI4oPvm 'RŖ.5nTRXjBpS)\ʕd߱QTrz4Eg88eRֵ k>>"[.ym{T/MhLlUNk{\=HCZ{e0\OXV.z/c*Ӆ4PZqQNst4PZ"yn6~N<OBxӥҥUSaJ0RrG G (@(DSoo˻|u 4[=? ¹6-t xLx]XYM3H5M <-q79ѫ67 'Sta]P,Rl.& *ԣ)<>' B.VW}z٤֪Qn,ğym/|s+G~$xoeߌl<7m|_].lt*Xiw^-7\Pߟ FiOj>"tmu]Bf77.mln,-紻[k[ ) RXgThEY#YU oӭ/~oh:$:͑_hmO?:ޙ[i<^*g!EރG2էJ0ܡPPԥnqB wOE0Ͱ%?| 0(fX,#t88* iBi;TQEyGghGsG;x _ k._:hڿ|Ish ᢼ??T-~<|M?Yx>:/Ax/7< :f)Vskfm 4}?'|;gß|?? r#|-Ưx?Ou|-wt?ZO^O<ƱsSi u[ xJ}cB'o#񟏾xS>|KBPS?|ET 4]V*ҟG_|7=[gxW,-j)byqzIS IO)K>r9+#0:ukxEX5*Ub=C/<7'If4kKaO TQErMw^Mw^QEQEC?XIgAFc?$WAFWC(?C9'aYgJ=I`(3g_ z֓_5'':^l~/G (/>+տ_:U~,,u*͝ΟsݤToX9chgx&Y I-n#Ym" dQJQ(N*Qqd(YI4iiٚQWVzjPB+QFrVZrSVH8ΝJs' )BIJ-4KgY]IgyA"I5YNKnojijufw1{[M%^uKE4R(d7qm-嬅nlnmo!+ Y_شizRi2Iqg5 ޕ}4(_Y X^L9l󨭌(P)MMP-[4 ɷ)ԅ(ܪFs ʎ'4Q4e%SSx|4:aN\^:L*8 EzT𥄭Ǣ+B( z͙wi~X^>"(Y"K7zoXC_Sٛkb<3Mx:/ k{EsbЕ''Niƥ I%:5'J9Rj5RJ;vT\J+aITi{*Tkß\=ZfMӵK B{+%ິ#xXeGDWRj4oi?9|5)>˦iڟ'7-g=[_ynizþBMӵK B{+%ິ#xXeGDWRI^GYAX֥{GAsNg)Q*)NpؿkR}2\G:r5 sGsnY9(Υj(ࢊ(jz&kZ.}kE]ņvj:u]Y_Y]Eͥݴ\[\EȒ"_izgmߊӬtYoTHizBHj[b7;3᧌4{Kn4ONխ#Km43[%Z{%[/V/̖6 b0%H*7r՜'_Fnjaqtӯ5aF?/dq^o%e(RkGi(NhU_Y}ᯈ5C[֥Jᯉog-7kO^/5x  UK0CJ5)7Q' ^){\.*'R4$*F3TJP%(6TOi&Z4QEHQEn chvȲ10RyԪ>U&6m4$24r.\dd0!dtu%$D*ȌȌ:mMY|tSȕCn|(q-mAOouaOVtᏣl.WSSJR:YV5{vaVTias,#&ͯf5wN)]s]"Y8.~eRGYԫ!UHA׋8NNe R8qe$(Ԣi4M5tQEHQ@Fs]_NʴMF˾sk /KUXj IN*%嶞+٤E).fP%ki-IQӬ 9",YʐGuk$-.eY4u繟DQVLTxtWOWRlŒyRr>Ycź婏 9g 6iR|ʗ3uqWP*N$*Gi¼s˹zُ*|n쿳/ Mf}_ŭm׋M;k?k 4?>O>"C kᯅ<'84WxQ_:>O|Nu$}O"OSTGtik?{=:58ZI4(.X$M~xj\*$Rl=jx6"+aW;5&V|ï'ĭS-u]W5Y5o K/=񍕥ڝoazƛhOSY珼??_|Uw1]#'Y][Wy&ckťZ|`}h6:F[LWǿQ(4d?˟? >\>^5? /jl4BPҵ ]u X :xsžx^&ҵo xIҵ+P5e''FjsmE&ghFSܼ,]E^Y)ƭ*ҧLvgR TэOk+գf9w Y& ;M Y& ;M((Hl93WgHlW=Ep hю*}yU[sXzؼUjשSLV+' QEtHQEWXYYA4Km;ŞH okKmk@xZ|O94MÚ^=6Wm妣]j0^YO-嬩=ݥ6ƓA<.*$9q'^]Bnu)צBV5NPL(WŏTы4#V\Όq1VcUթCIڢVUp0x|MWqC|OAǯZ隖#MNѦL,>"ƛ0yj#𦓦MxfJ|K} =Vޏ *yNFwjn+)*jEZVW,L4="p\<$*rЩh\j(Ȣ+ (:xLψMkÖ>+\m#е/hv:UYo.tfÞ-um^=9ۭx#Lտ|E]v^񕎡qkږo^S9_:6xGUbYx\>oO|kx .+!2 2 O}.Eos/xO";˛+Ywo/ >XiZM>>PaTs\Qӌ(fx8 QJS`WNhʶX 4++ONI2l+JJ7Q[ceh|A$Ṵմ]KΎ?Q纱-k5ރ]#\- X֥ZzqB:ԧ~Z'r IٻI4Lvi٫>QE( "]\k"Q3[k7;-[݄7 mrҢ,Q#ݜg4yOX{餑xli#MS)<CJ)ы2ުUiU҆cxMwKW{=gk&)QEQ@]ou?Q%/mo~éA:?5 ]nޞt${vE**ԝ*MΜR|$ӳI٦4iJէZjR e.YӒ%i'i$$٦:kIִ]W^4gP :;=m Ui-VOsjIo±$+mu,GyI[}jZWMͅz^ R%I%8P&2G -Q_OrmM֍i:v&:y0XJ4]%{`qUCM{ %j/PCN>JxݲezVyl,&'Zj?J?=yx uO'_ W^/5g/3y6x//-M<?[|=<{? x:_?xWǾώ o>4xzΝ? ¾#ӭx>!o4{yghΗyujuյ+=CW_?ɺ9Ncz)?m!u[uo-5 WYգѵ_:J&ft_&{^z^Zk|:wχ?VT%)}q[|!tAJI=a: &""1Nƴa.i5hVQ0xITb*5'NX+3(!,ov?౟?+΃+`?9s?_sXb(3g_ z֓_5]Qgο'TkNOOt8Z7|d_ QE~^}?^Ӿ*|{> _g|^棡|e'|U~>?_2]b7~S~|et 2j>|n?VY|YUW?a~ Ğ |Ati?i=[{ >_>7{O_gofO=[QegU@ EPEP[`tMe-UO$x=ûOl+sɫi|QRj(^$ (I3NjT8˫ IRq+ўBTbe*5%8SJqqѡԡЯJΝ{wGX\YC93S ׶%qZtV:9^U ͜zÏk$ב\x/Z?)r$޵j cg4Q]+TӧZ_/]Etk.l:? g$ |K}ou 4415-c<+cUkw~ˋ_?>'|B<o:E:I}%*krxW<=j?5xWBev:΍ 8cKku|SLJ"G;Q,5h<9g+%p$7[x/'^`}oDF&^h0Pn2))䶺́_*x×ƅj?|DxLj?:";3u{-s8~*_.~/ÿKo[Ny3k:v6~ծtoTKk7 O@O#?٣oiomgw?s"o_L??GF 7/jc |-<QEy_?VoO)'S!ߴO7>x/s'wi|2+Eټ[/w:įGJN2gk/?wMEώ>Iԣ ExRN5F *R@ %Ы_0k?kKC'(Om\N/SڏT ?5o>YutYEjڏcasqs +f~0|R> IL k cOτ# gE<[㿈;n'ï~ oþ7|Ah5?S 3~~<[m~*׎uO~&xVv IAw,7o <- CѼ{j>"{Cm/º~מ,NE7C4h_|3%{__`#8 Σm}~?|~YωzI<ិnxcශ{ x?joڣ࿉?Gn|k:wE?㿋Z_o3|?M#]k?Mν/W^6Qg CT,~tg_Z? %Ы_?L;=;T ok_amF_uϦХ/;?6T6ZviIt4kV*__?o:B_TF JeVjYF*.!INI9RN)RRNUgN!*UkJeZNUI4iRSrTS,"T,~tg_Z? %Ы_eASh*__?o:B_PG7 M~?Qo~ |'^,4~ǾW5>&.<|Ax&ju/㝭{h>2A/5Foº~&Q-ZO¾6xNuំ>~Ş9/=k7=Gÿ|oz_?GK/ ?SV~oZgX>)?ϴ?~ _1 wo>5?lŞh~?GƏxwكώ9t|3u3o/ t>-Ԯ`>xzGGFk|G??=lMN.o#>}_煼[o<1B*w⮏ƙe&VOOuU_*ݿ??ߋ|yˣVYw.>%Efoo:ZEϊӼ;Ꭵ>?thҥB*t(P 4hфiңJT)ҥN 0N"B*0QI$6mmۻmoVݟASh*__?o:B_V?/ eEç:*T,~tg_Zh Y|ο "KXTO߷YJ?i~·tbX **Avi`+JUГ(TQs9S:9AסRo*5(NQii5tW4M&FZ?_$G+oxYg|cύ'<+? sN+H7/s?i׿g>1Kğ߃2^=xŸٻ3 r^*W:/<7 {]O7_ ax'b?sKa{wwÏŷ>FOOuU ~5~?Տ? S٧þ${~Ҿ c?E)[$'xzK펣|*if'a/E&?f|3xOχu _G4COе]OG?ڴBX.ep %ЫGASk?/ eEç:*C _js}A~#"gֺNe(O fYIT)RRtԚMT9ƭXM7RJr9U&ԝ:))SJ1 U'M>YNk֍9֪ҩ4/ Mx>:/E_ Ş6|犼'j6LJMBMY-u/Q_K ?WߍzĿ7!L<  YBƃ "^G"eе 2[EA x?<]E||R[ʰ_zω5 wg[G/|3+m_G/4AhZx ?T_W/!LEw,SP~˦8쬵|2?ٞ"x"كOF韧 7ߏ/CßiῊ> ߴǀ/|U>"#_߉ kh}_ \]u k go'qs |C۟NV?_???*𗉾~Ŀ>g⯁?W&Om-%O A{៊tmk x_ln~>1Ǎ,f^,|/A|AWּ ϟ~0|>ž=_|!e?ſ<?¿(sk>A~?z$্|+dχ_m_~ y5fG '=G4Q|C>,?`/'wD7Ou3@*Yk:t~ A oğG<&&5~/׼mn'?z((I?lW?EuQ~sWQ_O(?CY/a91GK=I`(3g_ z֓_5'':^l~/G (/>(((((((((((((((((((((((((!,g?u?౟?+΃Qd.?_sXb(3g_ z֓_5p7C~|wׂ< )ҵ/xK.|g?x[~3oH5jVXlI/"V?lgٔ7-Oez?h@zgk'eGOQwq/qV{O{ /3~?*~7F)'NNPm}_x'pMpGc#K F5eL.!SiTN\I)FҲ"?~@V臤?m!_!/ǧ.Ď]Z_/k {C9=AgQ_p~?Ce +Bp~?Ce +BQ˭_?+>!Qh@+.GoZimq 7` D5/t]mR?\9>_"?A|V膣"?A|V膡};roy~%k 8m~D7_ D-D7_ D-!~=Ϯ5_?x33! "A|W腣"A|W腩 }pwO/s4|y(?m!_!h?m!_!i_Oj\Կ(?m!_!h?m!_!h }pw$rgws4|3EEh GEh B˫KF Lh(?m!_!h?m!_!h }pw$rgws4|3EEh GEh GHg_냿#;?+s4|y(?m!_!ihQ_!Ćx{{.[Կs4@+?.?Coojx?m/Rj!~=ϮĎ^O6poFy(?m!_!h?m!_!h_@HR?_x33! "A|W腣"A|W腧Q˭_F _c9>O;roy~!?9?~c?$_TW?]c'׈3Gşx&hVz--t{[W[Ju4oumB(uR|Np|Y+mʟeX,-~IJ1r>I86vW~E.|R*Une EX)r%.IIdoc/Octave2.jpg0000644000175000017500000016463010252703424012305 0ustar renereneJFIFCC" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?oQhO~-n{ԯ|E G9m J嶢z]YxsD~#S񾵥I݇qvM{lmgrvm$S=wZ%)E.O&&^G 4YWiGYkZகm+UM6;uAj?gu-ş-f *j3rxfO C2]66ގjd׈"Ϣ/ASL3ɲC1j>5 v%קC Jε|UH҅Jx?=c)qcVWkcq0*0*|rюP˱bKpվ9X-Tyg6^$ojo)4}@3[\|D`?u0Yzs͠ g'Np:poK xW~)%o[oхIk<-ᫍ2ķN.V=mE5ݪCQ}u|3oW>½:T/O|S|N|gtt]{BŮej6׺6og?L 3/Rx'`x1occ0YvXȲޢ;=X$t)U!SiT+,WqnWœ?>$n7\C)b ^xB,\6X\<-ѧ+rMq?2 eȴOD5"֯ïأxûOh%| ?4KG}7"՟_1/:/*|Mz|uhc^ |9oڇ}~?g+_|4\aq=77]8uxfI G<2_[VkQ7 7מ'|?ì' :Ye㽦"?T˸o1XgSsUX†WC| ^4(Wx,oF'/ѭQzUqyWR<*bsWLOioZ?"ek+NOywxw㖇C_4o_-$h &/KOuA]jZ/<RY}Ot}KK?>"~ѿ n_<[?K/ŸMix7 |R~0gψm#M..?I?%khs XrqVa g9z9k`#['Vhl-! Oj| ?-_G4O Y-}+_ &@?7_v7??ZC~7$𷄼 ]?/E6"{xĺ..t2;5=_Kpgg,bh_f:/WyyUVs0TgBZ'"G+x>S9ܳ /6H)+mJKDrR4_ W r3Ԗ'CU񃠥*pxRu)Ћ8iȡ ?-_G4O Y-u~ jOkh~*_|>>/|kன č[ 3 l4ۛmSK_'|a+~_~Yx'_Bp>,y/>AhAk,t~yg/F _PPObAO}???<[#B xo/X.jW Ao|.%??0_*׆/|OOy~>AO}???<[#B xo/X.jW Ao|.%??0_*׆/|OOy~>AO}???<[#B xo/X.jW Ao|.%??0_*׆/|OOy~?Jf;ԼM|]x_^ H>.獭T{355OBt~ֵ 4>}}<\dxolHث%Xd~͜ 8839|Oq࿀V_h_*]>Bw_۔?1;3 qH|C5vi7!='6GGSg4~߳WOm3Oпj? A2OxFt}rb]g't*Zq}G/xg g-_➝F!j.N1c3(u .o\G<>5 WV״k{&xW9Kmfkƕzq)@pu/.Q> lBbybg$yqq^{Ŝ/[.02LV"?0ȸvUeqX05//Pc>R.x7WP`k{*|.i:xoxv'MѬٱ4=e-9ZənlپBC?vs-n0z!ǜ/?j?u56k'sm7;Ï\xShz_f|=-GLүr4oJ|/b5mw^.75^}.U{3\~:-ܶ]O%V6W[k[yKD.g]kgxa>'3_񭿆|oꚯGZΥ>_3v-I>Zj7w8)Ͳ#$ ;s( 03r̓aiC0`+ϓ [Q}g`TT ZX&fZxn.*1ui/^oWUgj_π~(9I}v}G-Cd?_gjh:G;N4~DoH]BBǭhhHm/فW_ 尼caTnAR2> [x7P5k+[DNJu sjOk:UZ=ׯͨ-zVwrY9;ԡ3g֭I8~OC_6]?úߋuߤx L?|&мEe ^^(8)][t5_?aIy|0>ߴWY!>j?S/7"{|NԾ/h.O x~" j:k6ſ u㎻:߁~_P4/!6oXZTGu#~&M?3ii)NSFϟ'!IgxCƟ ¼7k h?|\.tu n|Ekm²Ql41_# K E_|#WZ|W|uy񥆏|Ė?5b Mܲޭ @h?o^܎>r3;JoeRpU ʦ ㈄c'J3uo_|_|O~(Ҽ?|^tIkPF?x?t$%ԓ_OmK!ѽUҾ(3kSM_oڷ_7j6L|J}kD4y-ǿ~i3W!iɦ燵[yGC3$'%.?_[_lo5x/d .ʞU^^ڝe/<^E^˱=Ǿ!J$qU8Wx~&\O #YR0BrlʕG0 uM;ѿ !J9?ï3xK54E>/|Y}+4?TozoEs|#Ծ/=nk{I+{?q|Kt x3?ռGEѼ1GM-+j%^ ˲,&YRaYOeUia,>ጮ XZUNtҝz؏~?]C/ ׿vI œ ?ie7?Շij'o˟Q 'M~^_ u-ƳF~>=o^ |O|kNjĿ oDž/ N223sYOg*a`cKW⣈[W-ҧOS.&_/WL]<=l'*尯S1թ'Ԧb%ZXq]|}~ /_x5tgO_g_ ⨾|.O qLv>"_=h?txZ /à[ࡿ d/A}?l's|_]3%q\꿴%~ |p?/+K!٨i~?~5t}[M7/E߷~ߌaoo'.i_k7}zG?|cuU?cO/6󂯑CgxSoɳ|^gZfJ^ex &#&0q <8=ZΞ0Ef3&3pXu 4k 1xis<\6;UC <^YcU\g|sE~^6OV#O k ߏ|Mx[_-ቾh F53}XZ>m xq7-yk1<>~G i4jF?~Ɵ_|lW q8O9qyXVbqT0'bV,YEwRQ׫Z3S э7oˡeY&T%;6)%7R*kfQ,6:qx+NXx#_!jm,5bqm-3[<#3$ wE#UQQ3~:Q*?QF?~Ɵ_|l_x_ѧ isx7 4Ӌ_bvI#<_9qxe^¦/[R4B4:Yƚ&r#)EJrm,G"yG|F?~Ɵ_|lGC}nF?mN6ʎo?z}7?m ???oc<f uU?cO/6!T? 6iozuw?T/8%xo/,G"yG|F?~Ɵ_|lGC} wl6 @k?_|pK1_=">?ENb'}Ni??O5_g d|o:Q*/էmq y?[~.?~jEOWC W 1ES5Å7F;-Pו%$3 O|[~.?~jEOWC W 1ES5Å7F;-Pו%$3 O|[~.?~jEOWC W 1ES5Å7F;-Pו%$3 O|[~.?~jEOWC W 1ES5Å7F;-Pו%$3 O|[~.?~jEOWC W 1ES5Å7F;-Pו%$3 O|[~.?~jEOWC W 1ES5Å7F;-Pו%$3 O|[~.?~jEOWC W 1ES5Å7F;-Pו%$3 O|[~.?~jEOWC W 1ES5Å7F;-Pו%$3 O|[~W9׎~T_7O_&x UV>"Ӝu?ࣿUc/~9_KߣJIZWl]wn?G-$9y:kV߮Atha5G?^rGC{E?O0/_o_pK(y/|?oM7O_&wO( ߎ_(u?ࣿUc/~9&Gk:t< /8%<_7O_&F/_wc/q:Q*Q}i:f_O?__/F/G# S ;E_18?O( ߎ_(4N3/v'KIce/{/# C{Ewc/q}pNAz;}%$2=tk!W"S ;E_18?o?vSLXC~ GTO~ɿ59eߵG{ҩGtF1=M#|IጐF?ڧïig/$e [16 W 5s|2^8*U1ѡVV-NZgiGCҮb("Iedh82;0UER\z~*7#IspCRRL^@L~ȭn$9< גAȟf*Mdy\:?֬gI7f? ~:exgc]ӧTnޟ}msr"?v!4ojΉ:g8Nv[xK? [xob]o$5  ǯ~OM&? !Sg9,.x|,'Np?X~6MQ)bqnI`VB< 8KT?/+TRnw؏A<{?b~0gu=|i'?[Nwl>vgxYֵOh_ >3;A>jזvF|JVsqq_Mgcn)?Go*7GPd8=ÿ8w_F++^Ǣx g-FOԴ:Сt/T7[Q//4ƚ{y>7 ⧄Jo|<`fFU g渌>S,vAxGO*rXlFiJ"Rzbh3xΩpG,nTL:s,.l[|%,N/CWԫJ1jtJSkǍ<'υvY!7 I߅>)xCA~Z^!#];W[WV&,Z ݝ^oO"׆'w<+o^kZfg#㶛WR(uk jzZK{C/$,=qA] :r?d_rre8$.?*qFs᷇O/8rb\<Y53xzYON3 T[,9c Gt/zxGþ1xR~u?5[ UҵIGDOP.岒[;IKX^p?B_/<:C=8>6Cbdyf %T_ xj8aN*I?} ~q_+g '/&(_3ls@YHc/?C_>@>)xD|r?mO?KoگѵFg:g ߆> ~ia؃G/5?^;o?o~_wk0_~ |0@k 8~7/O~ߵ7w?h|']O|Tؾ>/iޙUH/| `~П/Gn] @x;д/~M{/ yOS?VBR-?`~οNoT7ޏygDNS +ygDNS ~οNoT7ހ>~οNoT7޹V?dnj|=oOH'gx m~οNoT7ޏygDNS +ygDNS 7cK^mx߶xOvzSNW|Ux?c[iAOxZW,l~οNoT7ޏygDNS +ygDNS ~οNoT7ހ>~οNoT7޹V?dxW:ׇm'~|Y m<|'_i:Lj|MoB,5MgY/-t/N eP+ygDNS ~οNoT7ހ>~οNoT7ޏygDNS +ygDNS ~οNoT7ހ>8<'X{_ ixFgc?%~g|G[k7|CFwH4mgKӵM:{i╺ygDNS +ygDNS ~οNoT7ހ>~οNoT7ޏygDNS +U/Ǿώ ƞ ox;>[O~οNoT7ޏygDNS +ygDNS ~οNoT7ހ>8<3Xi\",%^ӭ|U/k>׆nox/YK*>V{X8:ygDNS +ygDNS ~οNoT7ހ>~οNoT7ޏygDNS +F~~#|Y{߶ ֗-৚^xW>:ϋ,lc|9 1ѵ+ +f5.~οNoT7ހ>~οNoT7ޏygDNS +ygDNS ~οNoT7ހ>84o*=GŚ?=o뺿Am?iz7 yj> U|3? ?Þ O<mXQ¾,ψbm#^.ygDNS +ygDNS ~οNoT7ހ>~οNoT7ޏygDNS +S_ վ0i>6[,񿃾57¿5z?i|'K #ivυ:Qcsir7W_ ~?_k9 )}k8\QxR(<=Ŀ'$xJuw7K?PpJ+鿧ғo adcMQcN/ˈ0,ς>-ek[|'WM ^?5kO?Ef>sSB|U%|oCĿ_ |O~|wIwN_S>&>;7M?q+|K|Tм-~?k?>|!5OFcAoZ?<e2#N+ ;g]e,#N+ ;g]e,袊(+%-'iE#Z~ig~ ]Vi/7|M=̺>-?W^QEQEWK[O|'BG?OX>㿁n P/e_o2{t}o#Z~OJ (((?~|K)KB2[?zƉ > xsR🋴/G4jfaiP\PEPEPEP'[O >|[/-u=c[w9O:ψ _G?Ou]OX?ڵ=BYe (((?O|4)B_ [?zƷ>sMt/j5~꺞jzQ@Q@Q@o>sRí >,R4=cWG8SƿZڵCS<]o.bOoG4*( ( (< | |Y #~ i)jz%;>|4)e - :gm_Gg꺟QEycgCþ&þ ?VjZ9kg/ ~ hio{e n:["#SAauMRۛgíwjܯh','S▅]wOxgN h_gú 3U>~_/X^RgO- ᷄?)g>} E|W@hW~c?OZg_ߏZvIgŞ=>&>.:vV~7<3;.|G _/>1Ѵx5<+?x[e4R mX~ٟgw~0ikO؃U.:kOº?&f-SúO_ُ&Q~w7=:^K?/5}wU3۫L\m'srWۓXlG:'7$~"Lj?~{og_9>'Qϲig&?WLn7/3O@=rlmf}CN"<,Ϭ诞| _ڿPNi//:]˦e;_~:d_t?:TNPتxn(!Nu2 89)EIQ|#xx/*|A''x. Z>*յ|K r.uF[@|'_>%=|0e߇ x/4c Τ _DH?_R*< _Yx~Ŗ3ҿNJS]/QҴxiτ^/ iu~'Ӿj>:yc㋟CLZg/?ߴ [~Q_ ;;o`EW-1.YX18enJ} FxE_gF*t|ΤJME {)kɥ>ӭm/? xGoFGԿC^jNi].&ewc?sm4IqC.qf%ѯR'7 \}.hՄ%kNsW/>,Gqu)ңS{3XVXE#2Y`ƮUj>(h(((((((((((((((((((((((((7iEX7iEX+GɿS'7 ΫGɿS'7 7M7{K-ß?ioڃſٷRv*CӞ>~-~͟?i_׍w}85Ra1? ^ ɻ?iqW?~߲?K|3Ŀ~:6i4O_~0xQN-r};O/t>(f[ֳ[~Q_'Gh__gx%?1/+_<85~׈fƩF%曨NaÖڕI.Iɟ~;kek>5whqgd~O5o^/ezO> ~);?_3"i_x]Ю,5W𶧥j:MΡiw\=ךmԐvQ_*p!ZZkS|ҜԄ?0˲˳L2t,^0Q`TMaq0B6n)-t{mO4/_Vu-RR>G6w:v:Nxm-+Iҵh5~]Ԣִv֭`n=%=_Ļ;k??٫ɤ꺖qh> mv;'@MwEO[^&֭^h:FtچiZXAycy7VEx+-2[g>9xVŗyK&ZXܶ~V',O1INSaJ4:m0W>%eV~5N7фyU >2_"rJp qV$n~ ~aů:]Kw~ʇ_nmeί> 4v]eS=Wgmq?|wy#Pu]}#K|Gt-]Z/z?o i1k3ZéxeZ}c5ΟiW\wK(8.גR<6:Qm.eGi9F2~єY'bRF%J/ӆr=GF,9 R9SpjN*)AiRR)T~+((((((((((((((((((((((z~)TRuO5WeUG5O h{5H%_|9⯵Yf|'w'?>Sl0&W_$9wks| 꿌O$:Nm_AAoo֖'\[%w?3[ҿӯ&ߵ__ik N~-͟?i鿧җeƜ_Q_GA_'&}kXѯ閿:OL>_)ǟCEa?Rgx8QEGQ@Q@Q@ =^[-m['SVuGߴ"Xo5= = !}msJtqQN,_ uekO w7Fx_ω>CmxOVPn}+_{ĺncռ%-'\.xGNm/Y+'>$=Z}?SN4鹓IoumH| c}ޏ['G/o4ojgsyZ2iDO'_V^cKO ]<9Y|'׆bQKpg=ʆ).j8SXTu2Z$Tew,5(1M[Ex},ӊ|񛃰tpa(UeJIC)S$?γ S3յxm/? xGoFGԿC^jNi].&ewc?sm4ISNiNiUjSNQ:(Nq'E-4gbN`,El&3S b%GFb(VVVJ% 2H*p(((((((((((((((((((?# b?# b +'N~ڿk; +&N+4I/wZX/닿3[zGs$omԇʿ4IAbƻ)|W}/? ^ ɻ?iqQE~g߱mkϿc? 5y$?)_)_׋ÇEWQEQEQEQEQEnѿ|s>H?sgN~!"-4oxz!x~ރĶ^g %?b8WroڋHlyckK\+-Ag5OxR'}/fE~&gQX#7),F^Qч4j9JShԓX?s'1㊸zt0#_І Wq B5 ?3/a)g5 z kZO|3]'M;-R4-B,tkEtWIt{7Rxnf QZ;o#gkaIEi~ xRf ľ Pi>2b{Uo xYgu2ͮ/ī¾έGXK}\M?+x]V., .&s eqL(FYW,󆰑XN3QE~!EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP)GOZ+ _)GOZ+ __/?VM;Wu_'?VN:i~p]ϖi(4IAbvCӯ&ߵ__ik鿧җeƜ_~Pxg %f'sT!Һ_;E2~ >?[~~x78/Po%/SJq |*h~fWςzl]]x}zoŏ5~ڞ9?i__[ᯁ> <a?i??~##{7>ssQo?*kS|_)ǟCEa?Rgx8QEGQ@Q@Q@Q@Q@Q@Q@{o4o xYտh_zVuCh/ī^&6H<9XK}g:ψt^"m|Yb7>ǣ|'˯ŕ )Ou-+OTvz5?V%"O#_`x+n,ը [.̪ N *ьaJ1:KB7v'fWĹ~%biˌ8+Y^mN.<WSZ|.pc:' Q_W ѿ< Qi L|] 㯆{EtC姇)cxJi;nj5߶U>Pg_r<-q(i:i]i)sK16ixW>%^"ӴuCIxoxW)e8c u|&1nsKPQ+s^2J} |-#cOkb%C/>pn&n:t(cV*.,&Y_Rh׭ ((((((((((((((((7iEXxs7wR} =%X_#WU| K^1k9" <:ڿO +'N~ڿk; +&N+4I7;,OθJg_Mjf?ӵx6?ZN]NJ_3?ᓋ7yG8[. (OԂ:OL>_-3_t}gcFS??%8U7ѫxp3(4y ( ( ( ( ( ( ( ( | /N㟆5ohn񏁼GxK:?w_~!/4[Ou .pN̶'䨫R*JsVRJr*S )BpZ' %(-J2I9xL.? |n `tip.&0؜=h΍|=z3*jtӜ82iQ?_D|3д?Rխt <^,#|Y! {mmZi|Ek.,Yjp ;;-wJ|Cc |{Ưqc?xZ>."3.T5 t㈩9805R~?Vke q\=jZ {ZU|N+G W¸j> F5p~+2P|naMk(b)M8s?w9YGp,F"x|cf|#J1X2brln"XhUlT 2 fG+O((((((((((((((>Sl0&W>Sl0&W_$9wks| 꿌_$9wks| }'?9n.4Wc"Cӯ&ߵ__ikN~-~kJ_|g 'nq\@QE(3_t}gcFZf?3_|Jq1DJoWfQEiQEQEQEQEQEQEQEQEQEQEnѿ|s>H?sgN~!"-4oxz!x~ރĶ^g %2f.?.084:źui34%(I'iR?\)SЍZuqa{E84q4eN*u#?_ѾҚv2SIixL~=懡hzWnV|UyxC+VZfcľ3״g d~cѾGᝯ?QƟ #'[AKŚ+O/A;+_I%?H|^4mRsaF+Ĥ*=JcUw?q7>91ΜNj9+1Ud%IJ)py__R.YE2' O O|A} 7um'?>Vޣo]|7kimj:U.u3״/^x(#LM{WfY34T e?kiA.38N1'FQRM/x|48#p3I/:4燫_Zl=z8># ZJ )TQE|QEQEQEQEQEQEQEQEQEQEQEQEßJof֊WßJof֊WW?NmonoW?NmonoAoo֖'<]%w>Ysȣӯ&ߵ__ikN~-~kҗe4~8wӋP>9|S |g4+?g G>-?jqo~'cc#]?/O"OO_=o|r>K~Wg߱m&û_ه#SXe@)|DO{G?z{|8{OφE]|@Q{O>Ͽc? 5y$?)_)_׋ÇEWQEQEQEQEQEQEQEQEQEQEQEQEg??l Yd/5_xwC־O@%j^*𿄴W-w^%Sg(cizyC*&zA#gg~ʺ7|SگIǀ~1jֺuugsVφ|+p7{mvo7h|'uU1x WI̲5Ri9IE2MF?_J|z&e5jG+ԩ =<<&S R8STq؉F.nzO(Š((((((((((((>Sl0&W_>%SoGt߈w ?ᦻ  >? _U_=K_Y_#>U;/} 1o1o< Mÿy`zOu$kk;_׍!ioڃůٯO^5wR8]'nq\@&߉7h~i~|o_Zw__fzO_?,go>ZƝW/u|q7_)kJ~G?߇~&>aO~#{ϊoهy?:HҼ{h?_,C_?t}gcFZf?3_|Jq1DJoWfQEiQEQEQEQEQEQEQEQEQEQEQEQE?l5ϲ3W?,cŞ o@AkWg?<< 7b **V*}W0E˱Ѓc05SY+[9U^~џׇKIͫCR_B]qhm?^ i1xf{:-:-SZsZ韵5pwL+pI`NOt'8ھJU0SRQ\9J Ŧ O a=Ya)ԩKupYi}bJ&N%Q^QEQEQEQEQEQEQEQEQEQEQEßJof֊WßJof֊WW?NmonoW?NmonoAoo֖'<\d_zOu$kk;_׍!ioڃůٯO^5VRc8]'nq\@QE(3_t}gcFZf?3_|Jq1DJoWfQEiQEQEQEQEQEQEQEQEQEQEQEQEQE~mOc#Ÿk?8?ů W?Z/-3eY/?lʿɞjc_;_ -hjobJU<%K _?Qb4Yu K/O/nciSGTgf~J}'xg@\oLLW"b%tQEVQEQEQEQEQEQEQEQEQEQEQEßJof֊WßJof֊WW?NmonoW?NmonoAoo֖'<]%w4Yӯ&ߵ__ikN~-~k/Ɯ_Wx~S)7HUx>$tC?g#k EgUm|A[^ߏ|5~{3_t}gcFq ~_>>xP/|meZx;J*OtGJEo>|"&xz%A~YNy収.|?s1k߇?t}gcFS??%8U7ѫxp3(4y ( ( ( ( ( ( ( ( ( ( ( ( ( PC~UǺέc▓/~4[ZZU3x3$u5-[&XS}#zsRgk7}d;l:j*xܷOsR9JޥZ1%:ѯ8ѩ8sG?l Os)ʅ]ip$0}6gHGxMŐ ^OW3G5Z>ѩ)էI˳ܺ1hƯ_-3_t}gcFS??%8U7ѫxp3(4y ( ( ( ( ( ( ( ( ( ( ( ( ( (?N'? &մGKG쥾5_g23ڟ?,6|_Edا ?/xź, Em/dWOÿش&<TeugS8\4:t$9KܧGJ^:Wm/+)O_|8|'>!BT'x;qN#*c3cqR״l9*p#EWy?aEPEPEPEPEPEPEPEPEPEPSӿ੿-/|?d'#k˯+ |k ŏ|@jKпZs_jOO_|9`M?h+}@HY7 sdA_HY7 sdA_ɦOٿib~sWxqcLU=' :mPص5ƿ4IAbvpRa1? ~ ɻ?iqQE~g߱mkϿc? 5y$?)_)_׋ÇEWQEQEQEQEQEQEQEQEQEQEQEQEQEQEW78<) fOؾZ~Z?ix?_[ox[O"˩fr,['ɋqtTڌyFtsZ?jIǩ*oÞ0xqƞn=?d9,c*_T̰S4˪~Yk3g?c Yk|l/5_\ɱO@%j^*Gu?Xw^%⟇~(ciiLxf"p|A|L KJ9CGj[EVU:jӜz ⯆Gi<CrQWL ΔL_c0AEW~~QEQEQEQEQEQEQEQEQE|Rdـ4U|Rdـ4Ub#d)[[gUb#d)[[Px&=f]3VD4IAbvCӯ&ߵ__ik)Kp2q1&(eEWW5Iɟ~;kek>5whqgd~O5o^/eQ_o!EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPaګ>/|MiNufg#)958bp#~(c0 b0*p&{Fa+jp76TKYJp -8~QE`ϸQEQEQEQEQEQEQEQEQEßJof֊WßJof֊WW?NmonoW?NmonoAoo֖'<]%w4Yӯ&ߵ__ikN~-~k/Ɯ_~P|e|e?P/>% g'J??e߶M0!=w|Au;nw? k_^7#þ&oj3_{|o6 SK|E?Q|/lxj/_g)'ݷ?.o}<'eF_t7|A|i/7'Go;}Q| ?~UTFx_>4#_+쳫 >ZoCxN#|so >5wh7x>7x>~ў30~^ 0~..|EW'[9ׇu?Gi ϋm |C>1j>5y\xߗ?t}gcFS??%8U7ѫxp3(4y ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( f3ڟG?,~ q_<;k_' ?/x_Zg+m/k)_u=Z_ s8-cۇ 0e[ OꙖ80qfuVq-`&6?oOK5ok6)ĭOK^(n Q[nĿ?Sm6-3IY2|;O a)b]({HKhЪB~ZsC!U߈<1?x0sX4q_Ta9Ҕ<6iUk fh(Š((((((((>Sl0&Wᧇ>SoGu/'߲^ ŏ?~_U_=7_eV~# +n} 1oy_IY; sdE_>ɦOx}ÿA~\]%w>Ysأӯ&ߵ__ikN~-~kߧ/Ɯ_Q_'A_'&}kXѯ閿:OL>_)ǟCEa?Rgx8QEGQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@FS%O??bOkCUt?kV KLm|e_oE>x6.G2g+~Z"Y;&m[LCxƺM >|&ev#5-B 5i=W~#~4NjpW !9c(}ReJSl ٦]U1zI+?? ( ( ( ( ( ( (>s)M??_V*s)M??_V* 1o1o| M}ßS?:+9s6?ZN_wu$kk;_׍v8?)|WN/?4l((/؏> O?O{b~_,_>|@5_?dO thڛ~;4~W[Y*|_Ï_џoLoKG$ZE ?so͟:OL>_)ǟCEa?Rgx8QEGQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@FS%O??bOkCUt?kV KLm|e_oE>x6.G2g23ڟ?,6|_Edا ?/xź, Em/dWOÿش&<V}xiG ۘTQٟwIz_S8ȿ#1غ|>5Q_ՇQEQEQEQEQEQEQE|Rdـ4U~`~_9+ ~;@ӿ? 5OSQWi^ u?1{C쿧W?w:Os ΫGS'_?7M7{֖\[%w?3[ҿӯ&ߵ__ikN~-~k/Ɯ_~`x c 'ho.i???cm;G [??Fbx2CB~6?>0QoO1Q?R>@;$|;k)@~|? ~㦟8k>%>*h^ѿfs >ާ#J·-~  o~,g߱mkϿc? 5y$?)_)_׋ÇEWQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW78<) fOؾZ~Z?ix?_[ox[O"˩fr,['ɋqtTڌyFtsZ?jIǩ*oÞ0xqƞn=?d9,c*_T̰S4˪~Yk3g?c Yk|l/5_\ɱO@%j^*Gu?Xw^%⟇~(ciiLxf"p|A|L KJ9CGj[EVU:jӜz ⯆Gi<CrQWL ΔL_c0AEW~~QEQEQEQEQEQE|Rdـ4U|Rdـ4Ub#t9?NmQ~?ƿ1o< Mÿ狿4YzOu$kk;_׍!ioڃůٯO^5_8cX~8wӋ+DH+Ͽc? 525Iɟ~;k8H~3SQ?'S}72(H((((((((((((((((((j~_'_ -hj`|JU i[-K|QehUL_FS7%ρbOkCUVxS(|e_J)w6ǏϣV62^yzhsJ:??3nS;8?~Kgbp;U/f+Š((((((>Sl0&W>Sl0&W_$9wks| 꿌_$9wks| }'?9+8sȞ6?ZN_wu$kk;_׍w}8?)|WN??4l(j?П ~4|?oimO_~)xQ6w%Ş64g\<9Ht/O%k:g߱m)a|C o񵗇Yi?+,x>+G{IW"Yyg};㯇>8?ů~g߱mN</TcF? ̢+?((((((((((((((((((+j~_'_ -hj`|JU i[-K|Qeh3Ezs-帺XWmF~_RںU9ЭJ|7<8O xn2Ö1l/?fXNt )C eZ??bLV5{ƷiSƿ$n#7t[^)״2j3yoڕZ}fwE.9>i7MTfX<>68ԦՄө q(z3 |:-L'pWf5ҩO٩brmlдB P`q4jUbR2(H(((((?# b?# b !+&N=~濌o$8ukt|!}'>i~sWxqcLU=# :mPص5ƿ4IAbvpRa1? ~ ɻ?iqW:coOh"F~|-oxn&i,jo^i9m[x+Ē韟?t}gcFZf?3_|Jq1DJoWfQEiQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE~mOc#Ÿk?8?ů W?Z/-3eY/?lʿɞjc_;_ -hjobJU<%K _?Qb4Yu K/O/nciSGTgf~J}'xg@\oLLW"b%tQEVQEQEQEQEQE=i*o K_c |:ᧈ+#Ec'4=$/VWڬ>;h)GOZ+ __/CVM?t|" ΫHS'?G*7M7{K.ß,9lQioڃſٳ;_ו!ioڃſٷRv*pRa1? ^ ɻ?iqQE~g߱mkϿc? 5y$?)_)_׋ÇEWQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW78<) fOؾZ~Z?ix?_[ox[O"˩fr,['ɋqtTڌyFtsZ?jIǩ*oÞ0xqƞn=?d9,c*_T̰S4˪~Yk3g?c Yk|l/5_\ɱO@%j^*Gu?Xw^%⟇~(ciiLxf"p|A|L KJ9CGj[EVU:jӜz ⯆Gi<CrQWL ΔL_c0AEW~~QEQEQEQE|Rdـ4U|Rdـ4Ub$?d)X~5W?NmonoCoo֚\[%w?3[ӯ&ߵ_gvCӯ&ߵ__ik)Kp2qx1&(eEWW5Iɟ~;kek>5whqgd~O5o^/eQ_o!EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP[l,~gV?UG~)^•<1 uٖڗ<;o 7/j e_'دgHC~ן_쫧ǺΓ}n/~4[ZZx3$u'~hS}#šßsMgkߍc:T*E)4MLr(1ӌ}jsLM˜*S̩|*O4SX> ܴirTC3VYW1seZ?QERQEQEQEQEßJof֊WßJof֊WW?NmonoW?NmonoAoo֖'\[%w?3[ӯ&ߵ__ikN~-~k/Ɯ_xcXiE8w2|t+oL?R|:#AOdj_g^X ?io٣A?g5[GJ$Ajo>?ڟG/7.oOx_O+g/hޓ|5 W> 3Iɟ~;kڟO?_g_/_?4_ٗ$O|GٗXu cAtMI~%_Y@_}>2x/xC? A?Ak^>+WWb08jF#G<=WJ򴢿ӗ,?G0?+FY&9|:Zs)$}?~я~ƨ?dG/Q  і~ɟ_%<)LgOC+wg?!W=?jN_`WLr=ug{?Zs)$?~я~ƨ?dG/Q  і~ɟ_%<)LgOC+wg?!W=?jN_`WLr=ug{?Zs)$?~я~ƨ?dG/Q  і~ɟ_%<)LgOC+wg?!W=?jN_`WLr=ug{?Zs)$?~я~ƨ?dG/Q  і~ɟ_%<)LgOC+wg?!W=?jN_`WLr=ug{?Zs)$?~я~ƨ?dG/Q  і~ɟ_%<)LgOC+wg?!W=?jN_`WLr=ug{?Zs)$?~я~ƨ?dG/Q  і~ɟ_%<)LgOC+wg?!W=?jN_`WLr=ug{?Zs)$?~я~ƨ?dG/Q  і~ɟ_%<)LgOC+wg?!W=?jN_`WLr=ug{?Zs)$?~я~ƨ?dG/Q  і~ɟ_%<)LgOC+wg?!W=?jN_`WLr=ug{?Zs)$?~я~ƨ?dG/Q  і~ɟ_%<)LgOC+wg?!W=?jN_`WLr=ug{?Zs)$?~я~ƨ?dG/Q  і~ɟ_%<)LgOC+wg?!W=?jN_`WLr=ug{?Zs)$?~я~ƫj~_'_ -hj`|JU i[-K|Qeh¿eg#c?dG/Wx?e2b],U+13r^ҍK;U:+GR(oU~xcžx6~Cr5*_d̰|ae8L_Ֆ:+`WLr=ug{ _ eZumR~ɿ5li㴊Q=n"Yn&P<[ ;i;:^kVU]Vtp>/0_Oq̾5b ZaچwN<~ն;i;?ӿK/Fo:3+tοhN,!?# b>߲ O3G?bk /ï3%?xs? _gҼ 1?w1?w< Mÿy`zWu$kk;_׍!ioڃůٯO^5_8cX~8wӋ+DH+>:~?4-?m 'ï3 '"? #gҳs)M??_V* ;(iـ~οk(+5пf :>8[c_WRU>CkA/»~7Xx/|jW~&'|_ xSŸÿ>#+|5_#>x_'oŏ| |R)/^(g/xs>4𝎩sks=+΂0&>.:vV~7<3;.|G _/>1Ѵx5<+?x[e4Rנ#oNkBoؿk tjZ7K&ŚP.|?MAmC^+D>)¿OkPE߶_࿌߳kك<';?>&Au]x6 5OZx~ڏti{kKAnSim_/?|  >|Eos~5j_ů7]Kோ>?c}+Sxw~ӺQE?kc_[_gN? OL?oOGH?A_WޑiY_0|k_*}koOÿ魧x[_<+QuXϋ? _Wxǿu:wG~Yo?Oo?~0t?e/-?5+W_|׃)??|=ڇ9_nxD>թj_/ +?)׾k&??'?)s_A'k_gdQE?kc_[_gN? OL?oOGH?A_WޑiY_0|k_*}koOÿ魧x[_<+QuXϋ? _Wxǿu:wG~Yo?Oo?~0mؿkV_3>V4|k_/ j:cm?:fx~Wе.YNtmVӯ"p|wd|;/><|?dٷ׈| |vw'/'|'Ԟ-@gO⿀ߴߌ| W3O~0|?u_QEh___t~џ~N _ ~1/ +xNu !ֵ 4-sTѭ$n4Ua zoi e??>Nj14i "i=e|:ŏ|E/:g?i;-nm39_s¿ |uw>'gş|cŸWSN&cK<{"?;>0x/Y4?cg_4Q@y/ >x]_ / 7_^2xwoX;nŚ#_iOO-|h% w|de^ΝH4/?<xKRWះ~:_5߃P|Tg<7uMbmؿß'Fx4/Ǿ ~;k?~i9Mky Od -n|{G/5'🉡duE>|q&KĿ>xO |eψ&xwYw-_G4WB kf]yWW0EO'eg@߀?O|Oϋj.> 3:~ʾ>R}G?Sc*R> h{_>/u~L|߄u/¾)WJ[C >5_j _=j?4x;mx( (?~!| U"~0_V| ~_?i|~+xº'|"eϋ?3x&_ImGޕDxHO `X /|''ï⟄5xwş wGx~_^"lzxD<3Rm|7eg|{_ &<O,w|'#<+=:X3H׼?zwZv][_Xm|-{?6|9xw~iɺFl(+?j8hៅ>;^ )¾;,;SkoZ[a nmSu5=Ak/kh__ <+'_8y^ '>9 xWOOx'X׆~$_ִ# /Ω([No--UK~|~~Ҟ8x?j~t&Ož$?cf|`WPښwH>|zVu;>c~1|SuJ|0ueOo |? /<7t/~,?|?Fi_ =P#{XW41o1o< Mÿy`zOu$kk;_y`G>~?|;?|2owBMSǟ?Hm6)>s|Q3D)|엤_|)mwxg? ^_Ļσ?ӯ&ߵ__i3?dW_~~?hYπi?~<'yq-n~˟xᖙ -oW=ߋtu5O9|AiS)Kp2qx1&(eڟRW/7g2)McW_Y j~^?^*z|UkW?mDMF__^g>'|6/߄uäxjB8ʟ?/oG>[|E"wۿ?U¿.j?Gb'-C:a77%dSUO|Z>k0|;]CE<) ?h {2O|6[;վx[B",[^Q?R<W?'~~1ѼY|lO~?j/ٿ]WNYsO+>L wi]>i8>UAc_B|S>)𞙦bN Տ}s)ލo oMڟ^x;Yo?|ki /_:gω> 5_Gu=3@g?h~~+&? :. >> `΍]g`_Owo-g 4? so៍Z??>оZ7=/PӴZ|85m_CK -ԟ<G?o/o |L=WK֏ߍZ?e/Cdssb/~*?b֟'f_cNQ⯊ |'5]{W[ֺ6tvjKy7%=??J?X%?f$Ï??n/__ ~|!c&|d0|L&h՗.)>8i_4tE?Wݟϟw0"??Nm8º;_Tk} S{ W_^'}wW+(L;+T_n~>?`؟S|EO_elGS/(<$?%+;[;3>s[>?ᯈfكk?("x?k߃w_Uן~ j 'K GQ[|nE1O?}<_)/v1O"ھ# O'"¿K%ڿG '"ٟ7/g~)|4`|oRu//~4xO/@񏄵7v-7?k_j0Ozߏ?; JLOj ~PO _~࿌ h@_xA_`|+/z^ig]?_ ] TPm~|ZgWRw¿gߋdGK?اgOPׯ?d~o-|G|%xv vŞw>n~6>1FMm/~?s? xF|?uoxntm:h^=c>ѼC-j_Y k4{Q_KkhPxN>|SOOoįHbb^L|Ggk þӼ[J[i); =oSVk{PEP\? Q ] xTtm;T| &>ׂ|i\:G+[='Nm;^6FӢ~((?gk ~54ᗊ??&uKObkoM?dxHҵ3COi{em<^E|_ xOs0k瀼As ~|)> x/Wa}9]\7:Ώ3M-Iju|_ w'i+:G|3H|?ivz^ivvvZXAmQ/AEQEQEx_;XH>[g? xŷïx_x^,|MO|@G> x]zޱojzs{Mf{_+/ gχF🃼=N|'_i?3hzF HmKӴ: h"z (((s=|_>;?eϋO¿U;:?M'i9tYE:w<casom] +o |-)^gs<;j"#=7H _Uu?>Ƨjw^mW_Nm_n5_Nm_n5Aoo֖'\[%w?3[[/4NYh_TzvZ/afV0"ɉ=qo1PHI|N7!DV_9?I{_3D)NMd,6);dI^MVT'R39ΝYJs攥'UJNMm7sd'nML>#O!DVI%tI$I%dK$I%dOB? MO[b%'V%'VQO'G?Go:_ yԓBO UO/{!/I?2蠣!/I?2蠢?t~w359< <6;'U<7$fV4 woJ2蟢_:I;yko#oSB] ?'K#P!DSO__p$ F[PR%(ݙZ_|E:?I;kK_B] ?'+o ('G>_k/y/?xlɿMO/{ K#OvekjI|FC+O(ᯆ?xmDvMj 0?'cLO|FCO(ᯆ|I!Gd&-K#OL()??̭>h |5RO%BO MO/{!.I@?V7$OE:?I;ykH?xlɿMO/{ L>#1K#OL(( |3RO$ <6_Gd*=B&'7$OE:?I;ygH_5;&5?oݍK#P!D woJ2蟢?t~v5ϗI<xmDvMjK#P!D/B_emAE'_k/y I7 C!/I?ٕ 'B] ?'袏 |3RO$ <6_Gd&-B%'V%'VQGNu'_B_emAGB_emAE'_k/y G? O|K#OL((K#OL((N{u $H?+o ?+o (?IygH_5;&5?o݇B_emAGB_emAE'gkry/ <6;'U<7$47$4(Oο^_$_p$H?+o ?+o ('G?Go:_ yԓBO ? O|%'V%'VQGN{w'!'Gd*=AF[PQF[PQE/ |5O% !Gd&-K#OL()??̭>hᯆ?~K#P!D/B_emAEt~v5חI<$F7$47$4(Oο>_$Ao#Sv oIiE oIiEQᯆ|I!'Gd*=AF[PQF[PQE:?I;ygH_5;&5?o݇B_emA_J |oKk~W~2o~xF7E6_Ǝ4;OlӪKҊ,QYc[.cVYѥ^4dq"JViM&'#ru,N5iԍ՚mU^\doc/copy_lp.htm0000644000175000017500000000466210550256406012461 0ustar renerene copy_lp

copy_lp

Copy an existing lprec structure to a new lprec structure.

lprec *copy_lp(lprec *lp);

Return Value

Returns a pointer to a new lprec structure. This must be provided to almost all lp_solve functions.
A NULL return value indicates an error. Specifically not enough memory available to setup an lprec structure.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The copy_lp function constructs a new LP from an existing lp structure. The new structure is independent from the original one.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp, *lpcopy;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /*
  .
  .
  .
  */

  lpcopy = copy_lp(lp);

  /*
  .
  .
  .
  */

  delete_lp(lp);
  delete_lp(lpcopy);

  return(0);
}

lp_solve API reference

See Also make_lp, delete_lp, free_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

doc/get_sensitivity_obj.htm0000644000175000017500000001567610237176656015120 0ustar renerene get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex

get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex

Returns the sensitivity of the objective function.

unsigned char get_sensitivity_obj(lprec *lp, REAL *objfrom, REAL *objtill);

unsigned char get_sensitivity_objex(lprec *lp, REAL *objfrom, REAL *objtill, REAL *objfromvalue, REAL *objtillvalue);

unsigned char get_ptr_sensitivity_obj(lprec *lp, REAL **ptr_objfrom, REAL **ptr_objtill);

unsigned char get_ptr_sensitivity_objex(lprec *lp, REAL **ptr_objfrom, REAL **ptr_objtill, REAL **ptr_objfromvalue, REAL **ptr_objtillvalue);

Return Value

get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

objfrom

An array that will contain the values of the lower limits on the objective function.

ptr_objfrom

The address of a pointer that will point to an array that will contain the values of the lower limits of the objective function.

objtill

An array that will contain the values of the upper limits of the objective function.

ptr_objtill

The address of a pointer that will point to an array that will contain the values of the upper limits of the objective function.

objfromvalue

An array that will contain the values of the variables at their lower limit. Only applicable when the value of the variable is 0 (rejected).

objtillvalue

Not used at this time.

ptr_objfromvalue

The address of a pointer that will point to an array that will contain the values of the variables at their lower limit. Only applicable when the value of the variable is 0 (rejected).

ptr_objtillvalue

Not used at this time.

Remarks

The get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex functions return the sensitivity of the objective function.
These values are only valid after a successful solve and if there are integer variables in the model then only if set_presolve is called before solve with parameter PRESOLVE_SENSDUALS. Functions get_sensitivity_obj, get_sensitivity_objex need arrays that are already dimensioned with get_Ncolumns elements. get_ptr_sensitivity_obj, get_ptr_sensitivity_objex returns a pointer to an array already dimensioned by lp_solve. Element 0 will contain the value of the first variable, element 1 of the second variable, ...
The meaning of these limits are the following. As long as the value of the coefficient of the objective function stays between the lower limit (objfrom) and the upper limit (objtill), the solution stays the same. Only the objective value itself changes with a value equal to the difference multiplied by the amount of this variable. If there is no lower/upper limit, then these values are (-)infinity.

Note that get_ptr_sensitivity_obj and get_ptr_sensitivity_objex return a pointer to memory allocated and maintained by lp_solve. Be careful what you do with it. Don't modify its contents or free the memory. Unexpected behaviour would occur. Also note that this memory pointer is only guaranteed to remain constant until a next lp_solve API call is done. You should call this function again to make sure you have again the correct pointer. Otherwise, this pointer could point to invalid memory. This should not be a problem since this call is very efficient.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL objfrom[1+2], objtill[1+2], *ptr_objfrom, *ptr_objtill;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  str_set_obj_fn(lp, "1 1");
  str_add_constraint(lp, "2 4", GE, 10);
  set_lowbo(lp, 1, 1);

  solve(lp);

  get_sensitivity_obj(lp, objfrom, objtill);
  get_ptr_sensitivity_obj(lp, &ptr_objfrom, &ptr_objtill);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs,

doc/get_epsb.htm0000644000175000017500000000563010237176652012606 0ustar renerene get_epsb

get_epsb

Returns the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.

REAL get_epsb(lprec *lp);

Return Value

get_epsb returns the value of epsb.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_epsb function returns the value that is used as a tolerance for the Right Hand Side (RHS) to determine whether a value should be considered as 0.
The default value for epsb is 1e-10

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL epsb;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  epsb = get_epsb(lp); /* will return 1e-10 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epsb, set_infinite, get_infinite, is_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb, set_mip_gap, get_mip_gap

doc/integer.htm0000644000175000017500000001572010663135352012447 0ustar renerene Integer variables

integer variables

Integer variables are variables that must take an integer value (0, 1, 2, ...). A special kind of integer variables is binary variables. Binary variables can only take the value 0 or 1. They are integer variables with a maximum of 1 on them (and don't forget there is always an implicit minimum of 0 on each variable). If all variables are integer then it is a pure integer model, else it is a mixed-integer model, sometimes denoted as MIP (Mixed Integer Programming).

There are many practical uses of such variables. Binary variables for example are used to specify that something may be used or not. Integer variables say that a variable must take a multiple of a given value. For example if you want that a given variable must be a multiple of 25 then you can construct following equation:

var - 25 i = 0

with i the integer variable and var the variable that must be a multiple of 25. So an extra variable and an extra constraint is needed. This is ok if only a limited number of such variables are in the model, but if there are alot then the model dimensions will increase considerably. As an alternative you can also do a substitution of the variable:

var = 25 i

Everywhere where variable var is used, substitute it by 25 i. This in the objective function, the constraints and bounds. So variable var is removed from the model and replaced by i. i can be defined as integer. The objective value of this substituted model will be the same as the original one. However to obtain the value of variable var, you must multiply the returned variable i with 25.

There is however one drawback on integer variables. These models are harder to solve and solution time can increment exponentially. The more integer variables there are the more time it takes to solve the model. A model without the integer variables may for example be solved in 0.1 seconds while the same model with some of the variables integer can take several minutes to solve. Be aware of this. Also try to limit the solution as much as possible. If you know some extra bounds on variables then it can be very good for the solution time to set them because this limits the number of combinations the algorithm has to examine. Another negative site on integer variables is the inaccurate sensitivity analysis when integer variables are used. See Inaccurate sensitivity analysis in a model with integer variables

The integer solution is searched via the so-called 'branch-and-bound' algorithm. The model is first solved without the integer restrictions. Then it is investigated which of the integer variables are non-integer. When such a variable is found the model is split in two sub models. A first one with a minimum restriction on this variable that has the ceiling integer value and a second one with a maximum restriction on this variable that has the floor integer value. Both these sub models are optimised again and now this variable will have an integer value (if there is a solution). The algorithm then looks again if there are still (other) integer variables that have a non-integer value and if so the process is done again. This until a solution is found where are integer variables have integer values. This solution is then remembered as the best-until-now solution and the algorithm continues until it finds again an integer solution and if it is better it takes this one as the best-until-now solution. The more integer variables there are, the more combinations must be investigated and the more time it takes to solve the model.

lp_solve supports integer variables since a long time. The API call set_int can be used to define a variable as integer. The API call set_binary can be used to define a variable as binary.

In the mps format, integer variables can be specified in the COLUMNS section. See mps-format .

Example:

ROWS
 N  r_0
 L  r_1
 G  r_2
 G  r_3
 G  r_4
COLUMNS
    x1        r_0                 -1   r_1                  1
    x1        r_2                  2   r_3                 -1
    x2        r_0                 -2   r_1                  1
    x2        r_2                 -1   r_3                  3
    MARK0000  'MARKER'                 'INTORG'
    x3        r_0                0.1   r_4                  1
    MARK0001  'MARKER'                 'INTEND'
    x4        r_0                  3   r_4                  1
RHS
    RHS       r_1                  5   r_4                0.5
BOUNDS
 LO BND       x3                 1.1
ENDATA
The red lines are two lines that specify that variable x3 is an integer variable. It also has a lower bound of 1.1 set on it. The solution of this model is:
Value of objective function: -8.13333

Actual values of the variables:
x1                   1.66667
x2                   3.33333
x3                   2
x4                   0

As can be seen, the value of x3 is 2, an integer value. If the integer restrictions would not be set on x3 then the value would be 1.1.

In the lp-format, variables can be specified as integer by putting them in the int section. See lp-format. The above mps example would be in lp-format:

min: -x1 -2 x2 +0.1 x3 +3 x4;
r_1: +x1 +x2 <= 5;
r_2: +2 x1 -x2 >= 0;
r_3: -x1 +3 x2 >= 0;
r_4: +x3 +x4 >= 0.5;
x3 >= 1.1;

int x3;

In the lp-format, variables can be specified as binary by putting them in the bin section. See lp-format. For example:

min: -x1 -2 x2 +0.1 x3 +3 x4;
r_1: +x1 +x2 <= 5;
r_2: +2 x1 -x2 >= 0;
r_3: -x1 +3 x2 >= 0;
r_4: +x3 +x4 >= 0.5;

bin x3;
doc/put_msgfunc.htm0000644000175000017500000001040710255113156013334 0ustar renerene put_msgfunc

put_msgfunc

Sets a message routine.

void put_msgfunc(lprec *lp, lphandleint_func newmsg, void *msghandle, int mask);

Return Value

put_msgfunc has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

newmsg

The message routine.

typedef void (__WINAPI lphandleint_func)(lprec *lp, void *userhandle, int message);

Note the __WINAPI attribute. This is important under Windows. It ensures __stdcall calling convention which is required.

msghandle

A parameter that will be provided to the message routine.

mask

Any combination of the following values:

MSG_PRESOLVE (1) Presolve done.
MSG_LPFEASIBLE (8) Feasible solution found.
MSG_LPOPTIMAL (16) Real optimal solution found. Only fired when there are integer variables at the start of B&B
MSG_MILPEQUAL (32) Equal MILP solution found. Only fired when there are integer variables during B&B
MSG_MILPFEASIBLE (128) First MILPsolution found. Only fired when there are integer variables during B&B
MSG_MILPBETTER (512) Better MILPsolution found. Only fired when there are integer variables during B&B

Remarks

The put_msgfunc function sets a message routine. This routine is called when a situation specified in mask occurs. Note that this routine is called while solving the model. This can be useful to follow the solving progress.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

void __WINAPI msgfunction(lprec *lp, void *userhandle, int msg)
{
 switch(msg) {
 case MSG_LPFEASIBLE:
  printf("Feasible solution found\n");
  break;
 case MSG_MILPFEASIBLE:
  printf("Integer feasible solution found\n");
  break;
 case MSG_MILPBETTER:
  printf("Better integer feasible solution found\n");
  break;
 }
}

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  put_msgfunc(lp, msgfunction, NULL, MSG_LPFEASIBLE | MSG_MILPFEASIBLE | MSG_MILPBETTER);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, put_abortfunc

doc/set_negrange.htm0000644000175000017500000000526510237176664013466 0ustar renerene set_negrange

set_negrange

Set negative value below which variables are split into a negative and a positive part.

void set_negrange(lprec *lp, REAL negrange);

Return Value

set_negrange has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

negrange

The negative value below which variables are split into a negative and a positive part.

Remarks

The set_negrange function specifies the negative value below which variables are split into a negative and a positive part. This value must always be zero or negative. If a positive value is specified, then 0 is taken.
In some cases, negative variables must be split in a positive part and a negative part. This is when a negative lower or upper bound is set on a variable. If a bound is less than this value, it is possibly split. The default is -1e6.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_negrange(lp, -1000);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_negrange

doc/Sysquake.htm0000644000175000017500000035413411244025456012623 0ustar renerene Using lpsolve from Sysquake

Using lpsolve from Sysquake

Sysquake?

Sysquake is an interactive design CAD tool for getting insight into complicated scientific problems and designing advanced technical devices.

To design technical devices, or to understand the physical and mathematical laws which describe their behavior, engineers and scientists frequently use computers to calculate and represent graphically different quantities, such as the sample sequence and the frequency response of a digital audio filter, or the trajectory and the mass of a rocket flying to Mars. Usually, these quantities are related to each other; they are different views of the same reality. Understanding these relationships is the key to a good design. In some cases, especially for simple systems, an intuitive understanding can be acquired. For more complicated systems, it is often difficult or impossible to "guess", for instance, whether increasing the thickness of a robot arm will increase or decrease the frequency of the oscillations.

Traditionally, the design of a complicated system is performed in several iterations. Specifications can seldom be used directly to calculate the value of the parameters of the system, because there is no explicit formula to link them. Hence each iteration is made of two phases. The first one, often called synthesis, consists in calculating the unknown parameters of the system based on a set of design variables. The design variables are more or less loosely related to the specifications. During the second phase, called analysis, the performance of the system is evaluated and compared to the specifications. If it does not match them, the design variables are modified and a new iteration is carried out.

When the relationship between the criteria used for evaluating the performance and the design parameters is not very well known, modifications of the design parameters might lead as well to poorer performance as to better one. Manual trial and error may work but is cumbersome. This is where interactive design may help. Instead of splitting each iteration between synthesis and analysis, both phases are merged into a single one where the effect of modifying a parameter results immediately in the update of graphics. The whole design procedure becomes really dynamic; the engineer perceives the gradient of the change of performance criteria with respect to what he manipulates, and the compromises which can be obtained are easily identified.

Sysquake's purpose is to support this kind of design in fields such as automatic control and signal processing. Several graphics are displayed simultaneously, and some of them contain elements which can be manipulated with the mouse. During the manipulation, all the graphics are updated to reflect the change. What the graphics show and how their update is performed are not fixed, but depend on programs written in an easy-to-learn language specialized for numerical computation. Several programs are included with Sysquake for common tasks, such as the design of PID controllers; but you are free to modify them to better suit your needs and to write new ones for other design methods or new applications.

Another area where Sysquake shines is teaching. Replacing the static figures you find in books or the animations you see on the Web with interactive graphics, where the student can manipulate himself the curves to acquire an intuitive understanding of the theory they represent, accelerates and improves the learning process tremendously.

We will not discuss the specifics of Sysquake here but instead refer the reader to the Sysquake website and documentation.

Sysquake and lpsolve

lpsolve is callable from Sysquake via an external interface or external code. As such, it looks like lpsolve is fully integrated with Sysquake. Matrices can directly be transferred between Sysquake and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for Sysquake (especially for matrix support). So you have full control to the complete lpsolve functionality via the sqlpsolve Sysquake driver. If you find that this involves too much work to solve an lp model then you can also work via a higher-level library that can make things a lot easier. See further in this article.

Sysquake is ideally suited to handle linear programming problems. These are problems in which you have a quantity, depending linearly on several variables, that you want to maximize or minimize subject to several constraints that are expressed as linear inequalities in the same variables.If the number of variables and the number of constraints are small, then there are numerous mathematical techniques for solving a linear programming problem. Indeed these techniques are often taught in high school or university level courses in finite mathematics.But sometimes these numbers are high, or even if low, the constants in the linear inequalities or the object expression for the quantity to be optimized may be numerically complicated in which case a software package like Sysquake is required to effect a solution.

Although there is a free version of Sysquake (Sysquake LE), it does not support to call external library code as needed by lpsolve. As such, the lpsolve link to Sysquake only works with the commercial version.

Installation

To make this possible, a driver program is needed: sqlpsolve (sqlpsolvext.dll under Windows, sqlpsolvext.so under Unix/Linux). This driver must be put in a directory known to Sysquake (LMEExt under Windows, sys under Unix/Linux) and Sysquake can call the sqlpsolve solver.

This driver calls lpsolve via the lpsolve shared library (lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux) (archive lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). This has the advantage that the sqlpsolve driver doesn't have to be recompiled when an update of lpsolve is provided. The shared library must be somewhere in the Windows path.

So note the difference between the Sysquake lpsolve driver that is called sqlpsolve, its physical name on disk (sqlpsolvext.*) and the lpsolve library that implements the API that is named lpsolve55.* on disk.

There is also the sqlpsolve.lml higher level library file and some example library files (.lml) as a quick start.

To test if everything is installed correctly, enter sqlpsolve(); in the Sysquake command window. If it gives the following, then everything is ok:

sqlpsolve Sysquake Interface version 5.5.0.7
using lpsolve version 5.5.0.15

Usage: ret = sqlpsolve('functionname', arg1, arg2, ...)

However, if you get the following:

Undefined function 'sqlpsolve'

Then Sysquake cannot find either sqlpsolve.dll/sqlpsolve.so or lpsolve55.dll/liblpsolve55.so.
On Unix/Linux, if liblpsolve55.so cannot be found, then an error message is also displayed when Sysquake is started when all external libraries are loaded:

liblpsolve55.so: cannot open shared object file: No such file or directory

Unfortunately, under Windows no message at all is shown and you can't know if the problem is that sqlpsolveext.dll cannot be found or lpsolve55.dll.

Note that it is necessary to restart Sysquake after having put the files in the specified directory. Sysquake loads the libraries only at startup. When started, a list of loaded extensions is given. Make sure that between the list, there is also:

lpsolve extension: sqlpsolve

You can also use the following Sysquake command:

info b

A list of loaded extension functions is given. LME/sqlpsolve must be in the list to be ok.

All this is developed and tested with Sysquake version 4.1 Pro.

Solve an lp model from Sysquake via sqlpsolve

In the following text, > before the Sysquake commands is the Sysquake prompt. Only the text after > must be entered.

To call an lpsolve function, the following syntax must be used:

> [ret1, ret2, ...] = sqlpsolve('functionname', arg1, arg2, ...)

The return values are optional and depend on the function called. functionname must always be enclosed between single quotes to make it alphanumerical and it is case sensitive. The number and type of arguments depend on the function called. Some functions even have a variable number of arguments and a different behaviour occurs depending on the type of the argument. functionname can be (almost) any of the lpsolve API routines (see lp_solve API reference) plus some extra Sysquake specific functions. Most of the lpsolve API routines use or return an lprec structure. To make things more robust in Sysquake, this structure is replaced by a handle or the model name. The lprec structures are maintained internally by the lpsolve driver. The handle is an incrementing number starting from 0. Starting from driver version 5.5.0.2, it is also possible to use the model name instead of the handle. This can of course only be done if a name is given to the model. This is done via lpsolve routine set_lp_name or by specifying the model name in routine read_lp. See Using model name instead of handle.

Almost all callable functions can be found in the lp_solve API reference. Some are exactly as described in the reference guide, others have a slightly different syntax to make maximum use of the Sysquake functionality. For example make_lp is used identical as described. But get_variables is slightly different. In the API reference, this function has two arguments. The first the lp handle and the second the resulting variables and this array must already be dimensioned. When lpsolve is used from Sysquake, nothing must be dimensioned in advance. The sqlpsolve driver takes care of dimensioning all return variables and they are always returned as return value of the call to sqlpsolve. Never as argument to the routine. This can be a single value as for get_objective (although Sysquake stores this in a 1x1 matrix) or a matrix or vector as in get_variables. In this case, get_variables returns a 4x1 matrix (vector) with the result of the 4 variables of the lp model.

Constants

Some API calls needs constant arguments. For example add_constraint has the constants LE, GE, EQ to define if the added constraint is a less than, greater than, equal to the RHS. Although it is legal and possible to use the constant numbers itself, it is easier, clearer and much readable to use labels. In this documentation these are used everywere. They are not defined in the external library sqlpsolveext.dll/so. They are however defined in the library sqlpsolve.lml. To use these, the library must first be loaded in Sysquaqe via a use statement:

use sqlpsolve

See also libraries

Here is a list of all constants defined in sqlpsolve.lml (end of file):

public

define LPSOLVE_ANTIDEGEN_BOUNDFLIP = 512;
define LPSOLVE_ANTIDEGEN_COLUMNCHECK = 2;
define LPSOLVE_ANTIDEGEN_DURINGBB = 128;
define LPSOLVE_ANTIDEGEN_DYNAMIC = 64;
define LPSOLVE_ANTIDEGEN_FIXEDVARS = 1;
define LPSOLVE_ANTIDEGEN_INFEASIBLE = 32;
define LPSOLVE_ANTIDEGEN_LOSTFEAS = 16;
define LPSOLVE_ANTIDEGEN_NONE = 0;
define LPSOLVE_ANTIDEGEN_NUMFAILURE = 8;
define LPSOLVE_ANTIDEGEN_RHSPERTURB = 256;
define LPSOLVE_ANTIDEGEN_STALLING = 4;
define LPSOLVE_BRANCH_AUTOMATIC = 2;
define LPSOLVE_BRANCH_DEFAULT = 3;
define LPSOLVE_BRANCH_CEILING = 0;
define LPSOLVE_BRANCH_FLOOR = 1;
define LPSOLVE_CRASH_LEASTDEGENERATE = 3;
define LPSOLVE_CRASH_MOSTFEASIBLE = 2;
define LPSOLVE_CRASH_NONE = 0;
define LPSOLVE_CRITICAL = 1;
define LPSOLVE_DEGENERATE = 4;
define LPSOLVE_DETAILED = 5;
define LPSOLVE_EQ = 3;
define LPSOLVE_FEASFOUND = 12;
define LPSOLVE_FR = 0;
define LPSOLVE_FULL = 6;
define LPSOLVE_GE = 2;
define LPSOLVE_IMPORTANT = 3;
define LPSOLVE_IMPROVE_BBSIMPLEX = 8;
define LPSOLVE_IMPROVE_DUALFEAS = 2;
define LPSOLVE_IMPROVE_NONE = 0;
define LPSOLVE_IMPROVE_SOLUTION = 1;
define LPSOLVE_IMPROVE_THETAGAP = 4;
define LPSOLVE_INFEASIBLE = 2;
define LPSOLVE_Infinite = 1e+030;
define LPSOLVE_LE = 1;
define LPSOLVE_MSG_LPFEASIBLE = 8;
define LPSOLVE_MSG_LPOPTIMAL = 16;
define LPSOLVE_MSG_MILPBETTER = 512;
define LPSOLVE_MSG_MILPEQUAL = 256;
define LPSOLVE_MSG_MILPFEASIBLE = 128;
define LPSOLVE_MSG_PRESOLVE = 1;
define LPSOLVE_NEUTRAL = 0;
define LPSOLVE_NODE_AUTOORDER = 8192;
define LPSOLVE_NODE_BRANCHREVERSEMODE = 16;
define LPSOLVE_NODE_BREADTHFIRSTMODE = 4096;
define LPSOLVE_NODE_DEPTHFIRSTMODE = 128;
define LPSOLVE_NODE_DYNAMICMODE = 1024;
define LPSOLVE_NODE_FIRSTSELECT = 0;
define LPSOLVE_NODE_FRACTIONSELECT = 3;
define LPSOLVE_NODE_GAPSELECT = 1;
define LPSOLVE_NODE_GREEDYMODE = 32;
define LPSOLVE_NODE_GUBMODE = 512;
define LPSOLVE_NODE_PSEUDOCOSTMODE = 64;
define LPSOLVE_NODE_PSEUDOCOSTSELECT = 4;
define LPSOLVE_NODE_PSEUDONONINTSELECT = 5;
define LPSOLVE_NODE_PSEUDORATIOSELECT = 6;
define LPSOLVE_NODE_RANDOMIZEMODE = 256;
define LPSOLVE_NODE_RANGESELECT = 2;
define LPSOLVE_NODE_RCOSTFIXING = 16384;
define LPSOLVE_NODE_RESTARTMODE = 2048;
define LPSOLVE_NODE_STRONGINIT = 32768;
define LPSOLVE_NODE_USERSELECT = 7;
define LPSOLVE_NODE_WEIGHTREVERSEMODE = 8;
define LPSOLVE_NOFEASFOUND = 13;
define LPSOLVE_NOMEMORY = -2;
define LPSOLVE_NORMAL = 4;
define LPSOLVE_NUMFAILURE = 5;
define LPSOLVE_OPTIMAL = 0;
define LPSOLVE_PRESOLVED = 9;
define LPSOLVE_PRESOLVE_BOUNDS = 262144;
define LPSOLVE_PRESOLVE_COLDOMINATE = 16384;
define LPSOLVE_PRESOLVE_COLFIXDUAL = 131072;
define LPSOLVE_PRESOLVE_COLS = 2;
define LPSOLVE_PRESOLVE_DUALS = 524288;
define LPSOLVE_PRESOLVE_ELIMEQ2 = 256;
define LPSOLVE_PRESOLVE_IMPLIEDFREE = 512;
define LPSOLVE_PRESOLVE_IMPLIEDSLK = 65536;
define LPSOLVE_PRESOLVE_KNAPSACK = 128;
define LPSOLVE_PRESOLVE_LINDEP = 4;
define LPSOLVE_PRESOLVE_MERGEROWS = 32768;
define LPSOLVE_PRESOLVE_NONE = 0;
define LPSOLVE_PRESOLVE_PROBEFIX = 2048;
define LPSOLVE_PRESOLVE_PROBEREDUCE = 4096;
define LPSOLVE_PRESOLVE_REDUCEGCD = 1024;
define LPSOLVE_PRESOLVE_REDUCEMIP = 64;
define LPSOLVE_PRESOLVE_ROWDOMINATE = 8192;
define LPSOLVE_PRESOLVE_ROWS = 1;
define LPSOLVE_PRESOLVE_SENSDUALS = 1048576;
define LPSOLVE_PRESOLVE_SOS = 32;
define LPSOLVE_PRICER_DANTZIG = 1;
define LPSOLVE_PRICER_DEVEX = 2;
define LPSOLVE_PRICER_FIRSTINDEX = 0;
define LPSOLVE_PRICER_STEEPESTEDGE = 3;
define LPSOLVE_PRICE_ADAPTIVE = 32;
define LPSOLVE_PRICE_AUTOPARTIAL = 256;
define LPSOLVE_PRICE_HARRISTWOPASS = 4096;
define LPSOLVE_PRICE_LOOPALTERNATE = 2048;
define LPSOLVE_PRICE_LOOPLEFT = 1024;
define LPSOLVE_PRICE_MULTIPLE = 8;
define LPSOLVE_PRICE_PARTIAL = 16;
define LPSOLVE_PRICE_PRIMALFALLBACK = 4;
define LPSOLVE_PRICE_RANDOMIZE = 128;
define LPSOLVE_PRICE_TRUENORMINIT = 16384;
define LPSOLVE_PROCBREAK = 11;
define LPSOLVE_PROCFAIL = 10;
define LPSOLVE_SCALE_COLSONLY = 1024;
define LPSOLVE_SCALE_CURTISREID = 7;
define LPSOLVE_SCALE_DYNUPDATE = 256;
define LPSOLVE_SCALE_EQUILIBRATE = 64;
define LPSOLVE_SCALE_EXTREME = 1;
define LPSOLVE_SCALE_GEOMETRIC = 4;
define LPSOLVE_SCALE_INTEGERS = 128;
define LPSOLVE_SCALE_LOGARITHMIC = 16;
define LPSOLVE_SCALE_MEAN = 3;
define LPSOLVE_SCALE_NONE = 0;
define LPSOLVE_SCALE_POWER2 = 32;
define LPSOLVE_SCALE_QUADRATIC = 8;
define LPSOLVE_SCALE_RANGE = 2;
define LPSOLVE_SCALE_ROWSONLY = 512;
define LPSOLVE_SCALE_USERWEIGHT = 31;
define LPSOLVE_SEVERE = 2;
define LPSOLVE_SIMPLEX_DUAL_DUAL = 10;
define LPSOLVE_SIMPLEX_DUAL_PRIMAL = 6;
define LPSOLVE_SIMPLEX_PRIMAL_DUAL = 9;
define LPSOLVE_SIMPLEX_PRIMAL_PRIMAL = 5;
define LPSOLVE_SUBOPTIMAL = 1;
define LPSOLVE_TIMEOUT = 7;
define LPSOLVE_UNBOUNDED = 3;
define LPSOLVE_USERABORT = 6;
Also see Using string constants for an alternative.

An example

(Note that you can execute this example by entering command per command as shown below or by just executing the command from example1.lml as follows:

use example1; example1;

This will execute example1.lml. It will also echo the executes commands. See also libraries)

> use sqlpsolve
> lp=sqlpsolve('make_lp', 0, 4);
> sqlpsolve('set_verbose', lp, 3);
> sqlpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
> sqlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], LPSOLVE_GE, 92.3);
> sqlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], LPSOLVE_LE, 14.8);
> sqlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], LPSOLVE_GE, 4);
> sqlpsolve('set_lowbo', lp, 1, 28.6);
> sqlpsolve('set_lowbo', lp, 4, 18);
> sqlpsolve('set_upbo', lp, 4, 48.98);
> sqlpsolve('set_col_name', lp, 1, 'COLONE');
> sqlpsolve('set_col_name', lp, 2, 'COLTWO');
> sqlpsolve('set_col_name', lp, 3, 'COLTHREE');
> sqlpsolve('set_col_name', lp, 4, 'COLFOUR');
> sqlpsolve('set_row_name', lp, 1, 'THISROW');
> sqlpsolve('set_row_name', lp, 2, 'THATROW');
> sqlpsolve('set_row_name', lp, 3, 'LASTROW');
> sqlpsolve('write_lp', lp, 'a.lp');
> sqlpsolve('get_mat', lp, 1, 2)
ans =
   78.2600
> sqlpsolve('solve', lp)
ans =
     0
> sqlpsolve('get_objective', lp)
ans =
   31.7828
> sqlpsolve('get_variables', lp)
ans =
   28.6000
    0.0000
    0.0000
   31.8276
> sqlpsolve('get_constraints', lp)
ans =
   92.3000
    6.8640
  391.2928

Note that there are some commands that return an answer. To see the answer, the command was not terminated with a semicolon (;). If the semicolon is put at the end of a command, the answer is not shown. However it is also possible to write the answer in a variable. For example:

> obj=sqlpsolve('get_objective', lp)
obj =
   31.7828

Or without echoing on screen:

> obj=sqlpsolve('get_objective', lp);

The last command will only write the result in variable obj without showing anything on screen. get_variables and get_constraints return a vector with the result. This can also be put in a variable:

> x=sqlpsolve('get_variables', lp);
> b=sqlpsolve('get_constraints', lp);

It is always possible to show the contents of a variable by just giving it as command:

> x
x =
   28.6000
    0.0000
    0.0000
   31.8276

Don't forget to free the handle and its associated memory when you are done:

> sqlpsolve('delete_lp', lp);

Using model name instead of handle

From driver version 5.5.0.2, it is possible to use the model name instead of the handle. From the moment the model has a name, you can use this name instead of the handle. This is best shown by an example. Above example would look like this:
> use sqlpsolve
> lp=sqlpsolve('make_lp', 0, 4);
> sqlpsolve('set_lp_name', lp, 'mymodel');
> sqlpsolve('set_verbose', 'mymodel', 3);
> sqlpsolve('set_obj_fn', 'mymodel', [1, 3, 6.24, 0.1]);
> sqlpsolve('add_constraint', 'mymodel', [0, 78.26, 0, 2.9], LPSOLVE_GE, 92.3);
> sqlpsolve('add_constraint', 'mymodel', [0.24, 0, 11.31, 0], LPSOLVE_LE, 14.8);
> sqlpsolve('add_constraint', 'mymodel', [12.68, 0, 0.08, 0.9], LPSOLVE_GE, 4);
> sqlpsolve('set_lowbo', 'mymodel', 1, 28.6);
> sqlpsolve('set_lowbo', 'mymodel', 4, 18);
> sqlpsolve('set_upbo', 'mymodel', 4, 48.98);
> sqlpsolve('set_col_name', 'mymodel', 1, 'COLONE');
> sqlpsolve('set_col_name', 'mymodel', 2, 'COLTWO');
> sqlpsolve('set_col_name', 'mymodel', 3, 'COLTHREE');
> sqlpsolve('set_col_name', 'mymodel', 4, 'COLFOUR');
> sqlpsolve('set_row_name', 'mymodel', 1, 'THISROW');
> sqlpsolve('set_row_name', 'mymodel', 2, 'THATROW');
> sqlpsolve('set_row_name', 'mymodel', 3, 'LASTROW');
> sqlpsolve('write_lp', 'mymodel', 'a.lp');
> sqlpsolve('get_mat', 'mymodel', 1, 2)
ans =
   78.2600
> sqlpsolve('solve', 'mymodel')
ans =
     0
> sqlpsolve('get_objective', 'mymodel')
ans =
   31.7828
> sqlpsolve('get_variables', 'mymodel')
ans =
   28.6000
    0.0000
    0.0000
   31.8276
> sqlpsolve('get_constraints', 'mymodel')
ans =
   92.3000
    6.8640
  391.2928

So everywhere a handle is needed, you can also use the model name. You can even mix the two methods. There is also a specific Sysquake routine to get the handle from the model name: get_handle.
For example:

> sqlpsolve('get_handle', 'mymodel')
ans =
     0

Don't forget to free the handle and its associated memory when you are done:

> sqlpsolve('delete_lp', 'mymodel');

In the next part of this documentation, the handle is used. But if you name the model, the name could thus also be used.

Matrices

In Sysquake, all numerical data is stored in matrices; even a scalar variable. Sysquake also supports complex numbers (a + b * i with i=SQRT(-1)). sqlpsolve can only work with real numbers.

Most of the time, variables are used to provide the data:

> sqlpsolve('add_constraint', lp, a1, LPSOLVE_LE, 14.8);

Where a1 is a matrix variable.

Note that if a matrix is provided, the dimension must exactly match the dimension that is expected by sqlpsolve. Matrices with too few or too much elements gives an 'invalid vector.' error.

Most of the time, sqlpsolve needs vectors (rows or columns). In all situations, it doesn't matter if the vectors are row or column vectors. The driver accepts them both. For example:

> sqlpsolve('add_constraint', lp, [0.24; 0; 11.31; 0], LPSOLVE_LE, 14.8);

Which is a column vector, but it is also accepted.

An important final note. Several lp_solve API routines accept a vector where the first element (element 0) is not used. Other lp_solve API calls do use the first element. In the Sysquake interface, there is never an unused element in the matrices. So if the lp_solve API specifies that the first element is not used, then this element is not in the Sysquake matrix.

Sets

All numerical data is stored in matrices. Alphanumerical data, however, is more difficult to store in matrices. Matrices require that each element has the same size (length) and that is difficult and unpractical for alphanumerical data. In a limited number of lpsolve routines, alphanumerical data is required or returned and in some also multiple elements. An example is set_col_name. For this, Sysquake sets are used. To specify a set of alphanumerical elements, the following notation is used: { 'element1', 'element2', ... }. Note the { and } symbols instead of [ and ] that are used with matrices.

Maximum usage of matrices/sets with sqlpsolve

Because Sysquake is all about matrices, all lpsolve API routines that need a column or row number to get/set information for that column/row are extended in the sqlpsolve Sysquake driver to also work with matrices. For example set_int in the API can only set the integer status for one column. If the status for several integer variables must be set, then set_int must be called multiple times. The sqlpsolve Sysquake driver however also allows specifying a vector to set the integer status of all variables at once. The API call is: return = sqlpsolve('set_int', lp, column, must_be_int). The matrix version of this call is: return = sqlpsolve('set_int', lp, [must_be_int]). The API call to return the integer status of a variable is: return = sqlpsolve('is_int', lp, column). The matrix version of this call is: [is_int] = sqlpsolve('is_int', lp)
Also note the get_mat and set_mat routines. In Sysquake these are extended to return/set the complete constraint matrix. See following example.

Above example can thus also be done as follows:
(Note that you can execute this example by entering command per command as shown below or by just executing the command from example2.lml as follows:

use example2; example2;

This will execute example2.lml. It will also echo the executes commands. See also libraries)

> use sqlpsolve
> lp=sqlpsolve('make_lp', 0, 4);
> sqlpsolve('set_verbose', lp, 3);
> sqlpsolve('set_obj_fn', lp, [1, 3, 6.24, 0.1]);
> sqlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], LPSOLVE_GE, 92.3);
> sqlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], LPSOLVE_LE, 14.8);
> sqlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], LPSOLVE_GE, 4);
> sqlpsolve('set_lowbo', lp, [28.6, 0, 0, 18]);
> sqlpsolve('set_upbo', lp, [Inf, Inf, Inf, 48.98]);
> sqlpsolve('set_col_name', lp, {'COLONE', 'COLTWO', 'COLTHREE', 'COLFOUR'});
> sqlpsolve('set_row_name', lp, {'THISROW', 'THATROW', 'LASTROW'});
> sqlpsolve('write_lp', lp, 'a.lp');
> sqlpsolve('get_mat', lp)
ans =
    0.0000   78.2600    0.0000    2.9000
    0.2400    0.0000   11.3100    0.0000
   12.6800    0.0000    0.0800    0.9000
> sqlpsolve('solve', lp)
ans =
     0
> sqlpsolve('get_objective', lp)
ans =
   31.7828
> sqlpsolve('get_variables', lp)
ans =
   28.6000
    0.0000
    0.0000
   31.8276
> sqlpsolve('get_constraints', lp)
ans =
   92.3000
    6.8640
  391.2928

Note the usage of Inf in set_upbo. This stands for 'infinity'. Meaning an infinite upper bound. It is also possible to use -Inf to express minus infinity. This can for example be used to create a free variable.

To show the full power of the matrices, let's now do some matrix calculations to check the solution. It works further on above example:

> A=sqlpsolve('get_mat', lp);
> X=sqlpsolve('get_variables', lp);
> B = A * X
B =
   92.3000
    6.8640
  391.2928

So what we have done here is calculate the values of the constraints (RHS) by multiplying the constraint matrix with the solution vector. Now take a look at the values of the constraints that lpsolve has found:

> sqlpsolve('get_constraints', lp)
ans =
   92.3000
    6.8640
  391.2928

Exactly the same as the calculated B vector, as expected.

Also the value of the objective can be calculated in a same way:

> C=sqlpsolve('get_obj_fn', lp);
> X=sqlpsolve('get_variables', lp);
> obj = C * X
obj =
   31.7828

So what we have done here is calculate the value of the objective by multiplying the objective vector with the solution vector. Now take a look at the value of the objective that lpsolve has found:

> sqlpsolve('get_objective', lp)
ans =
   31.7828

Again exactly the same as the calculated obj value, as expected.

Using string constants

From driver version 5.5.0.15 on, it is possible to use string constants everywhere an lp_solve constant is needed or returned. This is best shown by an example. In the above code we had:
> use sqlpsolve
> lp=sqlpsolve('make_lp', 0, 4);
> sqlpsolve('set_verbose', lp, 3);
> sqlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], LPSOLVE_GE, 92.3);
> sqlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], LPSOLVE_LE, 14.8);
> sqlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], LPSOLVE_GE, 4);

Note the 3rd parameter on set_verbose and the 4th on add_constraint. These are lp_solve constants. One can define all the possible constants in Sysquake as is done in the sqlpsolve library and then use them in the calls, but that has several disadvantages. First there stays the possibility to provide a constant that is not intended for that particular call. Another issue is that calls that return a constant are still returning it numerical.

Both issues can now be handled by string constants. The above code can be done as following with string constants:

> lp=sqlpsolve('make_lp', 0, 4);
> sqlpsolve('set_verbose', lp, 'IMPORTANT');
> sqlpsolve('add_constraint', lp, [0, 78.26, 0, 2.9], 'GE', 92.3);
> sqlpsolve('add_constraint', lp, [0.24, 0, 11.31, 0], 'LE', 14.8);
> sqlpsolve('add_constraint', lp, [12.68, 0, 0.08, 0.9], 'GE', 4);

This is not only more readable, there is much lesser chance that mistakes are being made. The calling routine knows which constants are possible and only allows these. So unknown constants or constants that are intended for other calls are not accepted. For example:

> sqlpsolve('set_verbose', lp, 'blabla');

BLABLA: Unknown.

> sqlpsolve('set_verbose', lp, 'GE');

GE: Not allowed here.

Note the difference between the two error messages. The first says that the constant is not known, the second that the constant cannot be used at that place.

Constants are case insensitive. Internally they are always translated to upper case. Also when returned they will always be in upper case.

The constant names are the ones as specified in the documentation of each API routine. There are only 3 exceptions, extensions actually. 'LE', 'GE' and 'EQ' in add_constraint and is_constr_type can also be '<', '<=', '>', '>=', '='. When returned however, 'GE', 'LE', 'EQ' will be used.

Also in the matrix version of calls, string constants are possible. For example:

> sqlpsolve('set_constr_type', lp, {'LE', 'EQ', 'GE'});

Some constants can be a combination of multiple constants. For example set_scaling:

> sqlpsolve('set_scaling', lp, 3+128);

With the string version of constants this can be done as following:

> sqlpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_INTEGERS');

| is the OR operator used to combine multiple constants. There may optinally be spaces before and after the |.

Not all OR combinations are legal. For example in set_scaling, a choice must be made between SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC or SCALE_CURTISREID. They may not be combined with each other. This is also tested:

> sqlpsolve('set_scaling', lp, 'SCALE_MEAN|SCALE_RANGE');

SCALE_RANGE cannot be combined with SCALE_MEAN

Everywhere constants must be provided, numeric or string values may be provided. The routine automatically interpretes them.

Returning constants is a different story. The user must let lp_solve know how to return it. Numerical or as string. The default is numerical:

> sqlpsolve('get_scaling', lp)

ans =

  131

To let lp_solve return a constant as string, a call to a new function must be made: return_constants

> sqlpsolve('return_constants', 1);

From now on, all returned constants are returned as string:

> sqlpsolve('get_scaling', lp)

ans =

SCALE_MEAN|SCALE_INTEGERS

Also when an array of constants is returned, they are returned as string when return_constants is set:

> sqlpsolve('get_constr_type', lp)

ans =

 {'LE','EQ','GE'}

This for all routines until return_constants is again called with 0:

> sqlpsolve('return_constants', 0);

The (new) current setting of return_constants is always returned by the call. Even when set:

> sqlpsolve('return_constants', 1)

ans =

    1

To get the value without setting it, don't provide the second argument:

> sqlpsolve('return_constants')

ans =

    1

In the next part of this documentation, return_constants is the default, 0, so all constants are returned numerical and provided constants are also numerical. This to keep the documentation as compatible as possible with older versions. But don't let you hold that back to use string constants in your code.

libraries

Sysquake can execute a sequence of statements stored in diskfiles. Such files are called "libraries". They must have the file type of ".lml" as the last part of their filename (extension). These files are usually created using your local editor.
Note that for Sysquake to be able to find these libraries that they must be put in a special directory named Lib under the Sysquake directory or the file path where the libraries are put must be identified to Sysquake. If you are working with the GUI version of Sysquake, this can be done via the menu option Edit, Preferences and then 'Set SQ File Path' or 'Path'. In that input multiple directories can be specified, line per line. This path can also be seen and changed via the Sysquake path command.

To use a library, it must first be loaded via the following command in Sysquake:

use libraryname

With libraryname the name of the library, without its extension. From that moment on, functions defined in it can be called directly from Sysquake.
All lpsolve examples use as functionname the same name as the libraryname.

The sqlpsolve Sysquake distribution contains some example library files to demonstrate this.

To see the contents of such a file also edit these files with your favourite text editor (or notepad).

example1.lml

Contains the commands as shown in the first example of this article.

example2.lml

Contains the commands as shown in the second example of this article.

example3.lml

Contains the commands of a practical example. See further in this article.

example4.lml

Contains the commands of a practical example. See further in this article.

example5.lml

Contains the commands of a practical example. See further in this article.

example6.lml

Contains the commands of a practical example. See further in this article.

sqlpsolve.lml

This library contains some higher-level functions to simplify things. To use it, first give following Sysquake command:

use sqlpsolve;

lp_solve

The first function herein is called lp_solve.
It accepts as arguments some matrices and options to create and solve an lp model.
type help lp_solve or just lp_solve to see its usage:

> use sqlpsolve
> help lp_solve
 LP_SOLVE  Solves mixed integer linear programming problems.

   SYNOPSIS: [obj,x,duals] = lp_solve(f,a,b,e,vlb,vub,xint,scalemode,keep)

      solves the MILP problem

              max v = f'*x
                a*x <> b
                  vlb <= x <= vub
                  x(int) are integer

   ARGUMENTS: The first four arguments are required:

            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) = -1  ==> Less Than
                      e(i) =  0  ==> Equals
                      e(i) =  1  ==> Greater Than
          vlb: n vector of lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
         keep: Flag for keeping the lp problem after it's been solved.
               If omitted, the lp will be deleted when solved.

   OUTPUT: A nonempty output is returned if a solution is found:

          obj: Optimal value of the objective function.
            x: Optimal value of the decision variables.
        duals: solution of the dual problem.

Example of usage. To create and solve following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

> use sqlpsolve
> [obj, x]=lp_solve([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])
obj =
     3
x =
     1
     2

lp_maker

A second function in sqlpsolve.lml is lp_maker. It is analog to lp_solve and also uses the API to create the higher-level function. This function accepts as arguments some matrices and options to create an lp model. Note that this function only creates a model and returns a handle.
type help lp_maker or just lp_maker to see its usage:

> use sqlpsolve
> help lp_maker
 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: Autoscale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Example of usage. To create following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

> use sqlpsolve
> lp=lp_maker([-1, 2], [2, 1; -4, 4], [5, 5], [-1, -1], [], [], [1, 2])
lp =
     0

To solve the model and get the solution:

> sqlpsolve('solve', lp)
ans =
     0
> sqlpsolve('get_objective', lp)
ans =
     3
> sqlpsolve('get_variables', lp)
ans =
     1
     2

Don't forget to free the handle and its associated memory when you are done:

> sqlpsolve('delete_lp', lp);

lpdemo.lml

Contains several examples to build and solve lp models.

ex.lml

Contains several examples to build and solve lp models. Also solves the lp_examples from the lp_solve distribution.

A practical example

We shall illustrate the method of linear programming by means of a simple example, giving a combination graphical/numerical solution, and then solve both a slightly as well as a substantially more complicated problem.

Suppose a farmer has 75 acres on which to plant two crops: wheat and barley. To produce these crops, it costs the farmer (for seed, fertilizer, etc.) $120 per acre for the wheat and $210 per acre for the barley.The farmer has $15000 available for expenses. But after the harvest, the farmer must store the crops while awaiting favourable market conditions. The farmer has storage space for 4000 bushels.Each acre yields an average of 110 bushels of wheat or 30 bushels of barley. If the net profit per bushel of wheat (after all expenses have been subtracted) is $1.30 and for barley is $2.00, how should the farmer plant the 75 acres to maximize profit?

We begin by formulating the problem mathematically. First we express the objective, that is the profit, and the constraints algebraically, then we graph them, and lastly we arrive at the solution by graphical inspection and a minor arithmetic calculation.

Let x denote the number of acres allotted to wheat and y the number of acres allotted to barley. Then the expression to be maximized, that is the profit, is clearly

P = (110)(1.30)x + (30)(2.00)y = 143x + 60y.

There are three constraint inequalities, specified by the limits on expenses, storage and acreage. They are respectively:

120x + 210y <= 15000
110x + 30y <= 4000
x + y <= 75

Strictly speaking there are two more constraint inequalities forced by the fact that the farmer cannot plant a negative number of acres, namely:

x >= 0,y >= 0.

Next we graph the regions specified by the constraints. The last two say that we only need to consider the first quadrant in the x-y plane. Here's a graph delineating the triangular region in the first quadrant determined by the first inequality.

Source

Now let's put in the other two constraint inequalities.

Source

The black area is the solution space that holds valid solutions. This means that any point in this area fulfils the constraints.

Now let's superimpose on top of this picture a contour plot of the objective function P.

Source

The lines give a picture of the objective function. All solutions that intersect with the black area are valid solutions, meaning that this result also fulfils the set constraints. The more the lines go to the right, the higher the objective value is. The optimal solution or best objective is a line that is still in the black area, but with an as large as possible value.

It seems apparent that the maximum value of P will occur on the level curve (that is, level line) that passes through the vertex of the polygon that lies near (22,53).
It is the intersection of x + y = 75 and 110*x + 30*y = 4000
This is a corner point of the diagram. This is not a coincidence. The simplex algorithm, which is used by lp_solve, starts from a theorem that the optimal solution is such a corner point.
In fact we can compute the result:

> x = [1 1; 110 30] \ [75; 4000]
x =
   21.8750
   53.1250

The acreage that results in the maximum profit is 21.875 for wheat and 53.125 for barley. In that case the profit is:

> format bank
> P = [143 60] * x
P =
 6315.63

That is, $6315.63.

Note that these command are in example3.lml

Now, lp_solve comes into the picture to solve this linear programming problem more generally. After that we will use it to solve two more complicated problems involving more variables and constraints.

For this example, we use the higher-level script lp_maker to build the model and then some lp_solve API calls to retrieve the solution. Here is again the usage of lp_maker:

> use sqlpsolve
> help lp_maker

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: Autoscale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Now let's formulate this model with lp_solve:

> use sqlpsolve
> f = [143 60];
> A = [120 210; 110 30; 1 1];
> b = [15000; 4000; 75];
> lp = lp_maker(f, A, b, [-1; -1; -1], [], [], [], 1, 0);
> solvestat = sqlpsolve('solve', lp)
solvestat =
    0.00
> format bank
> obj = sqlpsolve('get_objective', lp)
obj =
 6315.63
> format short
> x = sqlpsolve('get_variables', lp)
x =
   21.8750
   53.1250
> sqlpsolve('delete_lp', lp);

Note that these command are in example4.lml

With the higher-level script lp_maker, we provide all data to lp_solve. lp_solve returns a handle (lp) to the created model. Then the API call 'solve' is used to calculate the optimal solution of the model. The value of the objective function is retrieved via the API call 'get_objective' and the values of the variables are retrieved via the API call 'get_variables'. At last, the model is removed from memory via a call to 'delete_lp'. Don't forget this to free all memory allocated by lp_solve.

The solution is the same answer we obtained before. Note that the non-negativity constraints are accounted implicitly because variables are by default non-negative in lp_solve.

Well, we could have done this problem by hand (as shown in the introduction) because it is very small and it can be graphically presented.
Now suppose that the farmer is dealing with a third crop, say corn, and that the corresponding data is:

cost per acre$150.75
yield per acre125 bushels
profit per bushel$1.56

With three variables it is already a lot more difficult to show this model graphically. Adding more variables makes it even impossible because we can't imagine anymore how to represent this. We only have a practical understanding of 3 dimentions, but beyound that it is all very theorethical.

If we denote the number of acres allotted to corn by z, then the objective function becomes:

P = (110)(1.30)x + (30)(2.00)y+ (125)(1.56) = 143x + 60y + 195z

And the constraint inequalities are:

120x + 210y + 150.75z <= 15000
110x + 30y + 125z <= 4000
x + y + z <= 75
x >= 0,y >= 0, z >= 0

The problem is solved with lp_solve as follows:

> use sqlpsolve
> f = [143 60 195];
> A = [120 210 150.75; 110 30 125; 1 1 1];
> b = [15000; 4000; 75];
> lp = lp_maker(f, A, b, [-1; -1; -1], [], [], [], 1, 0);
> solvestat = sqlpsolve('solve', lp)
solvestat =
     0
> format bank
> obj = sqlpsolve('get_objective', lp)
obj =
 6986.84
> format short
> x = sqlpsolve('get_variables', lp)
x =
    0.0000
   56.5789
   18.4211
> sqlpsolve('delete_lp', lp);

Note that these command are in example5.lml

So the farmer should ditch the wheat and plant 56.5789 acres of barley and 18.4211 acres of corn.

There is no practical limit on the number of variables and constraints that Sysquake can handle. Certainly none that the relatively unsophisticated user will encounter.Indeed, in many true applications of the technique of linear programming, one needs to deal with many variables and constraints.The solution of such a problem by hand is not feasible, and software like Sysquake is crucial to success.For example, in the farming problem with which we have been working, one could have more crops than two or three. Think agribusiness instead of family farmer.And one could have constraints that arise from other things beside expenses, storage and acreage limitations. For example:

  • Availability of seed.This might lead to constraint inequalities like xj < k.
  • Personal preferences. Thus the farmer's spouse might have a preference for one variety over another and insist on a corresponding planting, or something similar with a collection of crops; thus constraint inequalities like xi < xj or x1 + x2 > x3.
  • Government subsidies. It may take a moment's reflection on the reader's part, but this could lead to inequalities like xj > k.

Below is a sequence of commands that solves exactly such a problem. You should be able to recognize the objective expression and the constraints from the data that is entered. But as an aid, you might answer the following questions:

  • How many crops are under consideration?
  • What are the corresponding expenses? How much is available for expenses?
  • What are the yields in each case? What is the storage capacity?
  • How many acres are available?
  • What crops are constrained by seed limitations? To what extent?
  • What about preferences?
  • What are the minimum acreages for each crop?
> use sqlpsolve
> f = [110*1.3 30*2.0 125*1.56 75*1.8 95*.95 100*2.25 50*1.35];
> A = [120 210 150.75 115 186 140 85;
        110 30 125 75 95 100 50;
        1 1 1 1 1 1 1;
        1 -1 0 0 0 0 0;
        0 0 1 0 -2 0 0;
        0 0 0 -1 0 -1 1];

> b = [55000;40000;400;0;0;0];
> lp = lp_maker(f, A, b, [-1; -1; -1; -1; -1; -1], [10 10 10 10 20 20 20], [100 Inf 50 Inf Inf 250 Inf], [], 1, 0);
> solvestat = sqlpsolve('solve', lp)
solvestat =
     0
> format bank
> obj = sqlpsolve('get_objective', lp)
obj =
 75398.04
> format short
> x = sqlpsolve('get_variables', lp)
x =
   10.0000
   10.0000
   40.0000
   45.6522
   20.0000
  250.0000
   20.0000
> sqlpsolve('delete_lp', lp);

Note that these command are in example6.lml

Note that we have used in this formulation the vlb and vub arguments of lp_maker. This to set lower and upper bounds on variables. This could have been done via extra constraints, but it is more performant to set bounds on variables. Also note that Inf is used for variables that have no upper limit. This stands for Infinity.

Note that despite the complexity of the problem, lp_solve solves it almost instantaneously. It seems the farmer should bet the farm on crop number 6.We strongly suggest you alter the expense and/or the storage limit in the problem and see what effect that has on the answer.

Another, more theoretical, example

Suppose we want to solve the following linear program using Sysquake:

max 4x1 + 2x2 + x3
s. t. 2x1 + x2 <= 1
x1 + 2x3 <= 2
x1 + x2 + x3 = 1
x1 >= 0
x1 <= 1
x2 >= 0
x2 <= 1
x3 >= 0
x3 <= 2

Convert the LP into Sysquake format we get:

f = [4 2 1]
A = [2 1 0; 1 0 2; 1 1 1]
b = [1; 2; 1]

Note that constraints on single variables are not put in the constraint matrix. lp_solve can set bounds on individual variables and this is more performant than creating additional constraints. These bounds are:

l = [ 0 0 0]
u = [ 1 1 2]

Now lets enter this in Sysquake:

> use sqlpsolve
> f = [4 2 1];
> A = [2 1 0; 1 0 2; 1 1 1];
> b = [1; 2; 1];
> l = [ 0 0 0];
> u = [ 1 1 2];

Now solve the linear program using Sysquake: Type the commands

> lp = lp_maker(f, A, b, [-1; -1; -1], l, u, [], 1, 0);
> solvestat = sqlpsolve('solve', lp)
solvestat =
     0
> obj = sqlpsolve('get_objective', lp)
obj =
    2.5000
> x = sqlpsolve('get_variables', lp)
x =
    0.5000
    0.0000
    0.5000
> sqlpsolve('delete_lp', lp);

What to do when some of the variables are missing ?
For example, suppose there are no lower bounds on the variables. In this case define l to be the empty set using the Sysquake command:

> l = [];

This has the same effect as before, because lp_solve has as default lower bound for variables 0.

But what if you want that variables may also become negative?
Then you can use -Inf as lower bounds:

> l = [-Inf -Inf -Inf];

Solve this and you get a different result:

> use sqlpsolve
> lp = lp_maker(f, A, b, [-1; -1; -1], l, u, [], 1, 0);
> solvestat = sqlpsolve('solve', lp)
solvestat =
     0
> obj = sqlpsolve('get_objective', lp)
obj =
    2.6667
> x = sqlpsolve('get_variables', lp)
x =
    0.6667
   -0.3333
    0.6667
> sqlpsolve('delete_lp', lp);

Overview of API routines

Note that everwhere where lp is used as argument that this can be a handle (lp_handle) or the models name.

  • add_column, add_columnex
    • return = sqlpsolve('add_column', lp, [column])
    • return = sqlpsolve('add_columnex', lp, [column])
    • Both have the same interface from add_column but act as add_columnex
  • add_constraint, add_constraintex
    • return = sqlpsolve('add_constraint', lp, [row], constr_type, rh)
    • return = sqlpsolve('add_constraintex', lp, [row], constr_type, rh)
    • Both have the same interface from add_constraint but act as add_constraintex
  • add_SOS
    • return = sqlpsolve('add_SOS', lp, name, sostype, priority, [sosvars], [weights])
    • The count argument in the API documentation is not needed in Sysquake since the number of elements is derived from the size of the sosvars and weights matrices. These must have the same size.
  • column_in_lp
    • return = sqlpsolve('column_in_lp', lp, [column])
    • No special considerations.
  • copy_lp
    • lp_handle = sqlpsolve('copy_lp', lp)
    • No special considerations.
  • default_basis
    • sqlpsolve('default_basis', lp)
    • No special considerations.
  • del_column
    • return = sqlpsolve('del_column', lp, column)
    • No special considerations.
  • del_constraint
    • return = sqlpsolve('del_constraint', lp, del_row)
    • No special considerations.
  • delete_lp
    • sqlpsolve('delete_lp', lp)
    • No special considerations.
  • free_lp
    • sqlpsolve('free_lp', lp)
    • lp is not changed as in the lpsolve API since it is a read_only input parameter. So it acts the same as delete_lp.
  • get_anti_degen
    • return = sqlpsolve('get_anti_degen', lp)
    • No special considerations.
  • get_basis
    • [bascolumn] = sqlpsolve('get_basis', lp {, nonbasic})
    • The bascolumn argument in the API documentation is here the return value. The nonbasic argument is optional in Sysquake. If not provided, then 0 is used.
  • get_basiscrash
    • return = sqlpsolve('get_basiscrash', lp)
    • No special considerations.
  • get_bb_depthlimit
    • return = sqlpsolve('get_bb_depthlimit', lp)
    • No special considerations.
  • get_bb_floorfirst
    • return = sqlpsolve('get_bb_floorfirst', lp)
    • No special considerations.
  • get_bb_rule
    • return = sqlpsolve('get_bb_rule', lp)
    • No special considerations.
  • get_bounds_tighter
    • return = sqlpsolve('get_bounds_tighter', lp)
    • No special considerations.
  • get_break_at_value
    • return = sqlpsolve('get_break_at_value', lp)
    • No special considerations.
  • get_col_name
    • name = sqlpsolve('get_col_name', lp, column)
    • [names] = sqlpsolve('get_col_name', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • get_column get_columnex
    • [column, return] = sqlpsolve('get_column', lp, col_nr)
    • [column, return] = sqlpsolve('get_columnex', lp, col_nr)
    • The column argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_constr_type
    • return = sqlpsolve('get_constr_type', lp, row)
    • [constr_type] = sqlpsolve('get_constr_type', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • get_constr_value
    • return = sqlpsolve('get_constr_value', lp, row {, primsolution})
    • The primsolution argument is optional. If not provided, then the solution of last solve is used.
  • get_constraints
    • [constr, return] = sqlpsolve('get_constraints', lp)
    • The constr argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_dual_solution
    • [duals, return] = sqlpsolve('get_dual_solution', lp)
    • The duals argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In Sysquake, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_epsb
    • return = sqlpsolve('get_epsb', lp)
    • No special considerations.
  • get_epsd
    • return = sqlpsolve('get_epsd', lp)
    • No special considerations.
  • get_epsel
    • return = sqlpsolve('get_epsel', lp)
    • No special considerations.
  • get_epsint
    • return = sqlpsolve('get_epsint', lp)
    • No special considerations.
  • get_epsperturb
    • return = sqlpsolve('get_epsperturb', lp)
    • No special considerations.
  • get_epspivot
    • return = sqlpsolve('get_epspivot', lp)
    • No special considerations.
  • get_improve
    • return = sqlpsolve('get_improve', lp)
    • No special considerations.
  • get_infinite
    • return = sqlpsolve('get_infinite', lp)
    • No special considerations.
  • get_lowbo
    • return = sqlpsolve('get_lowbo', lp, column)
    • [return] = sqlpsolve('get_lowbo', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • get_lp_index
    • return = sqlpsolve('get_lp_index', lp, orig_index)
    • No special considerations.
  • get_lp_name
    • name = sqlpsolve('get_lp_name', lp)
    • No special considerations.
  • get_mat
    • value = sqlpsolve('get_mat', lp, row, col)
    • [matrix, return] = sqlpsolve('get_mat', lp[, sparse])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix in the first return value. sparse is ignored in Sysquake.
  • get_max_level
    • return = sqlpsolve('get_max_level', lp)
    • No special considerations.
  • get_maxpivot
    • return = sqlpsolve('get_maxpivot', lp)
    • No special considerations.
  • get_mip_gap
    • return = sqlpsolve('get_mip_gap', lp, absolute)
    • No special considerations.
  • get_nameindex
    • return = sqlpsolve('get_nameindex', lp, name, isrow)
    • No special considerations.
  • get_Ncolumns
    • return = sqlpsolve('get_Ncolumns', lp)
    • No special considerations.
  • get_negrange
    • return = sqlpsolve('get_negrange', lp)
    • No special considerations.
  • get_nonzeros
    • return = sqlpsolve('get_nonzeros', lp)
    • No special considerations.
  • get_Norig_columns
    • return = sqlpsolve('get_Norig_columns', lp)
    • No special considerations.
  • get_Norig_rows
    • return = sqlpsolve('get_Norig_rows', lp)
    • No special considerations.
  • get_Nrows
    • return = sqlpsolve('get_Nrows', lp)
    • No special considerations.
  • get_obj_bound
    • return = sqlpsolve('get_obj_bound', lp)
    • No special considerations.
  • get_objective
    • return = sqlpsolve('get_objective', lp)
    • No special considerations.
  • get_orig_index
    • return = sqlpsolve('get_orig_index', lp, lp_index)
    • No special considerations.
  • get_origcol_name
    • name = sqlpsolve('get_origcol_name', lp, column)
    • [names] = sqlpsolve('get_origcol_name', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • get_origrow_name
    • name = sqlpsolve('get_origrow_name', lp, row)
    • [names] = sqlpsolve('get_origrow_name', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • get_pivoting
    • return = sqlpsolve('get_pivoting', lp)
    • No special considerations.
  • get_presolve
    • return = sqlpsolve('get_presolve', lp)
    • No special considerations.
  • get_presolveloops
    • return = sqlpsolve('get_presolveloops', lp)
    • No special considerations.
  • get_primal_solution
    • [pv, return] = sqlpsolve('get_primal_solution', lp)
    • The pv argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_print_sol
    • return = sqlpsolve('get_print_sol', lp)
    • No special considerations.
  • get_ptr_constraints
    • Not implemented.
  • get_ptr_dualsolution
    • Not implemented.
  • get_ptr_primal_solution
    • Not implemented.
  • get_ptr_sensitivity_obj, get_ptr_sensitivity_objex
    • Not implemented.
  • get_ptr_sensitivity_rhs
    • Not implemented.
  • get_ptr_variables
    • Not implemented.
  • get_rh
    • return = sqlpsolve('get_rh', lp, row)
    • [rh] = sqlpsolve('get_rh', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • get_rh_range
    • return = sqlpsolve('get_rh_range', lp, row)
    • [rh_ranges] = sqlpsolve('get_rh_range', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • get_row get_rowex
    • [row, return] = sqlpsolve('get_row', lp, row_nr)
    • [row, return] = sqlpsolve('get_rowex', lp, row_nr)
    • The row argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In Sysquake, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_row_name
    • name = sqlpsolve('get_row_name', lp, row)
    • [names] = sqlpsolve('get_row_name', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • get_scalelimit
    • return = sqlpsolve('get_scalelimit', lp)
    • No special considerations.
  • get_scaling
    • return = sqlpsolve('get_scaling', lp)
    • No special considerations.
  • get_sensitivity_obj, get_sensitivity_objex
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = sqlpsolve('get_sensitivity_obj', lp)
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = sqlpsolve('get_sensitivity_objex', lp)
    • The objfrom, objtill, objfromvalue, objtillvalue arguments in the API documentation are here the return values. Note that Sysquake allows the return of fewer variables. For example if only objfrom and objtill are needed then the call can be [objfrom, objtill] = sqlpsolve('get_sensitivity_obj', lp). The unrequested values are even not calculated.
    • Since the API routine doesn't calculate the objtillvalue value at this time, Sysquake always returns a zero vector for this.
    • The return code of the call is the last value.
    • get_sensitivity_obj and get_sensitivity_objex are both implemented, but have the same functionality.
  • get_sensitivity_rhs, get_sensitivity_rhsex
    • [duals, dualsfrom, dualstill, return] = sqlpsolve('get_sensitivity_rhs', lp)
    • [duals, dualsfrom, dualstill, return] = sqlpsolve('get_sensitivity_rhsex', lp)
    • The duals, dualsfrom, dualstill arguments in the API documentation are here the return values. Note that Sysquake allows the return of fewer variables. For example if only duals is needed then the call can be [duals] = sqlpsolve('get_sensitivity_rhs', lp). The unrequested values are even not calculated.
    • The return code of the call is the last value.
    • get_sensitivity_rhs and get_sensitivity_rhsex are both implemented, but have the same functionality.
  • get_simplextype
    • return = sqlpsolve('get_simplextype', lp)
    • No special considerations.
  • get_solutioncount
    • return = sqlpsolve('get_solutioncount', lp)
    • No special considerations.
  • get_solutionlimit
    • return = sqlpsolve('get_solutionlimit', lp)
    • No special considerations.
  • get_status
    • return = sqlpsolve('get_status', lp)
    • No special considerations.
  • get_statustext
    • return = sqlpsolve('get_statustext', lp, statuscode)
    • No special considerations.
  • get_timeout
    • return = sqlpsolve('get_timeout', lp)
    • No special considerations.
  • get_total_iter
    • return = sqlpsolve('get_total_iter', lp)
    • No special considerations.
  • get_total_nodes
    • return = sqlpsolve('get_total_nodes', lp)
    • No special considerations.
  • get_upbo
    • return = sqlpsolve('get_upbo', lp, column)
    • [upbo] = sqlpsolve('get_upbo', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • get_var_branch
    • return = sqlpsolve('get_var_branch', lp, column)
    • [var_branch] = sqlpsolve('get_var_branch', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • get_var_dualresult
    • return = sqlpsolve('get_var_dualresult', lp, index)
    • No special considerations.
  • get_var_primalresult
    • return = sqlpsolve('get_var_primalresult', lp, index)
    • No special considerations.
  • get_var_priority
    • return = sqlpsolve('get_var_priority', lp, column)
    • [var_priority] = sqlpsolve('get_var_priority', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • get_variables
    • [var, return] = sqlpsolve('get_variables', lp)
    • The var argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_verbose
    • return = sqlpsolve('get_verbose', lp)
    • No special considerations.
  • get_working_objective
    • return = sqlpsolve('get_working_objective', lp)
    • No special considerations.
  • guess_basis
    • [basisvector, return] = sqlpsolve('guess_basis', lp, [guessvector])
    • In the API, element 0 of guessvector is not used and values start from element 1. In Sysquake, there is no unused element in the matrix.
    • In the API, element 0 of basisvector is not used and values start from element 1. In Sysquake, there is no unused element in the matrix.
  • has_BFP
    • return = sqlpsolve('has_BFP', lp)
    • No special considerations.
  • has_XLI
    • return = sqlpsolve('has_XLI', lp)
    • No special considerations.
  • is_add_rowmode
    • return = sqlpsolve('is_add_rowmode', lp)
    • No special considerations.
  • is_anti_degen
    • return = sqlpsolve('is_anti_degen', lp, testmask)
    • No special considerations.
  • is_binary
    • return = sqlpsolve('is_binary', lp, column)
    • [binary] = sqlpsolve('is_binary', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • is_break_at_first
    • return = sqlpsolve('is_break_at_first', lp)
    • No special considerations.
  • is_constr_type
    • return = sqlpsolve('is_constr_type', lp, row, mask)
    • No special considerations.
  • is_debug
    • return = sqlpsolve('is_debug', lp)
    • No special considerations.
  • is_feasible
    • return = sqlpsolve('is_feasible', lp, [values] {, threshold})
    • The threshold argument is optional. When not provided, the value of get_epsint will be taken.
  • is_free is_unbounded
    • return = sqlpsolve('is_free', lp, column)
    • return = sqlpsolve('is_unbounded', lp, column)
    • [free] = sqlpsolve('is_free', lp)
    • [free] = sqlpsolve('is_unbounded', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • is_infinite
    • return = sqlpsolve('is_infinite', lp, value)
    • No special considerations.
  • is_int
    • return = sqlpsolve('is_int', lp, column)
    • [int] = sqlpsolve('is_int', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • is_integerscaling
    • return = sqlpsolve('is_integerscaling', lp)
    • No special considerations.
  • is_maxim
    • return = sqlpsolve('is_maxim', lp)
    • No special considerations.
  • is_nativeBFP
    • return = sqlpsolve('is_nativeBFP', lp)
    • No special considerations.
  • is_nativeXLI
    • return = sqlpsolve('is_nativeXLI', lp)
    • No special considerations.
  • is_negative
    • return = sqlpsolve('is_negative', lp, column)
    • [negative] = sqlpsolve('is_negative', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • is_piv_mode
    • return = sqlpsolve('is_piv_mode', lp, testmask)
    • No special considerations.
  • is_piv_rule
    • return = sqlpsolve('is_piv_rule', lp, rule)
    • No special considerations.
  • is_presolve
    • return = sqlpsolve('is_presolve', lp, testmask)
    • No special considerations.
  • is_scalemode
    • return = sqlpsolve('is_scalemode', lp, testmask)
    • No special considerations.
  • is_scaletype
    • return = sqlpsolve('is_scaletype', lp, scaletype)
    • No special considerations.
  • is_semicont
    • return = sqlpsolve('is_semicont', lp, column)
    • [semicont] = sqlpsolve('is_semicont', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • is_SOS_var
    • return = sqlpsolve('is_SOS_var', lp, column)
    • [SOS_var] = sqlpsolve('is_SOS_var', lp)
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a Sysquake matrix.
  • is_trace
    • return = sqlpsolve('is_trace', lp)
    • No special considerations.
  • is_use_names
    • return = sqlpsolve('is_use_names', lp, isrow)
    • No special considerations.
  • lp_solve_version
    • versionstring = sqlpsolve('lp_solve_version')
    • The sqlpsolve API routine returns the version information in 4 provided argument variables while the Sysquake version returns the information as a string in the format major.minor.release.build
  • make_lp
    • lp_handle = sqlpsolve('make_lp', rows, columns)
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
  • print_constraints
    • sqlpsolve('print_constraints', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Sysquake (Windows) this means that the output is not shown.
    • The same information can also be obtained via sqlpsolve('get_constraints', lp). This shows the result on screen.
  • print_debugdump
    • return = sqlpsolve('print_debugdump', lp, filename)
    • No special considerations.
  • print_duals
    • sqlpsolve('print_duals', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Sysquake (Windows) this means that the output is not shown.
    • The same information can be obtained via sqlpsolve('get_dual_solution', lp). This shows the result on screen.
  • print_lp
    • sqlpsolve('print_lp', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Sysquake (Windows) this means that the output is not shown.
  • print_objective
    • sqlpsolve('print_objective', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Sysquake (Windows) this means that the output is not shown.
    • The same information can be obtained via sqlpsolve('get_objective', lp). This shows the result on screen.
  • print_scales
    • sqlpsolve('print_scales', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Sysquake (Windows) this means that the output is not shown.
  • print_solution
    • sqlpsolve('print_solution', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Sysquake (Windows) this means that the output is not shown.
    • The same information can also be obtained via sqlpsolve('get_variables', lp). This shows the result on screen.
  • print_str
    • sqlpsolve('print_str', lp, str)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Sysquake (Windows) this means that the output is not shown.
  • print_tableau
    • sqlpsolve('print_tableau', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under Sysquake (Windows) this means that the output is not shown.
  • put_abortfunc
    • Not implemented.
  • put_logfunc
    • Not implemented.
    • However, the sqlpsolve driver sets a log function to redirect the output of lpsolve from stdout (which is not visible in Windows Sysquake) to the command window of Sysquake. As such, all reported output can be seen in Sysquake. How much output is seen is controlled by the verbose level that can be defined by set_verbose or can be specified in the read_ routines.
  • put_msgfunc
    • Not implemented.
  • read_basis
    • [ret, info] = sqlpsolve('read_basis', lp, filename)
    • No special considerations.
  • read_freemps, read_freeMPS
    • lp_handle = sqlpsolve('read_freemps', filename {, options})
    • lp_handle = sqlpsolve('read_freeMPS', filename {, options})
    • In the lpsolve API, read_freemps needs a FILE handle. In Sysquake it needs the filename and thus acts the same as read_freeMPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_lp, read_LP
    • lp_handle = sqlpsolve('read_lp', filename {, verbose {, lp_name}})
    • lp_handle = sqlpsolve('read_LP', filename {, verbose {, lp_name}})
    • In the lpsolve API, read_lp needs a FILE handle. In Sysquake it needs the filename and thus acts the same as read_LP.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not provided then NORMAL is used.
    • lp_name is optional. If not provided then no name is given to the model ('').
  • read_mps, read_MPS
    • lp_handle = sqlpsolve('read_mps', filename {, options})
    • lp_handle = sqlpsolve('read_MPS', filename {, options})
    • In the lpsolve API, read_mps needs a FILE handle. In Sysquake it needs the filename and thus acts the same as read_MPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_params
    • return = sqlpsolve('read_params', lp, filename {, options })
    • options is optional.
  • read_XLI
    • lp_handle = sqlpsolve('read_XLI', xliname, modelname {, dataname {, options {, verbose}}}
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • dataname is optional. When not provided, '' (NULL) is taken. '' is taken as NULL.
    • options is optional. When not provided, '' is taken.
    • verbose is optional. If not specified, then NORMAL is used.
  • reset_basis
  • set_basisvar
    • sqlpsolve('set_basisvar', lp, basisPos, enteringCol)
    • No special considerations.
  • set_add_rowmode
    • return = sqlpsolve('set_add_rowmode', lp, turnon)
    • No special considerations.
  • set_anti_degen
    • sqlpsolve('set_anti_degen', lp, anti_degen)
    • No special considerations.
  • set_basis
    • return = sqlpsolve('set_basis', lp, [bascolumn], nonbasic)
    • In the API, element 0 of bascolumn is not used and values start from element 1. In Sysquake, there is no unused element in the matrix.
  • set_basiscrash
    • sqlpsolve('set_basiscrash', lp, mode)
    • No special considerations.
  • set_bb_depthlimit
    • sqlpsolve('set_bb_depthlimit', lp, bb_maxlevel)
    • No special considerations.
  • set_bb_floorfirst
    • sqlpsolve('set_bb_floorfirst', lp, bb_floorfirst)
    • No special considerations.
  • set_bb_rule
    • sqlpsolve('set_bb_rule', lp, bb_rule)
    • No special considerations.
  • set_BFP
    • return = sqlpsolve('set_BFP', lp, filename)
    • No special considerations.
  • set_binary
    • return = sqlpsolve('set_binary', lp, column, must_be_bin)
    • return = sqlpsolve('set_binary', lp, [must_be_bin])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds
    • return = sqlpsolve('set_bounds', lp, column, lower, upper)
    • return = sqlpsolve('set_bounds', lp, [lower], [upper])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds_tighter
    • sqlpsolve('set_bounds_tighter', lp, tighten)
    • No special considerations.
  • set_break_at_first
    • sqlpsolve('set_break_at_first', lp, break_at_first)
    • No special considerations.
  • set_break_at_value
    • sqlpsolve('set_break_at_value', lp, break_at_value)
    • No special considerations.
  • set_col_name
    • return = sqlpsolve('set_col_name', lp, column, name)
    • return = sqlpsolve('set_col_name', lp, [names])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_column, set_columnex
    • return = sqlpsolve('set_column', lp, col_no, [column])
    • return = sqlpsolve('set_columnex', lp, col_no, [column])
    • Both have the same interface from set_column but act as set_columnex
  • set_constr_type
    • return = sqlpsolve('set_constr_type', lp, row, con_type)
    • return = sqlpsolve('set_constr_type', lp, [con_type])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_debug
    • sqlpsolve('set_debug', lp, debug)
    • No special considerations.
  • set_epsb
    • sqlpsolve('set_epsb', lp, epsb)
    • No special considerations.
  • set_epsd
    • sqlpsolve('set_epsd', lp, epsd)
    • No special considerations.
  • set_epsel
    • sqlpsolve('set_epsel', lp, epsel)
    • No special considerations.
  • set_epsint
    • sqlpsolve('set_epsint', lp, epsint)
    • No special considerations.
  • set_epslevel
    • sqlpsolve('set_epslevel', lp, epslevel)
    • No special considerations.
  • set_epsperturb
    • sqlpsolve('set_epsperturb', lp, epsperturb)
    • No special considerations.
  • set_epspivot
    • sqlpsolve('set_epspivot', lp, epspivot)
    • No special considerations.
  • set_free set_unbounded
    • return = sqlpsolve('set_free', lp, column)
    • return = sqlpsolve('set_unbounded', lp, column)
    • No special considerations.
  • set_improve
    • sqlpsolve('set_improve', lp, improve)
    • No special considerations.
  • set_infinite
    • sqlpsolve('set_infinite', lp, infinite)
    • No special considerations.
  • set_int
    • return = sqlpsolve('set_int', lp, column, must_be_int)
    • return = sqlpsolve('set_int', lp, [must_be_int])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lowbo
    • return = sqlpsolve('set_lowbo', lp, column, value)
    • return = sqlpsolve('set_lowbo', lp, [values])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lp_name
    • return = sqlpsolve('set_lp_name', lp, name)
    • In Sysquake, when you name a model, this name can be used everywhere where lp is specified. This to access the model via the name instead of via a handle.
  • set_mat
    • return = sqlpsolve('set_mat', lp, row, column, value)
    • return = sqlpsolve('set_mat', lp, [matrix])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows to set the whole matrix (all rows/columns) at once. This is the most performant way to provide the constraint matrix. The matrix must be two-dimentional.
  • set_maxim
    • sqlpsolve('set_maxim', lp)
    • No special considerations.
  • set_maxpivot
    • sqlpsolve('set_maxpivot', max_num_inv)
    • No special considerations.
  • set_minim
    • sqlpsolve('set_minim', lp)
    • No special considerations.
  • set_mip_gap
    • sqlpsolve('set_mip_gap', lp, absolute, mip_gap)
    • No special considerations.
  • set_negrange
    • sqlpsolve('set_negrange', negrange)
    • No special considerations.
  • set_obj
    • return = sqlpsolve('set_obj', lp, column, value)
    • return = sqlpsolve('set_obj', lp, [values])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables. It is then the same as set_obj_fn
  • set_obj_bound
    • sqlpsolve('set_obj_bound', lp, obj_bound)
    • No special considerations.
  • set_obj_fn, set_obj_fnex
    • return = sqlpsolve('set_obj_fn', lp, [row])
    • return = sqlpsolve('set_obj_fnex', lp, [row])
    • Both have the same interface from set_obj_fn but act as set_obj_fnex
    • In the API, element 0 is not used and values start from element 1. In Sysquake, there is no unused element in the matrix.
  • set_outputfile
    • return = sqlpsolve('set_outputfile', lp, filename)
    • In the API description it says that setting filename to NULL results in writing output back to stdout. In Sysquake under Windows, output to stdout it not shown. However it results in closing the file. Use '' to have the effect of NULL.
  • set_outputstream
    • Not implemented.
  • set_pivoting
    • sqlpsolve('set_pivoting', lp, pivoting)
    • No special considerations.
  • set_preferdual
    • sqlpsolve('set_preferdual', lp, dodual)
    • No special considerations.
  • set_presolve
    • sqlpsolve('set_presolve', lp, do_presolve {, maxloops})
    • The maxloops argument is optional in Sysquake. If not provided, then infinite is used.
  • set_print_sol
    • sqlpsolve('set_print_sol', lp, print_sol)
    • No special considerations.
  • set_rh
    • return = sqlpsolve('set_rh', lp, row, value)
    • return = sqlpsolve('set_rh', lp, [values])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows. Note that in this case, the value of row 0 is not specified in the matrix.
  • set_rh_range
    • return = sqlpsolve('set_rh_range', lp, row, deltavalue)
    • return = sqlpsolve('set_rh_range', lp, [deltavalues])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_rh_vec
    • sqlpsolve('set_rh_vec', lp, [rh])
    • In the API, element 0 is not used and values start from element 1. In Sysquake, there is no unused element in the matrix.
  • set_row, set_rowex
    • return = sqlpsolve('set_row', lp, row_no, [row])
    • return = sqlpsolve('set_rowex', lp, row_no, [row])
    • Both have the same interface from set_row but act as set_rowex
    • In the API, element 0 is not used and values start from element 1. In Sysquake, there is no unused element in the matrix.
  • set_row_name
    • return = sqlpsolve('set_row_name', lp, row, name)
    • return = sqlpsolve('set_row_name', lp, [names])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_scalelimit
    • sqlpsolve('set_scalelimit', lp, scalelimit)
    • No special considerations.
  • set_scaling
    • sqlpsolve('set_scaling', lp, scalemode)
    • No special considerations.
  • set_semicont
    • return = sqlpsolve('set_semicont', lp, column, must_be_sc)
    • return = sqlpsolve('set_semicont', lp, [must_be_sc])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_sense
    • sqlpsolve('set_sense', lp, maximize)
    • No special considerations.
  • set_simplextype
    • sqlpsolve('set_simplextype', lp, simplextype)
    • No special considerations.
  • set_solutionlimit
    • sqlpsolve('set_solutionlimit', lp, simplextype)
    • No special considerations.
  • set_timeout
    • sqlpsolve('set_timeout', lp, sectimeout)
    • No special considerations.
  • set_trace
    • sqlpsolve('set_trace', lp, trace)
    • No special considerations.
  • set_upbo
    • return = sqlpsolve('set_upbo', lp, column, value)
    • return = sqlpsolve('set_upbo', lp, [values])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_use_names
    • sqlpsolve('set_use_names', lp, isrow, use_names)
    • No special considerations.
  • set_var_branch
    • return = sqlpsolve('set_var_branch', lp, column, branch_mode)
    • return = sqlpsolve('set_var_branch', lp, [branch_mode])
    • In Sysquake, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_weights
    • return = sqlpsolve('set_var_weights', lp, [weights])
    • No special considerations.
  • set_verbose
    • sqlpsolve('set_verbose', lp, verbose)
    • No special considerations.
  • set_XLI
    • return = sqlpsolve('set_XLI', lp, filename)
    • No special considerations.
  • solve
    • result = sqlpsolve('solve', lp)
    • No special considerations.
  • str_add_column
    • Not implemented.
  • str_add_constraint
    • Not implemented.
  • str_set_obj_fn
    • Not implemented.
  • str_set_rh_vec
    • Not implemented.
  • time_elapsed
    • return = sqlpsolve('time_elapsed', lp)
    • No special considerations.
  • unscale
    • sqlpsolve('unscale', lp)
    • No special considerations.
  • write_basis
    • sqlpsolve('write_basis', lp, filename)
    • No special considerations.
  • write_freemps, write_freeMPS
    • return = sqlpsolve('write_freemps', lp, filename)
    • return = sqlpsolve('write_freeMPS', lp, filename)
    • In the lpsolve API, write_freeMPS needs a FILE handle. In Sysquake it needs the filename and thus acts the same as write_freemps.
  • write_lp, write_LP
    • return = sqlpsolve('write_lp', lp, filename)
    • return = sqlpsolve('write_LP', lp, filename)
    • In the lpsolve API, write_LP needs a FILE handle. In Sysquake it needs the filename and thus acts the same as write_lp.
  • write_mps, write_MPS
    • return = sqlpsolve('write_mps', lp, filename)
    • return = sqlpsolve('write_MPS', lp, filename)
    • In the lpsolve API, write_MPS needs a FILE handle. In Sysquake it needs the filename and thus acts the same as write_mps.
    • No special considerations.
  • write_XLI
    • return = sqlpsolve('write_XLI', lp, filename {, options {, results}})
    • No special considerations.

Extra Sysquake routines

These routines are not part of the lpsolve API, but are added for backwards compatibility. Most of them exist in the lpsolve API with another name.

  • [names] = sqlpsolve('get_col_names', lp)
    • The same as get_col_name. Implemented for backwards compatibility.
  • [constr_type] = sqlpsolve('get_constr_types', lp)
    • The same as get_constr_type. Implemented for backwards compatibility.
  • [int] = sqlpsolve('get_int', lp)
    • The same as is_int. Implemented for backwards compatibility.
  • return = sqlpsolve('get_no_cols', lp)
    • The same as get_Ncolumns. Implemented for backwards compatibility.
  • return = sqlpsolve('get_no_rows', lp)
    • The same as get_Nrows. Implemented for backwards compatibility.
  • name = sqlpsolve('get_objective_name', lp)
    • The same as get_row_name with row=0. Implemented for backwards compatibility.
  • [row_vec, return] = sqlpsolve('get_obj_fn', lp)
    [row_vec, return] = sqlpsolve('get_obj_fun', lp)
    • The same as get_row with row 0. Implemented for backwards compatibility.
  • name = sqlpsolve('get_problem_name', lp)
    • The same as get_lp_name. Implemented for backwards compatibility.
  • [costs] = sqlpsolve('get_reduced_costs', lp)
    • The same as get_dual_solution. Implemented for backwards compatibility.
  • [names] = sqlpsolve('get_row_names', lp)
    • The same as get_row_name. Implemented for backwards compatibility.
  • [obj, x, duals, return] = sqlpsolve('get_solution', lp)
    • Returns the value of the objective function, the values of the variables and the duals. Implemented for backwards compatibility.
    • The return code of the call is the last value.
  • value = sqlpsolve('mat_elm', lp)
    • The same as get_mat. Implemented for backwards compatibility.
  • [handle_vec] = sqlpsolve('print_handle')
    • Returns a vector with open handles. Can be handy to see which handles aren't closed yet with delete_lp or free_lp.
  • lp_handle = sqlpsolve('read_lp_file', filename {, verbose {, lp_name}})
    • The same as read_LP. Implemented for backwards compatibility.
  • lp_handle = sqlpsolve('get_handle', lp_name)
    • Get the handle for this model from the models name. If an unknown model name is given (or already deleted), -1 is returned.
  • return_constants = sqlpsolve('return_constants'[, return_constants])
    • Returns the setting of return_constants and optionally sets its value.

Compile the sqlpsolve driver

Under Windows, the sqlpsolve Sysquake driver is a dll: sqlpsolvext.dll
Under Unix/Linux, the sqlpsolve Sysquake driver is a shared library.: sqlpsolvext.so
This driver is an interface to the lpsolve library lpsolve55.dll/liblpsolve55.so that contains the implementation of lp_solve. lpsolve55.dll/liblpsolve55.so is distributed with the lp_solve package (archive lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). The sqlpsolve Sysquake driver is just a wrapper between Sysquake and lp_solve to translate the input/output to/from Sysquake and the lp_solve library.

Compilation

The sqlpsolve Sysquake driver is written in C. To compile this code, under Windows the Microsoft visual C compiler is needed and under Unix/Linux the standard cc compiler.
The needed commands are in a batch file/script.
Under Windows it is called cvc.bat, under Unix/Linux ccc.
In a command prompt/shell, go to the lpsolve Sysquake directory and enter cvc.bat/sh ccc and the compilation is done. The result is sqlpsolvext.dll/sqlpsolvext.so.

See also Using lpsolve from MATLAB, Using lpsolve from O-Matrix, Using lpsolve from Scilab, Using lpsolve from Octave, Using lpsolve from FreeMat, Using lpsolve from Euler, Using lpsolve from Python, Using lpsolve from Sage, Using lpsolve from PHP, Using lpsolve from R

doc/write_XLI.htm0000644000175000017500000000621310661665234012662 0ustar renerene write_XLI

write_XLI

Write a model to a file via the External Language Interface.

unsigned char write_XLI(lprec *lp, char *filename, char *options, unsigned char results);

Return Value

write_XLI returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

filename

Filename to write the model to.

options

Extra options that can be used by the writer.

results

FALSE to generate a model file and TRUE to generate a solution file.

Remarks

The write_XLI function writes the model to filename via the External Language Interface. Note that set_XLI must be called before this routine to set an XLI.

See External Language Interfaces for a complete description on XLIs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"
int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_XLI(lp, "xli_MathProg");

  write_XLI(lp, "model.mod", "", FALSE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, write_mps, write_freemps, write_MPS, write_freeMPS, MPS_writefileex, read_XLI, has_XLI, is_nativeXLI, set_XLI

doc/PHP.htm0000644000175000017500000037114711244025416011444 0ustar renerene Using lpsolve from PHP

Using lpsolve from PHP

PHP?

PHP is a general-purpose scripting language that is especially suited for web development. PHP generally runs on a web server, taking PHP code as its input and creating web pages as output. It can also be used for command-line scripting and client-side GUI applications. PHP can be deployed on most web servers, many operating systems and platforms, and can be used with many relational database management systems. It is available free of charge, and the PHP Group provides the complete source code for users to build, customize and extend for their own use. PHP primarily acts as a filter, taking input from a file or stream containing text and/or PHP instructions and outputs another stream of data; most commonly the output will be HTML. It can automatically detect the language of the user. From PHP 4, the PHP parser compiles input to produce bytecode for processing by the Zend Engine, giving improved performance over its interpreter predecessor. Originally designed to create dynamic web pages, PHP's principal focus is server-side scripting, and it is similar to other server-side scripting languages that provide dynamic content from a web server to a client, such as Microsoft's ASP.NET system, Sun Microsystems' JavaServer Pages, and mod_perl. PHP has also attracted the development of many frameworks that provide building blocks and a design structure to promote rapid application development (RAD). Some of these include CakePHP, PRADO, Symfony and Zend Framework, offering features similar to other web application frameworks.

We will not discuss the specifics of PHP here but instead refer the reader to the PHP website.
An introduction to PHP can be found at w3schools

PHP and lpsolve

lpsolve is callable from PHP via an extension or module. As such, it looks like lpsolve is fully integrated with PHP. Matrices can directly be transferred between PHP and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for PHP (especially for matrix support). So you have full control to the complete lpsolve functionality via the lpsolve PHP driver. If you find that this involves too much work to solve an lp model then you can also work via higher-level script files that can make things a lot easier. See further in this article.

Installation

To make this possible, a driver program is needed: php_phplpsolve55.dll (windows) or phplpsolve55.so (Unix/Linux).
Secondly in the file php.ini, which is a PHP configuration file, the location of the driver must be specified. The location of this ini file depends on the environment.
Under windows it is commonly \Program Files\php\php.ini
Under Unix/Linux it was found under /etc/php5/cli and /etc/php5/apache2
In that file there is an item extension_dir=. The driver program must be put in the directory specified by that item.
Then an extra entry 'extension' must be added.
Under windows it must be: extension=php_phplpsolve55.dll
Under Unix/Linux it must be: extension=phplpsolve55.so

Note that there is an alternative way but it is not always working, especially as webservice. In the php.ini file, specify enable_dl=on
Then in the PHP code, use the following command to load the lpsolve driver: dl('lpsolve.so');
However, this was not tested so use it at own risk.

To take these changes in effect, the webservice has to be restarted.
Under windows, this is done by restarting the service.
Under Unix/Linux it depends on the system. For example in Ubuntu the command is: sudo /etc/init.d/apache2 restart
This must be done with root privileges: sudo su -

This driver calls lpsolve via the lpsolve shared library (lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux) (archive lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). This has the advantage that the lpsolve driver doesn't have to be recompiled when an update of lpsolve is provided. The shared library must be somewhere in the Windows path.

So note the difference between the PHP lpsolve driver that is called (php_)phplpsolve55 and the lpsolve library that implements the API that is called lpsolve55.

Testing the installation

Note. In the following text PHP commands are given. They are just provided as is. However in a real PHP application, all PHP commands must be between <?php and ?>

Note. Some of these commands return new lines to continue on the next line. This is fine under CLI (php executed in a command line), but when PHP is used in a web environment and shown in html, then these newlines are by default just ignored by html. This gives an output that is not always that readable. Therefore you can put everything between <pre> </pre>
This combined with the note from above, put the commands in following block:

<?php
echo "<pre>";
// your php commands
echo "</pre>";
?>

To test if everything is installed correctly, execute the following statement in PHP.

lpsolve();

Note. As stated above, these commands must be between <?php and ?> and when used in html between a pre block as shown below:

<?php
echo "<pre>";
lpsolve();
echo "</pre>";
?>

Keep this in mind. This will not be repeated in the following text.

If it gives the following, then everything is ok:

lpsolve PHP Interface version 5.5.0.6
using lpsolve version 5.5.0.15

Usage: ret = lpsolve("functionname", arg1, arg2, ...)

If you get the following:

Windows:
PHP Warning:  PHP Startup: Unable to load dynamic library 'F:\php-5.2.6\Release_TS\php_phplpsolve55.dll' - The specified module could not be found. in Unknown on line 0
PHP Fatal error:  Call to undefined function lpsolve() in Command line code on line 1
Possible also with a messagebox saying:
---------------------------
php.exe - Unable To Locate Component
---------------------------
This application has failed to start because lpsolve55.dll was not found. Re-installing the application may fix this problem.
or Unix/Linux:
PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/lib/php5/20060613+lfs/phplpsolve55.so' - liblpsolve55.so: cannot open shared object file: No such file or directory in Unknown on line 0

Fatal error: Call to undefined function lpsolve() in Command line code on line 1

Note that the PHP Warning is not always shown. The Fatal error is. This was specifically noted in the web environment.

Then PHP can find the lpsolve driver program, but the driver program cannot find the lpsolve library that contains the lpsolve implementation. This library is called lpsolve55.dll under Windows and liblpsolve55.so under Unix/Linux.
Under Windows, the lpsolve55.dll file must be in a directory that in the PATH environment variable. This path can be shown via the following command in a command prompt: PATH
It is common to place this in the WINDOWS\system32 folder.

Under Unix/Linux, the liblpsolve55.so shared library must be either in the directories /lib or /usr/lib or in a directory specified by the LD_LIBRARY_PATH environment variable.

Note that in a web environment the webserver may need to be restarted after making changes in the configuration. For example on Ubuntu this is done by the following command:

sudo /etc/init.d/apache2 restart

Another way to check if the lpsolve extension is available in PHP is by entering the following command:

print_r(get_extension_funcs("lpsolve"));

This must return:

Array
(
    [0] => lpsolve
)

To return the version of lpsolve, the following PHP command can be executed:

echo phpversion("lpsolve");

This must return:

5.5.0.6

Note that this is the version of the PHP driver, not the version of lpsolve itself.

Solve an lp model from PHP via lpsolve

To call an lpsolve function, the following syntax must be used:

ret = lpsolve('functionname', arg1, arg2, ...);

The return value is optional and depend on the function called. Sometimes it is a single value, sometimes a vector and sometimes a vector of vector. functionname must always be enclosed between single or double quotes to make it alphanumerical and it is case sensitive. The number and type of arguments depend on the function called. Some functions even have a variable number of arguments and a different behaviour occurs depending on the type of the argument. functionname can be (almost) any of the lpsolve API routines (see lp_solve API reference) plus some extra PHP specific functions. Most of the lpsolve API routines use or return an lprec structure. To make things more robust in PHP, this structure is replaced by a handle or the model name. The lprec structures are maintained internally by the lpsolve driver. The handle is an incrementing number starting from 0. Starting from driver version 5.5.0.2, it is also possible to use the model name instead of the handle. This can of course only be done if a name is given to the model. This is done via lpsolve routine set_lp_name or by specifying the model name in routine read_lp. See Using model name instead of handle.

Almost all callable functions can be found in the lp_solve API reference. Some are exactly as described in the reference guide, others have a slightly different syntax to make maximum use of the PHP functionality. For example make_lp is used identical as described. But get_variables is slightly different. In the API reference, this function has two arguments. The first the lp handle and the second the resulting variables and this array must already be dimensioned. When lpsolve is used from PHP, nothing must be dimensioned in advance. The lpsolve driver takes care of dimensioning all return variables and they are always returned as return value of the call to lpsolve. Never as argument to the routine. This can be a single value as for get_objective or a matrix or vector as in get_variables. In this case, get_variables returns a 4x1 matrix (vector) with the result of the 4 variables of the lp model.

Note that you can get a usage of lpsolve, its arguments and the constants that it defines by entering the following in PHP:

lpsolve();
$a=get_defined_constants(true); print_r($a[lpsolve]);

This will give:

lpsolve  PHP Interface version 5.5.0.6
using lpsolve version 5.5.0.15

Usage: ret = lpsolve("functionname", arg1, arg2, ...)
Array
(
    [LE] => 1
    [EQ] => 3
    [GE] => 2
    [FR] => 0
    [SCALE_NONE] => 0
    [SCALE_EXTREME] => 1
    [SCALE_RANGE] => 2
    [SCALE_MEAN] => 3
    [SCALE_GEOMETRIC] => 4
    [SCALE_CURTISREID] => 7
    [SCALE_QUADRATIC] => 8
    [SCALE_LOGARITHMIC] => 16
    [SCALE_USERWEIGHT] => 31
    [SCALE_POWER2] => 32
    [SCALE_EQUILIBRATE] => 64
    [SCALE_INTEGERS] => 128
    [SCALE_DYNUPDATE] => 256
    [SCALE_ROWSONLY] => 512
    [SCALE_COLSONLY] => 1024
    [IMPROVE_NONE] => 0
    [IMPROVE_SOLUTION] => 1
    [IMPROVE_DUALFEAS] => 2
    [IMPROVE_THETAGAP] => 4
    [IMPROVE_BBSIMPLEX] => 8
    [PRICER_FIRSTINDEX] => 0
    [PRICER_DANTZIG] => 1
    [PRICER_DEVEX] => 2
    [PRICER_STEEPESTEDGE] => 3
    [PRICE_PRIMALFALLBACK] => 4
    [PRICE_MULTIPLE] => 8
    [PRICE_PARTIAL] => 16
    [PRICE_ADAPTIVE] => 32
    [PRICE_RANDOMIZE] => 128
    [PRICE_AUTOPARTIAL] => 256
    [PRICE_LOOPLEFT] => 1024
    [PRICE_LOOPALTERNATE] => 2048
    [PRICE_HARRISTWOPASS] => 4096
    [PRICE_TRUENORMINIT] => 16384
    [PRESOLVE_NONE] => 0
    [PRESOLVE_ROWS] => 1
    [PRESOLVE_COLS] => 2
    [PRESOLVE_LINDEP] => 4
    [PRESOLVE_SOS] => 32
    [PRESOLVE_REDUCEMIP] => 64
    [PRESOLVE_KNAPSACK] => 128
    [PRESOLVE_ELIMEQ2] => 256
    [PRESOLVE_IMPLIEDFREE] => 512
    [PRESOLVE_REDUCEGCD] => 1024
    [PRESOLVE_PROBEFIX] => 2048
    [PRESOLVE_PROBEREDUCE] => 4096
    [PRESOLVE_ROWDOMINATE] => 8192
    [PRESOLVE_COLDOMINATE] => 16384
    [PRESOLVE_MERGEROWS] => 32768
    [PRESOLVE_IMPLIEDSLK] => 65536
    [PRESOLVE_COLFIXDUAL] => 131072
    [PRESOLVE_BOUNDS] => 262144
    [PRESOLVE_DUALS] => 524288
    [PRESOLVE_SENSDUALS] => 1048576
    [ANTIDEGEN_NONE] => 0
    [ANTIDEGEN_FIXEDVARS] => 1
    [ANTIDEGEN_COLUMNCHECK] => 2
    [ANTIDEGEN_STALLING] => 4
    [ANTIDEGEN_NUMFAILURE] => 8
    [ANTIDEGEN_LOSTFEAS] => 16
    [ANTIDEGEN_INFEASIBLE] => 32
    [ANTIDEGEN_DYNAMIC] => 64
    [ANTIDEGEN_DURINGBB] => 128
    [ANTIDEGEN_RHSPERTURB] => 256
    [ANTIDEGEN_BOUNDFLIP] => 512
    [CRASH_NONE] => 0
    [CRASH_MOSTFEASIBLE] => 2
    [CRASH_LEASTDEGENERATE] => 3
    [SIMPLEX_PRIMAL_PRIMAL] => 5
    [SIMPLEX_DUAL_PRIMAL] => 6
    [SIMPLEX_PRIMAL_DUAL] => 9
    [SIMPLEX_DUAL_DUAL] => 10
    [NODE_FIRSTSELECT] => 0
    [NODE_GAPSELECT] => 1
    [NODE_RANGESELECT] => 2
    [NODE_FRACTIONSELECT] => 3
    [NODE_PSEUDOCOSTSELECT] => 4
    [NODE_PSEUDONONINTSELECT] => 5
    [NODE_PSEUDORATIOSELECT] => 6
    [NODE_USERSELECT] => 7
    [NODE_WEIGHTREVERSEMODE] => 8
    [NODE_BRANCHREVERSEMODE] => 16
    [NODE_GREEDYMODE] => 32
    [NODE_PSEUDOCOSTMODE] => 64
    [NODE_DEPTHFIRSTMODE] => 128
    [NODE_RANDOMIZEMODE] => 256
    [NODE_GUBMODE] => 512
    [NODE_DYNAMICMODE] => 1024
    [NODE_RESTARTMODE] => 2048
    [NODE_BREADTHFIRSTMODE] => 4096
    [NODE_AUTOORDER] => 8192
    [NODE_RCOSTFIXING] => 16384
    [NODE_STRONGINIT] => 32768
    [NOMEMORY] => -2
    [OPTIMAL] => 0
    [SUBOPTIMAL] => 1
    [INFEASIBLE] => 2
    [UNBOUNDED] => 3
    [DEGENERATE] => 4
    [NUMFAILURE] => 5
    [USERABORT] => 6
    [TIMEOUT] => 7
    [PRESOLVED] => 9
    [PROCFAIL] => 10
    [PROCBREAK] => 11
    [FEASFOUND] => 12
    [NOFEASFOUND] => 13
    [BRANCH_CEILING] => 0
    [BRANCH_FLOOR] => 1
    [BRANCH_AUTOMATIC] => 2
    [BRANCH_DEFAULT] => 3
    [MSG_PRESOLVE] => 1
    [MSG_LPFEASIBLE] => 8
    [MSG_LPOPTIMAL] => 16
    [MSG_MILPEQUAL] => 256
    [MSG_MILPFEASIBLE] => 128
    [MSG_MILPBETTER] => 512
    [NEUTRAL] => 0
    [CRITICAL] => 1
    [SEVERE] => 2
    [IMPORTANT] => 3
    [NORMAL] => 4
    [DETAILED] => 5
    [FULL] => 6
    [Infinite] => 1.0E+30
)

The array shows all constants defined by the lpsolve driver and are all the constants of the lpsolve API. That way one can enter these symbols instead of their numerical values.

Also see Using string constants for an alternative.

An example

(Note that you can execute this example by entering command per command as shown below or by executing script example1.php)

$lp = lpsolve('make_lp', 0, 4);
lpsolve('set_verbose', $lp, IMPORTANT);
$ret = lpsolve('set_obj_fn', $lp, Array(1, 3, 6.24, 0.1));
$ret = lpsolve('add_constraint', $lp, Array(0, 78.26, 0, 2.9), GE, 92.3);
$ret = lpsolve('add_constraint', $lp, Array(0.24, 0, 11.31, 0), LE, 14.8);
$ret = lpsolve('add_constraint', $lp, Array(12.68, 0, 0.08, 0.9), GE, 4);
$ret = lpsolve('set_lowbo', $lp, 1, 28.6);
$ret = lpsolve('set_lowbo', $lp, 4, 18);
$ret = lpsolve('set_upbo', $lp, 4, 48.98);
$ret = lpsolve('set_col_name', $lp, 1, 'COLONE');
$ret = lpsolve('set_col_name', $lp, 2, 'COLTWO');
$ret = lpsolve('set_col_name', $lp, 3, 'COLTHREE');
$ret = lpsolve('set_col_name', $lp, 4, 'COLFOUR');
$ret = lpsolve('set_row_name', $lp, 1, 'THISROW');
$ret = lpsolve('set_row_name', $lp, 2, 'THATROW');
$ret = lpsolve('set_row_name', $lp, 3, 'LASTROW');
$ret = lpsolve('write_lp', $lp, 'a.lp');
print lpsolve('get_mat', $lp, 1, 2) . "\n";
print lpsolve('solve', $lp) . "\n";
print lpsolve('get_objective', $lp) . "\n";
print_r(lpsolve('get_variables', $lp));
print_r(lpsolve('get_constraints', $lp));
lpsolve('delete_lp', $lp);

This gives as output:

78.26
0
31.7827586207
Array
(
    [0] => Array
        (
            [0] => 28.6
            [1] => 0
            [2] => 0
            [3] => 31.8275862069
        )

    [1] => 1
)
Array
(
    [0] => Array
        (
            [0] => 92.3
            [1] => 6.864
            [2] => 391.292827586
        )

    [1] => 1
)

Note that get_variables and get_constraints return two results: The result vector and a status. If only the vector is needed, then variable indexing must be used. For example:

$ret = lpsolve('get_variables', $lp);
$x = $ret[0];
$ret = $ret[1];
print_r($x);
print $ret . "\n";

Variable x will contain the result vector and ret the return status of the call:

Array
(
    [0] => 28.6
    [1] => 0
    [2] => 0
    [3] => 31.8275862069
)
1

Don't forget to free the handle and its associated memory when you are done:

lpsolve('delete_lp', $lp);

Using model name instead of handle

From driver version 5.5.0.2, it is possible to use the model name instead of the handle. From the moment the model has a name, you can use this name instead of the handle. This is best shown by an example. Above example would look like this:
$lp = lpsolve('make_lp', 0, 4);
$ret = lpsolve('set_lp_name', $lp, 'mymodel');
lpsolve('set_verbose', 'mymodel', IMPORTANT);
$ret = lpsolve('set_obj_fn', 'mymodel', Array(1, 3, 6.24, 0.1));
$ret = lpsolve('add_constraint', 'mymodel', Array(0, 78.26, 0, 2.9), GE, 92.3);
$ret = lpsolve('add_constraint', 'mymodel', Array(0.24, 0, 11.31, 0), LE, 14.8);
$ret = lpsolve('add_constraint', 'mymodel', Array(12.68, 0, 0.08, 0.9), GE, 4);
$ret = lpsolve('set_lowbo', 'mymodel', 1, 28.6);
$ret = lpsolve('set_lowbo', 'mymodel', 4, 18);
$ret = lpsolve('set_upbo', 'mymodel', 4, 48.98);
$ret = lpsolve('set_col_name', 'mymodel', 1, 'COLONE');
$ret = lpsolve('set_col_name', 'mymodel', 2, 'COLTWO');
$ret = lpsolve('set_col_name', 'mymodel', 3, 'COLTHREE');
$ret = lpsolve('set_col_name', 'mymodel', 4, 'COLFOUR');
$ret = lpsolve('set_row_name', 'mymodel', 1, 'THISROW');
$ret = lpsolve('set_row_name', 'mymodel', 2, 'THATROW');
$ret = lpsolve('set_row_name', 'mymodel', 3, 'LASTROW');
$ret = lpsolve('write_lp', 'mymodel', 'a.lp');
print lpsolve('get_mat', 'mymodel', 1, 2) . "\n";
print lpsolve('solve', 'mymodel') . "\n";
print lpsolve('get_objective', 'mymodel') . "\n";
print_r(lpsolve('get_variables', 'mymodel'));
print_r(lpsolve('get_constraints', 'mymodel'));
lpsolve('delete_lp', 'mymodel');

This gives:

78.26
0
31.7827586207
Array
(
    [0] => Array
        (
            [0] => 28.6
            [1] => 0
            [2] => 0
            [3] => 31.8275862069
        )

    [1] => 1
)
Array
(
    [0] => Array
        (
            [0] => 92.3
            [1] => 6.864
            [2] => 391.292827586
        )

    [1] => 1
)

So everywhere a handle is needed, you can also use the model name. You can even mix the two methods. There is also a specific PHP routine to get the handle from the model name: get_handle.
For example:

$lp = lpsolve('get_handle', 'mymodel');
print $lp;

This gives:

0

Don't forget to free the handle and its associated memory when you are done:

lpsolve('delete_lp', 'mymodel');

In the next part of this documentation, the handle is used. But if you name the model, the name could thus also be used.

Matrices

lpsolve uses PHP arrays to represent matrices (and vectors).
For example:
lpsolve('add_constraint', $lp, Array(0.24, 0, 11.31, 0), 1, 14.8);

Most of the time, variables are used to provide the data:

lpsolve('add_constraint', $lp, $a1, 1, 14.8);

Where $a1 is a variable of type array. Sometimes a two-dimensional matrix is used. In PHP, that is an array of arrays:

lpsolve('set_mat', $lp, Array(Array(1, 2, 3), Array(4, 5, 6)));

Array(1, 2, 3) is the first row and Array(4, 5, 6) is the second row.

PHP also supports sparse matrices because of the way arrays are internally supported.
For example:

$a[2] = 3;
$a[5] = 5;

print_r($a);

This gives:

Array
(
    [2] => 3
    [5] => 5
)

The lpsolve driver accepts these as is. No conversion or so is needed. The non-provided elements are seen as zero-values.

In fact, the lpsolve driver sees all provided matrices as sparse matrices. lpsolve uses sparse matrices internally and data can be provided sparse via the ex routines. For example add_constraintex. The lpsolve driver always uses the ex routines to provide the data to lpsolve. Even if you call from PHP the routine names that would require a dense matrix (for example add_constraint), the lpsolve driver will always call the sparse version of the routine (for example add_constraintex). This results in the most performing behaviour.

An important final note. Several lp_solve API routines accept a vector where the first element (element 0) is not used. Other lp_solve API calls do use the first element. In the PHP interface, there is never an unused element in the matrices. So if the lp_solve API specifies that the first element is not used, then this element is not in the PHP matrix.

Maximum usage of matrices with lpsolve

Because PHP has the array possibility to represent vectors, all lpsolve API routines that need a column or row number to get/set information for that column/row are extended in the lpsolve PHP driver to also work with vectors. For example set_int in the API can only set the integer status for one column. If the status for several integer variables must be set, then set_int must be called multiple times. The lpsolve PHP driver however also allows specifying a vector to set the integer status of all variables at once. The API call is: $return = lpsolve('set_int', $lp, $column, $must_be_int);. The matrix version of this call is: $return = lpsolve('set_int', $lp, $must_be_int);. Here $must_be_int must be an array variable. The API call to return the integer status of a variable is: $return = lpsolve('is_int', $lp, $column);. The matrix version of this call is: $is_int = lpsolve('is_int', $lp);
$is_int is again an array variable in this case. Also note the get_mat and set_mat routines. In PHP these are extended to return/set the complete constraint matrix. See following example.

Above example can thus also be done as follows:
(Note that you can execute this example by entering command per command as shown below or by executing script example2.php)

$lp = lpsolve('make_lp', 0, 4);
lpsolve('set_verbose', $lp, IMPORTANT);
$ret = lpsolve('set_obj_fn', $lp, Array(1, 3, 6.24, 0.1));
$ret = lpsolve('add_constraint', $lp, Array(0, 78.26, 0, 2.9), GE, 92.3);
$ret = lpsolve('add_constraint', $lp, Array(0.24, 0, 11.31, 0), LE, 14.8);
$ret = lpsolve('add_constraint', $lp, Array(12.68, 0, 0.08, 0.9), GE, 4);
$ret = lpsolve('set_lowbo', $lp, Array(28.6, 0, 0, 18));
$ret = lpsolve('set_upbo', $lp, Array(Infinite, Infinite, Infinite, 48.98));
$ret = lpsolve('set_col_name', $lp, Array('COLONE', 'COLTWO', 'COLTHREE', 'COLFOUR'));
$ret = lpsolve('set_row_name', $lp, Array('THISROW', 'THATROW', 'LASTROW'));
$ret = lpsolve('write_lp', $lp, 'a.lp');
print_r(lpsolve('get_mat', $lp));
print lpsolve('solve', $lp) . "\n";
print lpsolve('get_objective', $lp) . "\n";
print_r(lpsolve('get_variables', $lp));
print_r(lpsolve('get_constraints', $lp));
lpsolve('delete_lp', $lp);

This gives:

Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => 0
                    [1] => 78.26
                    [2] => 0
                    [3] => 2.9
                )

            [1] => Array
                (
                    [0] => 0.24
                    [1] => 0
                    [2] => 11.31
                    [3] => 0
                )

            [2] => Array
                (
                    [0] => 12.68
                    [1] => 0
                    [2] => 0.08
                    [3] => 0.9
                )

        )

    [1] => 1
)
0
31.7827586207
Array
(
    [0] => Array
        (
            [0] => 28.6
            [1] => 0
            [2] => 0
            [3] => 31.8275862069
        )

    [1] => 1
)
Array
(
    [0] => Array
        (
            [0] => 92.3
            [1] => 6.864
            [2] => 391.292827586
        )

    [1] => 1
)

Note the usage of Infinite in set_upbo. This stands for 'infinity'. Meaning an infinite upper bound. It is also possible to use -Infinite to express minus infinity. This can for example be used to create a free variable. Infinite is a constant defined by the lpsolve library.

To show the full power of the matrices, let's now do some matrix calculations to check the solution. It works further on above example. Note that PHP doesn't support much matrix calculations on arrays. We only need a matrix multiplication routine to demonstrate the following. For this the following routine can be used. Include it in the next code to perform the matrixmultiply:

function matrixmultiply($Array1, $Array2) {
        $rows2 = count($Array2);
        if (is_array($Array2[0])) {
            $dim2 = 2;
            $columns2 = count($Array2[0]);
        }
        else {
            $dim2 = 1;
            $columns2 = 1;
        }

        $rows1 = count($Array1);
        if (is_array($Array1[0])) {
            $dim1 = 2;
            $columns1 = count($Array1[0]);
        }
        else {
            $dim1 = 1;
            if ($rows2 == 1)
                $columns1 = 1;
            else {
                $columns1 = $rows1;
                $rows1 = 1;
            }
        }

        for($i=0; $i<$rows1; $i++){
                for($j=0; $j<$columns2; $j++){
                        $a = 0;
                        for($M=0;$M<$columns1;$M++){
                                if ($dim1 == 2)
                                    $b = $Array1[$i][$M];
                                else if ($rows2 == 1)
                                    $b = $Array1[$i];
                                else
                                    $b = $Array1[$M];
                                $c = $Array2[$M];
                                if ($dim2 == 2)
                                    $c = $c[$j];
                                $a = $a + $b * $c;
                        }
                        if ($dim2 == 2)
                            $ArrayMultipli[$i][$j] = $a;
                        else
                            $ArrayMultipli[$i] = $a;
                }
        }
        return $ArrayMultipli;
}

Now do the following calculations:

$lp = lpsolve('make_lp', 0, 4);
lpsolve('set_verbose', $lp, IMPORTANT);
$ret = lpsolve('set_obj_fn', $lp, Array(1, 3, 6.24, 0.1));
$ret = lpsolve('add_constraint', $lp, Array(0, 78.26, 0, 2.9), GE, 92.3);
$ret = lpsolve('add_constraint', $lp, Array(0.24, 0, 11.31, 0), LE, 14.8);
$ret = lpsolve('add_constraint', $lp, Array(12.68, 0, 0.08, 0.9), GE, 4);
$ret = lpsolve('set_lowbo', $lp, Array(28.6, 0, 0, 18));
$ret = lpsolve('set_upbo', $lp, Array(Infinite, Infinite, Infinite, 48.98));
$ret = lpsolve('set_col_name', $lp, Array('COLONE', 'COLTWO', 'COLTHREE', 'COLFOUR'));
$ret = lpsolve('set_row_name', $lp, Array('THISROW', 'THATROW', 'LASTROW'));
$ret = lpsolve('write_lp', $lp, 'a.lp');
lpsolve('solve', $lp);

$A = lpsolve('get_mat', $lp);
$A = $A[0];
print_r($A);
$X = lpsolve('get_variables', $lp);
$X = $X[0];
print_r($X);
$B = matrixmultiply($A, $X);
print_r($B);

$C = lpsolve('get_obj_fn', $lp);
$C = $C[0];
print_r($C);
$X = lpsolve('get_variables', $lp);
$X = $X[0];
$obj = matrixmultiply($C, $X);
print_r($obj);

So what we have done here is calculate the values of the constraints (RHS) by multiplying the constraint matrix with the solution vector.
This gives:

Array
(
    [0] => Array
        (
            [0] => 0
            [1] => 78.26
            [2] => 0
            [3] => 2.9
        )

    [1] => Array
        (
            [0] => 0.24
            [1] => 0
            [2] => 11.31
            [3] => 0
        )

    [2] => Array
        (
            [0] => 12.68
            [1] => 0
            [2] => 0.08
            [3] => 0.9
        )

)
Array
(
    [0] => 28.6
    [1] => 0
    [2] => 0
    [3] => 31.8275862069
)
Array
(
    [0] => 92.3
    [1] => 6.864
    [2] => 391.292827586
)
Array
(
    [0] => 1
    [1] => 3
    [2] => 6.24
    [3] => 0.0:
)
Array
(
    [0] => 31.7827586207
)

Now take a look at the values of the constraints that lpsolve has found:

print_r(lpsolve('get_constraints', $lp));

That gives:

Array
(
    [0] => Array
        (
            [0] => 92.3
            [1] => 6.864
            [2] => 391.292827586
        )

    [1] => 1
)

Exactly the same as the calculated B vector, as expected.

Also the value of the objective is calculated in $obj. What we have done is calculate the value of the objective by multiplying the objective vector with the solution vector. Now take a look at the value of the objective that lpsolve has found:

print lpsolve('get_objective', $lp);

That gives:

31.7827586207

Again exactly the same as the calculated obj value, as expected.

Using string constants

From driver version 5.5.0.15 on, it is possible to use string constants everywhere an lp_solve constant is needed or returned. This is best shown by an example. In the above code we had:
$lp=lpsolve('make_lp', 0, 4);
lpsolve('set_verbose', $lp, IMPORTANT);
lpsolve('add_constraint', $lp, Array(0, 78.26, 0, 2.9), GE, 92.3);
lpsolve('add_constraint', $lp, Array(0.24, 0, 11.31, 0), LE, 14.8);
lpsolve('add_constraint', $lp, Array(12.68, 0, 0.08, 0.9), GE, 4);

Note the 3rd parameter on set_verbose and the 4th on add_constraint. These are lp_solve constants. One can define all the possible constants in PHP as is done in the lpsolve driver and then use them in the calls, but that has several disadvantages. First there stays the possibility to provide a constant that is not intended for that particular call. Another issue is that calls that return a constant are still returning it numerical.

Both issues can now be handled by string constants. The above code can be done as following with string constants:

$lp=lpsolve('make_lp', 0, 4);
lpsolve('set_verbose', $lp, 'IMPORTANT');
lpsolve('add_constraint', $lp, Array(0, 78.26, 0, 2.9), 'GE', 92.3);
lpsolve('add_constraint', $lp, Array(0.24, 0, 11.31, 0), 'LE', 14.8);
lpsolve('add_constraint', $lp, Array(12.68, 0, 0.08, 0.9), 'GE', 4);

This is not only more readable, there is much lesser chance that mistakes are being made. The calling routine knows which constants are possible and only allows these. So unknown constants or constants that are intended for other calls are not accepted. For example:

lpsolve('set_verbose', $lp, 'blabla');
PHP Fatal error:  lpsolve() [<a href='function.lpsolve'>function.lpsolve</a>]:
BLABLA: Unknown.

lpsolve('set_verbose', $lp, 'GE');
PHP Fatal error:  lpsolve() [<a href='function.lpsolve'>function.lpsolve</a>]:
GE: Not allowed here.

Note the difference between the two error messages. The first says that the constant is not known, the second that the constant cannot be used at that place.

Constants are case insensitive. Internally they are always translated to upper case. Also when returned they will always be in upper case.

The constant names are the ones as specified in the documentation of each API routine. There are only 3 exceptions, extensions actually. 'LE', 'GE' and 'EQ' in add_constraint and is_constr_type can also be '<', '<=', '>', '>=', '='. When returned however, 'GE', 'LE', 'EQ' will be used.

Also in the matrix version of calls, string constants are possible. For example:

lpsolve('set_constr_type', $lp, Array('LE', 'EQ', 'GE'));

Some constants can be a combination of multiple constants. For example set_scaling:

lpsolve('set_scaling', $lp, 3+128);

With the string version of constants this can be done as following:

lpsolve('set_scaling', $lp, 'SCALE_MEAN|SCALE_INTEGERS');

| is the OR operator used to combine multiple constants. There may optinally be spaces before and after the |.

Not all OR combinations are legal. For example in set_scaling, a choice must be made between SCALE_EXTREME, SCALE_RANGE, SCALE_MEAN, SCALE_GEOMETRIC or SCALE_CURTISREID. They may not be combined with each other. This is also tested:

lpsolve('set_scaling', $lp, 'SCALE_MEAN|SCALE_RANGE');
PHP Fatal error:  lpsolve() [<a href='function.lpsolve'>function.lpsolve</a>]:
SCALE_RANGE cannot be combined with SCALE_MEAN

Everywhere constants must be provided, numeric or string values may be provided. The routine automatically interpretes them.

Returning constants is a different story. The user must let lp_solve know how to return it. Numerical or as string. The default is numerical:

echo lpsolve('get_scaling', $lp);
131

To let lp_solve return a constant as string, a call to a new function must be made: return_constants

lpsolve('return_constants', 1);

From now on, all returned constants are returned as string:

echo lpsolve('get_scaling', $lp);
SCALE_MEAN|SCALE_INTEGERS

Also when an array of constants is returned, they are returned as string when return_constants is set:

print_r(lpsolve('get_constr_type', $lp));
Array
(
    [0] => LE
    [1] => EQ
    [2] => GE
)

This for all routines until return_constants is again called with 0:

lpsolve('return_constants', 0);

The (new) current setting of return_constants is always returned by the call. Even when set:

echo lpsolve('return_constants', 1);
1

To get the value without setting it, don't provide the second argument:

echo lpsolve('return_constants');
1

In the next part of this documentation, return_constants is the default, 0, so all constants are returned numerical and provided constants are also numerical. This to keep the documentation as compatible as possible with older versions. But don't let you hold that back to use string constants in your code.

php-files

PHP can execute a sequence of statements stored in diskfiles. Such files are called PHP scripts and should have the file type of ".php" as the last part of their filename (extension).

You can put PHP commands in them and execute them at any time. The PHP script can be executed in the command line via the command php -f script.php. The script files contain plain ascii data. a PHP file can also be included by other PHP code. This via the include command. This way it is possible to define routine in one script and execute it in another. All this can be done via command line or via a webserver.

Note that when used under a webserver like apache that these php files must be in a specific location. For example /var/www

The lpsolve PHP distribution contains some example script to demonstrate this.

example1.php

Contains the commands as shown in the first example of this article.

example2.php

Contains the commands as shown in the second example of this article.

example3.php

Contains the commands of a practical example. See further in this article.

example4.php

Contains the commands of a practical example. See further in this article.

example5.php

Contains the commands of a practical example. See further in this article.

example6.php

Contains the commands of a practical example. See further in this article.

lp_solve.php

This script uses the API to create a higher-level function called lp_solve. This function accepts as arguments some matrices and options to create and solve an lp model. The script must first be inserted in the current code via an include command:

include "lp_solve.php";

Use lp_solve(); to see its usage:

LP_SOLVE  Solves mixed integer linear programming problems.

   SYNOPSIS: [obj,x,duals] = lp_solve(f,a,b,e,vlb,vub,xint,scalemode,keep)

      solves the MILP problem

              max v = f'*x
                a*x <> b
                  vlb <= x <= vub
                  x(int) are integer

   ARGUMENTS: The first four arguments are required:

            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) = -1  ==> Less Than
                      e(i) =  0  ==> Equals
                      e(i) =  1  ==> Greater Than
          vlb: n vector of lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: scale flag. Off when 0 or omitted.
         keep: Flag for keeping the lp problem after it's been solved.
               If omitted, the lp will be deleted when solved.

   OUTPUT: A nonempty output is returned if a solution is found:

          obj: Optimal value of the objective function.
            x: Optimal value of the decision variables.
        duals: solution of the dual problem.

Example of usage. To create and solve following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

include "lp_solve.php";
$ret = lp_solve(Array(-1, 2), Array(Array(2, 1), Array(-4, 4)), Array(5, 5), Array(-1, -1), null, null, Array(1, 2));
print_r($ret);
This gives:
Array
(
    [0] => 3
    [1] => Array
        (
            [0] => 1
            [1] => 2
        )

    [2] => Array
        (
            [0] => 0
            [1] => 0
        )

)

lp_maker.php

This script is analog to the lp_solve script and also uses the API to create a higher-level function called lp_maker. This function accepts as arguments some matrices and options to create an lp model. Note that this scripts only creates a model and returns a handle. The script must first be inserted in the current code via an include command:

include "lp_maker.php";

Use lp_maker(); to see its usage:

LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: Autoscale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Example of usage. To create following lp-model:

max: -x1 + 2 x2;
C1: 2x1 + x2 < 5;
-4 x1 + 4 x2 <5;

int x2,x1;

The following command can be used:

include "lp_maker.php";
$lp = lp_maker(Array(-1, 2), Array(Array(2, 1), Array(-4, 4)), Array(5, 5), Array(-1, -1), null, null, Array(1, 2));
print $lp . "\n";
This gives 0.

To solve the model and get the solution:

lpsolve('solve', $lp);
print lpsolve('get_objective', $lp) . "\n";
$ret = lpsolve('get_variables', $lp);
print_r($ret);
This gives:
3
Array
(
    [0] => Array
        (
            [0] => 1
            [1] => 2
        )

    [1] => 1
)

Don't forget to free the handle and its associated memory when you are done:

lpsolve('delete_lp', $lp);

lpdemo.php

Contains several examples to build and solve lp models.

ex.php

Contains several examples to build and solve lp models. Also solves the lp_examples from the lp_solve distribution.

A practical example

We shall illustrate the method of linear programming by means of a simple example, giving a combination graphical/numerical solution, and then solve both a slightly as well as a substantially more complicated problem.

Suppose a farmer has 75 acres on which to plant two crops: wheat and barley. To produce these crops, it costs the farmer (for seed, fertilizer, etc.) $120 per acre for the wheat and $210 per acre for the barley.The farmer has $15000 available for expenses. But after the harvest, the farmer must store the crops while awaiting favourable market conditions. The farmer has storage space for 4000 bushels.Each acre yields an average of 110 bushels of wheat or 30 bushels of barley. If the net profit per bushel of wheat (after all expenses have been subtracted) is $1.30 and for barley is $2.00, how should the farmer plant the 75 acres to maximize profit?

We begin by formulating the problem mathematically. First we express the objective, that is the profit, and the constraints algebraically, then we graph them, and lastly we arrive at the solution by graphical inspection and a minor arithmetic calculation.

Let x denote the number of acres allotted to wheat and y the number of acres allotted to barley. Then the expression to be maximized, that is the profit, is clearly

P = (110)(1.30)x + (30)(2.00)y = 143x + 60y.

There are three constraint inequalities, specified by the limits on expenses, storage and acreage. They are respectively:

120x + 210y <= 15000
110x + 30y <= 4000
x + y <= 75

Strictly speaking there are two more constraint inequalities forced by the fact that the farmer cannot plant a negative number of acres, namely:

x >= 0,y >= 0.

Next we graph the regions specified by the constraints. The last two say that we only need to consider the first quadrant in the x-y plane. Here's a graph delineating the triangular region in the first quadrant determined by the first inequality.

Source

Now let's put in the other two constraint inequalities.

Source

The black area is the solution space that holds valid solutions. This means that any point in this area fulfils the constraints.

Now let's superimpose on top of this picture a contour plot of the objective function P.

Source

The lines give a picture of the objective function. All solutions that intersect with the black area are valid solutions, meaning that this result also fulfils the set constraints. The more the lines go to the right, the higher the objective value is. The optimal solution or best objective is a line that is still in the black area, but with an as large as possible value.

It seems apparent that the maximum value of P will occur on the level curve (that is, level line) that passes through the vertex of the polygon that lies near (22,53).
It is the intersection of x + y = 75 and 110*x + 30*y = 4000
This is a corner point of the diagram. This is not a coincidence. The simplex algorithm, which is used by lpsolve, starts from a theorem that the optimal solution is such a corner point.
In fact we can compute the result. This is done here with an undefined function matrixinverse which is not available in PHP:

$x = matrixmultiply(inverse(Array(Array(1, 1), Array(110, 30))), array(75, 4000));
print_r($x);
With inverse(Array(Array(1, 1), Array(110, 30))) = Array(Array(-0.375, 0.0125), Array(1.375, -0.0125)) that is:
$x = matrixmultiply(Array(Array(-0.375, 0.0125), Array(1.375, -0.0125)), array(75, 4000));
print_r($x);
That gives:
Array
(
    [0] => 21.875
    [1] => 53.125
)

The acreage that results in the maximum profit is 21.875 for wheat and 53.125 for barley. In that case the profit is:

$P = matrixmultiply(Array(143, 60), $x);
print_r($P);

That gives:

Array
(
    [0] => 6315.625
)

That is, $6315.625.

Note that these command are in script example3.php

Now, lp_solve comes into the picture to solve this linear programming problem more generally. After that we will use it to solve two more complicated problems involving more variables and constraints.

For this example, we use the higher-level script lp_maker to build the model and then some lp_solve API calls to retrieve the solution. Here is again the usage of lp_maker:

 LP_MAKER  Makes mixed integer linear programming problems.

   SYNOPSIS: lp_handle = lp_maker(f,a,b,e,vlb,vub,xint,scalemode,setminim)
      make the MILP problem
        max v = f'*x
          a*x <> b
            vlb <= x <= vub
            x(int) are integer

   ARGUMENTS: The first four arguments are required:
            f: n vector of coefficients for a linear objective function.
            a: m by n matrix representing linear constraints.
            b: m vector of right sides for the inequality constraints.
            e: m vector that determines the sense of the inequalities:
                      e(i) < 0  ==> Less Than
                      e(i) = 0  ==> Equals
                      e(i) > 0  ==> Greater Than
          vlb: n vector of non-negative lower bounds. If empty or omitted,
               then the lower bounds are set to zero.
          vub: n vector of upper bounds. May be omitted or empty.
         xint: vector of integer variables. May be omitted or empty.
    scalemode: Autoscale flag. Off when 0 or omitted.
     setminim: Set maximum lp when this flag equals 0 or omitted.

   OUTPUT: lp_handle is an integer handle to the lp created.

Now let's formulate this model with lp_solve:

include "lp_maker.php";
$f = Array(143, 60);
$A = Array(Array(120, 210), Array(110, 30), Array(1, 1));
$b = Array(15000, 4000, 75);
$lp = lp_maker($f, $A, $b, Array(-1, -1, -1), null, null, null, 1, 0);
$solvestat = lpsolve('solve', $lp);
$obj = lpsolve('get_objective', $lp);
print $obj . "\n";
$x = lpsolve('get_variables', $lp);
print_r($x);
lpsolve('delete_lp', $lp);
That gives:
6315.625
Array
(
    [0] => Array
        (
            [0] => 21.875
            [1] => 53.125
        )

    [1] => 1
)

Note that these command are in script example4.php

With the higher-level script lp_maker, we provide all data to lp_solve. lp_solve returns a handle (lp) to the created model. Then the API call 'solve' is used to calculate the optimal solution of the model. The value of the objective function is retrieved via the API call 'get_objective' and the values of the variables are retrieved via the API call 'get_variables'. At last, the model is removed from memory via a call to 'delete_lp'. Don't forget this to free all memory allocated by lp_solve.

The solution is the same answer we obtained before. Note that the non-negativity constraints are accounted implicitly because variables are by default non-negative in lp_solve.

Well, we could have done this problem by hand (as shown in the introduction) because it is very small and it can be graphically presented.
Now suppose that the farmer is dealing with a third crop, say corn, and that the corresponding data is:

cost per acre$150.75
yield per acre125 bushels
profit per bushel$1.56

With three variables it is already a lot more difficult to show this model graphically. Adding more variables makes it even impossible because we can't imagine anymore how to represent this. We only have a practical understanding of 3 dimensions, but beyond that it is all very theoretical.

If we denote the number of acres allotted to corn by z, then the objective function becomes:

P = (110)(1.30)x + (30)(2.00)y+ (125)(1.56) = 143x + 60y + 195z

And the constraint inequalities are:

120x + 210y + 150.75z <= 15000
110x + 30y + 125z <= 4000
x + y + z <= 75
x >= 0,y >= 0, z >= 0

The problem is solved with lp_solve as follows:

include("lp_maker.php");

$f = Array(143, 60, 195);
$A = Array(Array(120, 210, 150.75), Array(110, 30, 125), Array(1, 1, 1));
$b = Array(15000, 4000, 75);
$lp = lp_maker($f, $A, $b, Array(-1, -1, -1), null, null, null, 1, 0);
$solvestat = lpsolve('solve', $lp);
$obj = lpsolve('get_objective', $lp);
print $obj . "\n";
$x = lpsolve('get_variables', $lp);
print_r($x);
lpsolve('delete_lp', $lp);
That gives:
6986.84210526
Array
(
    [0] => Array
        (
            [0] => 0
            [1] => 56.5789473684
            [2] => 18.4210526316
        )

    [1] => 1
)

Note that these command are in script example5.php

So the farmer should ditch the wheat and plant 56.5789 acres of barley and 18.4211 acres of corn.

There is no practical limit on the number of variables and constraints that PHP can handle. Certainly none that the relatively unsophisticated user will encounter.Indeed, in many true applications of the technique of linear programming, one needs to deal with many variables and constraints.The solution of such a problem by hand is not feasible, and software like PHP is crucial to success.For example, in the farming problem with which we have been working, one could have more crops than two or three. Think agribusiness instead of family farmer.And one could have constraints that arise from other things beside expenses, storage and acreage limitations. For example:

  • Availability of seed.This might lead to constraint inequalities like xj < k.
  • Personal preferences. Thus the farmer's spouse might have a preference for one variety over another and insist on a corresponding planting, or something similar with a collection of crops; thus constraint inequalities like xi < xj or x1 + x2 > x3.
  • Government subsidies. It may take a moment's reflection on the reader's part, but this could lead to inequalities like xj > k.

Below is a sequence of commands that solves exactly such a problem. You should be able to recognize the objective expression and the constraints from the data that is entered. But as an aid, you might answer the following questions:

  • How many crops are under consideration?
  • What are the corresponding expenses? How much is available for expenses?
  • What are the yields in each case? What is the storage capacity?
  • How many acres are available?
  • What crops are constrained by seed limitations? To what extent?
  • What about preferences?
  • What are the minimum acreages for each crop?
include("lp_maker.php");

$f = Array(110*1.3, 30*2.0, 125*1.56, 75*1.8, 95*.95, 100*2.25, 50*1.35);
$A = Array(Array(120, 210, 150.75, 115, 186, 140, 85), Array(110, 30, 125, 75, 95, 100, 50), Array(1, 1, 1, 1, 1, 1, 1), Array(1, -1, 0, 0, 0, 0, 0), Array(0, 0, 1, 0, -2, 0, 0), Array(0, 0, 0, -1, 0, -1, 1));
$b = Array(55000, 40000, 400, 0, 0, 0);
$lp = lp_maker($f, $A, $b, Array(-1, -1, -1, -1, -1, -1), Array(10, 10, 10, 10, 20, 20, 20), Array(100, Infinite, 50, Infinite, Infinite, 250, Infinite), null, 1, 0);
$solvestat = lpsolve('solve', $lp);
$obj = lpsolve('get_objective', $lp);
print $obj . "\n";
$x = lpsolve('get_variables', $lp);
print_r($x);
lpsolve('delete_lp', $lp);
That gives:
75398.0434783
Array
(
    [0] => Array
        (
            [0] => 10
            [1] => 10
            [2] => 40
            [3] => 45.652173913
            [4] => 20
            [5] => 250
            [6] => 20
        )

    [1] => 1
)

Note that these command are in script example6.php

Note that we have used in this formulation the vlb and vub arguments of lp_maker. This to set lower and upper bounds on variables. This could have been done via extra constraints, but it is more performant to set bounds on variables. Also note that Infinity is used for variables that have no upper limit.

Note that despite the complexity of the problem, lp_solve solves it almost instantaneously. It seems the farmer should bet the farm on crop number 6.We strongly suggest you alter the expense and/or the storage limit in the problem and see what effect that has on the answer.

Another, more theoretical, example

Suppose we want to solve the following linear program using PHP:

max 4x1 + 2x2 + x3
s. t. 2x1 + x2 <= 1
x1 + 2x3 <= 2
x1 + x2 + x3 = 1
x1 >= 0
x1 <= 1
x2 >= 0
x2 <= 1
x3 >= 0
x3 <= 2

Convert the LP into PHP format we get:

$f = Array(4, 2, 1);
$A = Array(Array(2, 1, 0), Array(1, 0, 2), Array(1, 1, 1));
$b = Array(1, 2, 1);

Note that constraints on single variables are not put in the constraint matrix. lp_solve can set bounds on individual variables and this is more performant than creating additional constraints. These bounds are:

$l = Array( 0, 0, 0);
$u = Array( 1, 1, 2);

Now lets enter this in PHP:

$f = Array(4, 2, 1);
$A = Array(Array(2, 1, 0), Array(1, 0, 2), Array(1, 1, 1));
$b = Array(1, 2, 1);
$l = Array( 0, 0, 0);
$u = Array( 1, 1, 2);

Now solve the linear program using PHP: Use the commands

include "lp_maker.php";
$lp = lp_maker($f, $A, $b, Array(-1, -1, -1), $l, $u, null, 1, 0);
$solvestat = lpsolve('solve', $lp);
$obj = lpsolve('get_objective', $lp);
print $obj . "\n";
$x = lpsolve('get_variables', $lp);
print_r($x);
lpsolve('delete_lp', $lp);
This gives:
2.5
Array
(
    [0] => Array
        (
            [0] => 0.5
            [1] => 0
            [2] => 0.5
        )

    [1] => 1
)

What to do when some of the variables are missing ?
For example, suppose there are no lower bounds on the variables. In this case define l to be the empty set using the PHP command:

l = null

This has the same effect as before, because lp_solve has as default lower bound for variables 0.

But what if you want that variables may also become negative?
Then you can use -Infinite as lower bounds:

$l = Array(-Infinite, -Infinite, -Infinite);

Solve this and you get a different result:

include "lp_maker.php";
$lp = lp_maker($f, $A, $b, Array(-1, -1, -1), $l, $u, null, 1, 0);
$solvestat = lpsolve('solve', $lp);
$obj = lpsolve('get_objective', $lp);
print $obj . "\n";
$x = lpsolve('get_variables', $lp);
print_r($x);
lpsolve('delete_lp', $lp);
This gives:
2.66666666667
Array
(
    [0] => Array
        (
            [0] => 0.666666666667
            [1] => -0.333333333333
            [2] => 0.666666666667
        )

    [1] => 1
)

Overview of API routines

Note that everwhere where lp is used as argument that this can be a handle (lp) or the models name.

  • add_column, add_columnex
    • return = lpsolve('add_column', lp, [column])
    • return = lpsolve('add_columnex', lp, [column])
    • Both have the same interface from add_column but act as add_columnex
  • add_constraint, add_constraintex
    • return = lpsolve('add_constraint', lp, [row], constr_type, rh)
    • return = lpsolve('add_constraintex', lp, [row], constr_type, rh)
    • Both have the same interface from add_constraint but act as add_constraintex
  • add_SOS
    • return = lpsolve('add_SOS', lp, name, sostype, priority, [sosvars], [weights])
    • The count argument in the API documentation is not needed in PHP since the number of elements is derived from the size of the sosvars and weights matrices. These must have the same size.
  • column_in_lp
    • return = lpsolve('column_in_lp', lp, [column])
    • No special considerations.
  • copy_lp
    • lp_handle = lpsolve('copy_lp', lp)
    • No special considerations.
  • default_basis
    • lpsolve('default_basis', lp)
    • No special considerations.
  • del_column
    • return = lpsolve('del_column', lp, column)
    • No special considerations.
  • del_constraint
    • return = lpsolve('del_constraint', lp, del_row)
    • No special considerations.
  • delete_lp
    • lpsolve('delete_lp', lp)
    • No special considerations.
  • free_lp
    • lpsolve('free_lp', lp)
    • lp is not changed as in the lpsolve API since it is a read_only input parameter. So it acts the same as delete_lp.
  • get_anti_degen
    • return = lpsolve('get_anti_degen', lp)
    • No special considerations.
  • get_basis
    • [bascolumn] = lpsolve('get_basis', lp {, nonbasic})
    • The bascolumn argument in the API documentation is here the return value. The nonbasic argument is optional in PHP. If not provided, then 0 is used.
  • get_basiscrash
    • return = lpsolve('get_basiscrash', lp)
    • No special considerations.
  • get_bb_depthlimit
    • return = lpsolve('get_bb_depthlimit', lp)
    • No special considerations.
  • get_bb_floorfirst
    • return = lpsolve('get_bb_floorfirst', lp)
    • No special considerations.
  • get_bb_rule
    • return = lpsolve('get_bb_rule', lp)
    • No special considerations.
  • get_bounds_tighter
    • return = lpsolve('get_bounds_tighter', lp)
    • No special considerations.
  • get_break_at_value
    • return = lpsolve('get_break_at_value', lp)
    • No special considerations.
  • get_col_name
    • name = lpsolve('get_col_name', lp, column)
    • [names] = lpsolve('get_col_name', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • get_column get_columnex
    • [column, return] = lpsolve('get_column', lp, col_nr)
    • [column, return] = lpsolve('get_columnex', lp, col_nr)
    • The column argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_constr_type
    • return = lpsolve('get_constr_type', lp, row)
    • [constr_type] = lpsolve('get_constr_type', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • get_constr_value
    • return = lpsolve('get_constr_value', lp, row {, primsolution})
    • The primsolution argument is optional. If not provided, then the solution of last solve is used.
  • get_constraints
    • [constr, return] = lpsolve('get_constraints', lp)
    • The constr argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_dual_solution
    • [duals, return] = lpsolve('get_dual_solution', lp)
    • The duals argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In PHP, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_epsb
    • return = lpsolve('get_epsb', lp)
    • No special considerations.
  • get_epsd
    • return = lpsolve('get_epsd', lp)
    • No special considerations.
  • get_epsel
    • return = lpsolve('get_epsel', lp)
    • No special considerations.
  • get_epsint
    • return = lpsolve('get_epsint', lp)
    • No special considerations.
  • get_epsperturb
    • return = lpsolve('get_epsperturb', lp)
    • No special considerations.
  • get_epspivot
    • return = lpsolve('get_epspivot', lp)
    • No special considerations.
  • get_improve
    • return = lpsolve('get_improve', lp)
    • No special considerations.
  • get_infinite
    • return = lpsolve('get_infinite', lp)
    • No special considerations.
  • get_lowbo
    • return = lpsolve('get_lowbo', lp, column)
    • [return] = lpsolve('get_lowbo', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • get_lp_index
    • return = lpsolve('get_lp_index', lp, orig_index)
    • No special considerations.
  • get_lp_name
    • name = lpsolve('get_lp_name', lp)
    • No special considerations.
  • get_mat
    • value = lpsolve('get_mat', lp, row, col)
    • [matrix, return] = lpsolve('get_mat', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix in the first return value. The return code of the call is the second return value.
  • get_max_level
    • return = lpsolve('get_max_level', lp)
    • No special considerations.
  • get_maxpivot
    • return = lpsolve('get_maxpivot', lp)
    • No special considerations.
  • get_mip_gap
    • return = lpsolve('get_mip_gap', lp, absolute)
    • No special considerations.
  • get_nameindex
    • return = lpsolve('get_nameindex', lp, name, isrow)
    • No special considerations.
  • get_Ncolumns
    • return = lpsolve('get_Ncolumns', lp)
    • No special considerations.
  • get_negrange
    • return = lpsolve('get_negrange', lp)
    • No special considerations.
  • get_nonzeros
    • return = lpsolve('get_nonzeros', lp)
    • No special considerations.
  • get_Norig_columns
    • return = lpsolve('get_Norig_columns', lp)
    • No special considerations.
  • get_Norig_rows
    • return = lpsolve('get_Norig_rows', lp)
    • No special considerations.
  • get_Nrows
    • return = lpsolve('get_Nrows', lp)
    • No special considerations.
  • get_obj_bound
    • return = lpsolve('get_obj_bound', lp)
    • No special considerations.
  • get_objective
    • return = lpsolve('get_objective', lp)
    • No special considerations.
  • get_orig_index
    • return = lpsolve('get_orig_index', lp, lp_index)
    • No special considerations.
  • get_origcol_name
    • name = lpsolve('get_origcol_name', lp, column)
    • [names] = lpsolve('get_origcol_name', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • get_origrow_name
    • name = lpsolve('get_origrow_name', lp, row)
    • [names] = lpsolve('get_origrow_name', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • get_pivoting
    • return = lpsolve('get_pivoting', lp)
    • No special considerations.
  • get_presolve
    • return = lpsolve('get_presolve', lp)
    • No special considerations.
  • get_presolveloops
    • return = lpsolve('get_presolveloops', lp)
    • No special considerations.
  • get_primal_solution
    • [pv, return] = lpsolve('get_primal_solution', lp)
    • The pv argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_print_sol
    • return = lpsolve('get_print_sol', lp)
    • No special considerations.
  • get_ptr_constraints
    • Not implemented.
  • get_ptr_dualsolution
    • Not implemented.
  • get_ptr_primal_solution
    • Not implemented.
  • get_ptr_sensitivity_obj, get_ptr_sensitivity_objex
    • Not implemented.
  • get_ptr_sensitivity_rhs
    • Not implemented.
  • get_ptr_variables
    • Not implemented.
  • get_rh
    • return = lpsolve('get_rh', lp, row)
    • [rh] = lpsolve('get_rh', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • get_rh_range
    • return = lpsolve('get_rh_range', lp, row)
    • [rh_ranges] = lpsolve('get_rh_range', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • get_row get_rowex
    • [row, return] = lpsolve('get_row', lp, row_nr)
    • [row, return] = lpsolve('get_rowex', lp, row_nr)
    • The row argument in the API documentation is here the first return value.
    • In the API, element 0 is not used and values start from element 1. In PHP, there is no unused element in the matrix.
    • The return code of the call is the second return value.
  • get_row_name
    • name = lpsolve('get_row_name', lp, row)
    • [names] = lpsolve('get_row_name', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • get_scalelimit
    • return = lpsolve('get_scalelimit', lp)
    • No special considerations.
  • get_scaling
    • return = lpsolve('get_scaling', lp)
    • No special considerations.
  • get_sensitivity_obj, get_sensitivity_objex
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = lpsolve('get_sensitivity_obj', lp)
    • [objfrom, objtill, objfromvalue, objtillvalue, return] = lpsolve('get_sensitivity_objex', lp)
    • The objfrom, objtill, objfromvalue, objtillvalue arguments in the API documentation are here the return values. Note that PHP allows the return of fewer variables. For example if only objfrom and objtill are needed then the call can be [objfrom, objtill] = lpsolve('get_sensitivity_obj', lp). The unrequested values are even not calculated.
    • Since the API routine doesn't calculate the objtillvalue value at this time, PHP always returns a zero vector for this.
    • The return code of the call is the last value.
    • get_sensitivity_obj and get_sensitivity_objex are both implemented, but have the same functionality.
  • get_sensitivity_rhs, get_sensitivity_rhsex
    • [duals, dualsfrom, dualstill, return] = lpsolve('get_sensitivity_rhs', lp)
    • [duals, dualsfrom, dualstill, return] = lpsolve('get_sensitivity_rhsex', lp)
    • The duals, dualsfrom, dualstill arguments in the API documentation are here the return values. Note that PHP allows the return of fewer variables. For example if only duals is needed then the call can be [duals] = lpsolve('get_sensitivity_rhs', lp). The unrequested values are even not calculated.
    • The return code of the call is the last value.
    • get_sensitivity_rhs and get_sensitivity_rhsex are both implemented, but have the same functionality.
  • get_simplextype
    • return = lpsolve('get_simplextype', lp)
    • No special considerations.
  • get_solutioncount
    • return = lpsolve('get_solutioncount', lp)
    • No special considerations.
  • get_solutionlimit
    • return = lpsolve('get_solutionlimit', lp)
    • No special considerations.
  • get_status
    • return = lpsolve('get_status', lp)
    • No special considerations.
  • get_statustext
    • return = lpsolve('get_statustext', lp, statuscode)
    • No special considerations.
  • get_timeout
    • return = lpsolve('get_timeout', lp)
    • No special considerations.
  • get_total_iter
    • return = lpsolve('get_total_iter', lp)
    • No special considerations.
  • get_total_nodes
    • return = lpsolve('get_total_nodes', lp)
    • No special considerations.
  • get_upbo
    • return = lpsolve('get_upbo', lp, column)
    • [upbo] = lpsolve('get_upbo', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • get_var_branch
    • return = lpsolve('get_var_branch', lp, column)
    • [var_branch] = lpsolve('get_var_branch', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • get_var_dualresult
    • return = lpsolve('get_var_dualresult', lp, index)
    • No special considerations.
  • get_var_primalresult
    • return = lpsolve('get_var_primalresult', lp, index)
    • No special considerations.
  • get_var_priority
    • return = lpsolve('get_var_priority', lp, column)
    • [var_priority] = lpsolve('get_var_priority', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • get_variables
    • [var, return] = lpsolve('get_variables', lp)
    • The var argument in the API documentation is here the first return value.
    • The return code of the call is the second return value.
  • get_verbose
    • return = lpsolve('get_verbose', lp)
    • No special considerations.
  • get_working_objective
    • return = lpsolve('get_working_objective', lp)
    • No special considerations.
  • guess_basis
    • [basisvector, return] = lpsolve('guess_basis', lp, [guessvector])
    • In the API, element 0 of guessvector is not used and values start from element 1. In PHP, there is no unused element in the matrix.
    • In the API, element 0 of basisvector is not used and values start from element 1. In PHP, there is no unused element in the matrix.
  • has_BFP
    • return = lpsolve('has_BFP', lp)
    • No special considerations.
  • has_XLI
    • return = lpsolve('has_XLI', lp)
    • No special considerations.
  • is_add_rowmode
    • return = lpsolve('is_add_rowmode', lp)
    • No special considerations.
  • is_anti_degen
    • return = lpsolve('is_anti_degen', lp, testmask)
    • No special considerations.
  • is_binary
    • return = lpsolve('is_binary', lp, column)
    • [binary] = lpsolve('is_binary', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • is_break_at_first
    • return = lpsolve('is_break_at_first', lp)
    • No special considerations.
  • is_constr_type
    • return = lpsolve('is_constr_type', lp, row, mask)
    • No special considerations.
  • is_debug
    • return = lpsolve('is_debug', lp)
    • No special considerations.
  • is_feasible
    • return = lpsolve('is_feasible', lp, [values] {, threshold})
    • The threshold argument is optional. When not provided, the value of get_epsint will be taken.
  • is_free is_unbounded
    • return = lpsolve('is_free', lp, column)
    • return = lpsolve('is_unbounded', lp, column)
    • [free] = lpsolve('is_free', lp)
    • [free] = lpsolve('is_unbounded', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • is_infinite
    • return = lpsolve('is_infinite', lp, value)
    • No special considerations.
  • is_int
    • return = lpsolve('is_int', lp, column)
    • [int] = lpsolve('is_int', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • is_integerscaling
    • return = lpsolve('is_integerscaling', lp)
    • No special considerations.
  • is_maxim
    • return = lpsolve('is_maxim', lp)
    • No special considerations.
  • is_nativeBFP
    • return = lpsolve('is_nativeBFP', lp)
    • No special considerations.
  • is_nativeXLI
    • return = lpsolve('is_nativeXLI', lp)
    • No special considerations.
  • is_negative
    • return = lpsolve('is_negative', lp, column)
    • [negative] = lpsolve('is_negative', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • is_piv_mode
    • return = lpsolve('is_piv_mode', lp, testmask)
    • No special considerations.
  • is_piv_rule
    • return = lpsolve('is_piv_rule', lp, rule)
    • No special considerations.
  • is_presolve
    • return = lpsolve('is_presolve', lp, testmask)
    • No special considerations.
  • is_scalemode
    • return = lpsolve('is_scalemode', lp, testmask)
    • No special considerations.
  • is_scaletype
    • return = lpsolve('is_scaletype', lp, scaletype)
    • No special considerations.
  • is_semicont
    • return = lpsolve('is_semicont', lp, column)
    • [semicont] = lpsolve('is_semicont', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • is_SOS_var
    • return = lpsolve('is_SOS_var', lp, column)
    • [SOS_var] = lpsolve('is_SOS_var', lp)
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows retrieving the values into a PHP matrix.
  • is_trace
    • return = lpsolve('is_trace', lp)
    • No special considerations.
  • is_use_names
    • return = lpsolve('is_use_names', lp, isrow)
    • No special considerations.
  • lp_solve_version
    • versionstring = lpsolve('lp_solve_version')
    • The lpsolve API routine returns the version information in 4 provided argument variables while the PHP version returns the information as a string in the format major.minor.release.build
  • make_lp
    • lp_handle = lpsolve('make_lp', rows, columns)
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
  • print_constraints
    • lpsolve('print_constraints', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under PHP (Windows) this means that the output is not shown.
    • The same information can also be obtained via lpsolve('get_constraints', lp). This shows the result on screen.
  • print_debugdump
    • return = lpsolve('print_debugdump', lp, filename)
    • No special considerations.
  • print_duals
    • lpsolve('print_duals', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under PHP (Windows) this means that the output is not shown.
    • The same information can be obtained via lpsolve('get_dual_solution', lp). This shows the result on screen.
  • print_lp
    • lpsolve('print_lp', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under PHP (Windows) this means that the output is not shown.
  • print_objective
    • lpsolve('print_objective', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under PHP (Windows) this means that the output is not shown.
    • The same information can be obtained via lpsolve('get_objective', lp). This shows the result on screen.
  • print_scales
    • lpsolve('print_scales', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under PHP (Windows) this means that the output is not shown.
  • print_solution
    • lpsolve('print_solution', lp {, columns})
    • columns is optional. If not specified, then 1 is used.
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under PHP (Windows) this means that the output is not shown.
    • The same information can also be obtained via lpsolve('get_variables', lp). This shows the result on screen.
  • print_str
    • lpsolve('print_str', lp, str)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under PHP (Windows) this means that the output is not shown.
  • print_tableau
    • lpsolve('print_tableau', lp)
    • First call set_outputfile to specify where the information is written to. In the API documentation it is written that by default, the output goes to stdout, but under PHP (Windows) this means that the output is not shown.
  • put_abortfunc
    • Not implemented.
  • put_logfunc
    • Not implemented.
    • However, the lpsolve driver sets a log function to redirect the output of lpsolve from stdout (which is not visible in Windows PHP) to the command window of PHP. As such, all reported output can be seen in PHP. How much output is seen is controlled by the verbose level that can be defined by set_verbose or can be specified in the read_ routines.
  • put_msgfunc
    • Not implemented.
  • read_basis
    • [ret, info] = lpsolve('read_basis', lp, filename)
    • No special considerations.
  • read_freemps, read_freeMPS
    • lp_handle = lpsolve('read_freemps', filename {, options})
    • lp_handle = lpsolve('read_freeMPS', filename {, options})
    • In the lpsolve API, read_freemps needs a FILE handle. In PHP it needs the filename and thus acts the same as read_freeMPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_lp, read_LP
    • lp_handle = lpsolve('read_lp', filename {, verbose {, lp_name}})
    • lp_handle = lpsolve('read_LP', filename {, verbose {, lp_name}})
    • In the lpsolve API, read_lp needs a FILE handle. In PHP it needs the filename and thus acts the same as read_LP.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • verbose is optional. If not provided then NORMAL is used.
    • lp_name is optional. If not provided then no name is given to the model ('').
  • read_mps, read_MPS
    • lp_handle = lpsolve('read_mps', filename {, options})
    • lp_handle = lpsolve('read_MPS', filename {, options})
    • In the lpsolve API, read_mps needs a FILE handle. In PHP it needs the filename and thus acts the same as read_MPS.
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • options is optional. If not specified, then NORMAL is used.
  • read_params
    • return = lpsolve('read_params', lp, filename {, options })
    • options is optional.
  • read_XLI
    • lp_handle = lpsolve('read_XLI', xliname, modelname {, dataname {, options {, verbose}}}
    • lp_handle is not a pointer to an lprec structure as in the API, but an incrementing handle number starting from 0.
    • dataname is optional. When not provided, '' (NULL) is taken. '' is taken as NULL.
    • options is optional. When not provided, '' is taken.
    • verbose is optional. If not specified, then NORMAL is used.
  • reset_basis
  • set_basisvar
    • lpsolve('set_basisvar', lp, basisPos, enteringCol)
    • No special considerations.
  • set_add_rowmode
    • return = lpsolve('set_add_rowmode', lp, turnon)
    • No special considerations.
  • set_anti_degen
    • lpsolve('set_anti_degen', lp, anti_degen)
    • No special considerations.
  • set_basis
    • return = lpsolve('set_basis', lp, [bascolumn], nonbasic)
    • In the API, element 0 of bascolumn is not used and values start from element 1. In PHP, there is no unused element in the matrix.
  • set_basiscrash
    • lpsolve('set_basiscrash', lp, mode)
    • No special considerations.
  • set_bb_depthlimit
    • lpsolve('set_bb_depthlimit', lp, bb_maxlevel)
    • No special considerations.
  • set_bb_floorfirst
    • lpsolve('set_bb_floorfirst', lp, bb_floorfirst)
    • No special considerations.
  • set_bb_rule
    • lpsolve('set_bb_rule', lp, bb_rule)
    • No special considerations.
  • set_BFP
    • return = lpsolve('set_BFP', lp, filename)
    • No special considerations.
  • set_binary
    • return = lpsolve('set_binary', lp, column, must_be_bin)
    • return = lpsolve('set_binary', lp, [must_be_bin])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds
    • return = lpsolve('set_bounds', lp, column, lower, upper)
    • return = lpsolve('set_bounds', lp, [lower], [upper])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_bounds_tighter
    • lpsolve('set_bounds_tighter', lp, tighten)
    • No special considerations.
  • set_break_at_first
    • lpsolve('set_break_at_first', lp, break_at_first)
    • No special considerations.
  • set_break_at_value
    • lpsolve('set_break_at_value', lp, break_at_value)
    • No special considerations.
  • set_col_name
    • return = lpsolve('set_col_name', lp, column, name)
    • return = lpsolve('set_col_name', lp, [names])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_column, set_columnex
    • return = lpsolve('set_column', lp, col_no, [column])
    • return = lpsolve('set_columnex', lp, col_no, [column])
    • Both have the same interface from set_column but act as set_columnex
  • set_constr_type
    • return = lpsolve('set_constr_type', lp, row, con_type)
    • return = lpsolve('set_constr_type', lp, [con_type])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_debug
    • lpsolve('set_debug', lp, debug)
    • No special considerations.
  • set_epsb
    • lpsolve('set_epsb', lp, epsb)
    • No special considerations.
  • set_epsd
    • lpsolve('set_epsd', lp, epsd)
    • No special considerations.
  • set_epsel
    • lpsolve('set_epsel', lp, epsel)
    • No special considerations.
  • set_epsint
    • lpsolve('set_epsint', lp, epsint)
    • No special considerations.
  • set_epslevel
    • lpsolve('set_epslevel', lp, epslevel)
    • No special considerations.
  • set_epsperturb
    • lpsolve('set_epsperturb', lp, epsperturb)
    • No special considerations.
  • set_epspivot
    • lpsolve('set_epspivot', lp, epspivot)
    • No special considerations.
  • set_free set_unbounded
    • return = lpsolve('set_free', lp, column)
    • return = lpsolve('set_unbounded', lp, column)
    • No special considerations.
  • set_improve
    • lpsolve('set_improve', lp, improve)
    • No special considerations.
  • set_infinite
    • lpsolve('set_infinite', lp, infinite)
    • No special considerations.
  • set_int
    • return = lpsolve('set_int', lp, column, must_be_int)
    • return = lpsolve('set_int', lp, [must_be_int])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lowbo
    • return = lpsolve('set_lowbo', lp, column, value)
    • return = lpsolve('set_lowbo', lp, [values])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_lp_name
    • return = lpsolve('set_lp_name', lp, name)
    • In PHP, when you name a model, this name can be used everywhere where lp is specified. This to access the model via the name instead of via a handle.
  • set_mat
    • return = lpsolve('set_mat', lp, row, column, value)
    • return = lpsolve('set_mat', lp, [matrix])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows to set the whole matrix (all rows/columns) at once. This is the most performant way to provide the constraint matrix. Consider using a PHP sparse matrix for maximum performance and least memory usage. The matrix must be two-dimensional.
  • set_maxim
    • lpsolve('set_maxim', lp)
    • No special considerations.
  • set_maxpivot
    • lpsolve('set_maxpivot', max_num_inv)
    • No special considerations.
  • set_minim
    • lpsolve('set_minim', lp)
    • No special considerations.
  • set_mip_gap
    • lpsolve('set_mip_gap', lp, absolute, mip_gap)
    • No special considerations.
  • set_negrange
    • lpsolve('set_negrange', negrange)
    • No special considerations.
  • set_obj
    • return = lpsolve('set_obj', lp, column, value)
    • return = lpsolve('set_obj', lp, [values])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables. It is then the same as set_obj_fn
  • set_obj_bound
    • lpsolve('set_obj_bound', lp, obj_bound)
    • No special considerations.
  • set_obj_fn, set_obj_fnex
    • return = lpsolve('set_obj_fn', lp, [row])
    • return = lpsolve('set_obj_fnex', lp, [row])
    • Both have the same interface from set_obj_fn but act as set_obj_fnex
    • In the API, element 0 is not used and values start from element 1. In PHP, there is no unused element in the matrix.
  • set_outputfile
    • return = lpsolve('set_outputfile', lp, filename)
    • In the API description it says that setting filename to NULL results in writing output back to stdout. In PHP under Windows, output to stdout it not shown. However it results in closing the file. Use '' to have the effect of NULL.
  • set_outputstream
    • Not implemented.
  • set_pivoting
    • lpsolve('set_pivoting', lp, pivoting)
    • No special considerations.
  • set_preferdual
    • lpsolve('set_preferdual', lp, dodual)
    • No special considerations.
  • set_presolve
    • lpsolve('set_presolve', lp, do_presolve {, maxloops})
    • The maxloops argument is optional in PHP. If not provided, then infinite is used.
  • set_print_sol
    • lpsolve('set_print_sol', lp, print_sol)
    • No special considerations.
  • set_rh
    • return = lpsolve('set_rh', lp, row, value)
    • return = lpsolve('set_rh', lp, [values])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows. Note that in this case, the value of row 0 is not specified in the matrix.
  • set_rh_range
    • return = lpsolve('set_rh_range', lp, row, deltavalue)
    • return = lpsolve('set_rh_range', lp, [deltavalues])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_rh_vec
    • lpsolve('set_rh_vec', lp, [rh])
    • In the API, element 0 is not used and values start from element 1. In PHP, there is no unused element in the matrix.
  • set_row, set_rowex
    • return = lpsolve('set_row', lp, row_no, [row])
    • return = lpsolve('set_rowex', lp, row_no, [row])
    • Both have the same interface from set_row but act as set_rowex
    • In the API, element 0 is not used and values start from element 1. In PHP, there is no unused element in the matrix.
  • set_row_name
    • return = lpsolve('set_row_name', lp, row, name)
    • return = lpsolve('set_row_name', lp, [names])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all rows.
  • set_scalelimit
    • lpsolve('set_scalelimit', lp, scalelimit)
    • No special considerations.
  • set_scaling
    • lpsolve('set_scaling', lp, scalemode)
    • No special considerations.
  • set_semicont
    • return = lpsolve('set_semicont', lp, column, must_be_sc)
    • return = lpsolve('set_semicont', lp, [must_be_sc])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_sense
    • lpsolve('set_sense', lp, maximize)
    • No special considerations.
  • set_simplextype
    • lpsolve('set_simplextype', lp, simplextype)
    • No special considerations.
  • set_solutionlimit
    • lpsolve('set_solutionlimit', lp, simplextype)
    • No special considerations.
  • set_timeout
    • lpsolve('set_timeout', lp, sectimeout)
    • No special considerations.
  • set_trace
    • lpsolve('set_trace', lp, trace)
    • No special considerations.
  • set_upbo
    • return = lpsolve('set_upbo', lp, column, value)
    • return = lpsolve('set_upbo', lp, [values])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_use_names
    • lpsolve('set_use_names', lp, isrow, use_names)
    • No special considerations.
  • set_var_branch
    • return = lpsolve('set_var_branch', lp, column, branch_mode)
    • return = lpsolve('set_var_branch', lp, [branch_mode])
    • In PHP, this routine has two formats. The first format is identical to the API. The second format allows setting a matrix of all variables.
  • set_var_weights
    • return = lpsolve('set_var_weights', lp, [weights])
    • No special considerations.
  • set_verbose
    • lpsolve('set_verbose', lp, verbose)
    • No special considerations.
  • set_XLI
    • return = lpsolve('set_XLI', lp, filename)
    • No special considerations.
  • solve
    • result = lpsolve('solve', lp)
    • No special considerations.
  • str_add_column
    • Not implemented.
  • str_add_constraint
    • Not implemented.
  • str_set_obj_fn
    • Not implemented.
  • str_set_rh_vec
    • Not implemented.
  • time_elapsed
    • return = lpsolve('time_elapsed', lp)
    • No special considerations.
  • unscale
    • lpsolve('unscale', lp)
    • No special considerations.
  • write_basis
    • lpsolve('write_basis', lp, filename)
    • No special considerations.
  • write_freemps, write_freeMPS
    • return = lpsolve('write_freemps', lp, filename)
    • return = lpsolve('write_freeMPS', lp, filename)
    • In the lpsolve API, write_freeMPS needs a FILE handle. In PHP it needs the filename and thus acts the same as write_freemps.
  • write_lp, write_LP
    • return = lpsolve('write_lp', lp, filename)
    • return = lpsolve('write_LP', lp, filename)
    • In the lpsolve API, write_LP needs a FILE handle. In PHP it needs the filename and thus acts the same as write_lp.
  • write_mps, write_MPS
    • return = lpsolve('write_mps', lp, filename)
    • return = lpsolve('write_MPS', lp, filename)
    • In the lpsolve API, write_MPS needs a FILE handle. In PHP it needs the filename and thus acts the same as write_mps.
    • No special considerations.
  • write_XLI
    • return = lpsolve('write_XLI', lp, filename {, options {, results}})
    • No special considerations.

Extra PHP routines

These routines are not part of the lpsolve API, but are added for backwards compatibility. Most of them exist in the lpsolve API with another name.

  • [names] = lpsolve('get_col_names', lp)
    • The same as get_col_name. Implemented for backwards compatibility.
  • [constr_type] = lpsolve('get_constr_types', lp)
    • The same as get_constr_type. Implemented for backwards compatibility.
  • [int] = lpsolve('get_int', lp)
    • The same as is_int. Implemented for backwards compatibility.
  • return = lpsolve('get_no_cols', lp)
    • The same as get_Ncolumns. Implemented for backwards compatibility.
  • return = lpsolve('get_no_rows', lp)
    • The same as get_Nrows. Implemented for backwards compatibility.
  • name = lpsolve('get_objective_name', lp)
    • The same as get_row_name with row=0. Implemented for backwards compatibility.
  • [row_vec, return] = lpsolve('get_obj_fn', lp)
    [row_vec, return] = lpsolve('get_obj_fun', lp)
    • The same as get_row with row 0. Implemented for backwards compatibility.
  • name = lpsolve('get_problem_name', lp)
    • The same as get_lp_name. Implemented for backwards compatibility.
  • [costs] = lpsolve('get_reduced_costs', lp)
    • The same as get_dual_solution. Implemented for backwards compatibility.
  • [names] = lpsolve('get_row_names', lp)
    • The same as get_row_name. Implemented for backwards compatibility.
  • [obj, x, duals, return] = lpsolve('get_solution', lp)
    • Returns the value of the objective function, the values of the variables and the duals. Implemented for backwards compatibility.
    • The return code of the call is the last value.
  • value = lpsolve('mat_elm', lp)
    • The same as get_mat. Implemented for backwards compatibility.
  • [handle_vec] = lpsolve('print_handle')
    • Returns a vector with open handles. Can be handy to see which handles aren't closed yet with delete_lp or free_lp.
  • lp_handle = lpsolve('read_lp_file', filename {, verbose {, lp_name}})
    • The same as read_LP. Implemented for backwards compatibility.
  • lp_handle = lpsolve('get_handle', lp_name)
    • Get the handle for this model from the models name. If an unknown model name is given (or already deleted), -1 is returned.
  • return_constants = lpsolve('return_constants'[, return_constants])
    • Returns the setting of return_constants and optionally sets its value.

Compile the lpsolve driver

The lpsolve PHP driver is called php_phplpsolve55.dll (windows) and phplpsolve55.so (Unix/Linux).
This driver is an interface to the lpsolve55.dll (windows) and liblpsolve55.so (Unix/Linux) lpsolve shared library that contains the implementation of lp_solve. lpsolve55.dll/liblpsolve55.so is distributed with the lp_solve package (archive lp_solve_5.5.0.15_dev.zip/lp_solve_5.5.0.15_dev.tar.gz). The lpsolve PHP driver is just a wrapper between PHP and lp_solve to translate the input/output to/from PHP and the lp_solve library.

The lpsolve PHP driver is written in C. To compile this code a C compiler is needed. Under Unix, this is the standard C compiler (c/gcc) and under windows it is the Microsoft compiler from Visual Studio .NET.

Windows:

First of all, the PHP sources are needed. These must be obtained from http://www.php.net
Extract the sources to a folder. In this example this is f:\php-5.2.6
Secondly, win32build.zip is needed. Note that is looks like this is only the case if method 1) is used. Method 2) works without this folder. This archive should be on that site also, but apparently it is deleted from there. It was however found on following location: http://viewcvs.php.net/viewvc.cgi/phpweb/extra/?hideattic=0
Extract the sources to \win32build. In this example this is f:\win32build

Then there are two ways to compile php_phplpsolve.dll:

1) This is somewhat the standard way, but not the easiest.
First of all, lpsolve must be under the php\ext folder. For example \php-5.2.6\ext\lpsolve
Secondly, a file config.w32 is needed. It is provided with the lpsolve PHP distribution.
To build, execute the following commands in a DOS prompt where the vcvars32.bat file of the Microsoft Visual C compiler:

F:\php-5.2.6>buildconf.bat
F:\php-5.2.6>cscript /nologo configure.js --without-xml --without-wddx --without-simplexml --without-dom --without-libxml --disable-zlib --without-sqlite --disable-odbc --disable-cgi --enable-cli --without-iconv --enable-phplpsolve55=shared --with-phplpsolve55path="z:\lp_solve_5.5"
F:\php-5.2.6>nmake php_phplpsolve55.dll

Each of these commands give some messages. Also note that in the cscript command, the path to lp_solve_5.5 must be provided. In this example this is z:\lp_solve_5.5

If all is successful, php_phplpsolve.dll is made in \php-5.2.6\Release_TS

2) An easier way is using the batch files cvc6.bat or cvc8NOmsvcrt80.bat
cvc6.bat can be used for Microsoft Visual compiler version 6 and cvc8NOmsvcrt80.bat for Microsoft Visual compilers from .NET.
In this case, the lpsolve PHP files do not have to be located under \php-5.2.6\ext. Instead they can be under \lp_solve_5.5\extra\PHP\lpsolve as in the distribution.
First edit cvc6.bat or cvc8NOmsvcrt80.bat
Two commands here must be revised:

set lp_solve=..\..
set php=F:\php-5.2.6

Normally the first one will be ok. The second one must be changed to the path where the PHP sources are located. Here F:\php-5.2.6

To build, execute the following commands in a DOS prompt where the vcvars32.bat file of the Microsoft Visual C compiler:

Z:\lp_solve_5.5\extra\PHP>cvc6.bat
or
Z:\lp_solve_5.5\extra\PHP>cvc8NOmsvcrt80.bat

Unix/Linux:

Go to the lpsolve PHP directory and enter the following commands:

$ phpize
$ ./configure --enable-maintainer-zts --with-phplpsolve55=../..
$ make

Note the ../.. path in the second command. That is the location to lp_solve_5.5 and that is normally 2 directories down.

After this is done, phplpsolve55.so is build in directory modules.

For both windows and unix/linux, don't forget to adapt php.ini as described above and possibly restart the webserver.

See also Using lpsolve from MATLAB, Using lpsolve from O-Matrix, Using lpsolve from Sysquake, Using lpsolve from Scilab, Using lpsolve from Octave, Using lpsolve from FreeMat, Using lpsolve from Euler, Using lpsolve from Python Using lpsolve from Sage, Using lpsolve from R

doc/column_in_lp.htm0000644000175000017500000000554110351321114013453 0ustar renerene column_in_lp

column_in_lp

Check if a column is already present in the lp.

int column_in_lp(lprec *lp, REAL *column);

Return Value

column_in_lp returns the (first) column number if the column is already in the lp and 0 if not.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

An array with 1+get_Nrows elements that are checked against the existing columns in the lp.

Remarks

The column_in_lp functions checks if a column is already present in the lp.
It does not look at bounds and types, only at matrix values.
The first matched column is returned. If there is no column match, then 0 is returned.
Note that element 0 is the objective function value. Element 1 is column 1, and so on.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL column[1+2]; /* must be 1 more then number of rows ! */
  int ret;

  /* Create a new LP model */
  lp = make_lp(2, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  column[0] = 0.0;
  column[1] = 0.0;
  column[2] = 0.0;
  ret = column_in_lp(lp, column); /* Will return 1 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, add_column, add_columnex, str_add_column, set_column, set_columnex, del_column

doc/free_lp.htm0000644000175000017500000000352410074574154012430 0ustar renerene free_lp

free_lp

Deletes an lprec structure and initialise the plp variable.

void free_lp(lprec **plp);

Return Value

None

Parameters

plp

lprec structure to delete. After the call, *plp will be set to NULL.

Remarks

The free_lp function frees all memory allocated to the lp structure and initialises the *plp variable.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  /* Model created */

  /*
  .
  .
  .
  */

  free_lp(&lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

doc/get_presolve.htm0000644000175000017500000001566410310665546013521 0ustar renerene get_presolve

get_presolve

Returns if a presolve must be done before solving.

int get_presolve(lprec *lp);

Return Value

get_presolve returns the current presolve setting. Can by the combination (OR) of any of the following values:

PRESOLVE_NONE (0) No presolve at all
PRESOLVE_ROWS (1) Presolve rows
PRESOLVE_COLS (2) Presolve columns
PRESOLVE_LINDEP (4) Eliminate linearly dependent rows
PRESOLVE_SOS (32) Convert constraints to SOSes (only SOS1 handled)
PRESOLVE_REDUCEMIP (64) If the phase 1 solution process finds that a constraint is redundant then this constraint is deleted
PRESOLVE_KNAPSACK (128) Simplification of knapsack-type constraints through addition of an extra variable, which also helps bound the OF
PRESOLVE_ELIMEQ2 (256) Direct substitution of one variable in 2-element equality constraints; this requires changes to the constraint matrix
PRESOLVE_IMPLIEDFREE (512) Identify implied free variables (releasing their explicit bounds)
PRESOLVE_REDUCEGCD (1024) Reduce (tighten) coefficients in integer models based on GCD argument
PRESOLVE_PROBEFIX (2048) Attempt to fix binary variables at one of their bounds
PRESOLVE_PROBEREDUCE (4096) Attempt to reduce coefficients in binary models
PRESOLVE_ROWDOMINATE (8192) Idenfify and delete qualifying constraints that are dominated by others, also fixes variables at a bound
PRESOLVE_COLDOMINATE (16384) Deletes variables (mainly binary), that are dominated by others (only one can be non-zero)
PRESOLVE_MERGEROWS (32768) Merges neighboring >= or <= constraints when the vectors are otherwise relatively identical into a single ranged constraint
PRESOLVE_IMPLIEDSLK (65536) Converts qualifying equalities to inequalities by converting a column singleton variable to slack. The routine also detects implicit duplicate slacks from inequality constraints, fixes and removes the redundant variable.This latter removal also tends to reduce the risk of degeneracy.The combined function of this option can have a dramatic simplifying effect on some models
PRESOLVE_COLFIXDUAL (131072) Variable fixing and removal based on considering signs of the associated dual constraint
PRESOLVE_BOUNDS (262144) Does bound tightening based on full-row constraint information. This can assist in tightening the OF bound, eliminate variables and constraints. At the end of presolve, it is checked if any variables can be deemed free, thereby reducing any chance that degeneracy is introduced via this presolve option.
PRESOLVE_DUALS (524288) Calculate duals
PRESOLVE_SENSDUALS (1048576) Calculate sensitivity if there are integer variables

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_presolve function returns if a presolve must be done before solving. Presolve looks at the model and tries to simplify it so that solving times are shorter. For example a constraint on only one variable is converted to a bound on this variable (and the constraint is deleted). Note that the model dimensions can change because of this, so be careful with this. Both rows and columns can be deleted by the presolve.
The default is not (PRESOLVE_NONE) doing a presolve.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int presolve;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  presolve = get_presolve(lp); /* returns the current presolve level */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_presolveloops, set_presolve, is_presolve

doc/get_column.htm0000644000175000017500000001122010553536550013140 0ustar renerene get_column

get_column, get_columnex

Get all (get_column) or only the non-zero (get_columnex) column elements from the matrix.

unsigned char get_column(lprec *lp, int col_nr, REAL *column);
int get_columnex(lprec *lp, int col_nr, REAL *column, int *nzrow);

Return Value

get_column returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
get_columnex returns the number of non-zero elements returned in column and nzrow. If an error occurs, then -1 is returned.
An error occurs when col_nr is not between 1 and the number of columns in the lp.
Note that row entry mode must be off, else these functions also fail. See set_add_rowmode

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

col_nr

Column number of the matrix. Must be between 1 and number of columns in the lp.

column

Array in which the values are returned. For get_column, the array must be dimensioned with at least 1get_Nrows elements in the lp. For get_columnex, the array must be dimentioned with at least the number of non-zero elements in the column. If that is unknown, then use 1+get_Nrows in the lp. The return value of the function indicates how many non-zero elements there are.

nzrow

Array in which the row numbers are returned. The array must be dimentioned with at least the number of non-zero elements in the column. If that is unknown, then use 1+get_Nrows in the lp. The return value of the function indicates how many non-zero elements there are.

Remarks

get_column retrieves all values for the given column.
Element 0 of the column array will contain the value of the objective function, element 1 will contain the value for column 1, Element 2 the value for column 2, ...
get_columnex retrieves only the non-zero values for a given column.
Returned values in column and nzrow start from element 0.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL column[1+2]; /* must be 1 greater than number of rows ! */

  /* Create a new LP model */
  lp = make_lp(2, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  get_column(lp, 1, column);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_mat, get_row, get_rowex, set_row, set_rowex, set_rh, set_rh_vec, str_set_rh_vec, add_constraint, add_constraintex, str_add_constraint, add_column, add_columnex, str_add_column, set_column, set_columnex

doc/ratio.htm0000644000175000017500000003642310505340366012131 0ustar renerene Ratio's

Ratios

Constraints

Linear constraints are of the form:

a1 x1 + a2 x2 + a3 x3 + ... >= minimum

a1 x1 + a2 x2 + a3 x3 + ... <= maximum

Where minimum and maximum are constants.

lp_solve can only handle these kind of Linear equations. However sometimes there are tricks to convert an equation that seems non-Linear at first sight to a Linear equation. One of these is ratio's:

a11 x1 + a12 x2 + a13 x3 + ... <= minimum
a21 x1 + a22 x2 + a23 x3 + ...

On condition that a21 x1 + a22 x2 + a23 x3 + ... is positive, this is equal to:

a11 x1 + a12 x2 + a13 x3 + ... <= minimum * (a21 x1 + a22 x2 + a23 x3 + ...)

If the denominator is always negative, then it can be converted to:

a11 x1 + a12 x2 + a13 x3 + ... >= minimum * (a21 x1 + a22 x2 + a23 x3 + ...)

Let's continue with the case that the denominator is positive, then the equation is also equal to:

a11 x1 + a12 x2 + a13 x3 + ... - minimum * (a21 x1 + a22 x2 + a23 x3 + ...) <= 0

Or

(a11 - minimum * a21) x1 + (a12 - minimum * a22) x2 + (a13 - minimum * a23) x3 + ... <= 0

And there we have again a Linear equation. The same can be done for a maximum or equality of course. Don't forget that there is one assumption: the denominator is positive or negative. If it can be both, then this trick cannot be used.

One example of this is for example that it is required that two variables must have a ration of 1/2. For example:

x1 = 1/2
x2

With the formula above, this gives:

x1 - 0.5 x2 = 0

Adding this equation will result in the fact that x2 will be two times larger than x1. Again in the assumption that x2 stays positive.

Oh, and what if the denominator is zero? Division by zero is undefined and cannot give a real value. In the above example with two variables, if x2 is zero, then x1 is also forced to be zero. That is the side effect by converting the non-Linear equation to a Linear equation.

Objective function

max   c0 + c1 x1 + c2 x2 + c3 x3 + ...
      d0 + d1 x1 + d2 x2 + d3 x3 + ...

s.t.  ai1 x1 + ai2 x2 + ai3 x3 + ... <= bi
      xj >= 0

Note that c0 and d0 are constants. They are optional and not required for this solution.
Also note that the explanation uses <= constraints, but they can as well be >= constraints without any modification.
And as a last note, this text uses maximization of the objective function, but minimization works as good without any modification.

Linear programming only accepts models with equations in the first degree. The objective function however has a numerator and denominator so this seems not possible to solve with pure linear programming. However there is a trick to overcome to this problem. This model can be transformed to another model that is pure linear. When the solution is found to this transformed model, the results can be recalculated back to the original model.

There is only one condition to make this possible: the denominator must be strictly positive (or negative, but in that case you can multiply numerator and denominator by -1 such that the denominator becomes positive).

      d0 + d1 x1 + d2 x2 + d3 x3 + ... > 0

Again note the > sign. The denominator may also not become zero. If the transformed model returns a solution saying that it is zero, then the solution is invalid.

Now with this assumption in mind, we can introduce a new variable y0:

      y0 =                   1               
            d0 + d1 x1 + d2 x2 + d3 x3 + ...

Then the model can also be written as:

max   c0 y0 + c1 x1 y0 + c2 x2 y0 + c3 x3 y0 + ...

s.t.  ai1 x1 + ai2 x2 + ai3 x3 + ... <= bi
      y0 =                   1               
            d0 + d1 x1 + d2 x2 + d3 x3 + ...
      y0, xj >= 0

The constraints can also be multiplied by y0 and the y0 constraint can be written differently:

max   c0 y0 + c1 x1 y0 + c2 x2 y0 + c3 x3 y0 + ...

s.t.  ai1 x1 y0 + ai2 x2 y0 + ai3 x3 y0 + ... <= bi y0
      d0 y0 + d1 x1 y0 + d2 x2 y0 + d3 x3 y0 + ... = 1
      y0, xj y0 >= 0

Note again that this can only be done if y0 > 0

Now also make following substitution:

      yj = xj y0

Also put the bi y0 term to the left:

max   c0 y0 + c1 y1 + c2 y2 + c3 y3 + ...

s.t.  -bi y0 + ai1 y1 + ai2 y1 + ai3 y3 + ... <= 0
      d0 y0 + d1 y1 + d2 y2 + d3 y3 + ... = 1
      yj >= 0

All yj are variables (j starting from 0)

This new transformed model is an exact transformation of the original model, but with the advantage that it is a pure linear model. Also note that this model has one extra variable (y0) with coefficients in the matrix which are the negative of the right hand side (-bi y0). A constraint is also added requiring the constant term in the denominator times the new variable (d0 y0) plus the denominator terms involving the transformed variables to equal 1. The transformed model uses the same aij's as the original. Its right hand sides are all 0's except the one in the new constraint. The objective function does not have a denominator term and the objective function altered to include the numerator constant times the new variable y0.
This model can now be solved with lp_solve. Then to get the solution of the original model we must do a reverse transformation of this solution. This can be easily done:

      yj = xj y0
      
So:

      xj = yj / y0
Example

Suppose that it is desirable to solve the following problem.

max         1.8 x1 + 1.7 x2  
       10 + 4.0 x1 + 4.1 x2

s.t.  1.5 x1 +   x2 <= 6
      3.0 x1 + 4 x2 <= 20
      x1, x2 >= 0

Then the transformed problem is:

max            1.8 y1 + 1.7 y2

s.t.   -6 y0 + 1.5 y1 +     y2 <= 0
      -20 y0 + 3.0 y1 +   4 y2 <= 0
       10 y0 + 4.0 y1 + 4.1 y2 = 1
          y0, y1, y2 >= 0

The solution of this transformed model is:

Value of objective function: 0.289916

Actual values of the variables:
y1                      0.0420168
y2                        0.12605
y0                      0.0315126

Dual values with from - till limits:
                           Dual value            From            Till
R1                           0.342437     -0.03278689       0.1090909
R2                         0.04222689      -0.3076923       0.1156069
R3                           0.289916               0          1e+030
y1                                  0         -1e+030          1e+030
y2                                  0         -1e+030          1e+030
y0                                  0         -1e+030          1e+030

The value of the objective function of this transformed model is also the value of the objective function of the original model. The values of the original xi variables are calculated by dividing the yi values by y0:

x1 = y1 / y0 = 0.0420168 / 0.0315126 = 1.33333333
x2 = y2 / y0 = 0.12605 / 0.0315126 = 4

Plugging back into the original problem, the numerator equals 9.2; the denominator, 31.73, and their fraction 0.289916 (the objective function value reported). One may also recover the dual values or reduced costs. In this case since the rows are multiplied by one over the denominator, the original values may be recovered by dividing through by the denominator (1 / y0 or multiplying them by y0). Thus the effective dual value for constraint 1 is 0.01079, and constraint 2 is 0.0013307. Constraint 3 has no analogue in the original problem, and thus, is not transformed. The From - Till limits can also be recalculated back by dividing them by y0 and correcting these values with the bi y0 term.

Comments

This is an exact transformation as long as the denominator remains strictly positive. The formulation fails if y0 equals zero in the optimal solution. Much research has been done on fractional programming. The original development appears in Charnes and Cooper (1962). A historical perspective and literature review can be found in Schaible and Ibaraki.

Integer variables
Extra complexity arises if there are integer variables in the original model. Ie, one or more of the xi variables must be integer. Remember that:
yj = xj y0
and
y0 = 1 / denominator
Because of the latter, y0 is a real number. So yj is real, even if xj is integer. None of the xj variables are in the transformed model and from above you can see that you can't make the yj variables integer to have xj integer. So is it then not possible to define something that xj become integer?
Remember that
xj = yj / y0
Suppose that xj must take an integer value i:
yj / y0 = i
or
yj = i * y0
Unfortunately, this constraint can't be handled by lpsolve since it is quadratic.
However a special case of integer variables can be solved:
Binary variables
Binary variables are a special kind of integer variables. They can only take 0 or 1 values. From the previous section we know that
yj = i * y0
In this case is i either zero or one. If zero, then yj must be zero. If one, then yj = y0. If we can put this into the formulation, then the xj variables will be binary.

To make this possible, you must introduce extra binary variables: zj

When zj = 0, then it must make yj = 0 and when zj = 1, then it must make yj = y0

One way to make this possible is by doing the following.
First you must determine a constant value f1 for which you know that f1 > yj in all cases and f2 for which you know that f2 > y0 in all cases.

Then you can write:
yj <= f1 zj
yj - y0 - f2 zj >= -f2
yj - y0 + f2 zj <= f2
Two cases have to be considered:

1) zj = 0
yj <= 0
yj - y0 >= -f2
yj - y0 <= f2
or
yj = 0
-y0 >= -f2
-y0 <= f2
or
yj = 0
y0 <= f2
y0 >= -f2
since you have chosen the constant f2 such that it is always larger than y0, equations 2 and 3 are redundant in this case and yj is indeed 0. And from above, this means that xj will be 0.

2) zj = 1
yj <= f1
yj - y0 - f2 >= -f2
yj - y0 + f2 <= f2
or
yj <= f1
yj - y0 >= 0
yj - y0 <= 0
since you have chosen the constant f1 such that it is always larger than yj, equation 1 is redundant. Equations 2 and 3 together make that yj equals y0. And from above, this means that xj will be 1.

Of course your model becomes alot more complex. Per xj integer variable, you must introduce an extra binary variable zj and add 3 constraints for each. And you must have a guess for f1 and f2. Don't take a very very large number like 1e10 or something like this because that would make the model very unstable because of scaling/rouding errors. You must deduce from your model what these two factors can be. Maybe by first solving the model without integer constraints and determine f1 and f2 from this real result.

Using the example from above, now requiring that both x1 and x2 are integer. The result of the real model is:
Value of objective function: 0.289916

Actual values of the variables:
y1                      0.0420168
y2                        0.12605
y0                      0.0315126
From this, choose f1 and f2 being 10.

Now add the following constraints to this model:
y1 <= 10 z1
y1 - y0 - 10 z1 >= -10
y1 - y0 + 10 z1 <= 10

y2 <= 10 z2
y2 - y0 - 10 z2 >= -10
y2 - y0 + 10 z2 <= 10

int z1, z2
The solution of this model is:
Value of objective function: 0.19337

Actual values of the variables:
y1                      0.0552486
y2                      0.0552486
y0                      0.0552486
z1                              1
z2                              1

x1 = y1 / y0 = 1
x2 = y2 / y0 = 1
Indeed binary values.
doc/get_bounds_tighter.htm0000644000175000017500000000601111127442403014654 0ustar renerene get_bounds_tighter

get_bounds_tighter

Returns if set bounds may only be tighter or also less restrictive.

unsigned char get_bounds_tighter(lprec *lp);

Return Value

get_bounds_tighter returns if bounds may only be tighter or also less restrictive.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_bounds_tighter function returns if bounds may only be tighter or also less restrictive. If set to TRUE then bounds may only be tighter. This means that when set_lowbo or set_lowbo is used to set a bound and the bound is less restrictive than an already set bound, then this new bound will be ignored. If FALSE, the new bound is accepted. This functionality is useful when several bounds are set on a variable and at the end you want the most restrictive ones. By default, this setting is FALSE. Note that this setting does not affect set_bounds.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int tighter;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  tighter = get_bounds_tighter(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_bounds_tighter, set_upbo, get_upbo, set_lowbo, get_lowbo, set_bounds, set_unbounded, is_unbounded, is_negative

doc/get_col_name.htm0000644000175000017500000000703510466457242013434 0ustar renerene get_col_name, get_origcol_name

get_col_name, get_origcol_name

Gets the name of a column in the lp.

char *get_col_name(lprec *lp, int column);

char *get_origcol_name(lprec *lp, int column);

Return Value

get_col_name and get_origcol_name return the name of the specified column. A return value of NULL indicates an error. The difference between get_col_name and get_origcol_name is only visible when a presolve (set_presolve) was done. Presolve can result in deletion of columns in the model. In get_col_name, column specifies the column number after presolve was done. In get_origcol_name, column specifies the column number before presolve was done, ie the original column number. If presolve is not active then both functions are equal.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column for which the name must be retrieved. Must be between 1 and the number of columns in the lp. In get_col_name, column specifies the column number after presolve was done. In get_origcol_name, column specifies the column number before presolve was done, ie the original column number.

Remarks

The get_col_name and get_origcol_name functions return the name of the column.
Column names are optional. If no column name was specified, the function returns Cx with x the column number.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  char *name;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  name = get_col_name(lp, 1); /* will be C1 since no column name was set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_col_name, set_row_name, get_row_name, get_origrow_name, get_nameindex

doc/scaling.htm0000644000175000017500000001253410206103360012415 0ustar renerene Scaling

Scaling

Scaling is a very important issue to consider in mathematical computations on a computer. A computer stores floating-point numbers with a limited precision because it uses a fixed number of bytes to store them. Consider for example the result of the following calculation: 1/3 In our metric system, the result of this computation cannot be represented with a finite number of digits. The value is 0.3333333333333... with an infinite number of digits. Because a computer only has a certain precision, the result is stored with a finite number of digits. For regular floating-point numbers this is about 15 digits, independent of its size. So this result would for example be stored as 0.333333333333333 on a computer. The computation of 100000000000000000/3 would be stored as 33333333333333300. In several cases, this is no problem. The stored value is close enough to the value that is needed. However, when doing calculations, problems can arise because of this. Especially if small and large values are added or subtracted from each other. In that case, the precision of the small number is lost. This can result in the effect that calculated values aren't correct anymore.

The more floating-point calculations are done, the more chance there is that numerical instability occurs and doing calculations with big and small numbers results in faster occurrence of this effect. Then there is also the effect of accumulating rounding errors which can result in a totally screwed up data matrix after having done several calculations.

The simplex algorithm is a typical iterating process where factors of thousands of floating calculations are done to find the optimal solution. The chance of numerical instability is then also quite big. But scaling not only improves numerical stability and minimizes rounding errors, it also improves performance. This may seem strange, but it is true. When a model is not scaled, the algorithm could reject certain pivot elements because they are too small and because of this, the solver doesn't choose the shortest route to the solution. If a model is proper scaled, this effect will not occur.

There are several ways to cope with this and it starts with the input data. The chance for numerical instability and rounding errors is considerably larger when the input data contains both large and small numbers. So to improve stability, one must try to work with numbers that are somewhat in the same range. Ideally in the neighbourhood of 1.

You should realize, that you the user are probably in a better position to scale the problem than any computer algorithm. The way to do this is: first choose appropriately scaled units for the extensive variables of the problem, e.g., kilo-tons instead of pounds, tankcar loads instead of gallons, millions of dollars instead of pennies, or nanometers instead of feet, so that the numerical spread of the coefficients in each single constraint, and in the objective function, will be at most one or two orders of magnitude; and then second scale the constraints themselves, by multiplying each entire constraint relation by an appropriate positive constant, so that the numerical spread of the coefficients in the different constraints is at most another one or two orders of magnitude. For example saying:

10000 x1 + 20000 x2 <= 30000

Can also be expressed as:

1 x1 + 2 x2 <= 3

lp_solve also has some build-in scaling routines which can take over this scaling job from the modeller or maybe better, to do additional scaling. This is implemented in such a way that it is transparent to the user. When scaling is done, lp_solve scales rows and/or columns, but the user doesn't see anything of this process. The returned values are still as if no scaling was done. See set_scaling for the possible scaling types. Note that lp_solve, by default doesn't do scaling. It must be invoked explicitly. Also note that even when scaling is enabled that integer variables are then again by default not scaled. To scale also integer variables, SCALE_INTEGERS must be added to the scale mode. This is done because of the nature of integer variables. If you want them integer, but you also scale them, then they aren't integer anymore. It is possible to scale those variables with the SCALE_INTEGERS flag, but some accuracy on being integer can be lost.

Conslusion. You should always do some sort of scaling. It starts when you design the model. Extra scaling can be accomplished by one of the scaling options of lp_solve.

doc/Infeasible.htm0000644000175000017500000001276210471726230013054 0ustar renerene Infeasible models

Infeasible models

A linear program is infeasible if there exists no solution that satisfies all of the constraints -- in other words, if no feasible solution can be constructed. Since any real operation that you are modelling must remain within the constraints of reality, infeasibility most often indicates an error of some kind. Simplex-based LP software like lp_solve efficiently detects when no feasible solution is possible.

The source of infeasibility is often difficult to track down. It may stem from an error in specifying some of the constraints in your model, or from some wrong numbers in your data. It can be the result of a combination of factors, such as the demands at some customers being too high relative to the supplies at some warehouses.

Upon detecting infeasibility, LP codes typically show you the most recent infeasible solution that they have encountered. Sometimes this solution provides a good clue as to the source of infeasibility. If it fails to satisfy certain capacity constraints, for example, then you would do well to check whether the capacity is sufficient to meet the demand; perhaps a demand number has been mistyped, or an incorrect expression for the capacity has been used in the capacity constraint, or the model simply lacks any provision for coping with increasing demands. More often, unfortunately, LP codes respond to an infeasible problem by returning a meaninglessly infeasible solution, such as one that violates material balances. lp_solve is behaving also as such.

lp_solve currently doesn't provide analysis routines to detect infeasible constraints however that doesn't mean that it stops there.

A useful approach is to forestall meaningless infeasibilities by explicitly modelling those sources of infeasibility that you view as realistic. As a simple example, you could add a new "slack" variable on each capacity constraint, having a very high penalty cost. Then infeasibilities in your capacities would be signalled by positive values for these slacks at the optimal solution, rather than by a mysterious lack of feasibility in the linear program as a whole. Modelling approaches that use this technique are called sometimes "elastic programming" or "elastic filter".

So in practice, if a constraint is a < constraint, add a variable to the model and give it for that constraint a -1 coefficient for that variable. In the objective you give it a relative large cost. If a constraint is a > constraint, add a variable to the model and give it for that constraint a +1 coefficient for that variable. In the objective you give it a relative large cost. If a constraint is an equal constraint, add two variables to the model and give it for that constraint respectively a -1 and +1 coefficient for that variable. In the objective you give them a relative large cost. Or you only add one variable and give it an -infinite lower bound.

This will result in an automatic relaxation of the constraint(s) when needed (if that constraint would make the model infeasible). To make sure that these added variables only get non-zero values when the constraint is violating, the value in the objective must be relative large. Like that this variable gets a penalty cost and it will only become non-zero when really needed. Note that the signs of these objective coefficients must be positive when minimizing and negative when maximizing. Don't make these costs too big also because that introduces instabilities. If none of these added variables have a non-zero value then the model was initially feasible. When at least one is non-zero then the original model is infeasible. Note that the objective value will then not be very useful. However you could subtract the cost * value of all these variables from the objective to obtain the objective value of the relaxed model.

Note that a model can also become infeasible because of bounds set on variables. Above approach doesn't relax these.

Example:

min: x + y;
c1: x >= 6;
c2: y >= 6;
c3: x + y <= 11;

This model is clearly infeasible. Now introduce extra variables to locate the infeasibility:

min: x + y + 1000 e1 + 1000 e2 + 1000 e3;
c1: x + e1 >= 6;
c2: y + e2 >= 6;
c3: x + y - e3 <= 11;

The result of this model is:

Value of objective function: 1011

Actual values of the variables:
x                               5
y                               6
e1                              1
e2                              0
e3                              0

With this simple example model, multiple solutions were possible. Here, the first constraint was relaxed since e1 is non-zero. Only this one constraint had to be relaxed to make the model feasible. The objective value of 1011 isn't saying very much. However if we subtract 1000 e1 + 1000 e2 + 1000 e3 from it, then it becomes 11 which is the value of the original objective function (x + y).

doc/DIMACS_asn.htm0000644000175000017500000003460210427460532012612 0ustar renerene DIMACS assignment problems

DIMACS assignment problems

DIMACS (Center for Discrete Mathematics and Theoretical Computer Science (see http://dimacs.rutgers.edu/)) has formulated some 'challenges' for some specific problem instances (see http://dimacs.rutgers.edu/Challenges/). One of these challenges is network flows and matching - the first DIMACS implementation challenge.

One of these network flows are assignment problems:

There are a number of agents and a number of tasks. Any agent can be assigned to perform any task, incurring some cost that may vary depending on the agent-task assignment. It is required to perform all tasks by assigning exactly one agent to each task in such a way that the total cost of the assignment is minimized.

Network Structure

  • A network is a directed graph with n nodes and m arcs.
  • Nodes are identified by integers 1...n.
  • Graphs do not have to be symmetric: if an arc (v,w) is in the graph, the reverse arc (w,v) does not have to be in the graph.
  • Parallel arcs are not allowed.
  • Self-loops are not allowed.
  • Arc capacities are 32-bit signed integers.
  • The source and the sink are distinct.
  • The sink may be unreachable from the source.

There is a specific file format available for these kinds of problems:

The following information makes up a DIMACS assignment problem input file:

  • comment lines
  • problem line
  • node descriptors
  • arc descriptors

As noted above, information is collected into lines, which begin with one-character designators. We describe each type of information line in turn.

  1. Comment Lines: Comment lines give human-readable information about the file and are ignored by programs. Comment lines can appear anywhere in the file. Each comment line begins with a lower-case character c.
        c This is an example of a comment line.
  2. Problem Line: There is one problem line per input file. The problem line must appear before any node or arc descriptor lines. For assignment problem instances the problem line has the following format:
        p asn NODES ARCS

    The lower-case character p signifies that this is a problem line. The three-character problem designator asn identifies the file as containing specification information for an assignment problem. The NODES field contains an integer value specifying n, the number of nodes in the network. The ASCS field contains an integer value specifying m, the number of arcs in the network.

  3. Node Descriptors: All node descriptor lines must appear before all arc descriptor lines. For assignment problem instances, the node descriptor lines describe supply nodes. That is, only nodes with nonzero node supply values appear. There is one node descriptor line for each such node, with the following format.
        n ID

    The lower-case character n signifies that this is a node descriptor line. The ID field gives a node identification number, an integer between 1 and n.

  4. Arc Descriptors: There is one arc descriptor line for each arc in the network. For an assignment problem instance, arc descriptor lines are of the following form.
        a SRC DST COST

    The lower-case character a signifies that this is an arc descriptor line. For a directed arc (v,w) the SRC field gives the identification number for the source vertex v, and the DST field gives the destination vertex w. Identification numbers are integers between 1 and n. The COST field contains the per-unit cost of flow sent along arc (v,w).

Input File Example :

Consider the table below which shows the cost of allocating 5 jobs to 5 machines.

         Machine
      6  7  8  9  10
Job 1 22 30 26 16 25
    2 27 29 28 20 32
    3 33 25 21 29 23
    4 24 24 30 19 26
    5 30 33 32 37 31

Which jobs should be allocated to which machines so as to minimise the total cost?

  • each source (job) can supply one unit
  • each sink (machine) demands one unit
  • each arc has a capacity of one unit of flow and a cost taken from the table above.

Assignment model graph

Problems of this type are called assignment problems since they involve the assignment of n (in this case n=5) distinct entities to another n distinct entities. For example in the area of production planning we might be interested in assigning operators to machines, or in assigning operators to jobs, or (as above) in assigning jobs to machines.

c This is a simple example file to demonstrate the DIMACS
c input file format for assignment problems.
c
c Problem line (resources+tasks) (resources*tasks)
p asn 10 25
c
c Node descriptor lines (indeces of assignable resources only)
n 1
n 2
n 3
n 4
n 5
c
c Arc descriptor lines (tasks over each resource and "score")
a 1  6 22
a 1  7 30
a 1  8 26
a 1  9 16
a 1 10 25
a 2  6 27
a 2  7 29
a 2  8 28
a 2  9 20
a 2 10 32
a 3  6 33
a 3  7 25
a 3  8 21
a 3  9 29
a 3 10 23
a 4  6 24
a 4  7 24
a 4  8 30
a 4  9 19
a 4 10 26
a 5  6 30
a 5  7 33
a 5  8 32
a 5  9 37
a 5 10 31
c
c End of file

lp_solve can read/write and solve these models via the xli_DIMACS XLI driver (see External Language Interfaces). It reads such a model in above format and solves it via linear programming. The xli can also generate a DIMACS formatted file.

For example:

lp_solve -rxli xli_DIMACS assignment.net

This gives as result:

Value of objective function: 118

Actual values of the variables:
C1                              1
C2                              0
C3                              0
C4                              0
C5                              0
C6                              0
C7                              0
C8                              0
C9                              1
C10                             0
C11                             0
C12                             0
C13                             1
C14                             0
C15                             0
C16                             0
C17                             1
C18                             0
C19                             0
C20                             0
C21                             0
C22                             0
C23                             0
C24                             0
C25                             1

Also from within the IDE, this XLI can be used. However, some entries must be added in LpSolveIDE.ini (in the folder where the IDE is installed).

In the [XLI] section the following must be added:

lib6=xli_DIMACS

And a new section for the DIMACS XLI must also be added:

[xli_DIMACS]
extension=.net
language=DIMACS

Then make sure that the xli_DIMACS.dll is available for the IDE. This must be done by placing this dll in the IDE folder or in the Windows system32 folder.

Solution :

The solution vector of above example is [1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1]
This must be interpreted as follows:
There are as many variables as there are arc descriptor lines in the input file and they appear in the same order. So:

C1 specifies how much flow there is for the first arc definition, in this case from 1 -> 6
C2 specifies how much flow there is for the second arc definition, in this case from 1 -> 7
...

This means there is a flow from node 1 to 6, a flow from node 2 to 9, a flow from node 3 to 8, a flow from node 4 to 7, a flow from node 5 to 10
This gives a total cost of 22 + 20 + 21 + 24 + 31 = 118
The value of the objective is the cost of the flow: 118

Output :

The solution of the model can also be written in a DIMACS format:

  • comment lines
  • solution lines
  • flow assignments

For each network problem, the solution is an integer-valued flow assignment. The output file should list the solution and flow assignment for all arcs in the graph. As noted above, information is collected into lines, which begin with one-character designators. We describe each type of information line in turn.

  1. Comment Lines: Comment lines give human-readable information about the file and are ignored by programs. Comment lines can appear anywhere in the file. Each comment line begins with a lower-case character c.
        c This is an example of a comment line.
  2. Solution line. The solution line contains the flow value and has the following format:
        s VALUE

    The lower-case character s signifies that this is a solution line. The VALUE field contains the value of the objective.

  3. Flow assignments. There is one flow assignment line for each arc in the input network. These lines have the following format:
        f SRC DST FLOW
    The lower-case character f signifies that this is a flow assignment line. For arc (u,v), the SRC and DST fields give v and w, respectively. The FLOW field gives the amount of flow assigned to arc (u,v).

lp_solve can generate a solution file via the xli_DIMACS XLI driver (see External Language Interfaces).

For example:

lp_solve -rxli xli_DIMACS assignment.net -wxlisol xli_DIMACS assignment.sol

This generates the following solution contents:

c assignment.net
c
c Dimacs-format network assignment result file
c generated by lp_solve
c
c Solution
s 118
c
c SRC DST FLOW
f 1 6 1
f 1 7 0
f 1 8 0
f 1 9 0
f 1 10 0
f 2 6 0
f 2 7 0
f 2 8 0
f 2 9 1
f 2 10 0
f 3 6 0
f 3 7 0
f 3 8 1
f 3 9 0
f 3 10 0
f 4 6 0
f 4 7 1
f 4 8 0
f 4 9 0
f 4 10 0
f 5 6 0
f 5 7 0
f 5 8 0
f 5 9 0
f 5 10 1
c
c End of file

lp_solve can also generate a solution file with only non-zero values.

For example:

lp_solve -rxli xli_DIMACS assignment.net -wxlisol xli_DIMACS assignment.sol -wxlisolopt "-nz"

This generates the following solution contents:

c assignment.net
c
c Dimacs-format network assignment result file
c generated by lp_solve
c
c Solution
s 118
c
c Only non-zero flows are written
c SRC DST FLOW
f 1 6 1
f 2 9 1
f 3 8 1
f 4 7 1
f 5 10 1
c
c End of file

See Also DIMACS minimum cost flow problems, DIMACS maximum flow problems

doc/set_rh_range.htm0000644000175000017500000000611210237176664013455 0ustar renerene set_rh_range

set_rh_range

Set the range on a constraint.

unsigned char set_rh_range(lprec *lp, int row, REAL deltavalue);

Return Value

set_rh_range returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row number of the constraint on which the range must be set. It must be between 1 and the number of rows in the lp.

deltavalue

The range on the constraint.

Remarks

The set_rh_range function sets a range on the constraint (row) identified by row.
Setting a range on a row is the way to go instead of adding an extra constraint (row) to the model. Setting a range doesn't increase the model size that means that the model stays smaller and will be solved faster.
If the row has a less than constraint then the range means setting a minimum on the constraint that is equal to the RHS value minus the range. If the row has a greater than constraint then the range means setting a maximum on the constraint that is equal to the RHS value plus the range.
Note that the range value is the difference value and not the absolute value.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_rh_range(lp, 1, 1.0);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_rh_range

doc/read_mps.htm0000644000175000017500000001277411250024212012573 0ustar renerene read_mps, read_freemps, read_MPS, read_freeMPS

read_mps, read_freemps, read_MPS, read_freeMPS

Create an lprec structure and read an mps model from file.

lprec *read_mps(FILE *stream, int options);

lprec *read_freemps(FILE *stream, int options);

lprec *read_MPS(char *filename, int options);

lprec *read_freeMPS(char *filename, int options);

Return Value

Returns a pointer to a new lprec structure. This must be provided to almost all lp_solve functions.
A NULL return value indicates an error. Specifically file could not be opened or file has wrong structure or not enough memory available to setup an lprec structure.

Parameters

stream

Pointer to FILE structure.

filename

Filename to read the mps model from.

options

Specifies the verbose level and how to interprete the MPS layout.

The verbose level can be one of the following values:
CRITICAL (1), SEVERE (2), IMPORTANT (3), NORMAL (4), DETAILED (5), FULL (6)

See also set_verbose and get_verbose.

This can be ORed by any one of the following combinations:

MPS_FREE (8) The MPS format is free MPS format. If not specified, read_MPS and read_mps use by default the fixed MPS format. The option is not needed for read_freemps and read_freeMPS as these routine already interprete the file in free MPS format, but it is allowed to specify the option anyway. See also MPS file format
MPS_IBM (16) Interprete integer variables without bounds as binary variables. That is the original IBM standard. By default lp_solve interpretes variables without bounds as having no upperbound as for real variables. See also MPS file format (section G.)
MPS_NEGOBJCONST (32) Interprete the objective constant with an oposite sign. Some solvers interprete the objective constant as a value in the RHS and negate it when brought at the LHS. This option allows to let lp_solve do this also. See also MPS file format

Remarks

The read_mps, read_freemps, read_MPS, read_freeMPS functions construct a new lprec structure and read the model from filename. read_mps, read_freemps need a file pointer to an already opened file. read_MPS, read_freeMPS accepts the name of the file. The latter functions will generally be more convenient.

The model in the file must be in mps-format. The read_free* routines accept files only in free MPS format. The other routines by default accept files in fixed MPS format. However via the options parameter this can be set to free format also. That makes the read_free* routines obsolete, but they are kept for backward compatibility. The second argument of the routines was originally called verbose. This is extended from version 5.5.15 on to verbose with the possibility to add extra options.

It is advised not to read/write the lprec structure. Instead, use the function interface to communicate with the lp_solve library. This because the structure can change over time. The function interface will be more stable.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"
int main(void)
{
  lprec *lp;

  /* Read MPS model */
  lp = read_MPS("model.mps", NORMAL);
  if(lp == NULL) {
    fprintf(stderr, "Unable to read model\n");
    return(1);
  }

  /* Model read */

  /*
  .
  .
  .
  */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, write_mps, write_freemps, write_MPS, write_freeMPS, MPS_writefileex, read_lp, read_LP, write_lp, write_LP, write_lpex

doc/get_timeout.htm0000644000175000017500000000467610237176656013360 0ustar renerene get_timeout

get_timeout

Gets the timeout.

long get_timeout(lprec *lp);

Return Value

get_timeout returns the number of seconds after which a timeout occurs.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_timeout function returns a timeout in seconds. The solve and lag_solve functions may not last longer than this time or the routines return with a timeout. There is no valid solution at this time. The default timeout is 0, resulting in no timeout.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  long timeout;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  timeout = get_timeout(lp); /* will return 0 since no timeout was set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_timeout, time_elapsed, solve, lag_solve

doc/get_sensitivity_rhs.htm0000644000175000017500000002064310516446106015116 0ustar renerene get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult

get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult

Returns the sensitivity of the constraints and the variables.

unsigned char get_sensitivity_rhs(lprec *lp, REAL *duals, REAL *dualsfrom, REAL *dualstill);

unsigned char get_ptr_sensitivity_rhs(lprec *lp, REAL **ptr_duals, REAL **ptr_dualsfrom, REAL **ptr_dualstill);

unsigned char get_dual_solution(lprec *lp, REAL *duals);

unsigned char get_ptr_dual_solution(lprec *lp, REAL **ptr_duals);

REAL get_var_dualresult(lprec *lp, int index);

Return Value

get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.
get_var_dualresult returns the reduced cost.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

duals

An array that will contain the values of the dual variables aka reduced costs.

ptr_duals

The address of a pointer that will point to an array that will contain the values of the dual variables aka reduced costs.

dualsfrom

An array that will contain the values of the lower limits on the dual variables aka reduced costs.

ptr_dualsfrom

The address of a pointer that will point to an array that will contain the values of the lower limits of the dual variables aka reduced costs.

dualstill

An array that will contain the values of the upper limits on the dual variables aka reduced costs.

ptr_dualstill

The address of a pointer that will point to an array that will contain the values of the upper limits of the dual variables aka reduced costs.

index

The column of the variable for which the reduced cost is required. Note that this is the column number before presolve was done, if active. If index is 0, then the value of the objective function is returned by get_var_dualresult

Remarks

The get_sensitivity_rhs, get_ptr_sensitivity_rhs functions return the values of the dual variables aka reduced costs and their limits.
The get_dual_solution, get_ptr_dual_solution, get_var_dualresult functions return only the value(s) of the dual variables aka reduced costs.
These values are only valid after a successful solve and if there are integer variables in the model then only if set_presolve is called before solve with parameter PRESOLVE_SENSDUALS.
Function get_sensitivity_rhs needs an array that is already dimensioned with get_Nrows+get_Ncolumns elements.
Function get_dual_solution needs an array that is already dimensioned with 1+get_Nrows+get_Ncolumns elements.
get_ptr_sensitivity_rhs and get_ptr_dual_solution return a pointer to an array already dimensioned by lp_solve.

For functions get_sensitivity_rhs and get_ptr_sensitivity_rhs, Element 0 will contain the value of the first row, element 1 of the second row, ... Element get_Nrows contains the value for the first variable, element get_Nrows+1 the value for the second variable and so on.

For functions get_dual_solution and get_ptr_dual_solution the index starts from 1 and element 0 is not used. The first get_Nrows elements contain the duals of the constraints, the next get_Ncolumns elements contain the duals of the variables.

The dual values or reduced costs values indicate that the objective function will change with the value of the reduced cost if the restriction is changed with 1 unit. There will only be a reduced cost if the value is bounded by the restriction, else it is zero. Note that the sign indicates if the objective function will increase or decrease. The reduced costs remains constant as long as the restriction stays within the lower/upper range also provided with these functions (dualsfrom, dualstill). If there is no reduced cost, or no lower/upper limit, then these values are (-)infinity.

Note that get_ptr_sensitivity_rhs and get_ptr_dual_solution return a pointer to memory allocated and maintained by lp_solve. Be careful what you do with it. Don't modify its contents or free the memory. Unexpected behaviour would occur. Also note that this memory pointer is only guaranteed to remain constant until a next lp_solve API call is done. You should call this function again to make sure you have again the correct pointer. Otherwise, this pointer could point to invalid memory. This should not be a problem since this call is very efficient.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL duals[1+2], dualsfrom[1+2], dualstill[1+2], *ptr_duals, *ptr_dualsfrom, *ptr_dualstill;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  str_set_obj_fn(lp, "1 1");
  str_add_constraint(lp, "2 4", GE, 10);
  set_lowbo(lp, 1, 1);

  solve(lp);

  get_sensitivity_rhs(lp, duals, dualsfrom, dualstill);
  get_ptr_sensitivity_rhs(lp, &ptr_duals, &ptr_dualsfrom, &ptr_dualstill);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex,

doc/set_solutionlimit.htm0000644000175000017500000000527410237176664014613 0ustar renerene set_solutionlimit

set_solutionlimit

Sets the solution number that must be returned.

void set_solutionlimit(lprec *lp, int limit);

Return Value

set_solutionlimit has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

limit

The solution number that must be returned. This value gives the number of the solution that must be returned.

Remarks

This function is only valid if there are integer, semi-continious or SOS variables in the model so that the branch-and-bound algoritm is used. If there are more solutions with the same objective value, then this number specifies which solution must be returned. This can be used to retrieve all possible solutions. Start with 1 till get_solutioncount

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_solutionlimit(lp, 3); /* return the 3rd solution */

  solve(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_solutionlimit, get_solutioncount

doc/put_logfunc.htm0000644000175000017500000000624310255113156013332 0ustar renerene put_logfunc

put_logfunc

Sets a log routine.

void put_logfunc(lprec *lp, lphandlestr_func newlog, void *loghandle);

Return Value

put_logfunc has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

newlog

The log routine.

typedef void (__WINAPI lphandlestr_func)(lprec *lp, void *userhandle, char *buf);
Note the __WINAPI attribute. This is important under Windows. It ensures __stdcall calling convention which is required.

loghandle

A parameter that will be provided to the log routine.

Remarks

The put_logfunc function sets a log routine.
When set, the log routine is called when lp_solve has someting to report. The return value of this routine should be 0. The log routine can be cleared by specifying NULL as log routine.
This function is called at the same time as something is written to file set via set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

void __WINAPI logfunction(lprec *lp, void *userhandle, char *buf)
{

 /* do something with buf (the message) */

}

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  put_logfunc(lp, logfunction, NULL);
  set_verbose(lp, FULL);

  del_column(lp, 1); /* Will generate an error because column 1 does not exist */
                     /* Note that del_column returns FALSE (0) to indicate an error */
  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, put_abortfunc

doc/get_verbose.htm0000644000175000017500000000741110255112776013316 0ustar renerene get_verbose

get_verbose

Returns the verbose level.

int get_verbose(lprec *lp);

Return Value

get_verbose returns the current verbose level. Can be one of the following values:

NEUTRAL (0) Only some specific debug messages in de debug print routines are reported.
CRITICAL (1) Only critical messages are reported. Hard errors like instability, out of memory, ...
SEVERE (2) Only severe messages are reported. Errors.
IMPORTANT (3) Only important messages are reported. Warnings and Errors.
NORMAL (4) Normal messages are reported. This is the default.
DETAILED (5) Detailed messages are reported. Like model size, continuing B&B improvements, ...
FULL (6) All messages are reported. Useful for debugging purposes and small models.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_verbose function returns the verbose level.
lp_solve reports information back to the user. How much information is reported depends on the verbose level. The default verbose level is NORMAL. lp_solve determines how verbose a given message is. For example specifying a wrong row/column index values is considered as a SEVERE error. verbose determines how much of the lp_solve message are reported. All messages equal to and below the set level are reported.
The default reporting device is the console screen. It is possible to set a used defined reporting routine via put_logfunc.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int verbose;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  verbose = get_verbose(lp); /* Will return 4 (NORMAL) */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_verbose, put_logfunc

doc/list.gif0000644000175000017500000000026110031136370011722 0ustar renereneGIF89a{{{{{! ,^0I$8kK@ U|' 䅢Hi扳dPA.a" b)jXDSAB DDަBv^^. ;doc/Sage.htm0000644000175000017500000001366311170702073011667 0ustar renerene Using lpsolve from Sage

Using lpsolve from Sage

Sage?

Sage is free, open-source math software that supports research and teaching in algebra, geometry, number theory, cryptography, numerical computation, and related areas. Both the Sage development model and the technology in Sage itself are distinguished by an extremely strong emphasis on openness, community, cooperation, and collaboration: we are building the car, not reinventing the wheel. The overall goal of Sage is to create a viable, free, open-source alternative to Maple, Mathematica, Magma, and MATLAB.

We will not discuss the specifics of Sage here but instead refer the reader to the Sage website. Also see Sage Tutorial, Sage Tutorial (pdf), Sage Feature Tour and Sage For Newbies.

Sage and lpsolve

The primary implementation language of Sage is Python. Sage is build on top of Python. See Sage afterword.
Because there is already a link from lpsolve to Python (see Using lpsolve from Python), the link from Sage to lpsolve is in fact quite easy and ready available. Nothing special must be done except for installing the lpsolve Python driver.
lpsolve is callable from Sage via this Python extension or module. As such, it looks like lpsolve is fully integrated with Sage. Matrices can directly be transferred between Sage and lpsolve in both directions. The complete interface is written in C so it has maximum performance. The whole lpsolve API is implemented with some extra's specific for Sage (especially for matrix support). So you have full control to the complete lpsolve functionality via the lpsolve Sage driver. If you find that this involves too much work to solve an lp model then you can also work via higher-level script files that can make things a lot easier. See further in this article.

Sage is ideally suited to handle linear programming problems. These are problems in which you have a quantity, depending linearly on several variables, that you want to maximize or minimize subject to several constraints that are expressed as linear inequalities in the same variables.If the number of variables and the number of constraints are small, then there are numerous mathematical techniques for solving a linear programming problem. Indeed these techniques are often taught in high school or university level courses in finite mathematics.But sometimes these numbers are high, or even if low, the constants in the linear inequalities or the object expression for the quantity to be optimised may be numerically complicated in which case a software package like Sage is required to effect a solution.

Installation

To make this possible, the Python driver program is needed. This driver must be put in a directory known to Sage and Sage can call the lpsolve solver.
How this can be done can be read in the Python documentation: Using lpsolve from Python.

There is only one thing that must be considered: Sage comes with its own version of Python. So not the Python version that is already installed on the system (/usr/bin/python and /usr/lib/pythonx.y/*) is used, but a Python version in a subdirectory of the sage installation. For example /sage-3.4-linux-Ubuntu_8.10-i686-Linux/local/bin and /sage-3.4-linux-Ubuntu_8.10-i686-Linux/local/lib/pythonx.y/*

The consequence is that the lpsolve Python driver must also be installed on that place. The same installation files as for Python can be used, but they must be installed on the sage directory.
For example /sage-3.4-linux-Ubuntu_8.10-i686-Linux/local/lib/python2.5/site-packages. There lpsolve55.so, lp_solve.py, lp_solve.pyc, lp_maker.py, lp_maker.pyc and lpsolve55-5.5.0.6-py2.5.egg-info must reside after the installation.
See also Install the lpsolve driver for the installation of these files.

Solve an lp model from Sage via lpsolve

See Using lpsolve from Python. Everything that is written there also applies to sage.
Note however that the prompt is different.

Under Python the prompt is >>>
Under Sage the prompt is sage:

That is the only difference.

Sage also has a web interface called Sage Notebook. Also in this application lpsolve can be called in the same way.

Also note that you can enter the command load "filename" with filename a .py Python file with commands. The lpsolve examples (example1.py, ...) can be loaded and executed from the sage prompt as such.

See also Using lpsolve from MATLAB, Using lpsolve from O-Matrix, Using lpsolve from Sysquake, Using lpsolve from Scilab, Using lpsolve from Octave, Using lpsolve from FreeMat, Using lpsolve from Euler, Using lpsolve from Python, Using lpsolve from PHP, Using lpsolve from R

doc/get_pivoting.htm0000644000175000017500000001211310256364036013502 0ustar renerene get_pivoting

get_pivoting

Returns the pivot rule and mode.

int get_pivoting(lprec *lp);

Return Value

get_pivoting returns the pivot rule and mode. Can be one of the following rules:

PRICER_FIRSTINDEX (0) Select first
PRICER_DANTZIG (1) Select according to Dantzig
PRICER_DEVEX (2) Devex pricing from Paula Harris
PRICER_STEEPESTEDGE (3) Steepest Edge

Some of these values can be combined with any (ORed) of the following modes:

PRICE_PRIMALFALLBACK (4) In case of Steepest Edge, fall back to DEVEX in primal
PRICE_MULTIPLE (8) Preliminary implementation of the multiple pricing scheme.This means that attractive candidate entering columnsfrom one iteration may be used in the subsequent iteration, avoiding full updating of reduced costs. In the current implementation, lp_solve only reuses the 2nd best entering column alternative
PRICE_PARTIAL (16) Enable partial pricing
PRICE_ADAPTIVE (32) Temporarily use alternative strategy if cycling is detected
PRICE_RANDOMIZE (128) Adds a small randomization effect to the selected pricer
PRICE_AUTOPARTIAL (512) Indicates automatic detection of segmented/staged/blocked models.It refers to partial pricing rather than full pricing. With full pricing, all non-basic columns are scanned, but with partial pricing only a subset is scanned for every iteration. This can speed up several models
PRICE_LOOPLEFT (1024) Scan entering/leaving columns left rather than right
PRICE_LOOPALTERNATE (2048) Scan entering/leaving columns alternatingly left/right
PRICE_HARRISTWOPASS (4096) Use Harris' primal pivot logic rather than the default
PRICE_TRUENORMINIT (16384) Use true norms for Devex and Steepest Edge initializations

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_pivoting function returns the pivot rule (rule for selecting row and column entering/leaving) and mode. The rule is an exclusive option and the mode is a modifier to the rule. This rule/mode can influence solving times considerably. Depending on the model one rule/mode can be best and for another model another rule/mode.
The default is PRICER_DEVEX | PRICE_ADAPTIVE (34).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int pivoting;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  pivoting = get_pivoting(lp); /* will return 18 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_piv_rule, set_pivoting, is_piv_mode

doc/print_scales.htm0000644000175000017500000000556510237176420013504 0ustar renerene print_scales

print_scales

Prints the scales of the lp.

void print_scales(lprec *lp);

Return Value

print_scales has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The print_scales function prints the scales of the lp. This can only be done after a successful solve. It will only output something when the model is scaled.
This function is meant for debugging purposes. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_scaling(lp, CURTISREIDSCALE);

  solve(lp);

  print_scales(lp);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, print_lp, print_objective, print_solution, print_constraints, print_duals, print_tableau, print_str, set_outputstream, set_outputfile, set_scaling, print_debugdump

doc/download.htm0000644000175000017500000000141611247043321012607 0ustar renerene Download

Download

All needed files can be downloaded from sourceforge on the following location: http://sourceforge.net/projects/lpsolve/

doc/get_lambda.htm0000644000175000017500000001100610351321162013050 0ustar renerene get_lambda, get_ptr_lambda

get_lambda, get_ptr_lambda

Returns the Lamdba vectors (Lagrangian optimization).

unsigned char get_lambda(lprec *lp, REAL *lambda);

unsigned char get_ptr_lambda(lprec *lp, REAL **ptr_lambda);

Return Value

get_lambda, get_ptr_lambda returns TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

lambda

An array that will contain the values of the Lamdba vectors.

ptr_lambda

The address of a pointer that will point to an array that will contain the values of the Lamdba vectors.

Remarks

The get_lambda, get_ptr_lambda functions retrieve the Lamdba vectors.
These values are only valid after a successful lag_solve. Function get_lambda needs an array that is already dimensioned with get_Lrows elements. get_ptr_lambda returns a pointer to an array already dimensioned by lp_solve.

Note that get_ptr_lambda returns a pointer to memory allocated and maintained by lp_solve. Be careful what you do with it. Don't modify its contents or free the memory. Unexpected behaviour would occur. Also note that this memory pointer is only guaranteed to remain constant until a next lp_solve API call is done. You should call this function again to make sure you have again the correct pointer. Otherwise, this pointer could point to invalid memory. This should not be a problem since this call is very efficient.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;
  REAL row[1+2]; /* must be 1 more than number of columns ! */
  REAL *ptr_lambda, lambda[1];

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  row[1] = 1.0;
  row[2] = 1.0;
  add_lag_con(lp, row, LE, 1.0);

  ret = lag_solve(lp, 0, 30, FALSE);

  get_lambda(lp, lambda);
  get_ptr_lambda(lp, &ptr_lambda);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_primal_solution, get_ptr_primal_solution, get_var_primalresult, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex, get_constraints, get_ptr_constraints, get_constr_value, lag_solve

doc/set_bounds_tighter.htm0000644000175000017500000000634510237211404014676 0ustar renerene set_bounds_tighter

set_bounds_tighter

Specifies if set bounds may only be tighter or also less restrictive.

void set_bounds_tighter(lprec *lp, unsigned char tighten);

Return Value

set_bounds_tighter has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

tighten

Specifies if set bounds may only be tighter (TRUE) or also less restrictive (FALSE).

Remarks

The set_bounds_tighter function sets if bounds may only be tighter or also less restrictive. If set to TRUE then bounds may only be tighter. This means that when set_lowbo or set_lowbo is used to set a bound and the bound is less restrictive than an already set bound, then this new bound will be ignored. If tighten is set to FALSE, the new bound is accepted. This functionality is useful when several bounds are set on a variable and at the end you want the most restrictive ones. By default, this setting is FALSE. Note that this setting does not affect set_bounds.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 2);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_bounds_tighter(lp, TRUE);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_bounds_tighter, set_upbo, get_upbo, set_lowbo, get_lowbo, set_bounds, set_unbounded, is_unbounded, is_negative

doc/fold.gif0000644000175000017500000000016710031136370011700 0ustar renereneGIF89a!,@ get_maxpivot

get_maxpivot

Returns the maximum number of pivots between a re-inversion of the matrix.

int get_maxpivot(lprec *lp);

Return Value

get_maxpivot returns the maximum number of pivots between a re-inversion of the matrix.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_maxpivot function returns the maximum number of pivots between a re-inversion of the matrix.
For stability reasons, lp_solve re-inverts the matrix on regular times. max_num_inv determines how frequently this inversion is done. This can influence numerical stability. However, the more often this is done, the slower the solver becomes.
The default is 250 for the LUSOL bfp and 42 for the other BFPs.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int max_num_inv;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  max_num_inv = get_maxpivot(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_maxpivot

doc/LPFML.htm0000644000175000017500000002135211246262327011663 0ustar renerene LPFML

LPFML

LPFML is a modeling format in XML structure. It started as its own project but is now part of the bigger COIN-OR OSlL project

See https://www.coin-or.org/OS/OSlL.html for the home page of this tool and examples.

lp_solve can read/write and solve these LPFML models directly via the xli_LPFML XLI driver (see External Language Interfaces).

Reading LPFML models

It reads such a model in above format and can solve it then.

For example:

lp_solve -rxli xli_LPFML parinc.xml

This gives as result:

Value of objective function: 7667.94172245

Actual values of the variables:
x1                        539.984
x2                        252.011
Options

none

Generating LPFML models

The XLI can also create a LPFML model.

For example:

lp_solve model.lp -wxli xli_LPFML model.xml

This gives as model.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<mathProgram xmlns="http://FML/lpfml.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://FML/lpfml.xsd
 lpfml.xsd">

  <linearProgramDescription>
    <source></source>
    <maxOrMin>max</maxOrMin>
    <numberRows>4</numberRows>
    <numberVars>2</numberVars>
  </linearProgramDescription>

  <linearProgramData>
    <rows>
      <row rowName="cutanddye" rowUB="630"/>
      <row rowName="sewing" rowUB="600"/>
      <row rowName="finishing" rowUB="708"/>
      <row rowName="inspectandpack" rowUB="135"/>
    </rows>
    <columns>
      <col colName="x1" colType="C" objVal="10"/>
      <col colName="x2" colType="C" objVal="9"/>
    </columns>
    <amatrix>
      <sparseMatrix>
        <pntANonz>
          <el>4</el>
          <el>8</el>
        </pntANonz>
        <rowIdx>
          <el>0</el>
          <el>1</el>
          <el>2</el>
          <el>3</el>
          <el>0</el>
          <el>1</el>
          <el>2</el>
          <el>3</el>
        </rowIdx>
        <nonz>
          <el>0.7</el>
          <el>0.5</el>
          <el>1</el>
          <el>0.1</el>
          <el>1</el>
          <el>0.8333</el>
          <el>0.6667</el>
          <el>0.25</el>
        </nonz>
      </sparseMatrix>
    </amatrix>
  </linearProgramData>

</mathProgram>
Options

The XLI accepts several options:

  -b64
  -comp          Compress.
  -can           Canonical.

API

Use the lpsolve API call read_XLI to read a model and write_XLI to write a model. See also External Language Interfaces.

IDE

Also from within the IDE, this XLI can be used. However, some entries must be added in LpSolveIDE.ini (in the folder where the IDE is installed).

In the [XLI] section the following must be added:

lib4=xli_LPFML

And a new section for the LPFML XLI must also be added:

[xli_LPFML]
extension=.xml
language=XML

Then make sure that the xli_LPFML.dll is available for the IDE. This must be done by placing this dll in the IDE folder or in the Windows system32 folder. There are also 2 extra dlls needed: Xalan-C_1_6_0.dll and xerces-c_2_3_0.dll. It is advised to put these in the system32 folder

Example models

parinc.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- Sample XML file generated by XMLSPY v5 U (http://www.xmlspy.com)-->
<!-- $Id: parinc.xml,v 1.8 2003/08/08 19:50:04 kipp Exp $ -->
<mathProgram xmlns="http://FML/lpfml.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://FML/lpfml.xsd
http://gsbkip.uchicago.edu/fml/testproblems/lpfml.xsd">

	<linearProgramDescription>
		<source>Par Inc. Problem from Anderson, Sweeny, and Williams</source>
	<maxOrMin>max</maxOrMin>
		<objConstant>0.</objConstant>
		<numberRows>4</numberRows>
		<numberVars>2</numberVars>
	</linearProgramDescription>
	<linearProgramData>
		<rows>
			<row rowName="cutanddye"  rowUB="630" />
			<row rowName="sewing" rowUB="600"/>
			<row rowName="finishing" rowUB="708"/>
			<row rowName="inspectandpack" rowUB="135" />
		</rows>
		<columns>
			<col objVal="10.0" colName="x1" colType="C" colLB="0.0" />
			<col objVal="9" colName="x2" colType="C" colLB="0.0" />
		</columns>
		<amatrix>
			<sparseMatrix>
				<pntANonz>
					<el>4</el>
					<el>8</el>
				</pntANonz>
				<rowIdx>
					<el>0</el>
					<el>1</el>
					<el>2</el>
					<el>3</el>
					<el>0</el>
					<el>1</el>
					<el>2</el>
					<el>3</el>
				</rowIdx>
				<nonz>
					<el>.7</el>
					<el>.5</el>
					<el>1.0</el>
					<el>0.1</el>
					<el>1.0</el>
					<el>0.8333</el>
					<el>0.6667</el>
					<el>0.25</el>
				</nonz>
			</sparseMatrix>
		</amatrix>
	</linearProgramData>
	<linearProgramSolution>
		<primalSolution>
			<sol idx="1" name="x1" val="540"/>
			<sol idx="2" name="x2" val="252"/>
		</primalSolution>
		<dualSolution>
			<sol idx="1" name="cutanddye" val="4.37457"/>
			<sol idx="3" name="finishing" val="6.9378"/>
		</dualSolution>
		<optimalValue>7667.94</optimalValue>
		<status statusId="optimalSolutionFound">Put in here any other status message desired</status>
		<solverMessage>This was solved using LINDO from LINDO Systems, Inc.</solverMessage>
	</linearProgramSolution>
</mathProgram>
model.lp
/* Objective function */
max: +10 x1 +9 x2;

/* Constraints */
cutanddye: +0.7 x1 +x2 <= 630;
sewing: +0.5 x1 +0.8333 x2 <= 600;
finishing: +x1 +0.6667 x2 <= 708;
inspectandpack: +0.1 x1 +0.25 x2 <= 135;
doc/get_var_branch.htm0000644000175000017500000000746610237176656013777 0ustar renerene get_var_branch

get_var_branch

Returns, for the specified variable, which branch to take first in branch-and-bound algorithm.

int get_var_branch(lprec *lp, int column);

Return Value

get_var_branch returns which branch to take first in branch-and-bound algorithm.

Can by any of the following values:

BRANCH_CEILING (0) Take ceiling branch first
BRANCH_FLOOR (1) Take floor branch first
BRANCH_AUTOMATIC (2) Algorithm decides which branch being taken first

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

column

The column number of the variable on which the mode must be returned. It must be between 1 and the number of columns in the lp. If it is not within this range, the return value is the value of get_bb_floorfirst

Remarks

The get_var_branch function returns which branch to take first in branch-and-bound algorithm. This can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
When no value was set via set_var_branch, the return value is the value of get_bb_floorfirst. It also returns the value of get_bb_floorfirst when set_var_branch was called with branch mode BRANCH_DEFAULT (3).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int branch_mode;

  /* Create a new LP model */
  lp = make_lp(0, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  branch_mode = get_var_branch(lp, 1); /* will return BRANCH_FLOOR (1), the default branch mode */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_var_branch, set_bb_floorfirst, get_bb_floorfirst, set_var_weights, get_var_priority

doc/set_row.htm0000644000175000017500000001343110351321652012463 0ustar renerene set_row, set_rowex

set_row, set_rowex

set a constraint in the lp.

unsigned char set_row(lprec *lp, int row_no, REAL *row);

unsigned char set_rowex(lprec *lp, int row_no, int count, REAL *row, int *colno);

Return Value

set_row, set_rowex return TRUE (1) if the operation was successful. A return value of FALSE (0) indicates an error.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row_no

The row number that must be changed.

count

Number of elements in row and colno.

row

An array with 1+get_Ncolumns (count for set_rowex, if colno is different from NULL) elements that contains the values of the row.

colno

A zero-based array with count elements that contains the column numbers of the row. However this variable can also be NULL. In that case element i in the variable row is column i and values start at element 1.

Remarks

The set_row, set_rowex functions change the values of an existing row in the model at once.

Note that add_constraint, add_constraintex, str_add_constraint add a row to the model, making the number of rows one larger. These functions change an existing row.

Note that for set_row (and set_rowex when colno is NULL) element 1 of the array is column 1, element 2 is column 2, ... element 0 is not used.

set_rowex has the possibility to specify only the non-zero elements. And in contrary to set_row, set_rowex reads the arrays starting from element 0. However when colno is NULL then set_rowex acts as set_row and then values start at element 1. When colno is provided, then it specifies the column numbers of the non-zero elements. This will speed up building the model considerably if there are a lot of zero values.

In most cases the matrix is sparse and has many zero value. Thus it is almost always better to use set_rowex instead of set_row. set_rowex is always at least as performant as set_row.

It is more performant to call these functions than multiple times set_mat.

Note that unspecified values by set_rowex are set to zero.

Note that these routines will perform much better when set_add_rowmode is called before adding constraints.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL row[1+3];     /* must be 1 more than number of columns ! */
  REAL sparserow[2]; /* must be the number of non-zero values */
  int colno[2];

  /* Create a new LP model */
  lp = make_lp(2, 3);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  row[1] = 1.0;
  row[2] = 0.0; /* also zero elements must be provided */
  row[3] = 2.0;
  set_row(lp, 1, row); /* changes the values of existing row 1 */
  
  colno[0] = 1; sparserow[0] = 1.0; /* column 1 */
  colno[1] = 3; sparserow[1] = 2.0; /* column 3 */
  set_rowex(lp, 2, 2, sparserow, colno);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_row, get_rowex, add_constraint, add_constraintex, str_add_constraint, set_obj_fn, set_obj_fnex, str_set_obj_fn, set_obj, set_add_rowmode, is_add_rowmode, get_constr_type, is_constr_type, del_constraint, add_column, add_columnex, str_add_column, set_column, set_columnex, get_column, get_columnex, get_mat

doc/is_constr_type.htm0000644000175000017500000000570510237176660014064 0ustar renerene is_constr_type

is_constr_type

Returns if constraint type specified in mask is active.

unsigned char is_constr_type(lprec *lp, int row, int mask);

Return Value

is_constr_type returns TRUE or FALSE

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the constraint type must be retrieved. Must be between 1 and number of rows in the lp.

mask

Any of the following values:
LE (1) Less than or equal (<=)
EQ (3) Equal (=)
GE (2) Greater than or equal (>=)

Remarks

The is_constr_type function returns a flag if constraint type specified in mask is active.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char constr;

  /* Create a new LP model */
  lp = make_lp(1, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  constr = is_constr_type(lp, 1, LE); /* will be TRUE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_constr_type, set_constr_type, add_constraint, add_constraintex, str_add_constraint, del_constraint

doc/set_break_at_value.htm0000644000175000017500000000567210237176662014644 0ustar renerene set_break_at_value

set_break_at_value

Specifies if the branch-and-bound algorithm stops when the object value is better than a given value.

void set_break_at_value(lprec *lp, REAL break_at_value);

Return Value

set_break_at_value has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

break_at_value

The value to break on.

Remarks

The set_break_at_value function allows the branch-and-bound algorithm to stops when the object value is better than a given value. Stopping at a given object value can be useful if you are only interested for a solution that has an object value which is at least a given value, but not necessarily (and most probably) the most optimal solution.
The default value is (-) infinity.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_break_at_value(lp, 1000); /* Will stop if object value is better than 1000 */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_break_at_value, set_break_at_first, is_break_at_first, set_obj_bound, get_obj_bound, set_mip_gap, get_mip_gap

doc/get_rh.htm0000644000175000017500000000624710242132024012250 0ustar renerene get_rh

get_rh

Gets the value of the right hand side (RHS) vector (column 0) for one row.

REAL get_rh(lprec *lp, int row);

Return Value

get_rh returns the value of the RHS for the specified row. If row is out of range it returns 0. If no previous value was set, then it also returns 0, the default RHS value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

row

The row for which the RHS value must be retrieved. Must be between 0 and number of rows in the lp.

value

The value of the RHS.

Remarks

The get_rh function returns the value of the RHS vector (column 0) for the specified row.
Note that row can also be 0 with this function. In that case it returns the initial value of the objective function.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL a;

  /* Create a new LP model */
  lp = make_lp(2, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  a = get_rh(lp, 1); /* will return 0 since no value was previously set */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_rh, set_rh_vec, str_set_rh_vec, add_constraint, add_constraintex, str_add_constraint, get_column, get_columnex, add_column, add_columnex, str_add_column, set_column, set_columnex, get_row, get_rowex, get_mat

doc/get_epspivot.htm0000644000175000017500000000637610237176654013540 0ustar renerene get_epspivot

get_epspivot

Returns epspivot.

REAL get_epspivot(lprec *lp);

Return Value

get_epspivot returns the value of epspivot.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_epspivot function returns the value that is used as a tolerance for the pivot element to determine whether a value should be considered as 0.
Floating-point calculations always result in loss of precision and rounding errors. Therefore a very small value (example 1e-99) could be the result of such errors and should be considered as 0 for the algorithm. epspivot specifies the tolerance to determine if a pivot element should be considered as 0. If abs(value) is less than this epspivot value it is considered as 0 and at first instance rejected as pivot element. Only when no larger other pivot element can be found and the value is different from 0 it will be used as pivot element.
The default epspivot value is 2e-7

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  REAL epspivot;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  epspivot = get_epspivot(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_epspivot, set_infinite, get_infinite, set_epsint, get_epsint, set_epsd, get_epsd, set_epsel, get_epsel, get_epsperturb, set_epsperturb, set_mip_gap, get_mip_gap

doc/set_improve.htm0000644000175000017500000000612010244174374013342 0ustar renerene set_improve

set_improve

Specifies the iterative improvement level.

void set_improve(lprec *lp, int improve);

Return Value

set_improve has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

improve

Specifies the iterative improvement level. Can by any of the following values:

IMPROVE_NONE (0) improve none
IMPROVE_SOLUTION (1) Running accuracy measurement of solved equations based on Bx=r (primal simplex), remedy is refactorization.
IMPROVE_DUALFEAS (2) Improve initial dual feasibility by bound flips (highly recommended, and default)
IMPROVE_THETAGAP (4) Low-cost accuracy monitoring in the dual, remedy is refactorization
IMPROVE_BBSIMPLEX (8) By default there is a check for primal/dual feasibility at optimum only for the relaxed problem, this also activates the test at the node level

Remarks

The default is IMPROVE_DUALFEAS + IMPROVE_THETAGAP (6).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_improve(lp, IMPROVE_DUALFEAS | IMPROVE_BBSIMPLEX);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_improve

doc/get_bb_rule.htm0000644000175000017500000001367210534655116013271 0ustar renerene get_bb_rule

get_bb_rule

Returns the branch-and-bound rule.

int get_bb_rule(lprec *lp);

Return Value

get_bb_rule returns the branch-and-bound rule. Can by any of the following values:

NODE_FIRSTSELECT (0) Select lowest indexed non-integer column
NODE_GAPSELECT (1) Selection based on distance from the current bounds
NODE_RANGESELECT (2) Selection based on the largest current bound
NODE_FRACTIONSELECT (3) Selection based on largest fractional value
NODE_PSEUDOCOSTSELECT (4) Simple, unweighted pseudo-cost of a variable
NODE_PSEUDONONINTSELECT (5) This is an extended pseudo-costing strategy based on minimizing the number of integer infeasibilities
NODE_PSEUDORATIOSELECT (6) This is an extended pseudo-costing strategy based on maximizing the normal pseudo-cost divided by the number of infeasibilities. Effectively, it is similar to (the reciprocal of) a cost/benefit ratio
NODE_USERSELECT (7)  

One of these values may be or-ed with one or more of the following values:

NODE_WEIGHTREVERSEMODE (8) Select by criterion minimum (worst), rather than criterion maximum (best)
NODE_BRANCHREVERSEMODE (16) In case when get_bb_floorfirst is BRANCH_AUTOMATIC, select the oposite direction (lower/upper branch) that BRANCH_AUTOMATIC had chosen.
NODE_GREEDYMODE (32)  
NODE_PSEUDOCOSTMODE (64) Toggles between weighting based on pseudocost or objective function value
NODE_DEPTHFIRSTMODE (128) Select the node that has already been selected before the most number of times
NODE_RANDOMIZEMODE (256) Adds a randomization factor to the score for any node candicate
NODE_GUBMODE (512)  
NODE_DYNAMICMODE (1024) When NODE_DEPTHFIRSTMODE is selected, switch off this mode when a first solution is found.
NODE_RESTARTMODE (2048) Enables regular restarts of pseudocost value calculations
NODE_BREADTHFIRSTMODE (4096) Select the node that has been selected before the fewest number of times or not at all
NODE_AUTOORDER (8192) Create an "optimal" B&B variable ordering. Can speed up B&B algorithm.
NODE_RCOSTFIXING (16384) Do bound tightening during B&B based of reduced cost information
NODE_STRONGINIT (32768) Initialize pseudo-costs by strong branching

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The get_bb_rule function returns the branch-and-bound rule for choosing which non-integer variable is to be selected. This rule can influence solving times considerably. Depending on the model one rule can be best and for another model another rule.
The default is NODE_PSEUDONONINTSELECT + NODE_GREEDYMODE + NODE_DYNAMICMODE + NODE_RCOSTFIXING (17445).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int bb_rule;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  bb_rule = get_bb_rule(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_bb_rule, put_bb_nodefunc

doc/lag_solve.htm0000644000175000017500000001135011022517767012764 0ustar renerene lag_solve

lag_solve

Solve the model via Lagrangian relaxation.

The Lagrangian solver does not work. Do not use this call.

int lag_solve(lprec *lp, REAL start_bound, int num_iter, short verbose);

Return Value

TIMEOUT (-2) A timeout occurred. A timeout was set via set_timeout
USERABORT (-3) The abort routine returned TRUE. See put_abortfunc
OPTIMAL (0) An optimal solution was obtained
INFEASIBLE (2) The model is infeasible
FEAS_FOUND (6) An feasible solution was obtained, but num_iter was reached
NO_FEAS_FOUND (7) No feasible solution found

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

start_bound

Initial bound.

num_iter

Maximum number of iterations.

verbose

Not used. Still included for backwards compatibility. Use set_lag_trace to set the verbose level.

Remarks

The Lagrangian solver does not work. Do not use this call.

The lag_solve function solves the model via Lagrangian relaxation. Gives the ability to find an integer solution without the branch-and-bound algorithm.
At least 1 Lagrangian constraint must be added via add_lag_con, str_add_lag_con before lag_solve can be used.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  int ret;
  REAL row[1+2]; /* must be 1 more then number of columns ! */

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  row[1] = 1.0;
  row[2] = 1.0;
  add_lag_con(lp, row, LE, 1.0);

  ret = lag_solve(lp, 0, 30, FALSE);

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, solve, get_statustext, is_feasible, get_objective, get_working_objective, get_variables, get_ptr_variables, get_constraints, get_ptr_constraints, get_constr_value, get_sensitivity_rhs, get_ptr_sensitivity_rhs, get_dual_solution, get_ptr_dual_solution, get_var_dualresult, get_sensitivity_obj, get_ptr_sensitivity_obj, get_sensitivity_objex, get_ptr_sensitivity_objex, add_lag_con, get_Lrows

doc/set_anti_degen.htm0000644000175000017500000001107010244172116013746 0ustar renerene set_anti_degen

set_anti_degen

Specifies if special handling must be done to reduce degeneracy/cycling while solving.

void set_anti_degen(lprec *lp, int anti_degen);

Return Value

set_anti_degen has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

anti_degen

Can be any combination (OR) of following values:

ANTIDEGEN_NONE (0) No anti-degeneracy handling
ANTIDEGEN_FIXEDVARS (1) Check if there are equality slacks in the basis and try to drive them out in order to reduce chance of degeneracy in Phase 1
ANTIDEGEN_COLUMNCHECK (2)  
ANTIDEGEN_STALLING (4)  
ANTIDEGEN_NUMFAILURE (8)  
ANTIDEGEN_LOSTFEAS (16)  
ANTIDEGEN_INFEASIBLE (32)  
ANTIDEGEN_DYNAMIC (64)  
ANTIDEGEN_DURINGBB (128)  
ANTIDEGEN_RHSPERTURB (256) Perturbation of the working RHS at refactorization
ANTIDEGEN_BOUNDFLIP (512) Limit bound flips that can sometimes contribute to degeneracy in some models

Remarks

The set_anti_degen function specifies if special handling must be done to reduce degeneracy/cycling while solving. Setting this flag can avoid cycling, but can also increase numerical instability. The default is ANTIDEGEN_INFEASIBLE + ANTIDEGEN_STALLING + ANTIDEGEN_FIXEDVARS (37).

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_anti_degen(lp, ANTIDEGEN_FIXEDVARS | ANTIDEGEN_PERTURB);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, get_anti_degen, is_anti_degen

doc/is_infinite.htm0000644000175000017500000000557710237176660013327 0ustar renerene is_infinite

is_infinite

Checks if the provided absolute of the value is larger or equal to "infinite".

unsigned char is_infinite(lprec *lp, REAL value);

Return Value

is_infinite returns TRUE if the value is equal or larger to "infinite".

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

value

The value to check against "infinite".

Remarks

Note that the absolute of the provided value is checked against the value set by set_infinite.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;
  unsigned char infinite;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  infinite = is_infinite(lp, 1.0e31); /* will return TRUE */

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_infinite, get_infinite, set_epsint, get_epsint, set_epsb, get_epsb, set_epsd, get_epsd, set_epsel, get_epsel, get_epspivot, set_epspivot, set_epsperturb, get_epsperturb

doc/free.htm0000644000175000017500000000664210546554012011734 0ustar renerene Free variables

free variables

Free variables are variables that have no lower or upper bound. By default, variables don't have an upper bound, but they do have a lower bound of zero. So they can only take positive values. Free variables can also become negative until -infinite.

lp_solve supports free variables since a long time. Internally, these variables are split in a positive and negative part. So the result of using free variables is that the number of columns increases. However this is transparent to the user. The API call set_unbounded can be used to define a variable as free.

In the mps format, free variables can be specified in the BOUNDS section. See mps-format.

Example:

NAME
ROWS
 N  R0
 L  R1
 G  R2
 G  R3
 G  R4
COLUMNS
    x1        R0        -1.000000000   R1        1.0000000000
    x1        R2        2.0000000000   R3        -1.000000000
    x2        R0        -2.000000000   R1        1.0000000000
    x2        R2        -1.000000000   R3        3.0000000000
    x3        R0        4.0000000000   R4        1.0000000000
    x4        R0        3.0000000000   R4        1.0000000000
RHS
    RHS       R1        5.0000000000   R4        0.5000000000
BOUNDS
 FR BND       x2
 UP BND       x3        10.000000000
 LO BND       x3        1.1000000000
 FR BND       x4
ENDATA
The red lines specify that variables x2 and x4 are free variables.

In the lp format, free variables can be specified in the free section. See lp-format.

Example:

max: x1 + 2x2 - 4x3 -3x4;
x1 + x2 <= 5;
2x1 - x2 >= 0;
-x1 + 3x2 >= 0;
x3 + x4 >= .5;
x3 >= 1.1;
x3 <= 10;

free x2, x4;

The red line specifies that variables x2 and x4 are free variables. The solution of this model is:
Value of objective function: 5.73333

Actual values of the variables:
x1                        1.66667
x2                        3.33333
x3                            1.1
x4                           -0.6

As can be seen, the value of x4 is -0.6, a negative value. If the variable would not be set as free, it would not be negative.

doc/print_str.htm0000644000175000017500000000534410255113032013023 0ustar renerene print_str

print_str

Prints a string.

void print_str(lprec *lp, char *str);

Return Value

print_str has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

str

The string to print

Remarks

The print_str function prints a string. By default, the output is stdout. However this can be changed via a call to set_outputstream, set_outputfile.
This function can be useful for debugging/demo purposes.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(1, 1);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  solve(lp);

  print_str(lp, "We are here\n");

  delete_lp(lp);

  return(0);
}

lp_solve API reference

See Also delete_lp, free_lp, make_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, print_objective, print_solution, print_constraints, print_duals, print_scales, print_tableau, set_outputstream, set_outputfile, print_debugdump

doc/set_minim.htm0000644000175000017500000000425310237176664013005 0ustar renerene set_minim

set_minim

Set objective function to minimize.

void set_minim(lprec *lp);

Return Value

set_minim has no return value.

Parameters

lp

Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI

Remarks

The set_minim function sets the objective direction to minimize. The default of lp_solve is to minimize, except for read_lp, read_LP where the default is to maximize.

Example

#include <stdio.h>
#include <stdlib.h>
#include "lp_lib.h"

int main(void)
{
  lprec *lp;

  /* Create a new LP model */
  lp = make_lp(0, 0);
  if(lp == NULL) {
    fprintf(stderr, "Unable to create new LP model\n");
    return(1);
  }

  set_minim(lp);

  delete_lp(lp);
  return(0);
}

lp_solve API reference

See Also make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI, set_maxim, is_maxim, set_sense

doc/dimacs_maxf.gif0000644000175000017500000001630610410107560013231 0ustar renereneGIF89a999SSShhhzzzsuT `V! D `p;``O;xH~`; p`p`l D0 ڷb `R@h >H D` Ǥ D| D;B`H Dh} \`  BG Dh}P0B`;Bn[ D[` Dak0gԈ0Ԉ*  D§ D!0 hm hm pj D DkHHZ D)1T`lT`(XF,3H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷p=Kݻx˷߿ ᐃ+^̸c#K8wʖ3k^ysΞCo-"Ҩ Np5k]V({o̭V14TZp ^h#pث^(A@3(z!xݭ;ΞD?~h}T-tEx@T@x0 gנ@0T,^~":`A͉7 D0ߏD'ҷ c!qP dPV``!b,0:7^aO  d$HdB dA5B6f(r|xQ@jrҩ*^T~\e9_rbƊ::1A,-d5z*Ƞ y @f9!j⋞)T1_S2EEp. \7tU\OrZE$:x FAL<I;s[1MӠ̯!$0?P}9b@r6|Ngz?jB,e :jRN!%EǶdwIC2=x ܣLGfɲ{2f %[8=!KY jM,):L2?\*oł 1ќZ-/9:zm}.͖ZDrJRD멏baQXVIAA`*Ɋ)[bOsKHC; ѯv_VgI3ظqR6thO4s"eoNNh9Qa;ly+5KPK<73Sh]8y^n|84XEzK[كlS!遵Kͪ3D3_NW*ev읁ɻ!= UCq0"nŖu4ҳްySlH!x!_L ;<.]뤎G#9F.ri\r;\ vj~Qn^4\'ʆSE 1z e^?;L޶0Hz}闇<[2<'Yc/ ܁r$':=σޔ'G2;jUWh"|Z2Km8w*G2_oINGkDAxB7 Z̷텱V~|(Dh{| mKwN_(gS]Bz|]*yO]q#`KEpGXp'@'CYQQ7KQQG|"<`0~H~S,dW/:wI+hNT6GYeuw}8_ 4G۷l6tF}Ã?XHL؄!=pwV暈GxA^dfIgOR3peWdžkdBDnä|p]xJ=5%GTWVtDg|YbY8+F7buEKoX) VA!s1D'Ud!s(A#8 !>d!3un" b8xAj[5CoEU_D8cs6'@Qe})!2S_0]CBQ[2262/"4%ZU !@Q,5's$D?hx+C4943!It4$av,0b!)l7P!O )x>(I*hP~x3@I&\+arW@5i*A!s4Xc*Ƀ_{'!I$u"0&D. w i\[t\3pq+F&_g+Q2r:=H '+و2d0D0ٗ~f'#1 r&<0 W h3S"I3q@; 3!ɚ;UL(>54<#Џ,6⁔jbr!v):Qٙ1q+Ȝyҹ`6dRI*H!9?J+]"(6뉗6e/)iU!+H)7 %0"@ o`nEa-dBٕ "%,iȸRd4s5 0RxъoȍinHER!dL Uq?idŋlʥfQYcuDҊ6_:T3XmZF#eCe=ÝUd@2{jqb:T|6_8*RDAyb3l SE(S:A!Aaz,77Jz6cX@_vz6ęlvQv`si*\:Έ"&3 s1j1ê%q˺Gф>Y R'ҧRm0[h0H ('7۪9PJ1|풪o [ߖQ?kd!_Dk'`evBb1񦂅oFխfA+Bƺ#5ge\'8r2q:ǚFZ UTk-VtۻȪd8 Dgek~b-tvk+x!_IkȽ1*qhH)H~裃fGԾƾ$;ye%R wv܆>ۨr}$-w>^~ꨞꪾ>^~븞뺾~!0A%0]D6Q1+5R킥W}=Q鼴30q~_n% l7#r4 jb> 3!2Ar^q" #aUi#/P@N#%Bo )ϑe"ug #Dr9T+tgt#P)_"+6? &6b;OI(6!^fGes!{i#Ƒ)WuD{I; e]0=Cc/7nsQݱ $+uJ(66)¹}_LQ[ ~"I"I*@P\)xC"å(L+3cx,U&pJ*-~o'|J@pW_1ksFFO""`?&o3J!M_bv1ݭ' z)*ѕD!C f `Z0:X"*@`H%MDRJ-]SlY4Xس 5@ Ғ",:0i BӃC=KV-¬ln:a > Il{k,sR(1 Dnk-ؑd4(qD/?ViΦ_guӱ2}\p8ߒd FuXsJrPk'Jh9ͫv\Ϋ92S`X0g?hH" ; < cp3*8FZ5Ƣ ><(W$E_1ƒ$Bb. x[+=皫 OZ< n GtAN3q@#C  z;O-ծD 1n$2"83Is;*6eD4QE5̉bDh-R6DK ZkTI)mGdqBGrҸrM5tL0`pk=`)vAY &R cy$LM Ԃ: z/ 6L͑<-b.8OS뀽n@ "_Khtĉ\rʉ}gG_q& +p)Hƀ&.p "LHv}2ul݉ 9I2pi5XHows׾|-HsT]sӕϓ 8K?'ڧ,=bcD CrghI# 2>#ʵB!-Rˬ% /ؠ@(hBҵЅ/j`8CEQ7auCsɐ? 8D"ш8%6щO"pt(yZE.vы_c8F2ьgDcոF6эoc8G:юwcG>яd 9HBҐDd"HF6ґd$%9IJV2;