This is Info file pm.info, produced by Makeinfo version 1.68 from the
input file bigpm.texi.


File: pm.info,  Node: Math/Financial,  Next: Math/FixedPrecision,  Prev: Math/FFT,  Up: Module List

Calculates figures relating to loans and annuities.
***************************************************

NAME
====

   Math::Financial - Calculates figures relating to loans and annuities.

SYNOPSIS
========

   $calc = new Math::Financial(fv => 100000, pv => 1000); $calc->set->(pmt
=> 500, ir => 8);

   $calc->compound_interest(find => 'fv');

DESCRIPTION
===========

   This package contains solves mathematical problems relating to loans
and annuities.

   The attributes that are used in the equations may be set on a
per-object basis, allowing you to run a set of different calculations
using the same numbers, or they may be fed directly to the methods.

   The attribute types, accessed through the get and set methods are

pv	=> 	Present Value
fv	=> 	Future Value
ir	=>  Yearly Interest Rate (in percent)
pmt	=>	Payment Amount
np	=>	Number of Payments/Loan Term
tpy	=>	Terms Per Year (defaults to 12)
pd	=>	Payments made so far (used only for loan/annuity balances)
   Attributes are case-insensitive.  The documentation for the individual
methods indicates which attributes must be set for those methods.

   Calculations are based *either* on the attributes set with the new or
set methods, or with arguments fed directly to the methods.  This seemed
like the least confusing way to make the interface flexible for people who
are using the module in different ways.

   Also, performing a calculation does not update the attribute of the
solution.  In other words, if you solve an equation that returns fv, the
solution is returned but the internal fv field is unaffected.

   Any attempted calculation which cannot be completed - due to either
missing or invalid attributes - will return undef.

   I am interested to hear from people using this module - let me know what
you think about the interface and how it can be improved.

METHODS
=======

new
---

   C<$calc = new Math::Financial();

   `$calc = new Math::Financial(pv => 10000, ir => 5, np =' 12)>

   Object constructor.  See above for a description of the available
attributes.  You do not *have* to set attributes here, you can also do so
using set, or feed attributes directly to the methods.

   There are no default values for any of the attributes except `TPY'
(Terms Per Year), which is 12 by default, and `PD' which defaults to zero.

   If you don't want to use the object-oriented interface, see the
`EXPORTS' in this node section below.

