gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge bugfix #430 to branch 1.2
0 2 0
merge 1.2
1 file changed with 12 insertions and 4 deletions:
↑ Collapse diff ↑
Ignore white space 384 line context
... ...
@@ -1429,432 +1429,432 @@
1429 1429
      for(typename T1::MapIt i(t); i!=INVALID; ++i){
1430 1430
        colUpperBound(*i, value);
1431 1431
      }
1432 1432
    }
1433 1433
#endif
1434 1434

	
1435 1435
    /// Set the lower and the upper bounds of a column (i.e a variable)
1436 1436

	
1437 1437
    /// The lower and the upper bounds of
1438 1438
    /// a variable (column) have to be given by an
1439 1439
    /// extended number of type Value, i.e. a finite number of type
1440 1440
    /// Value, -\ref INF or \ref INF.
1441 1441
    void colBounds(Col c, Value lower, Value upper) {
1442 1442
      _setColLowerBound(cols(id(c)),lower);
1443 1443
      _setColUpperBound(cols(id(c)),upper);
1444 1444
    }
1445 1445

	
1446 1446
    ///\brief Set the lower and the upper bound of several columns
1447 1447
    ///(i.e variables) at once
1448 1448
    ///
1449 1449
    ///This magic function takes a container as its argument
1450 1450
    ///and applies the function on all of its elements.
1451 1451
    /// The lower and the upper bounds of
1452 1452
    /// a variable (column) have to be given by an
1453 1453
    /// extended number of type Value, i.e. a finite number of type
1454 1454
    /// Value, -\ref INF or \ref INF.
1455 1455
#ifdef DOXYGEN
1456 1456
    template<class T>
1457 1457
    void colBounds(T &t, Value lower, Value upper) { return 0;}
1458 1458
#else
1459 1459
    template<class T2>
1460 1460
    typename enable_if<typename T2::value_type::LpCol,void>::type
1461 1461
    colBounds(T2 &t, Value lower, Value upper,dummy<0> = 0) {
1462 1462
      for(typename T2::iterator i=t.begin();i!=t.end();++i) {
1463 1463
        colBounds(*i, lower, upper);
1464 1464
      }
1465 1465
    }
1466 1466
    template<class T2>
1467 1467
    typename enable_if<typename T2::value_type::second_type::LpCol, void>::type
1468 1468
    colBounds(T2 &t, Value lower, Value upper,dummy<1> = 1) {
1469 1469
      for(typename T2::iterator i=t.begin();i!=t.end();++i) {
1470 1470
        colBounds(i->second, lower, upper);
1471 1471
      }
1472 1472
    }
1473 1473
    template<class T2>
1474 1474
    typename enable_if<typename T2::MapIt::Value::LpCol, void>::type
1475 1475
    colBounds(T2 &t, Value lower, Value upper,dummy<2> = 2) {
1476 1476
      for(typename T2::MapIt i(t); i!=INVALID; ++i){
1477 1477
        colBounds(*i, lower, upper);
1478 1478
      }
1479 1479
    }
1480 1480
#endif
1481 1481

	
1482 1482
    /// Set the lower bound of a row (i.e a constraint)
1483 1483

	
1484 1484
    /// The lower bound of a constraint (row) has to be given by an
1485 1485
    /// extended number of type Value, i.e. a finite number of type
1486 1486
    /// Value or -\ref INF.
1487 1487
    void rowLowerBound(Row r, Value value) {
1488 1488
      _setRowLowerBound(rows(id(r)),value);
1489 1489
    }
1490 1490

	
1491 1491
    /// Get the lower bound of a row (i.e a constraint)
1492 1492

	
1493 1493
    /// This function returns the lower bound for row (constraint) \c c
1494 1494
    /// (this might be -\ref INF as well).
1495 1495
    ///\return The lower bound for row \c r
1496 1496
    Value rowLowerBound(Row r) const {
1497 1497
      return _getRowLowerBound(rows(id(r)));
1498 1498
    }
1499 1499

	
1500 1500
    /// Set the upper bound of a row (i.e a constraint)
1501 1501

	
1502 1502
    /// The upper bound of a constraint (row) has to be given by an
1503 1503
    /// extended number of type Value, i.e. a finite number of type
1504 1504
    /// Value or -\ref INF.
1505 1505
    void rowUpperBound(Row r, Value value) {
1506 1506
      _setRowUpperBound(rows(id(r)),value);
1507 1507
    }
