OR-TOOL 背包算法

起因:最近公司要发票自动匹配,

比如财务输入10000W块,找到发票中能凑10000的。然后可以快速核销。

废话不多,

一 官方文档

https://developers.google.cn/optimization/pack/knapsack?hl=zh-cn

二 POM文件

复制代码
        <!--google 算法包-->
        <dependency>
            <groupId>com.google.ortools</groupId>
            <artifactId>ortools-java</artifactId>
            <version>9.9.3963</version>
        </dependency>
        <!--google 算法包-->

三 代码

1 查询业务数据

说明:根据条件查询List<FsBill>,

由于发票金额的匹配,只有一个维度,所以设置values=amount,

capacities是需要匹配的金额大小。

然后调用knapsackSolver_invoice背包核心算法。

复制代码
    @Override
    public List<FsBill> solverBill(CheckingBill_Req req) {
        List<FsBill> fsBills = findCheckingBill(req);
        //背包算法只支持Long,所以amount*1000转换
        //由于不需要考虑价值因素,所以设置values=amount.这样可以匹配正好的金额。
        long[] values = fsBills.stream().mapToLong(x -> x.getTotalRateAmount().multiply(new BigDecimal(1000)).longValue()).toArray();
        //金额:小数*1000,作整数处理。
        long[][] amount = {values};
        //总金额*1000,作整数处理。
        long[] capacities = {req.getTotalAmount().multiply(new BigDecimal(1000)).longValue()};
        List<Integer> fsBillIndexs = knapsackSolver_invoice(values, amount, capacities);
        List<FsBill> solverBill = new ArrayList<>();
        if (!CollectionUtils.isEmpty(fsBillIndexs)) {
            for (Integer i : fsBillIndexs) {
                solverBill.add(fsBills.get(i));
            }
        }
        return solverBill;
    }

2 背包核心算法

说明:

values:代表物品价值(发票只有一个金额维度,所以values=weights)

weights:物品重量(此处可以传递发票金额amount)

capacities:背包容量

返回的是List<Integer>数组下标,可以对应到List<FsBill>的对象。

复制代码
@Override
    public List<Integer> knapsackSolver_invoice(long[] values, long[][] weights, long[] capacities) {
        //加载OR-TOOL本地库
        Loader.loadNativeLibraries();
        //开始业务
        System.out.println("=========Begin : 匹配发票");
        KnapsackSolver solver = new KnapsackSolver(
                KnapsackSolver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "test");

        solver.init(values, weights, capacities);
        final long computedValue = solver.solve();

        ArrayList<Integer> packedItems = new ArrayList<>();
        ArrayList<Long> packedWeights = new ArrayList<>();
        int totalWeight = 0;
        for (int i = 0; i < values.length; i++) {
            if (solver.bestSolutionContains(i)) {
                packedItems.add(i);
                packedWeights.add(weights[0][i]);
                totalWeight = (int) (totalWeight + weights[0][i]);
            }
        }
        //匹配金额
        System.out.println("Target amounts: " + capacities[0]);
        //总价值
        System.out.println("Total values: " + computedValue);
        //总重量
        System.out.println("Total amounts: " + totalWeight);
        //装载项的下标,可对应List<发票>的下标
        System.out.println("Packed items: " + packedItems);
        //装载项的重量
        System.out.println("Packed amounts: " + packedWeights);
        System.out.println("=========End : 匹配发票");
        //如果没有完全匹配金额,则清空packedItems
        if (capacities[0] != totalWeight) {
            packedItems.clear();
        }
        return packedItems;
    }
相关推荐
_OP_CHEN几秒前
【算法基础篇】(五十七)线性代数之矩阵乘法从入门到实战:手撕模板 + 真题详解
线性代数·算法·矩阵·蓝桥杯·c/c++·矩阵乘法·acm/icpc
天天爱吃肉82185 分钟前
【跨界封神|周杰伦×王传福(陶晶莹主持):音乐创作与新能源NVH测试,底层逻辑竟完全同源!(新人必看入行指南)】
python·嵌入式硬件·算法·汽车
im_AMBER6 分钟前
Leetcode 114 链表中的下一个更大节点 | 删除排序链表中的重复元素 II
算法·leetcode
考琪9 分钟前
Nginx打印变量到log方法
java·运维·nginx
岱宗夫up18 分钟前
Python 数据分析入门
开发语言·python·数据分析
xhbaitxl18 分钟前
算法学习day38-动态规划
学习·算法·动态规划
多恩Stone19 分钟前
【3D AICG 系列-6】OmniPart 训练流程梳理
人工智能·pytorch·算法·3d·aigc
wangjialelele20 分钟前
Linux中的进程管理
java·linux·服务器·c语言·c++·个人开发
码界筑梦坊20 分钟前
325-基于Python的校园卡消费行为数据可视化分析系统
开发语言·python·信息可视化·django·毕业设计
历程里程碑21 分钟前
普通数组----轮转数组
java·数据结构·c++·算法·spring·leetcode·eclipse