set
---

   `$calc->set(fv => 100000, pmt => 500)'

   You can set any of the stored attributes using this method, which is is
also called by <new>.  Returns the number of attributes set.

get
---

   `$calc->get(field =' 'ir')>

   `$calc->get('ir','pmt','pv')'

   `$calc->get([qw(ir pmt pv)])'

   You can get one or several attributes using this method.  In the
multiple attribute formats, it accepts either a list or a list reference
as input.

   In single attribute context, returns a scalar.  In multiple attribute
context, it returns a list or a reference to a list, depending on the
calling context.

compound_interest
-----------------

   `$calc->compound_interest'

   `$calc->compound_interest->('fv')'

   `$calc->compound_interest->(find => 'fv')'

   Calculates compund interest for an annuity.  With any 3 of pv, fv, np,
and ir, you can always solve the fourth.

   Without arguments, the method will attempt to figure out what you'd
like to solve based on what attributes of the object are defined.
Usually, you'll probably want to explicitly request what attribute you'd
like returned, which you can do using the second or third method.

funding_annuity
---------------

   `$calc->funding_annuity'

   `$calc->funding_annuity->(pmt => 2000, ir => 6.50, np => 40, tpy =' 4)>

   funding_annuity calculates how much money ( fv ) you will have at the
end of np periods if you deposit pmt into the account each period and the
account earns ir interest per year.

   You may want to set the tpy attribute here to something other than 12,
since, while loans usually compound monthly, annuities rarely do.

loan_balance
------------

   `$calc->loan_balance'

   `$calc->loan_balance->(pmt => 2000, ir => 6.50, np => 360, pd => 12)'

   loan_balance calculates the balance on a loan that is being made in np
equal payments, given that pd payments have already been made. You can
also use this method to determine the amount of money left in an annuity
that you are drawing down.

loan_payment
------------

   `$calc->loan_payment'

   Return the payment amount, per period, of a loan.  This is also known
as amortizing.  The ir, np, and pv fields must be set.

loan_size
---------

   `$calc->loan_term'

   `$calc->loan_size->(pmt => 2000, ir => 6.50, np => 360)'

   loan_size calculates the size of loan you can get based on the monthly
payment you can afford.

loan_term
---------

   `$calc->loan_term'

   Return the number of payments (term) of a loan given the interest rate
ir, payment amount pmt and loan amount pv.   The ir, pmt, and pv fields
must be set.

simple_interest
---------------

   `$calc->simple_interest'

   `$calc->simple_interest->('ir')'

   `$calc->simple_interest->(find => 'ir')'

   This works just like compound interest, but there is no consideration
of np.  With any 2 of pv, fv, and ir, you can always solve for the third.

   Without arguments, the method will attempt to figure out what you'd
like to solve based on what attributes of the object have been defined.
Usually, you'll probably want to explicitly request what attribute you'd
like returned, which you can do using the second or third method.

REQUIRES
========

   POSIX - c_type functions

   (c_types might work under Windows.  I really don't know.  I'd
appreciate it if someome would let me know.  If they don't, in a future
release, I'll provide a runtime replacement for the POSIX functions so
it'll work on Win releases.  )

EXPORTS
=======

   By default, nothing.

   If you'd like to use a procedural interface, you can `use
Math::Financial qw(:standard)'.

   Then you can call the methods as function, without an object reference,
like

   `$term = loan_term(ir => 6.5, pmt => 1000, pv => 200000);'

   All of the methods are exported in this fashion, except for set and
get; this just seemed too confusing.

   You can still use the facility of set and get with the procedural
interface (i.e., you can set the attributes and them use them for many
different calculations), but you must call them as `Math::Financial::set'
and `Math::Financial::get'.

AUTHOR
======

   Eric Fixler <fix@fixler.com>, 1999

TODO
====

   Add more equations!  Send me equations and I'll put them in.

ACKNOWLEDGEMENTS
================

   Larry Freeman, whose Financial Formulas Page
`http://ourworld.compuserve.com/homepages/Larry_Freeman/finance.htm' was
essential for this project.


File: pm.info,  Node: Math/FixedPrecision,  Next: Math/Fortran,  Prev: Math/Financial,  Up: Module List

Decimal Math without Floating Point Errors
******************************************

NAME
====

   Math::FixedPrecision - Decimal Math without Floating Point Errors

SYNOPSIS
========

   use Math::FixedPrecision; $height  = Math::FixedPrecision->new(12.362);
 # 3 decimal places $width   = Math::FixedPrecision->new(9.65);     # 2
decimal places $area    = $height * $width; # area is now 119.29 not
119.2933 $length  = Math::FixedPrecision->new("100.00"); # 2 decimal places
$section = $length / 9; # section is now 11.11 not 11.1111111...

DESCRIPTION
===========

   There are numerous instances where floating point math is unsuitable,
yet the data does not consist solely of integers.  This module is designed
to completely overload all standard math functions.  The module takes care
of all conversion and rounding automatically.  Rounding is handled using
the IEEE 754 standard even mode.  This is a complete rewrite to use
Math::BigFloat, rather than Math::BigInt to handle the underlying math
operations.

   This module is not a replacement for Math::BigFloat; rather it serves a
similar but slightly different purpose.  By strictly limiting precision
automatically, this module operates slightly more natually than
Math::BigFloat when dealing with floating point numbers of limited
accuracy.  Math::BigFloat can unintentially inflate the apparent accuracy
of a calculation.

   Please examine assumptions you are operating under before deciding
between this module and Math::BigFloat.  With this module the assumption
is that your data is not very accurate and you do not want to overstate
any resulting values; with Math::BigFloat, you can completely avoid the
rounding problems associated with floating point notation.

new(number[,precision])
-----------------------

   The constructor accepts either a number or a string that looks like a
number.  But if you want to enforce a specific precision, you either need
to pass an exact string or include the second term.  In other words, all
of the following variables have different precisions:

   $var1 = Math::FixedPrecision->new(10);           # 10 to infinite
decimals   $var2 = Math::FixedPrecision->new(10,2);           # 10.00 to 2
decimals   $var3 = Math::FixedPrecision->new("10.000");           # 10.000
to 3 decimals

   All calculations will return a value rounded to the level of precision
of the least precise datum.  A number which looks like an integer (like
$var1 above) has infinite precision (no decimal places).  This is
important to note since Perl will happily truncate all trailing zeros from
a number like 10.000 and the code will get 10 no matter how many zeros you
typed.  If you need to assert a specific precision, you need to either
explicitly state that like $var2 above, or quote the number like $var3.
For example:

     $var4 = $var3 * 2; # 20.000 to 3 decimals
     $var5 = Math::FixedPrecision->new("2.00");
             # 2.00 to 2 decimals
     $var6 = $var3 * $var 5;
             # 20.00 to 2 decimals, not 3

EXPORT None by default.
-----------------------

AUTHOR
======

   John Peacock <jpeacock@rowman.com>

SEE ALSO
========

   Math::BigFloat


File: pm.info,  Node: Math/Fortran,  Next: Math/Fraction,  Prev: Math/FixedPrecision,  Up: Module List

SYNOPSIS
========

     use Math::Fortran qw(log10 sign);
     $v=log10($x);
     $v=sign($y);
     $v=sign($x,$y);

DESCRIPTION
===========

   This module provides and exports some mathematical functions which are
built in in Fortran but not in Perl. Currently there are only 2 included.

log10 log to the base of 10 =item sign with 1 parameter, +1 if $y>=0, -1 otherwise, with 2 parameters +abs($x) if $y>=0, -abs($x) otherwise.
HISTORY
=======

   $Log: Fortran.pm,v $ Revision 1.1  1995/12/26 09:43:01  willijar
Initial revision

BUGS
====

   I welcome other entries for this module and bug reports.

AUTHOR
======

   John A.R. Williams <J.A.R.Williams@aston.ac.uk>


File: pm.info,  Node: Math/Fraction,  Next: Math/FractionDemo,  Prev: Math/Fortran,  Up: Module List

To Manipulate Exact Fractions (v.53b, Beta Release)
***************************************************

NAME
====

   Math::Fraction - To Manipulate Exact Fractions (v.53b, Beta Release)

SYNOPSIS
========

     use Math::Fraction;

     $a = frac(1,2); $b = frac(6,7);

     print "$a + $b = ", $a + $b, "$a * $b = ", $a * $b;
     print $a->num;

DESCRIPTION
===========

   This program is meant to replace the old bigrat perl library.  It can do
everything it can do and a lot more.

   Some of its features include:

   * Being able to add, subtract, multiply, and divide, among other things
     just like you would normal numbers that's to the overload module.

   * Being able to convert a decimal, including repeating ones, into a
     fraction.  For example, 1.142857142857 would become 8/7.

   * Being able to control how the fraction is displayed.  For example 8/7
     verses 1 1/7

   * Being able to use arbitrary size numbers in the numerator and the
     denominator.

   * Being able to covert between SMALL (using normal floats/integers) and
     BIG (using arbitrary size floats/integers) as needed so you do not
     have to worry about it. (New as of ver .4a)

   * Being able to have multiple default sets so that a function can modify
     the defaults with out effecting other functions (New as of ver .4a)

Usage
-----

     frac(FRACTION, TAGS) || Math::Fraction->new(FRACTION, TAGS)
     ex $f1=frac(2,3); $f2=frac(7,3,MIXED); $f3=frac("-10 3/4");

   FRACTION can equal any of the following:

(Numerator, Denominator)
(Number, Numerator, Denominator)
Decimal
"Numerator/Denominator"
"Number Numerator/Denominator"
   Any of these numbers can be any real number however if you enter in
negative numbers in anything but the First Number for the Mixed (3
numbers) the negative will be ignored.

   TAGS can equal 0, one or more of the following

NORMAL|MIXED|MIXED_RAW|RAW|DEF_MIXED
     Controls How the fraction is displayed:

    NORMAL
          display it in the #/# form

    MIXED_RAW
          display it in the # #/# form

    MIXED
          the same as MIXED_RAW but if one part is equal to 0 it will
          leave it off

    RAW
          the same as NORAML but always includes the sign

    DEF_MIXED
          will let it be what ever the default value is at the time

REDUCE|NO_REDUCE|DEF_REDUCE
     Controls the automatic reduction of fraction after operations are
     performed on it.

AUTO|NO_AUTO|DEF_AUTO
     Set rether to automatically convert between BIG and SMALL as needed
     see `Notes on the AUTO tag' in this node.

SMALL|BIG|DEF_BIG
     When the AUTO tag is NOT set it will set whether to use
     Arbitrary-Length numbers using the Math::BigInt and Math::BigFloat
     package. (Not the ** operator will not work however due to
     limitations of the packages.)  When the AUTO tag is set these tags
     will have NO effect.  (Note the default tags are NORMAL REDUCE AUTO
     and SMALL)

Methods
-------

reduce
     returns a reduced fraction but leaves the original object untouched.

string(NORMAL|MIXED|MIXED_RAW|RAW)
     returns the fraction as a string.  if no parameters are given the
     objects default display method will be used.

decimal|num
     returned the decimal value of the fraction

list|list(MIXED)
     returns a list containing the fraction if MIXED is used than a 3 item
     list is returned.

is_tag
     returns 1 is that tag exists in the fraction undef if is set to the
     default -1 otherwise

is_tag(INC_DEF)
     returns 1 is that tag exists in the fraction -1 if is tag does not
     exist but the default is set to that, 0 otherwise.

tags
     returns a list of the objects tags

tags(INC_DEF)
     returns a list of the objects tags if a particular tag is set to read
     a default the default tag is returned instead.

   All of the above methods may all be exported so that they can be used
as functions with a fraction as their first parameter. The string,
decimal|num functions can be imported with the tag STR_NUM instead of
having to list each one.

modify
     modifies the object.  Works almost the same as the new method but it
     doesn't return anything and preserves the objects tags unless
     overridden by new entries

modify_reduce
     same as reduce but it modifies the object instead of returning a
     fraction.

modify_num(Numerator)
     modifies the fraction's numerator.

modify_den(Denominator)
     modified the fraction's denominator.

modify_tag(TAGS)
     modifies the fraction tags.

   The is_tag, tags, and modify_tags methods can be used on the class its
self to get at or modify the default tags.

   The following methods will always modify or read the Class defaults

digits
     returns the default number of digests to return when doing floating
     point operations with BIG numbers, if set to undef Math::BigFloat
     will decide.

          modify_digits(NUM)

Dafault Sets
------------

   Default sets are way of modifying the defaults with out effecting other
functions.  Functions that relay on the default values or modify the
default should start with a `$set_id = temp_set' and end with a
`temp_set($set_id)'.

   See `"EXAMPLES"' in this node for examples of how default sets work.

   The following methods are met to manage default sets and will always
work on the Class defaults.

sets
     returns a list of all the sets;

name_set
     return the name of the current set.

name_set(NAME)
     name the current set

save_set
     saves the current sent based on its name as given above

save_set(NAME)
     save the current set as NAME

save_set(RAND)
     save the current set using a unique name

load_set(NAME)
     loads a set.

copy_set(NAME_ORG, NAME_NEW)
     copies a set. Returns true if successful.

del_set(NAME)
     deletes a set.

exists_set(NAME)
     returns true if the set exists.

use_set(NAME)
     uses a set, that is any changes you make to the used set will also
     change the original set, like a link.

temp_set
     loads a temp set using the default default values and returns a
     unique id you need to keep.

temp_set(ID)
     restores the original set based on the id you should of kept.

   Unless otherwise specified all the set methods will return the name of
the set being worked on if it was successful, false otherwise

tags(SET)
     lists all the tags in SET.

is_tag(TAG, SET)
     returns true if TAG exists in SET

digits(SET)
     returns what digits is set to in SET;

Overloaded Operators
--------------------

   The following operations have been overridden and will return a
fraction:

     +  -  /  *  +  +=  -=  *=  /=  ++  -- abs

   The following operations have also been overridden:

     <=> == != < <= > >=

   The following operations have also been overridden however they may spit
out nasty fractions.

     ** sqrt

   Whenever you try to access a fraction as a string the string method
will be called and when try to access it as a number the decimal method
will be called.

   This means that almost all other operations will work however some might
return decimals like the sin and cos;

Notes on the AUTO tag
---------------------

   With the AUTO tag set Fractions will be converted between SMALL and BIG
as needed.  The BIG and SMALL tag will be **ignorded** unless you
explicitly specify NO_AUTO in auto to control how the fraction is stored.

   When you give it a number it will decide if it is small enough to be
stored as a SMALL or if the fraction needs to converted to BIG.  However,
in order for it to recognize a big fraction the number needs to be in
quotes, thus `frac(7823495784957895478,781344567825678454)' will still be
stored as a small with some of the digits lost.

   When calculating to SMALL numbers that results in a number that is to
big for SMALL the calculation is done AGAIN but this time with BIG numbers
(so that it will calculate all the digits correctly) and the new fraction
will become a BIG.

   When calculating to BIG numbers that results in a number that is small
enough to be a SMALL the new fraction will become a SMALL.

   Normally, the AUTO tag will save time as calculating with BIG numbers
can be quite time consuming however it might slow thinks down if it
constantly converts between the two thus in some cases it may be wise to
turn it off.

EXAMPLES
========

   This is a small demonstration of what the fraction module can do.

   It is run for the most part with these two functions.

     sub pevel {print ">$_[0]\n"; $ans = eval $_[0]; print " $ans\n"; }
     sub evelp {print ">$_[0]\n"; eval $_[0]; }

   You can see it for yourself my typing in `perl -e "use
Math::FractionDemo; frac_calc;"' then frac_demo.

     >frac(1, 3)
      1/3
     >frac(4, 3, MIXED)
      1 1/3
     >frac(1, 1, 3)
      4/3
     >frac(1, 1, 3, MIXED)
      1 1/3
     >frac(10)
      10/1
     >frac(10, MIXED)
      10
     >frac(.66667)
      2/3
     >frac(1.33333, MIXED)
      1 1/3
     >frac("5/6")
      5/6
     >frac("1 2/3")
      5/3
     >frac(10, 20, NO_REDUCE)
      10/20

     >$f1=frac(2,3); $f2=frac(4,5);
     >$f1 + $f2
      22/15
     >$f1 * $f2
      8/15
     >$f1 + 1.6667
      7/3
     >$f2->modify_tag(MIXED)
     >$f2 + 10
      10 4/5
     >frac($ans, NORMAL) # trick to create new fraction with different tags
      54/5
     >$f1 + $f2          # Add two unlikes it goes to default mode
      22/15
     >$f1**1.2
      229739670999407/373719281884655
     >$f1->num**1.2
      0.614738607654485
     >frac(1,2)+frac(2,5)
      9/10

     >$f1=frac(5,3,NORMAL); $f2=frac(7,5);
     >"$f1  $f2"
      5/3  7/5
     >Math::Fraction->modify_tag(MIXED)
     >"$f1  $f2"
      5/3  1 2/5
     >$f1 = frac("3267893629762/32678632179820")
      3267893629762/32678632179820
     >$f2 = frac("5326875886785/76893467996910")
      5326875886785/76893467996910
     >$f1->is_tag(BIG).",".$f2->is_tag(BIG) # Notice how neither is BIG
      0,0
     >$f1+$f2
      21267734600460495169085706/125638667885089122116217810
     >$ans->is_tag(BIG)                     # But this answer is.
      1
     >$f1*$f2
      1740766377695750621849517/251277335770178244232435620
     >$ans->is_tag(BIG)                     # And so is this one.
      1

     >$f1 = frac("3267893629762/32678632179820", BIG)
      3267893629762/32678632179820
     >$f1->is_tag(BIG)   # Notice how the big tag had no effect.
      0
     >$f1->modify_tag(NO_AUTO, BIG)
     >$f1->is_tag(BIG)   # But now it does.  You have to turn off AUTO.
      1
     >$f1->num
      .10000093063197482237806917498797382196606
     >Math::Fraction->modify_digits(15)
     >$f1->num
      .1000009306319748
     >$f1 = frac("0.1231231234564564564564564564561234567891234567891234")
      13680347037037036999999999999963000037/
                                 111111111000000000000000000000000000000
     >Math::Fraction->modify_digits(65)
     >$f1->num
      .123123123456456456456456456456123456789123456789123456789123456789

     >$f1 = frac(7,5);
     >$f2 = frac("3267893629762/32678632179820", NO_AUTO, BIG)
     >Math::Fraction->modify_tag(MIXED); Math::Fraction->modify_digits(60)
     >"$f1 ".$f2->num
      1 2/5 .1000009306319748223780691749879738219660647769485035912494771
     >Math::Fraction->load_set(DEFAULT)
     >"$f1 ".$f2->num
      7/5 .10000093063197482237806917498797382196606
     >Math::Fraction->modify_digits(25)
     >"$f1 ".$f2->num
      7/5 .10000093063197482237806917
     >$s = Math::Fraction->temp_set
     >Math::Fraction->modify_tag(MIXED); Math::Fraction->modify_digits(15)
     >"$f1 ".$f2->num
      1 2/5 .1000009306319748
     >Math::Fraction->temp_set($s)
     >Math::Fraction->exists_set($s)
     
     >"$f1 ".$f2->num  # Notice how it goes back to the previous settings.
      7/5 .10000093063197482237806917
     
     >Math::Fraction->name_set('temp1')
     >Math::Fraction->modify_tag(MIXED, NO_AUTO)
     >Math::Fraction->modify_digits(60)
     >&s(Math::Fraction->tags, Math::Fraction->digits)
      MIXED REDUCE SMALL NO_AUTO 60
     >Math::Fraction->save_set  # If no name is given it will be saved via
     >                          # its given name
     >Math::Fraction->load_set(DEFAULT)
     >&s(Math::Fraction->tags, Math::Fraction->digits)
      NORMAL REDUCE SMALL AUTO undef
     >&s(Math::Fraction->tags('temp1'), Math::Fraction->digits('temp1'))
      MIXED REDUCE SMALL NO_AUTO 60
     >  # ^^ Notice how this lets you preview other sets w/out loading them.
     >Math::Fraction->load_set(DEFAULT)
     >Math::Fraction->use_set('temp1')
     >Math::Fraction->modify_tag(NO_REDUCE)
     >&s(Math::Fraction->tags, Math::Fraction->digits)
      MIXED NO_REDUCE SMALL NO_AUTO 60
     >&s(Math::Fraction->tags('temp1'), Math::Fraction->digits('temp1'))
      MIXED NO_REDUCE SMALL NO_AUTO 60
     >  # ^^ Notice how this also modifies the temp1 tag becuase it is
     >  #    being used if it was just loaded it would not do this
     >  #    becuase there is no link.

NOTES
=====

   Beta Release

   Originally Developed with Perl v 5.003_37 for Win32.

   Has been testing on Perl Ver 5.003 on a solaris machine and perl 5.004
on Windows 95.

   Built on a Linux 2 machine with perl v5.003.

   Please send me feedback at kevina@clark.net

   This is my first real attempt at writing a Perl Module and at
Object-Oriented Programming. (Although I know this is not a true-true
Object-Oriented Module as I cheated a little). I mainly wrote it to teach
my self how to program Object-Oriently in Perl and for the challenge.

   If you know of any faster or simpler way of doing any this please let me
know.

SEE ALSO
========

   *Note Math/FractionDemo: Math/FractionDemo,, `perl(1b)' in this node

AUTHOR and COPYRIGHT
====================

   Kevin Atkinson, kevina@clark.net

   Copyright (c) 1997 Kevin Atkinson.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.


File: pm.info,  Node: Math/FractionDemo,  Next: Math/GMP,  Prev: Math/Fraction,  Up: Module List

Math::Fraction demo script (v.51b, Beta Release)
************************************************

NAME
====

   Math::FractionDemo - Math::Fraction demo script (v.51b, Beta Release)

SYNOPSIS
========

   `perl -e "use Math::FractionDemo; frac_calc;"'

DESCRIPTION
===========

   This is nothing but a simple perl "calculator" and demo script.

Functions
---------

frac_calc
     A simple perl "calculator" for trying out the Math::Fraction package.

frac_demo [OUTPUT] [,INDENT]
     A simple demo script.  OUTPUT will default to STDOUT unless otherwise
     specified.  If OUTPUT is STDOUT it will run interactivly otehrwsise
     it will dump the results to the OUTPUT file stream.

     INDENT controles how many spaces each line is indented.  INDENT
     defaults to 0 unless otherwise specified.

     This script can also be run from frac_calc.

SEE ALSO
========

   *Note Math/Fraction: Math/Fraction,, `perl(1p)' in this node

AUTHOR and COPYRIGHT
====================

   Kevin Atkinson, kevina@clark.net

   Copyright (c) 1997 Kevin Atkinson.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.


File: pm.info,  Node: Math/GMP,  Next: Math/Geometry,  Prev: Math/FractionDemo,  Up: Module List

High speed arbitrary size integer math
**************************************

NAME
====

   Math::GMP - High speed arbitrary size integer math

SYNOPSIS
========

     use Math::GMP;
     my $n = new Math::GMP 2;

     $n = $n ** (256*1024);
     $n = $n - 1;
     print "n is now $n\n";

DESCRIPTION
===========

   Math::GMP is designed to be a drop-in replacement both for Math::BigInt
and for regular integer arithmetic.  Unlike BigInt, though, Math::GMP uses
the GNU gmp library for all of its calculations, as opposed to straight
Perl functions.  This results in a speed increase of anywhere from 5 to 30
times.  The downside is that this module requires a C compiler to install
- a small tradeoff in most cases.

   A Math::GMP object can be used just as a normal numeric scalar would be
- the module overloads the normal arithmetic operators to provide as
seamless an interface as possible.  However, if you need a perfect
interface, you can do the following:

     use Math::GMP qw(:constant);

     $n = 2 ** (256 * 1024);
     print "n is $n\n";

   This would fail without the ':constant' since Perl would use normal
doubles to compute the 250,000 bit number, and thereby overflow it into
meaninglessness (smaller exponents yield less accurate data due to
floating point rounding).

BUGS
====

   As of version 1.0, Math::GMP is mostly compatible with Math::BigInt.
There are some slight incompatibilities, such as output of positive
numbers not being prefixed by a '+' sign.  This is intentional.

   The install process of the gmp library is rather contrived.  This needs
fixing and testing on various platforms.

AUTHOR
======

   Chip Turner <chip@zfx.com>, based on Math::BigInt by Mark Biggar and
Ilya Zakharevich.


File: pm.info,  Node: Math/Geometry,  Next: Math/Integral/Romberg,  Prev: Math/GMP,  Up: Module List

Geometry related functions
**************************

NAME
====

   Math::Geometry - Geometry related functions

SYNOPSIS
========

     use Math::Geometry;

     @P2=rotx(@P1,$angle);
     @P3=rotx(@P1,$angle);
     @N =triangle_normal(@P1,@P2,@P3);
     @ZP=zplane_project(@P1,$d);

NOTES
=====

   Currently for zplane_project onto a plane with normal of the z axis and
z=0, the function returns the orthographic projections as opposed to a
perspective projection. I'm currently looking into how to properly handle
z=0 and will update it shortly.

DESCRIPTION
===========

   This package implements classic geometry methods. It should be
considered alpha software and any feedback at all is greatly appreciated.
The following methods are available:

vector_product.
---------------

   Also known as the cross product, given two vectors in Geometry space,
the vector_product of the two vectors, is a vector which is perpendicular
to the plane of AB with length equal to the length of A multiplied by the
length of B, multiplied by the sin of @, where @ is the angle between the
two vectors.

triangle_normal
---------------

   Given a triangle ABC that defines a plane P. This function will return
a vector N, which is a normal to the plane P.

     ($Nx,$Ny,$Nz) =
        triangle_normal(($Ax,$Ay,$Az),($Bx,$By,$Bz),($Cx,$Cy,$Cz));

zplane_project
--------------

   Project a point in Geometry space onto a plane with the z-axis as the
normal, at a distance d from z=0.

     ($x2,$y2,$z2) = zplane_project ($x1,$y1,$z1,$d);

rotx
----

   Rotate about the x axis r radians.

   ($x2,$y2,$z2) = rotx ($x1,$y1,$z1,$r);

roty
----

   Rotate about the y axis r radians.

   ($x2,$y2,$z2) = roty ($x1,$y1,$z1,$r);

rotz
----

   Rotate about the z axis r radians.

   ($x2,$y2,$z2) = rotz ($x1,$y1,$z1,$r);

deg2rad
-------

   Convert degree's to radians.

rad2deg
-------

   Convert radians to degree's.

pi
--

   Returns an approximate value of Pi, the code has been cribed from
Pg146, Programming Perl 2nd Ed.

EXAMPLE
=======

     use Math::Geometry;

AUTHOR
======

     Greg McCarroll <greg@mccarroll.demon.co.uk>


File: pm.info,  Node: Math/Integral/Romberg,  Next: Math/Interpolate,  Prev: Math/Geometry,  Up: Module List

scalar numerical integration
****************************

NAME
====

     Math::Integral::Romberg - scalar numerical integration

SYNOPSIS
========

     use Math::Integral::Romberg 'integral';
     $area = integral(\&f, $x1, $x2);    # Short form
     $area = integral                    # Long form
      (\&f, $x1, $x2, $rel_err, $abs_err, $max_split, $min_split);

     # an alternative way of doing the long form
     $Math::Integral::Romberg::rel_err = $rel_err;
     $Math::Integral::Romberg::abs_err = $abs_err;
     $Math::Integral::Romberg::max_split = $max_split;
     $Math::Integral::Romberg::min_split = $min_split;
     $area = integral(\&f, $x1, $x2);

DESCRIPTION
===========

   integral() numerically estimates the integral of f() using Romberg
integration, a faster relative of Simpson's method.

Parameters
----------

$f
     A reference to the function to be integrated.

$x1, $x2
     The two extreme values of the range to be integrated.  `&$f(x)' must
     be finite at $x1 and $x2.

$rel_err
     Maximum acceptable relative error . Estimates of relative and
     absolute error are based on a comparison of the estimate computed
     using `2**n + 1' points with the estimate computed using `2**(n-1) +
     1' points.

     Once $min_split has been reached (see below), computation stops as
     soon as relative error drops below $rel_err, absolute error drops
     below $abs_err, or $max_split is reached.

     If not supplied, uses the value *$Math::Integral::Romberg::rel_err*
     whose default is 10**-10. A value of 10**-15 is close to the accuracy
     limits of double-precision floating point.

$abs_err
     Maximum acceptable absolute error. If not supplied uses
     *$Math::Integral::Romberg::abs_err*, which defaults to 10**-20.

$max_split
     At most `2 ** $max_split + 1' different sample x values are used to
     estimate the integral of `f()'. If not supplied, uses the value of
     *$Math::Integral::Romberg::max_split*, which defaults to 16,
     corresponding to 65537 sample points.

$min_split
     At least `2 ** $min_split + 1' different sample x values are used to
     estimate the integral of `f()'. If not supplied, uses the value of
     *$Math::Integral::Romberg::max_split*, which defaults to 5,
     corresponding to 33 sample points.

$Math::Integral::Romberg::return_point_count
     This value defaults to 0.  If you set it to 1, then when invoked in a
     list context, integral() will return a two-element list, containing
     the estimate followed by the number of sample points used to compute
     the estimate.

$Math::Integral::Romberg::abort
     This value is set to 1 if neither the $rel_err nor the $abs_err
     thresholds are reached before computation stops.  Once set, this
     variable remains set until you reset it to 0.

Default values
--------------

   Using the long form of integral() sets the convergence parameters for
that call only - you must use the package-qualified variable names (e.g.
$Math::Integral::Romberg::abs_tol) to change the values for all calls.

About the Algorithm
-------------------

   Romberg integration uses progressively higher-degree polynomial
approximations each time you double the number of sample points.  For
example, it uses a 2nd-degree polynomial approximation (as Simpson's
method does) after one split (2**1 + 1 sample points), and it uses a
10th-degree polynomial approximation after five splits (2**5 + 1 sample
points).  Typically, this will greatly improve accuracy (compared to
simpler methods) for smooth functions, while not making much difference
for badly behaved ones.

AUTHOR
======

   Eric Boesch (ebo@notes.dannet.dk)


File: pm.info,  Node: Math/Interpolate,  Next: Math/IntervalSearch,  Prev: Math/Integral/Romberg,  Up: Module List

Interpolate the value Y from X using a list of (X, Y) pairs
***********************************************************

NAME
====

   Math::Interpolate - Interpolate the value Y from X using a list of (X,
Y) pairs

SYNOPSIS
========

     use Math::Interpolate qw(derivatives constant_interpolate
                              linear_interpolate robust_interpolate);
     my @x = (1..5);
     my @y = (5, 10, 13, -4.5, 3);
     my @dy = derivatives(\@x, \@y);
     my ($l_y, $l_dy) = linear_interpolate(3.4, \@x, \@y);
     my ($r_y, $r_dy) = robust_interpolate(3.4, \@x, \@y);
     ($r_y, $r_dy) = robust_interpolate(3.4, \@x, \@y, [-2, 3, 4, -1, 4]);

DESCRIPTION
===========

SUBROUTINES
===========

derivatives *x_sequence* *y_sequence*
     Given a reference to an array of x values in *x_sequence* and a
     reference to an array of y values in *y_sequence*, return an array of
     reasonable derivatives.  The *x_sequence* values are presumed to be
     sorted in increasing numerical order.

     If there is an error in the input, such as *x_sequence* and
     *y_sequence* containing a different number of elements, then the
     subroutine returns an empty list in list context, an undefined value
     in scalar context, or nothing in a void context.

constant_interpolate x *x_sequence* *y_sequence*
     Given a reference to an array of x values in *x_sequence* and a
     reference to an array of y values in *y_sequence*, return the y value
     associated with the first x value less than or equal to x.  In other
     words, if    *x_sequence*->[i] <= x < *x_sequence*->[i+1]

     then return    *y_sequence*->[i]

     If x is less than *x_sequence*->[0], then return *y_sequence*->[0].
     If x is greater than *x_sequence-*[-1], then return
     *y_sequence*->[-1].

     If there is an error in the input, such as *x_sequence* and
     *y_sequence* containing a different number of elements, then the
     subroutine returns an empty list in list context, an undefined value
     in scalar context, or nothing in a void context.

linear_interpolate x *x_sequence* *y_sequence*
     Given a reference to an array of x values in *x_sequence* and a
     reference to an array of y values in *y_sequence*, calculate the
     interpolated value y that corresponds to the value x.  The returned
     value y lies on the straight line between the two points surrounding
     x.  If <x> lies outside of the range of values spanned by
     *x_sequence* then a linear extrapolation will be done.

     In an array context, linear_interpolate will return an array
     containing the y value and and slope between the two nearest
     surrounding points.

     If there is an error in the input, such as *x_sequence* and
     *y_sequence* containing a different number of elements, then the
     subroutine returns an empty list in list context, an undefined value
     in scalar context, or nothing in a void context.

robust_interpolate value *x_sequence* *y_sequence* [*dy_sequence*]
     Given a reference to an array of x values in *x_sequence* and a
     reference to an array of y values in *y_sequence*, calculate the
     interpolated value y that corresponds to the value x.  The
     interpolated curve generated by robust_interpolate is smooth and even
     the derivatives of the curve are smooth with only a few exceptions.

     The returned value y lies on the curve between the two points
     surrounding x.  If <x> lies outside of the range of values spanned by
     *x_sequence* then a linear extrapolation will be done.

     In an array context, linear_interpolate will return an array
     containing the y value and and slope between the two nearest
     surrounding points.

     If there is an error in the input, such as *x_sequence* and
     *y_sequence* containing a different number of elements, then the
     subroutine returns an empty list in list context, an undefined value
     in scalar context, or nothing in a void context.

AUTHOR
======

   Blair Zajac <bzajac@geostaff.com>.

COPYRIGHT
=========

   Copyright (c) 1998 by Blair Zajac.


File: pm.info,  Node: Math/IntervalSearch,  Next: Math/Kleene,  Prev: Math/Interpolate,  Up: Module List

Search where an element lies in a list of sorted elements
*********************************************************

NAME
====

   Math::IntervalSearch - Search where an element lies in a list of sorted
elements

SYNOPSIS
========

     use Math::IntervalSearch qw(interval_search);
     my @array = (1..5);
     my $location = interval_search(2.4, \@array);

     # Use your own comparison operators.
     sub ReverseLessThan {
       $_[0] < $_[1];
     }

     sub ReverseLessThanEqualTo {
       $_[0] <= $_[1];
     }

     $location = interval_search(2.4,
                                 \@array,
                                 \&ReverseLessThan,
                                 \&ReverseLessThanEqualTo);

DESCRIPTION
===========

   This subroutine is used to locate a position in an array of values where
a given value would fit.  It has been designed to be efficient in the
common situation that it is called repeatedly.  The user can supply a
different set of comparison operators to replace the standard < and <=.

SUBROUTINES
===========

interval_search value sequence [*less_than* [*less_than_equal_to*]]
     Given a value interval_search returns the location in the reference
     to an array sequence where the value would fit.  The default <
     operator to compare the elements in sequence can be replaced by the
     subroutine *less_than* which should return 1 if the first element
     passed to *less_than* is less than the second.  The default <=
     operator to compare the elements in sequence can be replaced by the
     subroutine *less_than* which should return 1 if the first element
     passed to *less_than* is less than the second.

     The values in sequence should already be sorted in numerically
     increasing order or in the order that would be produced by using the
     *less_than* subroutine.

     Let N be the number of elements in referenced array sequence, then
     interval_search returns these values:     -1  if
     value < sequence->[0]     i   if sequence->[i]   <= value <
     sequence->[i+1]     N-1 if sequence->[N-1] <= value

     If a reference is made to an empty array, then -1 is always returned.

     If there is illegal input to interval_search, such as an improper
     number of arguments, then an empty list in list context, an undefined
     value in scalar context, or nothing in a void context is returned.

     This subroutine is designed to be efficient in the common situation
     that it is called repeatedly, with value taken from an increasing or
     decreasing list of values.  This will happen, e.g., when an irregular
     waveform is interpolated to create a sequence with constant
     separation.  The first guess for the output is therefore taken to be
     the value returned at the previous call and stored in the variable
     ilo.  A first check ascertains that ilo is less than the number of
     data points in sequence.  This is necessary since the present call
     may have nothing to do with the previous call.  Then, if
     sequence->[ilo] <= value < sequence->[ilo+1],

     we set left = ilo and are done after just three comparisons.
     Otherwise, we repeatedly double the difference     istep = ihi - ilo

     while also moving ilo and ihi in the direction of x, until
     sequence->[ilo] <= x < sequence->[ihi],

     after which bisection is used to get, in addition,     ilo+1 = ihi.

     Then left = ilo is returned.

AUTHOR
======

   Blair Zajac <bzajac@geostaff.com>.

COPYRIGHT
=========

   Copyright (c) 1998 by Blair Zajac.


File: pm.info,  Node: Math/Kleene,  Next: Math/LP,  Prev: Math/IntervalSearch,  Up: Module List

the theory behind it
********************

NAME
====

   Kleene's Algorithm - the theory behind it

   brief introduction

DESCRIPTION
===========

Semi-Rings
----------

   A Semi-Ring (S, +, ., 0, 1) is characterized by the following
properties:

  1. a)  `(S, +, 0) is a Semi-Group with neutral element 0'

     b)  `(S, ., 1) is a Semi-Group with neutral element 1'

     c)  `0 . a = a . 0 = 0  for all a in S'

  2. `"+"' is commutative and *idempotent*, i.e., `a + a = a'

  3. Distributivity holds, i.e.,

     a)  `a . ( b + c ) = a . b + a . c  for all a,b,c in S'

     b)  `( a + b ) . c = a . c + b . c  for all a,b,c in S'

  4. `SUM_{i=0}^{+infinity} ( a[i] )'

     exists, is well-defined and unique

     `for all a[i] in S'

     and associativity, commutativity and idempotency hold

  5. Distributivity for infinite series also holds, i.e.,

          ( SUM_{i=0}^{+infty} a[i] ) . ( SUM_{j=0}^{+infty} b[j] )
          = SUM_{i=0}^{+infty} ( SUM_{j=0}^{+infty} ( a[i] . b[j] ) )

        EXAMPLES:

   * `S1 = ({0,1}, |, &, 0, 1)'

     Boolean Algebra

     See also `Math::MatrixBool(3)' in this node

   * `S2 = (pos. reals with 0 and +infty, min, +, +infty, 0)'

     Positive real numbers including zero and plus infinity

     See also `Math::MatrixReal(3)' in this node

   * `S3 = (Pot(Sigma*), union, concat, {}, {''})'

     Formal languages over Sigma (= alphabet)

     See also `DFA::Kleene(3)' in this node

