【Python】lpsolve_wrapper——线性规划求解器Lpsolve的Python高级Api包装类

Lpsolve是一个跨平台的开源混合整数线性规划(MILP)求解器,提供了Python Api。
http://web.mit.edu/lpsolve/doc/Python.htm

lpsolve_wrapper是lp_solve的python包装类,提供了基于变量的Api。
https://github.com/hangvane/lpsolve_wrapper


动机

Lpsolve虽提供了Python Api,但Lpsolve的Python Api无法管理变量(特别是包含多个值的变量集,如 x i , j x_{i,j} xi,j),也无法对每个变量的系数矩阵自动压平为1维、自动拼接多个变量、得到的最优变量取值也不会自动按变量切割、反压平为单个变量的对应shape。目前使用Lpsolve的常见代码类似于:

from lp_maker import lp_maker, lpsolve
import numpy as np

x = np.ones((2, 2))
y = np.ones((3, 3))

f = np.concatenate([x.ravel(), y.ravel()]).tolist()

x.fill(0)
y.fill(0)
for i in range(2):
    x[0][i] = 1

for n in range(3):
    y[0][n] = 1
A = [np.concatenate([x.ravel(), y.ravel()]).tolist()]
b = 5
e = [-1, ]

x.fill(0)
y.fill(0)
vlb = np.concatenate([x.ravel(), y.ravel()]).tolist()
x.fill(1)
y.fill(2)
vub = np.concatenate([x.ravel(), y.ravel()]).tolist()
xint = []
scalemode = 1
setminimium = 0

lp = lp_maker(f, A, b, e, vlb, vub, xint, scalemode, setminimium)
lpsolve('solve', lp)
obj = lpsolve('get_objective', lp)
raw_notation = lpsolve('get_variables', lp)[0]

print('objective:', obj)
offset = 0
print('x:', raw_notation[0:2 * 2])
offset += 2 * 2
print('y:', raw_notation[offset + 1:offset + 3 * 3])


需要反复进行细节确认,目前只有2个小规模变量就乱成一团,大规模线性规划就是在写一坨屎山,而且最后得到的目标变量取值还没有反压平reshape。且在写以上demo时我出现了4个bug,全部和numpy结合lpsolve,以及lpsolve提供的接口细节相关,编码效率极低。


lpsolve_wrapper

lpsolve_wrapper是lp_solve的python包装类,提供了基于变量的Api。


特性

  • 支持变量管理
  • 自动偏移管理
  • 自动压平/反压平
  • 支持多种约束添加方式
  • 支持Python 2.x/3.x

安装

强烈推荐通过 conda 安装 lpsolve

conda install -c rmg lpsolve55

如果你是windows用户,可以前往
https://www.lfd.uci.edu/~gohlke/pythonlibs/#lp_solve
下载编译好的 .whl 包,并通过pip离线安装:

pip install the_name_of_lpsolve55.whl

然后将 lpsolve_wrapper.py 添加到你的项目中。


教程

这里提供了几个例子,可以基于这些例子创建更复杂的线性规划,一个简单的例子如下:

  1. 引入 lpsolve_wrapper
import lpsolve_wrapper as lw
  1. 创建求解器实例,并添加两个变量:
model = lw.Model(
    notations={
        'x': lw.notation(
            lower_bound=0,
        ),
        'y': lw.notation(
            lower_bound=0,
        )
    })
  1. 调用 lpsolve_wrapper 中的方法添加约束和求解:
model.add_constr(
    coefs=[
        lw.coef('x', 1),
        lw.coef('y', 1),
    ],
    right_value=75,
    constr_type=lw.LEQ
)
objective, notation_list = model.lp_solve(
    obj_func={
        'x': 143,
        'y': 60,
    },
    minimize=False
)
print('objective:', objective)
print('x:', notation_list['x'])
print('y:', notation_list['y'])

lpsolve_wrapper 提供了3个方法来添加约束:

  1. 通过给单个变量赋值的方式:
model.add_constr(
    coefs=[
        lw.coef(name='x', idx=[2, 3], value=1),
        lw.coef(name='y', idx=[0], value=2),
    ],
    right_value=75,
    constr_type=lw.GEQ
)
  1. 通过输入变量系数矩阵的方式:
model.add_constr_mat(
    coef_mats={
        'x': [1, 1, 1],
        'y': [[1, 2], [3, 4]]
    },
    right_value=1,
    constr_type=lw.EQ
)
  1. 通过传入回调函数的方式:
def tmp_func(y):
    y[2][3] = 1


model.add_constr_callback(
    callbacks={
        'x': lambda x: x[0].fill(1),
        'y': tmp_func

    },
    right_value=1,
    constr_type=lw.EQ,
)

还有若干用例和用例的公式表述可供参考

-add_constr()add_constr_mat()add_constr_callback()
用例 0
用例 1
用例 2
用例 3
用例 4
用例 5
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在.env_wrapper.py中创建一个环境包装,可以通过继承 OpenAI Gym 的环境类来实现。具体来说,你需要定义一个新的类,继承原来的环境类,并在这个新类中重写需要修改的方法,从而实现对环境的包装。以下是一个简单的示例,假设你想要为 CartPole-v0 环境添加一个观察空间的噪声: ```python import gym class NoisyObservationWrapper(gym.Wrapper): def __init__(self, env, noise_scale=0.1): super().__init__(env) self.noise_scale = noise_scale def reset(self, **kwargs): obs = self.env.reset(**kwargs) obs = obs + self.noise_scale * np.random.randn(*obs.shape) return obs def step(self, action): obs, reward, done, info = self.env.step(action) obs = obs + self.noise_scale * np.random.randn(*obs.shape) return obs, reward, done, info ``` 在这个例子中,我们定义了一个 `NoisyObservationWrapper` 类,继承了 `gym.Wrapper` 类。在这个类中,我们实现了 `reset` 方法和 `step` 方法,用来对环境的状态进行修改。在 `reset` 方法中,我们首先调用原来环境的 `reset` 方法来获取初始状态,然后将状态添加一个噪声,最后返回新的状态。在 `step` 方法中,我们同样首先调用原来环境的 `step` 方法来执行动作,并获取新的状态、奖励、完成标志和信息。然后将新的状态添加一个噪声,并将结果返回。 使用这个包装,我们可以在创建环境时,将原来的环境对象传入到包装中,从而得到一个新的被包装的环境对象: ```python env = gym.make('CartPole-v0') wrapped_env = NoisyObservationWrapper(env, noise_scale=0.1) ``` 这里我们创建了一个 CartPole-v0 的环境对象,并将其传入到了我们定义的包装中,得到了一个新的被包装的环境对象 `wrapped_env`。现在,当我们调用 `wrapped_env.reset()` 或 `wrapped_env.step()` 方法时,就会自动将环境状态加上噪声。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值