1508 1508

	
1509 1509
    /// Get the upper bound of a row (i.e a constraint)
1510 1510

	
1511 1511
    /// This function returns the upper bound for row (constraint) \c c
1512 1512
    /// (this might be -\ref INF as well).
1513 1513
    ///\return The upper bound for row \c r
1514 1514
    Value rowUpperBound(Row r) const {
1515 1515
      return _getRowUpperBound(rows(id(r)));
1516 1516
    }
1517 1517

	
1518 1518
    ///Set an element of the objective function
1519 1519
    void objCoeff(Col c, Value v) {_setObjCoeff(cols(id(c)),v); };
1520 1520

	
1521 1521
    ///Get an element of the objective function
1522 1522
    Value objCoeff(Col c) const { return _getObjCoeff(cols(id(c))); };
1523 1523

	
1524 1524
    ///Set the objective function
1525 1525

	
1526 1526
    ///\param e is a linear expression of type \ref Expr.
1527 1527
    ///
1528 1528
    void obj(const Expr& e) {
1529 1529
      _setObjCoeffs(ExprIterator(e.comps.begin(), cols),
1530 1530
                    ExprIterator(e.comps.end(), cols));
1531 1531
      obj_const_comp = *e;
1532 1532
    }
1533 1533

	
1534 1534
    ///Get the objective function
1535 1535

	
1536 1536
    ///\return the objective function as a linear expression of type
1537 1537
    ///Expr.
1538 1538
    Expr obj() const {
1539 1539
      Expr e;
1540 1540
      _getObjCoeffs(InsertIterator(e.comps, cols));
1541 1541
      *e = obj_const_comp;
1542 1542
      return e;
1543 1543
    }
1544 1544

	
1545 1545

	
1546 1546
    ///Set the direction of optimization
1547 1547
    void sense(Sense sense) { _setSense(sense); }
1548 1548

	
1549 1549
    ///Query the direction of the optimization
1550 1550
    Sense sense() const {return _getSense(); }
1551 1551

	
1552 1552
    ///Set the sense to maximization
1553 1553
    void max() { _setSense(MAX); }
1554 1554

	
1555 1555
    ///Set the sense to maximization
1556 1556
    void min() { _setSense(MIN); }
1557 1557

	
1558 1558
    ///Clears the problem
1559 1559
    void clear() { _clear(); }
1560 1560

	
1561 1561
    /// Sets the message level of the solver
1562 1562
    void messageLevel(MessageLevel level) { _messageLevel(level); }
1563 1563

	
1564 1564
    ///@}
1565 1565

	
1566 1566
  };
1567 1567

	
1568 1568
  /// Addition
1569 1569

	
1570 1570
  ///\relates LpBase::Expr
1571 1571
  ///
1572 1572
  inline LpBase::Expr operator+(const LpBase::Expr &a, const LpBase::Expr &b) {
1573 1573
    LpBase::Expr tmp(a);
1574 1574
    tmp+=b;
1575 1575
    return tmp;
1576 1576
  }
1577 1577
  ///Substraction
1578 1578

	
1579 1579
  ///\relates LpBase::Expr
1580 1580
  ///
1581 1581
  inline LpBase::Expr operator-(const LpBase::Expr &a, const LpBase::Expr &b) {
1582 1582
    LpBase::Expr tmp(a);
1583 1583
    tmp-=b;
1584 1584
    return tmp;
1585 1585
  }
1586 1586
  ///Multiply with constant
1587 1587

	
1588 1588
  ///\relates LpBase::Expr
1589 1589
  ///
1590 1590
  inline LpBase::Expr operator*(const LpBase::Expr &a, const LpBase::Value &b) {
1591 1591
    LpBase::Expr tmp(a);
1592 1592
    tmp*=b;
1593 1593
    return tmp;
1594 1594
  }
1595 1595

	
1596 1596
  ///Multiply with constant
1597 1597

	
1598 1598
  ///\relates LpBase::Expr
1599 1599
  ///
1600 1600
  inline LpBase::Expr operator*(const LpBase::Value &a, const LpBase::Expr &b) {
1601 1601
    LpBase::Expr tmp(b);
1602 1602
    tmp*=a;
1603 1603
    return tmp;
1604 1604
  }
1605 1605
  ///Divide with constant
1606 1606

	
1607 1607
  ///\relates LpBase::Expr
1608 1608
  ///