Operator '*'
------------

   (reflexive and transitive closure)

   Define an operator called "*" as follows:

     a in S   ==>   a*  :=  SUM_{i=0}^{+infty} a^i

   where

     a^0  =  1,   a^(i+1)  =  a . a^i

   Then, also

     a*  =  1 + a . a*,   0*  =  1*  =  1

   hold.

Kleene's Algorithm
------------------

   In its general form, Kleene's algorithm goes as follows:

     for i := 1 to n do
         for j := 1 to n do
         begin
             C^0[i,j] := m(v[i],v[j]);
             if (i = j) then C^0[i,j] := C^0[i,j] + 1
         end
     for k := 1 to n do
         for i := 1 to n do
             for j := 1 to n do
                 C^k[i,j] := C^k-1[i,j] +
                             C^k-1[i,k] . ( C^k-1[k,k] )* . C^k-1[k,j]
     for i := 1 to n do
         for j := 1 to n do
             c(v[i],v[j]) := C^n[i,j]

Kleene's Algorithm and Semi-Rings
---------------------------------

   Kleene's algorithm can be applied to any Semi-Ring having the properties
listed previously (above). (!)

   EXAMPLES:

   * `S1 = ({0,1}, |, &, 0, 1)'

     `G(V,E)' be a graph with set of vortices V and set of edges E:

     `m(v[i],v[j])  :=  ( (v[i],v[j]) in E ) ? 1 : 0'

     Kleene's algorithm then calculates

     `c^{n}_{i,j} = ( path from v[i] to v[j] exists ) ? 1 : 0'

     using

     `C^k[i,j]  =  C^k-1[i,j]  |  C^k-1[i,k]  &  C^k-1[k,j]'

     (remember ` 0*  =  1*  =  1 ')

   * `S2 = (pos. reals with 0 and +infty, min, +, +infty, 0)'

     `G(V,E)' be a graph with set of vortices V and set of edges E, with
     costs `m(v[i],v[j])' associated with each edge `(v[i],v[j])' in E:

     `m(v[i],v[j])  :=  costs of (v[i],v[j])'

     `for all (v[i],v[j]) in E'

     Set `m(v[i],v[j]) := +infinity' if an edge (v[i],v[j]) is not in E.

     `  ==>  a* = 0  for all a in S2'

     `  ==>  C^k[i,j]  =  min( C^k-1[i,j] ,'

     `           C^k-1[i,k]  +  C^k-1[k,j] )'

     Kleene's algorithm then calculates the costs of the "shortest" path
     from any `v[i]' to any other `v[j]':

     `C^n[i,j] = costs of "shortest" path from v[i] to v[j]'

   * `S3 = (Pot(Sigma*), union, concat, {}, {''})'

     `M in DFA(Sigma)' be a Deterministic Finite Automaton with a set of
     states Q, a subset F of Q of accepting states and a transition
     function `delta : Q x Sigma --> Q'.

     Define

     `m(v[i],v[j])  :='

     `    { a in Sigma | delta( q[i] , a ) = q[j] }'

     and

     `C^0[i,j] := m(v[i],v[j]);'

     `if (i = j) then C^0[i,j] := C^0[i,j] union {''}'

     (`{''}' is the set containing the empty string, whereas `{}' is the
     empty set!)

     Then Kleene's algorithm calculates the language accepted by
     Deterministic Finite Automaton M using

     `C^k[i,j] = C^k-1[i,j] union'

     `    C^k-1[i,k] concat ( C^k-1[k,k] )* concat C^k-1[k,j]'

     and

     `L(M)  =  UNION_{ q[j] in F }  C^n[1,j]'

     (state `q[1]' is assumed to be the "start" state)

     finally being the language recognized by Deterministic Finite
     Automaton M.

   Note that instead of using Kleene's algorithm, you can also use the "*"
