kerigard/lpsolve 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

kerigard/lpsolve

Composer 安装命令:

composer require kerigard/lpsolve

包简介

LPSolve extension as simple PHP library

README 文档

README

Build Status Total Downloads Latest Stable Version License

PHP wrapper around LPSolve 5.5, providing a safe and convenient interface for building and solving linear optimization problems.

Installation

Install via Composer

composer require kerigard/lpsolve

Load the Composer autoloader

require 'vendor/autoload.php'

Important

This library requires the lp_solve PHP extension.

Note

The official lp_solve extension only supports PHP 5, so it needs to be compiled manually for modern PHP versions.

Building the lp_solve extension

(for PHP 5.6 - 8.x)

The repository Kerigard/lp-solve-php-docker contains maintained source directories for building the lp_solve extension for different PHP versions:

Branch PHP version
5.x PHP 5.x
7.x PHP 7.x
8.x PHP 8.x

1. Install lp-solve system package

apt update && apt install -y lp-solve

2. Download source code

curl -fsSL https://github.com/Kerigard/lp-solve-php-docker/archive/8.x.tar.gz \
    | tar -xz -C /tmp --strip-components=1

Replace 8.x with the desired branch.

3. Build and install

(cd /tmp/lp-solve/extra/PHP && phpize && ./configure && make && make install)
rm -r /tmp/lp-solve

4. Enable the extension

Add to your php.ini:

extension=phplpsolve55.so

Usage

Maximization with constraints

use Kerigard\LPSolve\Constraint;
use Kerigard\LPSolve\Problem;
use Kerigard\LPSolve\Solver;

$problem = new Problem(
    objective: [143, 60, 195],
    constraints: [
        new Constraint([120, 210, 150.75], LE, 15000),
        new Constraint([110, 30, 125], LE, 4000),
        new Constraint([1, 1, 1], LE, 75),
    ]
);

$solver = new Solver(Solver::MAX);
$solution = $solver->solve($problem);

var_dump($solution->getStatus()); // OPTIMAL solution
var_dump($solution->getCount()); // 1
var_dump($solution->getIterations()); // 2

if ($solution->getCode() === OPTIMAL) {
    var_dump($solution->getObjective()); // 6986.842105...
    var_dump($solution->getVariables()); // [0, 56.578947..., 18.421052...]
}

Minimization with bounds

$problem = new Problem(
    objective: [-1, -2, 0.1, 3],
    constraints: [
        new Constraint([1, 1, 0, 0], LE, 5),
        new Constraint([2, -1, 0, 0], GE, 0),
        new Constraint([-1, 3, 0, 0], GE, 0),
        new Constraint([0, 0, 1, 1], GE, 0.5),
    ],
    lowerBounds: [0, 0, 1.1, 0],
    upperBounds: []
);

$solver = new Solver(Solver::MIN);
$solution = $solver->setScaling(SCALE_MEAN | SCALE_INTEGERS)->solve($problem);

var_dump($solution->getObjective()); // -8.223333...

Integer and Binary Variables

$problem = new Problem(
    objective: [-1, -2, 0.1, 3],
    constraints: [
        new Constraint([1, 1, 0, 0], LE, 5),
        new Constraint([2, -1, 0, 0], GE, 0),
        new Constraint([-1, 3, 0, 0], GE, 0),
        new Constraint([0, 0, 1, 1], GE, 0.5),
    ],
    integerVariables: [0, 0, 1, 0], // integer variables (only variable #3 is integer)
    binaryVariables: [1, 0, 0, 1] // binary variables (variables #1 and #4 are binary)
);

$solver = new Solver(Solver::MIN);
$solution = $solver->setVerbose(DETAILED)->solve($problem);

var_dump($solution->getVariables()); // [1, 2, 1, 0]

If you pass true instead of an array, all variables will become integer or binary.

Error handling

Invalid problem definition

$problem = new Problem(
    [1],
    [new Constraint([0, 78.26, 0, 2.9], GE, 92.3)]
);

try {
    $solver = new Solver();
    $solver->setTimeout(0)->solve($problem);
} catch (\LPSolveException $e) {
    var_dump($e->getMessage()); // Invalid vector
}

Throwing exceptions for non-optimal solutions

$problem = new Problem(
    [10, 10],
    [
        Constraint::fromString('1x + 1y = 20'),
        Constraint::fromString('0x + 1y <= 5'),
        Constraint::fromString('1x + 0y <= 5'),
    ]
);

try {
    $solver = new Solver(Solver::MIN);
    $solver->throw()->solve($problem);
} catch (\LPSolveException $e) {
    var_dump($e->getMessage()); // Model is primal INFEASIBLE
    var_dump($e->getCode() === INFEASIBLE); // true
}

Additional behavioral notes:

  • The original lp_solve extension may produce fatal errors for malformed equations.
  • When built via Kerigard/lp-solve-php-docker, internal errors become LPSolveException.
  • Calling ->throw() forces an exception for all non-optimal results.

Callbacks

$problem = new Problem(
    [1, 3, 6.24, 0.1],
    [
        new Constraint([0, 78.26, 0, 2.9], GE, 92.3),
        new Constraint([0.24, 0, 11.31, 0], LE, 14.8),
        new Constraint([12.68, 0, 0.08, 0.9], GE, 4),
    ]
);

$solver = (new Solver())
    ->beforeSolve(function ($lpsolve, $problem) {
        lpsolve('set_improve', $lpsolve, IMPROVE_SOLUTION);
    })
    ->afterSolve(function ($lpsolve, $problem, $solution) {
        lpsolve('write_lp', $lpsolve, 'model.lp');
    });

$solution = $solver->solve($problem);

License

MIT. Please see the LICENSE FILE for more information.

kerigard/lpsolve 适用场景与选型建议

kerigard/lpsolve 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 13.15k 次下载、GitHub Stars 达 2, 最近一次更新时间为 2024 年 03 月 10 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「php」 「math」 「programming」 「solver」 「simplex」 「linear」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 kerigard/lpsolve 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 kerigard/lpsolve 我们能提供哪些服务?
定制开发 / 二次开发

基于 kerigard/lpsolve 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 13.15k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 2
  • 点击次数: 29
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 2
  • Watchers: 2
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-03-10