1609 1609
  inline LpBase::Expr operator/(const LpBase::Expr &a, const LpBase::Value &b) {
1610 1610
    LpBase::Expr tmp(a);
1611 1611
    tmp/=b;
1612 1612
    return tmp;
1613 1613
  }
1614 1614

	
1615 1615
  ///Create constraint
1616 1616

	
1617 1617
  ///\relates LpBase::Constr
1618 1618
  ///
1619 1619
  inline LpBase::Constr operator<=(const LpBase::Expr &e,
1620 1620
                                   const LpBase::Expr &f) {
1621
    return LpBase::Constr(0, f - e, LpBase::INF);
1621
    return LpBase::Constr(0, f - e, LpBase::NaN);
1622 1622
  }
1623 1623

	
1624 1624
  ///Create constraint
1625 1625

	
1626 1626
  ///\relates LpBase::Constr
1627 1627
  ///
1628 1628
  inline LpBase::Constr operator<=(const LpBase::Value &e,
1629 1629
                                   const LpBase::Expr &f) {
1630 1630
    return LpBase::Constr(e, f, LpBase::NaN);
1631 1631
  }
1632 1632

	
1633 1633
  ///Create constraint
1634 1634

	
1635 1635
  ///\relates LpBase::Constr
1636 1636
  ///
1637 1637
  inline LpBase::Constr operator<=(const LpBase::Expr &e,
1638 1638
                                   const LpBase::Value &f) {
1639
    return LpBase::Constr(- LpBase::INF, e, f);
1639
    return LpBase::Constr(LpBase::NaN, e, f);
1640 1640
  }
1641 1641

	
1642 1642
  ///Create constraint
1643 1643

	
1644 1644
  ///\relates LpBase::Constr
1645 1645
  ///
1646 1646
  inline LpBase::Constr operator>=(const LpBase::Expr &e,
1647 1647
                                   const LpBase::Expr &f) {
1648
    return LpBase::Constr(0, e - f, LpBase::INF);
1648
    return LpBase::Constr(0, e - f, LpBase::NaN);
1649 1649
  }
1650 1650

	
1651 1651

	
1652 1652
  ///Create constraint
1653 1653

	
1654 1654
  ///\relates LpBase::Constr
1655 1655
  ///
1656 1656
  inline LpBase::Constr operator>=(const LpBase::Value &e,
1657 1657
                                   const LpBase::Expr &f) {
1658 1658
    return LpBase::Constr(LpBase::NaN, f, e);
1659 1659
  }
1660 1660

	
1661 1661

	
1662 1662
  ///Create constraint
1663 1663

	
1664 1664
  ///\relates LpBase::Constr
1665 1665
  ///
1666 1666
  inline LpBase::Constr operator>=(const LpBase::Expr &e,
1667 1667
                                   const LpBase::Value &f) {
1668
    return LpBase::Constr(f, e, LpBase::INF);
1668
    return LpBase::Constr(f, e, LpBase::NaN);
1669 1669
  }
1670 1670

	
1671 1671
  ///Create constraint
1672 1672

	
1673 1673
  ///\relates LpBase::Constr
1674 1674
  ///
1675 1675
  inline LpBase::Constr operator==(const LpBase::Expr &e,
1676 1676
                                   const LpBase::Value &f) {
1677 1677
    return LpBase::Constr(f, e, f);
1678 1678
  }
1679 1679

	
1680 1680
  ///Create constraint
1681 1681

	
1682 1682
  ///\relates LpBase::Constr
1683 1683
  ///
1684 1684
  inline LpBase::Constr operator==(const LpBase::Expr &e,
1685 1685
                                   const LpBase::Expr &f) {
1686 1686
    return LpBase::Constr(0, f - e, 0);
1687 1687
  }
1688 1688

	
1689 1689
  ///Create constraint
1690 1690

	
1691 1691
  ///\relates LpBase::Constr
1692 1692
  ///
1693 1693
  inline LpBase::Constr operator<=(const LpBase::Value &n,
1694 1694
                                   const LpBase::Constr &c) {
1695 1695
    LpBase::Constr tmp(c);
1696 1696
    LEMON_ASSERT(isNaN(tmp.lowerBound()), "Wrong LP constraint");
1697 1697
    tmp.lowerBound()=n;
1698 1698
    return tmp;
1699 1699
  }
1700 1700
  ///Create constraint
1701 1701

	
1702 1702
  ///\relates LpBase::Constr