operator on the associated matrix:

   Define  `A[i,j]  :=  m(v[i],v[j])'

   `  ==>   A*[i,j]  =  c(v[i],v[j])'

   Proof:

   `A*  =  SUM_{i=0}^{+infty} A^i'

   where  `A^0  =  E_{n}'

   (matrix with one's in its main diagonal and zero's elsewhere)

   and  `A^(i+1)  =   A . A^i'

   Induction over k yields:

   `A^k[i,j]  =  c_{k}(v[i],v[j])'

`k = 0:'
     `c_{0}(v[i],v[j])  =  d_{i,j}'

     with  `d_{i,j}  :=  (i = j) ? 1 : 0'

     and  `A^0  =  E_{n}  =  [d_{i,j}]'

`k-1 -> k:'
     `c_{k}(v[i],v[j])'

     `= SUM_{l=1}^{n} m(v[i],v[l]) . c_{k-1}(v[l],v[j])'

     `= SUM_{l=1}^{n} ( a[i,l] . a[l,j] )'

     `= [a^{k}_{i,j}]  =  A^1 . A^(k-1)  =  A^k'

   qed

   In other words, the complexity of calculating the closure and doing
matrix multiplications is of the same order `O( n^3 )' in Semi-Rings!

SEE ALSO
========

   Math::MatrixBool(3), Math::MatrixReal(3), DFA::Kleene(3).

   (All contained in the distribution of the "Set::IntegerFast" module)

   Dijkstra's algorithm for shortest paths.

