Ticket #13518: trac_13518_sens_analysis_imp.patch

File trac_13518_sens_analysis_imp.patch, 11.1 KB (added by Nathann Cohen, 10 years ago)

glpk_backend extensions for sensitivity analysis (updated2)

  • sage/numerical/backends/glpk_backend.pxd

    # HG changeset patch
    # User Christian Kuper <christian.kuper@t-online.de>
    # Date 1353698007 -3600
    # Node ID 17f316e74bf5c6b03258e9c9fda82bc8d5ecc895
    # Parent  23061edf00176562a9d754123cfebbb8e3f631d3
    Trac 13518: GLPK Backend extensions for sensitivity analysis
    
    diff --git a/sage/numerical/backends/glpk_backend.pxd b/sage/numerical/backends/glpk_backend.pxd
    a b  
    7676     void glp_delete_prob(c_glp_prob *)
    7777     double glp_get_col_prim(c_glp_prob *, int)
    7878     double glp_get_obj_val(c_glp_prob *)
     79     double glp_get_col_dual(c_glp_prob *, int)
     80     double glp_get_row_dual(c_glp_prob *, int)
     81     int glp_print_ranges(c_glp_prob *lp, int,int, int, char *fname)
    7982     int glp_get_num_rows(c_glp_prob *)
    8083     int glp_get_num_cols(c_glp_prob *)
    8184     double glp_mip_col_val(c_glp_prob *, int)
     
    203206    cdef c_glp_smcp * smcp
    204207    cdef int simplex_or_intopt
    205208    cpdef GLPKBackend copy(self)
     209
     210    cpdef int print_ranges(self, char * filename = *) except -1
     211    cpdef double get_row_dual(self, int variable)
     212    cpdef double get_col_dual(self, int variable)
  • sage/numerical/backends/glpk_backend.pyx

    diff --git a/sage/numerical/backends/glpk_backend.pyx b/sage/numerical/backends/glpk_backend.pyx
    a b  
    66- Nathann Cohen (2010-10): initial implementation
    77- John Perry (2012-01): glp_simplex preprocessing
    88- John Perry and Raniere Gaia Silva (2012-03): solver parameters
     9- Christian Kuper (2012-10): Additions for sensitivity analysis
    910"""
    1011
    1112##############################################################################
     
    8788            sage: p.add_variable(continuous=True, integer=True)
    8889            Traceback (most recent call last):
    8990            ...
    90             ValueError: ...            
     91            ValueError: ...           
    9192            sage: p.add_variable(name='x',obj=1.0)
    9293            3
    9394            sage: p.col_name(3)
     
    12311232            1
    12321233            sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
    12331234            sage: p.set_objective([2, 5])
    1234             sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))
     1235            sage: p.write_mps(os.path.join(SAGE_TMP, "lp_problem.mps"), 2)
    12351236        """
    12361237        glp_write_mps(self.lp, modern, NULL,  filename)
    12371238
     
    14551456
    14561457         * - ``iteration_limit``
    14571458
    1458            - (int) iteration limit of the simplex algorithn.  The default is
     1459           - (int) iteration limit of the simplex algorithm.  The default is
    14591460             ``INT_MAX``.
    14601461
    14611462         * - ``presolve_simplex``
     
    17031704        else:
    17041705            raise ValueError("This parameter is not available.")
    17051706
     1707
     1708    cpdef int print_ranges(self, char * filename = NULL) except -1:
     1709        r"""
     1710        Print results of a sensitivity analysis
     1711
     1712        If no filename is given as an input the results of the
     1713        sensitivity analysis are displayed on the screen. If a
     1714        filename is given they are written to a file.
     1715
     1716        INPUT:
     1717
     1718        - ``filename`` -- (optional) name of the file
     1719
     1720        OUTPUT:
     1721
     1722        Zero if the operations was successful otherwise nonzero.
     1723
     1724        .. NOTE::
     1725
     1726            This method is only effective if an optimal solution has been found
     1727            for the lp using the simplex algorithm. In all other cases an error
     1728            message is printed.
     1729
     1730        EXAMPLE::
     1731
     1732            sage: from sage.numerical.backends.generic_backend import get_solver
     1733            sage: p = get_solver(solver = "GLPK")
     1734            sage: p.add_variables(2)
     1735            1
     1736            sage: p.add_linear_constraint(zip([0, 1], [1, 2]), None, 3)
     1737            sage: p.set_objective([2, 5])
     1738            sage: import sage.numerical.backends.glpk_backend as backend
     1739            sage: p.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
     1740            sage: p.print_ranges()
     1741            ...
     1742            1
     1743            sage: p.solve()
     1744            0
     1745            sage: p.print_ranges()
     1746            GLPK ... - SENSITIVITY ANALYSIS REPORT                                                                         Page   1
     1747            <BLANKLINE>
     1748            Problem:   
     1749            Objective:  7.5 (MAXimum)
     1750            <BLANKLINE>
     1751               No. Row name     St      Activity         Slack   Lower bound       Activity      Obj coef  Obj value at Limiting
     1752                                                      Marginal   Upper bound          range         range   break point variable
     1753            ------ ------------ -- ------------- ------------- -------------  ------------- ------------- ------------- ------------
     1754                 1              NU       3.00000        .               -Inf         .           -2.50000        .     
     1755                                                       2.50000       3.00000           +Inf          +Inf          +Inf
     1756            <BLANKLINE>
     1757            GLPK ... - SENSITIVITY ANALYSIS REPORT                                                                         Page   2
     1758            <BLANKLINE>
     1759            Problem:   
     1760            Objective:  7.5 (MAXimum)
     1761            <BLANKLINE>
     1762               No. Column name  St      Activity      Obj coef   Lower bound       Activity      Obj coef  Obj value at Limiting
     1763                                                      Marginal   Upper bound          range         range   break point variable
     1764            ------ ------------ -- ------------- ------------- -------------  ------------- ------------- ------------- ------------
     1765                 1              NL        .            2.00000        .                -Inf          -Inf          +Inf
     1766                                                       -.50000          +Inf        3.00000       2.50000       6.00000
     1767            <BLANKLINE>
     1768                 2              BS       1.50000       5.00000        .                -Inf       4.00000       6.00000
     1769                                                        .               +Inf        1.50000          +Inf          +Inf
     1770            <BLANKLINE>
     1771            End of report
     1772            <BLANKLINE>
     1773            0
     1774
     1775
     1776        """
     1777
     1778        from sage.misc.all import SAGE_TMP
     1779
     1780        if filename == NULL:
     1781            fname = SAGE_TMP+"/ranges.tmp"
     1782        else:
     1783            fname = filename
     1784
     1785        res = glp_print_ranges(self.lp, 0, 0, 0, fname)
     1786
     1787        if filename == NULL:
     1788            if res == 0:
     1789                with open(fname) as f:
     1790                    for line in f:
     1791                        print line,
     1792                print
     1793
     1794        return res
     1795
     1796    cpdef double get_row_dual(self, int variable):
     1797        r"""
     1798        Returns the dual value of a constraint.
     1799
     1800        The dual value of the ith row is also the value of the ith variable
     1801        of the dual problem.
     1802
     1803        The dual value of a constraint is the shadow price of the constraint.
     1804        The shadow price is the amount by which the objective value will change
     1805        if the constraints bounds change by one unit under the precondition
     1806        that the basis remains the same.
     1807
     1808        INPUT:
     1809
     1810        - ``variable`` -- The number of the constraint
     1811
     1812        .. NOTE::
     1813
     1814           Behaviour is undefined unless ``solve`` has been called before.
     1815           If the simplex algorithm has not been used for solving 0.0 will
     1816           be returned.
     1817
     1818        EXAMPLE::
     1819
     1820            sage: from sage.numerical.backends.generic_backend import get_solver
     1821            sage: lp = get_solver(solver = "GLPK")
     1822            sage: lp.add_variables(3)
     1823            2
     1824            sage: lp.add_linear_constraint(zip([0, 1, 2], [8, 6, 1]), None, 48)
     1825            sage: lp.add_linear_constraint(zip([0, 1, 2], [4, 2, 1.5]), None, 20)
     1826            sage: lp.add_linear_constraint(zip([0, 1, 2], [2, 1.5, 0.5]), None, 8)
     1827            sage: lp.set_objective([60, 30, 20])
     1828            sage: import sage.numerical.backends.glpk_backend as backend
     1829            sage: lp.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
     1830            sage: lp.solve()
     1831            0
     1832            sage: lp.get_row_dual(0)   # tolerance 0.00001
     1833            0.0
     1834            sage: lp.get_row_dual(1)   # tolerance 0.00001
     1835            10.0
     1836
     1837
     1838        """
     1839
     1840        if self.simplex_or_intopt == simplex_only:
     1841            return glp_get_row_dual(self.lp, variable+1)
     1842        else:
     1843            return 0.0
     1844
     1845    cpdef double get_col_dual(self, int variable):
     1846        """
     1847        Returns the dual value (reduced cost) of a variable
     1848
     1849        The dual value is the reduced cost of a variable.
     1850        The reduced cost is the amount by which the objective coefficient
     1851        of a non basic variable has to change to become a basic variable.
     1852
     1853        INPUT:
     1854
     1855        - ``variable`` -- The number of the variable
     1856
     1857        .. NOTE::
     1858
     1859           Behaviour is undefined unless ``solve`` has been called before.
     1860           If the simplex algorithm has not been used for solving just a
     1861           0.0 will be returned.
     1862
     1863
     1864        EXAMPLE::
     1865
     1866            sage: from sage.numerical.backends.generic_backend import get_solver
     1867            sage: p = get_solver(solver = "GLPK")
     1868            sage: p.add_variables(3)
     1869            2
     1870            sage: p.add_linear_constraint(zip([0, 1, 2], [8, 6, 1]), None, 48)
     1871            sage: p.add_linear_constraint(zip([0, 1, 2], [4, 2, 1.5]), None, 20)
     1872            sage: p.add_linear_constraint(zip([0, 1, 2], [2, 1.5, 0.5]), None, 8)
     1873            sage: p.set_objective([60, 30, 20])
     1874            sage: import sage.numerical.backends.glpk_backend as backend
     1875            sage: p.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
     1876            sage: p.solve()
     1877            0
     1878            sage: p.get_col_dual(1)
     1879            -5.0
     1880
     1881        """
     1882        if self.simplex_or_intopt == simplex_only:
     1883            return glp_get_col_dual(self.lp, variable+1)
     1884        else:
     1885            return 0.0
     1886
     1887
    17061888    def __dealloc__(self):
    17071889        """
    17081890        Destructor
  • sage/numerical/mip.pyx

    diff --git a/sage/numerical/mip.pyx b/sage/numerical/mip.pyx
    a b  
    18331833        return self.linear_functions_parent()(d)
    18341834
    18351835
     1836    def get_backend(self):
     1837        r"""
     1838        Returns the backend instance used.
     1839
     1840        This might be useful when acces to additional functions provided by
     1841        the backend is needed.
     1842
     1843        EXAMPLE:
     1844
     1845        This example uses the simplex algorthm and prints information::
     1846
     1847            sage: p = MixedIntegerLinearProgram()
     1848            sage: x, y = p[0], p[1]
     1849            sage: p.add_constraint(2*x + 3*y, max = 6)
     1850            sage: p.add_constraint(3*x + 2*y, max = 6)
     1851            sage: p.set_objective(x + y + 7)
     1852            sage: b = p.get_backend()
     1853            sage: b.solver_parameter("simplex_or_intopt", "simplex_only")
     1854            sage: b.solver_parameter("verbosity_simplex", "GLP_MSG_ALL")
     1855            sage: p.solve() # tol 0.00001
     1856            9.4
     1857
     1858        """
     1859        return self._backend
     1860
    18361861class MIPSolverException(RuntimeError):
    18371862    r"""
    18381863    Exception raised when the solver fails.