1703 1703
  ///
1704 1704
  inline LpBase::Constr operator<=(const LpBase::Constr &c,
1705 1705
                                   const LpBase::Value &n)
1706 1706
  {
1707 1707
    LpBase::Constr tmp(c);
1708 1708
    LEMON_ASSERT(isNaN(tmp.upperBound()), "Wrong LP constraint");
1709 1709
    tmp.upperBound()=n;
1710 1710
    return tmp;
1711 1711
  }
1712 1712

	
1713 1713
  ///Create constraint
1714 1714

	
1715 1715
  ///\relates LpBase::Constr
1716 1716
  ///
1717 1717
  inline LpBase::Constr operator>=(const LpBase::Value &n,
1718 1718
                                   const LpBase::Constr &c) {
1719 1719
    LpBase::Constr tmp(c);
1720 1720
    LEMON_ASSERT(isNaN(tmp.upperBound()), "Wrong LP constraint");
1721 1721
    tmp.upperBound()=n;
1722 1722
    return tmp;
1723 1723
  }
1724 1724
  ///Create constraint
1725 1725

	
1726 1726
  ///\relates LpBase::Constr
1727 1727
  ///
1728 1728
  inline LpBase::Constr operator>=(const LpBase::Constr &c,
1729 1729
                                   const LpBase::Value &n)
1730 1730
  {
1731 1731
    LpBase::Constr tmp(c);
1732 1732
    LEMON_ASSERT(isNaN(tmp.lowerBound()), "Wrong LP constraint");
1733 1733
    tmp.lowerBound()=n;
1734 1734
    return tmp;
1735 1735
  }
1736 1736

	
1737 1737
  ///Addition
1738 1738

	
1739 1739
  ///\relates LpBase::DualExpr
1740 1740
  ///
1741 1741
  inline LpBase::DualExpr operator+(const LpBase::DualExpr &a,
1742 1742
                                    const LpBase::DualExpr &b) {
1743 1743
    LpBase::DualExpr tmp(a);
1744 1744
    tmp+=b;
1745 1745
    return tmp;
1746 1746
  }
1747 1747
  ///Substraction
1748 1748

	
1749 1749
  ///\relates LpBase::DualExpr
1750 1750
  ///
1751 1751
  inline LpBase::DualExpr operator-(const LpBase::DualExpr &a,
1752 1752
                                    const LpBase::DualExpr &b) {
1753 1753
    LpBase::DualExpr tmp(a);
1754 1754
    tmp-=b;
1755 1755
    return tmp;
1756 1756
  }
1757 1757
  ///Multiply with constant
1758 1758

	
1759 1759
  ///\relates LpBase::DualExpr
1760 1760
  ///
1761 1761
  inline LpBase::DualExpr operator*(const LpBase::DualExpr &a,
1762 1762
                                    const LpBase::Value &b) {
1763 1763
    LpBase::DualExpr tmp(a);
1764 1764
    tmp*=b;
1765 1765
    return tmp;
1766 1766
  }
1767 1767

	
1768 1768
  ///Multiply with constant
1769 1769

	
1770 1770
  ///\relates LpBase::DualExpr
1771 1771
  ///
1772 1772
  inline LpBase::DualExpr operator*(const LpBase::Value &a,
1773 1773
                                    const LpBase::DualExpr &b) {
1774 1774
    LpBase::DualExpr tmp(b);
1775 1775
    tmp*=a;
1776 1776
    return tmp;
1777 1777
  }
1778 1778
  ///Divide with constant
1779 1779

	
1780 1780
  ///\relates LpBase::DualExpr
1781 1781
  ///
1782 1782
  inline LpBase::DualExpr operator/(const LpBase::DualExpr &a,
1783 1783
                                    const LpBase::Value &b) {
1784 1784
    LpBase::DualExpr tmp(a);
1785 1785
    tmp/=b;
1786 1786
    return tmp;
1787 1787
  }
1788 1788

	
1789 1789
  /// \ingroup lp_group
1790 1790
  ///
1791 1791
  /// \brief Common base class for LP solvers
1792 1792
  ///
1793 1793
  /// This class is an abstract base class for LP solvers. This class
1794 1794
  /// provides a full interface for set and modify an LP problem,
1795 1795
  /// solve it and retrieve the solution. You can use one of the
1796 1796
  /// descendants as a concrete implementation, or the \c Lp