AUTHOR
======

   This document is based on lecture notes and has been put into POD
format by Steffen Beyer <sb@sdm.de>.

COPYRIGHT
=========

   Copyright (c) 1997 by Steffen Beyer. All rights reserved.


File: pm.info,  Node: Math/LP,  Next: Math/LP/Constraint,  Prev: Math/Kleene,  Up: Module List

Object oriented interface to solving of linear programs using the lp_solve library
**********************************************************************************

NAME
====

   Math::LP - Object oriented interface to solving of linear programs
using the lp_solve library

SYNOPSIS
========

     use Math::LP qw(:types);             # imports optimization types
     use Math::LP::Constraint qw(:types); # imports constraint types

     # make a new LP
     $lp = new Math::LP;

     # make the variables for the LP
     $x1 = new Math::LP::Variable(name => 'x1');
     $x2 = new Math::LP::Variable(name => 'x2');

     # maximize the objective function to x1 + 2 x2
     $obj_fn = make Math::LP::LinearCombination($x1,1.0,$x2,2.0);
     $lp->maximize_for($obj_fn);

     # add the constraint x1 + x2 <= 2
     $constr = new Math::LP::Constraint(
         lhs  => make Math::LP::LinearCombination($x1,1.0,$x2,1.0),
         rhs  => 2.0,
         type => $LE,
     );
     $lp->add_constraint($constr);
     
     # solve the LP and print the results
     $lp->solve() or die "Could not solve the LP";
     print "Optimum = ", $obj_fn->{value}, "\n";
     print "x1 = ", $x1->{value}, "\n";
     print "x2 = ", $x1->{value}, "\n";
     print "slack = ", $constr->{slack}, "\n";

