解决平等和不平等的混合体系

时间:2014-05-24 14:35:44

标签: r sympy

简介:我成功地使用rSymPy库来象征性地解决以下示例系统的平等问题。

x + y = 20; x + 2y = 10

library(rSymPy)
sympy("var('x')")
sympy("var('y')")  
sympy("solve([
  Eq(x+y, 20),     
  Eq(x+2*y, 10)
  ], 
  [x,y])")
# output
#[1] "{x: 30, y: -10}"

用例:在我的用例中,我想象征性地解决一个混合的平等和不平等系统。这是一个可重现的例子: x + y = 20; x + 2y> 10

不平等可以用Gt在rSymPy中成功编码:

sympy("Gt(x+2*y, 10)")
# output
# [1] "10 < x + 2*y"

问题:混合系统的代码遇到错误:

sympy("solve([
      Eq(x + y, 20),     
      Gt(x+2*y, 10)
      ], 
      [x,y])")

# output    
# Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl,  : 
#   Traceback (most recent call last):
#   File "<string>", line 1, in <module>
#   File "/Users/.../R/3.0/library/rSymPy/Lib/sympy/solvers/solvers.py", line 308, in solve 
#   raise NotImplementedError()
# NotImplementedError

问题:如何成功重构代码以解决混合系统问题?

4 个答案:

答案 0 :(得分:4)

1)定义一个正变量z。然后,系统可以在z

方面重铸为一个平等系统
x <- Var('x')
y <- Var('y')
z <- Var('z')
sympy("solve( [ Eq(x+y, 20), Eq(x + 2*y - z, 10) ], [x, y] )")

,并提供:

[1] "{x: 30 - z, y: -10 + z}"

2)这是一个线性编程问题,所以如果您只是寻找约束的任何可行解决方案,那么lpSolve package可以提供这样的解决方案。在这种情况下,它给出了对应于(1)中的z=10的解决方案:

library(lpSolve)
out <- lp(, c(0, 0), matrix(c(1, 1, 1, 2), 2), c("=", ">"), c(20, 10))
out$solution
## [1] 20  0

ADDED 第一个解决方案,以回应海报的评论。增加了一些进一步的讨论。

答案 1 :(得分:1)

看起来NotImplmentedError本身就是SymPy。看起来它无法解决多元不等式。它只能减少它们(这就是你的例子所做的)。该库似乎不支持该类型的系统。

def _solve_inequality(ie, s, assume=True):
    """ A hacky replacement for solve, since the latter only works for
        univariate inequalities. """
    if not ie.rel_op in ('>', '>=', '<', '<='):
        raise NotImplementedError
    expr = ie.lhs - ie.rhs
    try:
        p = Poly(expr, s)
        if p.degree() != 1:
            raise NotImplementedError
    except (PolynomialError, NotImplementedError):
        try:
            n, d = expr.as_numer_denom()
            return reduce_rational_inequalities([[ie]], s, assume=assume)
        except PolynomialError:
            return solve_univariate_inequality(ie, s, assume=assume)
    a, b = p.all_coeffs()
    if a.is_positive:
        return ie.func(s, -b/a)
    elif a.is_negative:
        return ie.func(-b/a, s)
    else:
        raise NotImplementedError

答案 2 :(得分:0)

与此同时,我发现了优秀的LIM package,它很好地允许符号解决各种线性逆问题:

ASCII文件linprog.lim包含人类可读形式的符号问题(它与R代码位于同一目录中):

## UNKNOWNS
  X
  Y
## END UNKNOWNS

## EQUALITIES
  X + Y = 20
## END EQUALITIES

## INEQUALITIES
  X + 2 * Y > 10
## END INEQUALITIES

## PROFIT
  X + Y
## END PROFIT

以下R代码提供了线性编程问题的解决方案:

require(LIM)

model= Setup("linprog.lim")
model.solved= Linp(model, ispos=F, verbose=T)
model.solved

输出:

$residualNorm
[1] 3.552714e-15

$solutionNorm
[1] 20

$X
      X Y
[1,] 20 0

答案 3 :(得分:0)

这是另一种使用Rglpk库的方法,它可以读入并解决R中的GNU MathProg脚本问题:

# in case CRAN install does not work
install.packages("Rglpk", repos="http://cran.us.r-project.org")

library(Rglpk)

## read file
x= Rglpk_read_file("mathprog1.mod", type = "MathProg", verbose=T)

## optimize
Rglpk_solve_LP(obj= x$objective, 
               mat= x$constraints[[1]], 
               dir= x$constraints[[2]], 
               rhs= x$constraints[[3]], 
               bounds= x$bounds,
               types= x$types,
               max= x$maximum)

档案mathprog1.mod

# Define Variables
var x;
var y;

# Define Constraints
s.t. A: x + y = 20;
s.t. B: x + 2*y >= 10;

# Define Objective
maximize z: x + y;

# Solve
solve;
end;

R控制台输出:

# $optimum
# [1] 20

# $solution
# [1]  0 20

# $status
# [1] 0