1797 1797
  /// default LP solver. However, if you would like to handle LP
1798 1798
  /// solvers as reference or pointer in a generic way, you can use
1799 1799
  /// this class directly.
1800 1800
  class LpSolver : virtual public LpBase {
1801 1801
  public:
1802 1802

	
1803 1803
    /// The problem types for primal and dual problems
1804 1804
    enum ProblemType {
1805 1805
      /// = 0. Feasible solution hasn't been found (but may exist).
1806 1806
      UNDEFINED = 0,
1807 1807
      /// = 1. The problem has no feasible solution.
1808 1808
      INFEASIBLE = 1,
1809 1809
      /// = 2. Feasible solution found.
1810 1810
      FEASIBLE = 2,
1811 1811
      /// = 3. Optimal solution exists and found.
1812 1812
      OPTIMAL = 3,
1813 1813
      /// = 4. The cost function is unbounded.
1814 1814
      UNBOUNDED = 4
1815 1815
    };
1816 1816

	
1817 1817
    ///The basis status of variables
1818 1818
    enum VarStatus {
1819 1819
      /// The variable is in the basis
1820 1820
      BASIC,
1821 1821
      /// The variable is free, but not basic
1822 1822
      FREE,
1823 1823
      /// The variable has active lower bound
1824 1824
      LOWER,
1825 1825
      /// The variable has active upper bound
1826 1826
      UPPER,
1827 1827
      /// The variable is non-basic and fixed
1828 1828
      FIXED
1829 1829
    };
1830 1830

	
1831 1831
  protected:
1832 1832

	
1833 1833
    virtual SolveExitStatus _solve() = 0;
1834 1834

	
1835 1835
    virtual Value _getPrimal(int i) const = 0;
1836 1836
    virtual Value _getDual(int i) const = 0;
1837 1837

	
1838 1838
    virtual Value _getPrimalRay(int i) const = 0;
1839 1839
    virtual Value _getDualRay(int i) const = 0;
1840 1840

	
1841 1841
    virtual Value _getPrimalValue() const = 0;
1842 1842

	
1843 1843
    virtual VarStatus _getColStatus(int i) const = 0;
1844 1844
    virtual VarStatus _getRowStatus(int i) const = 0;
1845 1845

	
1846 1846
    virtual ProblemType _getPrimalType() const = 0;
1847 1847
    virtual ProblemType _getDualType() const = 0;
1848 1848

	
1849 1849
  public:
1850 1850

	
1851 1851
    ///Allocate a new LP problem instance
1852 1852
    virtual LpSolver* newSolver() const = 0;
1853 1853
    ///Make a copy of the LP problem
1854 1854
    virtual LpSolver* cloneSolver() const = 0;
1855 1855

	
1856 1856
    ///\name Solve the LP
1857 1857

	
1858 1858
    ///@{
1859 1859

	
1860 1860
    ///\e Solve the LP problem at hand
Ignore white space 384 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#include <sstream>
20 20
#include <lemon/lp_skeleton.h>
21 21
#include "test_tools.h"
22 22
#include <lemon/tolerance.h>
23 23

	
24 24
#include <lemon/config.h>
25 25

	
26 26
#ifdef LEMON_HAVE_GLPK
27 27
#include <lemon/glpk.h>
28 28
#endif
29 29

	
30 30
#ifdef LEMON_HAVE_CPLEX
31 31
#include <lemon/cplex.h>
32 32
#endif
33 33

	
34 34
#ifdef LEMON_HAVE_SOPLEX
35 35
#include <lemon/soplex.h>
36 36
#endif
37 37

	
38 38
#ifdef LEMON_HAVE_CLP
39 39
#include <lemon/clp.h>
40 40
#endif
41 41

	
42 42
using namespace lemon;
43 43

	
44 44
void lpTest(LpSolver& lp)
45 45
{
46 46

	
47 47
  typedef LpSolver LP;
48 48

	
49 49
  std::vector<LP::Col> x(10);
50 50
  //  for(int i=0;i<10;i++) x.push_back(lp.addCol());
51 51
  lp.addColSet(x);
52 52
  lp.colLowerBound(x,1);
53 53
  lp.colUpperBound(x,1);
54 54
  lp.colBounds(x,1,2);
55 55

	
56 56
  std::vector<LP::Col> y(10);
57 57
  lp.addColSet(y);
58 58

	
59 59
  lp.colLowerBound(y,1);
60 60
  lp.colUpperBound(y,1);
61 61
  lp.colBounds(y,1,2);
62 62

	
63 63
  std::map<int,LP::Col> z;
64 64

	
65 65
  z.insert(std::make_pair(12,INVALID));
66 66
  z.insert(std::make_pair(2,INVALID));
67 67
  z.insert(std::make_pair(7,INVALID));
68 68
  z.insert(std::make_pair(5,INVALID));
69 69

	
70 70
  lp.addColSet(z);
71 71

	
72 72
  lp.colLowerBound(z,1);
73 73
  lp.colUpperBound(z,1);
74 74
  lp.colBounds(z,1,2);
75 75

	
76 76
  {
77 77
    LP::Expr e,f,g;
78 78
    LP::Col p1,p2,p3,p4,p5;
79 79
    LP::Constr c;
80 80

	
81 81
    p1=lp.addCol();
82 82
    p2=lp.addCol();
83 83
    p3=lp.addCol();
84 84
    p4=lp.addCol();
85 85
    p5=lp.addCol();
86 86

	
87 87
    e[p1]=2;
88 88
    *e=12;
89 89
    e[p1]+=2;
90 90
    *e+=12;
91 91
    e[p1]-=2;
92 92
    *e-=12;
93 93

	
94 94
    e=2;
95 95
    e=2.2;
96 96
    e=p1;
97 97
    e=f;
98 98

	
99 99
    e+=2;
100 100
    e+=2.2;
101 101
    e+=p1;
102 102
    e+=f;
103 103

	
104 104
    e-=2;
105 105
    e-=2.2;
106 106
    e-=p1;
107 107
    e-=f;
108 108

	
109 109
    e*=2;
110 110
    e*=2.2;
111 111
    e/=2;
112 112
    e/=2.2;
113 113

	
114 114
    e=((p1+p2)+(p1-p2)+(p1+12)+(12+p1)+(p1-12)+(12-p1)+
115 115
       (f+12)+(12+f)+(p1+f)+(f+p1)+(f+g)+
116 116
       (f-12)+(12-f)+(p1-f)+(f-p1)+(f-g)+
117 117
       2.2*f+f*2.2+f/2.2+
118 118
       2*f+f*2+f/2+
119 119
       2.2*p1+p1*2.2+p1/2.2+
120 120
       2*p1+p1*2+p1/2
121 121
       );
122 122

	
123 123

	
124 124
    c = (e  <= f  );
125 125
    c = (e  <= 2.2);
126 126
    c = (e  <= 2  );
127 127
    c = (e  <= p1 );
128 128
    c = (2.2<= f  );
129 129
    c = (2  <= f  );
130 130
    c = (p1 <= f  );
131 131
    c = (p1 <= p2 );
132 132
    c = (p1 <= 2.2);
133 133
    c = (p1 <= 2  );
134 134
    c = (2.2<= p2 );
135 135
    c = (2  <= p2 );
136 136

	
137 137
    c = (e  >= f  );
138 138
    c = (e  >= 2.2);
139 139
    c = (e  >= 2  );
140 140
    c = (e  >= p1 );
141 141
    c = (2.2>= f  );
142 142
    c = (2  >= f  );
143 143
    c = (p1 >= f  );
144 144
    c = (p1 >= p2 );
145 145
    c = (p1 >= 2.2);
146 146
    c = (p1 >= 2  );
147 147
    c = (2.2>= p2 );
148 148
    c = (2  >= p2 );
149 149

	
150 150
    c = (e  == f  );
151 151
    c = (e  == 2.2);
152 152
    c = (e  == 2  );
153 153
    c = (e  == p1 );
154 154
    c = (2.2== f  );
155 155
    c = (2  == f  );
156 156
    c = (p1 == f  );
157 157
    //c = (p1 == p2 );
158 158
    c = (p1 == 2.2);
159 159
    c = (p1 == 2  );
160 160
    c = (2.2== p2 );
161 161
    c = (2  == p2 );
162 162

	
163 163
    c = ((2 <= e) <= 3);
164 164
    c = ((2 <= p1) <= 3);
165 165

	
166 166
    c = ((2 >= e) >= 3);
167 167
    c = ((2 >= p1) >= 3);
168 168

	
169
    { //Tests for #430
170
      LP::Col v=lp.addCol();
171
      LP::Constr c = v >= -3;
172
      c = c <= 4;
173
      LP::Constr c2;
174
      c2 = -3 <= v <= 4;
175
    }
176

	
169 177
    e[x[3]]=2;
170 178
    e[x[3]]=4;
171 179
    e[x[3]]=1;
172 180
    *e=12;
173 181

	
174 182
    lp.addRow(-LP::INF,e,23);
175 183
    lp.addRow(-LP::INF,3.0*(x[1]+x[2]/2)-x[3],23);
176 184
    lp.addRow(-LP::INF,3.0*(x[1]+x[2]*2-5*x[3]+12-x[4]/3)+2*x[4]-4,23);
177 185

	
178 186
    lp.addRow(x[1]+x[3]<=x[5]-3);
179 187
    lp.addRow((-7<=x[1]+x[3]-12)<=3);
180 188
    lp.addRow(x[1]<=x[5]);
181 189

	
182 190
    std::ostringstream buf;
183 191

	
184 192

	
185 193
    e=((p1+p2)+(p1-0.99*p2));
186 194
    //e.prettyPrint(std::cout);
187 195
    //(e<=2).prettyPrint(std::cout);
188 196
    double tolerance=0.001;
189 197
    e.simplify(tolerance);
190 198
    buf << "Coeff. of p2 should be 0.01";
191 199
    check(e[p2]>0, buf.str());
192 200

	
193 201
    tolerance=0.02;
194 202
    e.simplify(tolerance);
195 203
    buf << "Coeff. of p2 should be 0";
196 204
    check(const_cast<const LpSolver::Expr&>(e)[p2]==0, buf.str());
197 205

	
198 206
    //Test for clone/new
199 207
    LP* lpnew = lp.newSolver();
200 208
    LP* lpclone = lp.cloneSolver();
201 209
    delete lpnew;
202 210
    delete lpclone;
203 211

	
204 212
  }
205 213

	
206 214
  {
207 215
    LP::DualExpr e,f,g;
208 216
    LP::Row p1 = INVALID, p2 = INVALID, p3 = INVALID,
209 217
      p4 = INVALID, p5 = INVALID;
210 218

	
211 219
    e[p1]=2;
212 220
    e[p1]+=2;
213 221
    e[p1]-=2;
214 222

	
215 223
    e=p1;
216 224
    e=f;
217 225

	
218 226
    e+=p1;
219 227
    e+=f;
220 228

	
221 229
    e-=p1;
222 230
    e-=f;
223 231

	
224 232
    e*=2;
225 233
    e*=2.2;
226 234
    e/=2;
227 235
    e/=2.2;
228 236

	
229 237
    e=((p1+p2)+(p1-p2)+
230 238
       (p1+f)+(f+p1)+(f+g)+
231 239
       (p1-f)+(f-p1)+(f-g)+
232 240
       2.2*f+f*2.2+f/2.2+
233 241
       2*f+f*2+f/2+
234 242
       2.2*p1+p1*2.2+p1/2.2+
235 243
       2*p1+p1*2+p1/2
236 244
       );
237 245
  }
238 246

	
239 247
}
240 248

	
241 249
void solveAndCheck(LpSolver& lp, LpSolver::ProblemType stat,
242 250
                   double exp_opt) {
243 251
  using std::string;
244 252
  lp.solve();
245 253

	
246 254
  std::ostringstream buf;
247 255
  buf << "PrimalType should be: " << int(stat) << int(lp.primalType());
248 256

	
249 257
  check(lp.primalType()==stat, buf.str());
250 258

	
251 259
  if (stat ==  LpSolver::OPTIMAL) {
252 260
    std::ostringstream sbuf;
253 261
    sbuf << "Wrong optimal value (" << lp.primal() <<") with "
254 262
         << lp.solverName() <<"\n     the right optimum is " << exp_opt;
255 263
    check(std::abs(lp.primal()-exp_opt) < 1e-3, sbuf.str());
256 264
  }
257 265
}
258 266

	
259 267
void aTest(LpSolver & lp)
260 268
{
261 269
  typedef LpSolver LP;
262 270

	
263 271
 //The following example is very simple
264 272

	
265 273
  typedef LpSolver::Row Row;
266 274
  typedef LpSolver::Col Col;
267 275

	
268 276

	
269 277
  Col x1 = lp.addCol();
270 278
  Col x2 = lp.addCol();
271 279

	
272 280

	
273 281
  //Constraints
274 282
  Row upright=lp.addRow(x1+2*x2 <=1);
275 283
  lp.addRow(x1+x2 >=-1);
276 284
  lp.addRow(x1-x2 <=1);
277 285
  lp.addRow(x1-x2 >=-1);
278 286
  //Nonnegativity of the variables
279 287
  lp.colLowerBound(x1, 0);
280 288
  lp.colLowerBound(x2, 0);
281 289
  //Objective function
282 290
  lp.obj(x1+x2);
283 291

	
284 292
  lp.sense(lp.MAX);
285 293

	
286 294
  //Testing the problem retrieving routines
287 295
  check(lp.objCoeff(x1)==1,"First term should be 1 in the obj function!");
288 296
  check(lp.sense() == lp.MAX,"This is a maximization!");
289 297
  check(lp.coeff(upright,x1)==1,"The coefficient in question is 1!");
290 298
  check(lp.colLowerBound(x1)==0,
291 299
        "The lower bound for variable x1 should be 0.");
292 300
  check(lp.colUpperBound(x1)==LpSolver::INF,
293 301
        "The upper bound for variable x1 should be infty.");
294 302
  check(lp.rowLowerBound(upright) == -LpSolver::INF,
295 303
        "The lower bound for the first row should be -infty.");
296 304
  check(lp.rowUpperBound(upright)==1,
297 305
        "The upper bound for the first row should be 1.");
298 306
  LpSolver::Expr e = lp.row(upright);
299 307
  check(e[x1] == 1, "The first coefficient should 1.");
300 308
  check(e[x2] == 2, "The second coefficient should 1.");
301 309

	
302 310
  lp.row(upright, x1+x2 <=1);
303 311
  e = lp.row(upright);
304 312
  check(e[x1] == 1, "The first coefficient should 1.");
305 313
  check(e[x2] == 1, "The second coefficient should 1.");
306 314

	
307 315
  LpSolver::DualExpr de = lp.col(x1);
308 316
  check(  de[upright] == 1, "The first coefficient should 1.");
309 317

	
310 318
  LpSolver* clp = lp.cloneSolver();
311 319

	
312 320
  //Testing the problem retrieving routines
313 321
  check(clp->objCoeff(x1)==1,"First term should be 1 in the obj function!");
314 322
  check(clp->sense() == clp->MAX,"This is a maximization!");
315 323
  check(clp->coeff(upright,x1)==1,"The coefficient in question is 1!");
316 324
  //  std::cout<<lp.colLowerBound(x1)<<std::endl;
317 325
  check(clp->colLowerBound(x1)==0,
318 326
        "The lower bound for variable x1 should be 0.");
319 327
  check(clp->colUpperBound(x1)==LpSolver::INF,
320 328
        "The upper bound for variable x1 should be infty.");
321 329

	
322 330
  check(lp.rowLowerBound(upright)==-LpSolver::INF,
323 331
        "The lower bound for the first row should be -infty.");
324 332
  check(lp.rowUpperBound(upright)==1,
325 333
        "The upper bound for the first row should be 1.");
326 334
  e = clp->row(upright);
327 335
  check(e[x1] == 1, "The first coefficient should 1.");
328 336
  check(e[x2] == 1, "The second coefficient should 1.");
329 337

	
330 338
  de = clp->col(x1);
331 339
  check(de[upright] == 1, "The first coefficient should 1.");
332 340

	
333 341
  delete clp;
334 342

	
335 343
  //Maximization of x1+x2
336 344
  //over the triangle with vertices (0,0) (0,1) (1,0)
337 345
  double expected_opt=1;
338 346
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
339 347

	
340 348
  //Minimization
341 349
  lp.sense(lp.MIN);
342 350
  expected_opt=0;
343 351
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
344 352

	
345 353
  //Vertex (-1,0) instead of (0,0)
346 354
  lp.colLowerBound(x1, -LpSolver::INF);
347 355
  expected_opt=-1;
348 356
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
349 357

	
350 358
  //Erase one constraint and return to maximization
351 359
  lp.erase(upright);
352 360
  lp.sense(lp.MAX);
353 361
  expected_opt=LpSolver::INF;
354 362
  solveAndCheck(lp, LpSolver::UNBOUNDED, expected_opt);
355 363

	
356 364
  //Infeasibilty
357 365
  lp.addRow(x1+x2 <=-2);
358 366
  solveAndCheck(lp, LpSolver::INFEASIBLE, expected_opt);
359 367

	
360 368
}
0 comments (0 inline)