DESCRIPTION
===========

   The Math::LP package provides an object oriented interface to defining
and solving mixed linear/integer programs. It uses the lp_solve library as
the underlying solver. Please note that this is not a two way relation. An
LP is defined using Math::LP, converted to an lp_solve data structure, and
solved with lp_solve functions. It is not possible to grab an lp_solve
structure somehow and convert it to a Math::LP object for manipulation and
inspection. If you want to do that kind of stuff in Perl, use the
Math::LP::Solve package instead.

   That being said, the logical way of constructing an LP consists of

  1. Construct Math::LP::Variable objects, in the meanwhile marking
     integer variables

  2. Construct Math::LP::LinearCombination objects with the variables and
     use them as the objective function and constraints

  3. Solve the LP

  4. Fetch the variable values from the Math::LP::Variable objects, the
     slacks and dual values from the Math::LP::Constraint objects.  and
     the row values (including the optimum) from the corresponding
     Math::LP::LinearCombination.


DATA FIELDS
===========

solver_status
     Holds the status of the last solve() call.  Can be either $OPTIMAL,
     $MILP_FAIL, $INFEASIBLE, $UNBOUNDED, $FAILURE, $RUNNING, $FEAS_FOUND,
     $NO_FEAS_FOUND or $BREAK_BB.

variables
     A ref to a hash with all the Math::LP::Variable objects used in the
     LP indexed on their name.

constraints
     A ref to an array with all Math::LP::Constraint objects used in the
     LP.

objective_function
     A Math::LP::LinearCombination object representing the objective
     function

type
     The optimization type. Can be either $MAX or $MIN.

METHODS
=======

new()
     returns a new, empty LP

nr_rows()
     returns the number of rows, i.e. the number of constraints in the LP

nr_cols()
     returns the number of columns, i.e. the number of variables in the LP

add_variable($var)
     registers the variable as belonging to the LP. The index field of the
     variable is set as a side effect. For this reason it is not allowed
     to use 1 variable in 2 LP objects.

add_constraint($constr)
     adds a Math::LP::Constraint to the LP. The index field of the
     constraint is likewise set. It is thus also not allowed to use a
     single constraint in more than 1 LP. All variables present in the
     constraint are automatically registered.

set_objective_function($lincomb,$type)
     sets the objective function of the LP, specified by the following
     parameters:

    $lincomb
          a Math::LP::LinearCombination forming the objective function.
          New variables in the linear combination are automatically added
          to the LP.

    $type
          the optimization type, either $MAX or $MIN

maximize_for($lincomb)
     shortcut for set_objective_function($lincomb,$MAX)

minimize_for($lincomb)
     shortcut for set_objective_function($lincomb,$MIN)

solve([$lag_solve])
     Solves the LP, returns true if succeeded (i.e. the status value is
     $OPTIMAL), false otherwise. The status of the solver is available in
     the status field afterwards. The default is to solve using solve().
     If however $lag_solve is specified and true, lag_solve() will be used.

optimum()
     Returns the value of the objective function obtained by the solver.

SEE ALSO
========

   More info on the packages used in Math::LP is found in *Note
Math/LP/Object: Math/LP/Object,, *Note Math/LP/Variable: Math/LP/Variable,
and *Note Math/LP/LinearCombination: Math/LP/LinearCombination,.

   The underlying wrapper to the lp_solve library is documented in
`Math::LP::Solve' in this node. More info on using the lp_solve library
written by Michel Berkelaar and adapted by Jeroen Dirks is found in its
source code available from ftp://ftp.ics.ele.tue.nl/pub/lp_solve/

AUTHOR
======

   Wim Verhaegen <wim.verhaegen@ieee.org>

COPYRIGHT
=========

   Copyright(c) 2000 Wim Verhaegen. All rights reserved.  This program is
free software; you can redistribute and/or modify it under the same terms
as Perl itself.


