多目标跟踪中用到的求解线性分配问题(Linear Assignment Problem,LAP)Python

news2024/12/22 20:05:23

多目标跟踪中用到的求解线性分配问题(Linear Assignment Problem,LAP)Python

flyfish

如果想看 C++版本的,请点这里。

线性分配问题(LAP,Linear Assignment Problem)是一个经典的优化问题,其目标是在若干任务和若干工人之间进行分配,以最小化总成本。成本可以是时间、金钱等。
LAPJV算法(Linear Assignment Problem Jonker-Volgenant algorithm)是解决线性分配问题的一种具体方法。这是一种基于Jonker和Volgenant提出的优化算法,旨在高效地求解LAP。

我们有一个公司,当前有5个任务需要完成,同时公司有5名工人可供选择。每个工人完成每个任务的成本(例如时间、金钱等)不同。公司的目标是找到一种分配方案,使得所有任务都能被一个工人完成,并且总成本最小。

具体而言,成本矩阵如下:

任务1任务2任务3任务4任务5
工人191114117
工人2615131310
工人31213688
工人411910129
工人5712141014

该矩阵中的每个值表示分配工人完成任务的成本。公司希望最小化这些成本的总和。
用Python代码来理解,使用lap库来验证写的对不对

依赖库

conda install -c conda-forge lap

代码实现

import numpy as np
import matplotlib.pyplot as plt
import lap

class LAPJV:
    def __init__(self, cost_matrix):
        self.cost_matrix = np.array(cost_matrix)
        self.n = self.cost_matrix.shape[0]
        self.x = np.full(self.n, -1, dtype=int)
        self.y = np.full(self.n, -1, dtype=int)
        self.v = np.zeros(self.n)
        self.free_rows = []

    def solve(self):
        self.column_reduction()
        self.augment()

    def column_reduction(self):
        for j in range(self.n):
            min_cost = np.min(self.cost_matrix[:, j])
            self.cost_matrix[:, j] -= min_cost
            self.v[j] = min_cost

        for j in range(self.n):
            i = np.argmin(self.cost_matrix[:, j])
            if self.x[i] == -1:
                self.x[i] = j
                self.y[j] = i
            else:
                self.y[j] = -1

        for i in range(self.n):
            if self.x[i] == -1:
                self.free_rows.append(i)
            elif self.y[self.x[i]] != i:
                self.x[i] = -1
                self.free_rows.append(i)

    def augment(self):
        while self.free_rows:
            self.find_augmenting_path()

    def find_augmenting_path(self):
        d = np.full(self.n, np.inf)
        pred = np.full(self.n, -1, dtype=int)
        cols = np.arange(self.n)

        i = self.free_rows.pop(0)
        for j in range(self.n):
            d[j] = self.cost_matrix[i, j] - self.v[j]
            pred[j] = i

        u = np.zeros(self.n)
        visited = np.zeros(self.n, dtype=bool)
        final_j = -1

        while final_j == -1:
            min_d = np.min(d[~visited])
            for j in cols[~visited]:
                if d[j] == min_d:
                    if self.y[j] == -1:
                        final_j = j
                        break
                    visited[j] = True
                    i = self.y[j]
                    u[j] = min_d
                    for k in cols[~visited]:
                        new_d = self.cost_matrix[i, k] - self.v[k] - u[j]
                        if new_d < d[k]:
                            d[k] = new_d
                            pred[k] = j

        while final_j != -1:
            i = pred[final_j]
            j = self.x[i]
            self.y[final_j] = i
            self.x[i] = final_j
            final_j = j

    def get_assignment(self):
        return self.x

def plot_assignment(cost_matrix, assignment):
    n = len(cost_matrix)
    fig, ax = plt.subplots()
    im = ax.imshow(cost_matrix, cmap='viridis')

    for i in range(n):
        ax.plot(assignment[i], i, 'ro')

    ax.set_xticks(np.arange(n))
    ax.set_yticks(np.arange(n))
    ax.set_xticklabels([f'Job {j+1}' for j in range(n)])
    ax.set_yticklabels([f'Worker {i+1}' for i in range(n)])

    plt.title('Job Assignment')
    plt.colorbar(im)
    plt.show()

# 更复杂的示例成本矩阵
cost_matrix = [
    [9, 11, 14, 11, 7],
    [6, 15, 13, 13, 10],
    [12, 13, 6, 8, 8],
    [11, 9, 10, 12, 9],
    [7, 12, 14, 10, 14]
]

# 创建并解决LAPJV问题
lap_solver = LAPJV(cost_matrix)
lap_solver.solve()
assignment = lap_solver.get_assignment()

# 使用lap库验证结果
cost_matrix_np = np.array(cost_matrix)
row_ind, col_ind, _ = lap.lapjv(cost_matrix_np)

# 打印分配结果
print("Custom LAPJV Assignment:")
for i, j in enumerate(assignment):
    print(f"Worker {i+1} is assigned to Job {j+1}")

print("\nLAP Library Assignment:")
for i, j in enumerate(col_ind):
    print(f"Worker {i+1} is assigned to Job {j+1}")

# 绘制分配结果
plot_assignment(cost_matrix, assignment)
Custom LAPJV Assignment:
Worker 1 is assigned to Job 5
Worker 2 is assigned to Job 1
Worker 3 is assigned to Job 3
Worker 4 is assigned to Job 2
Worker 5 is assigned to Job 4

LAP Library Assignment:
Worker 1 is assigned to Job 5
Worker 2 is assigned to Job 1
Worker 3 is assigned to Job 3
Worker 4 is assigned to Job 2
Worker 5 is assigned to Job 4

在这里插入图片描述

如何使用~来选择未访问的列:

import numpy as np

# 示例数据
visited = np.array([True, False, True, False])
cols = np.array([0, 1, 2, 3])

# 选择未访问的列
unvisited_cols = cols[~visited]

print("Visited:", visited)
print("Cols:", cols)
print("Unvisited Cols:", unvisited_cols)
Visited: [ True False  True False]
Cols: [0 1 2 3]
Unvisited Cols: [1 3]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1843882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

虚拟机配置桥接模式

背景 因为要打一些awd比赛,一些扫描工具什么的,要用到kali,就想着换成一个桥接模式 但是我看网上的一些文章任然没弄好,遇到了一些问题 前置小问题 每次点开虚拟网络编辑器的时候都没有vmnet0,但是点击更改的时候却有vmnet0 第一步: 点击更改设置 第二步: 把wmnet0删掉 …

AD使用快捷键

1、如何实现元器件旋转45放置 在Preferences >> PCB Editor >> General中将Rotation Step&#xff08;旋转的步进值&#xff09;由90改为45&#xff0c;这样以后每次按空格键旋转器件时旋转角度为45。 2、显示网络、隐藏网络 N 3、对齐 2、设置DRC检查选项&#xf…

[17] 使用Opencv_CUDA 进行滤波操作

使用Opencv_CUDA 进行滤波操作 邻域处理操作 > 滤波操作&#xff0c;拒绝或者允许某特定频段通过如果图像某处的灰度级变化缓慢&#xff0c;那么就是低频区域&#xff0c;如果灰度级变化剧烈&#xff0c;就是高频区域邻域滤波即卷积操作形态学处理&#xff1a;膨胀&#xf…

vue小总结

知识总结 【 1 】es6 语法总结 # let 定义变量 # const定义常量 ------块级作用域---- # var 以后尽量少用&#xff0c;函数作用域var 在 JavaScript 中是函数作用域或全局作用域。而 let 和 const 是块级作用域。 // 使用 var 声明全局变量 var globalVar "Im a globa…

酸性设计震撼登场,让你眼前一亮!

说起酸性&#xff08;ACID&#xff09;&#xff0c;你会想到什么&#xff1f;”我们通常会想到酸味&#xff0c;酸设计的视觉魅力是通过图形、颜色、排版给人复古、迷幻、黑暗、叛逆的感觉&#xff0c;反复几何图形和高饱和的颜色&#xff0c;使设计非常时尚&#xff0c;非常适…

linux精通 4.1

2.1.3 http服务器实现 目的 reactor应用——webserver webclient 每次上课前 看大纲down code 复习&#xff1a; 不行啊 编译给的代码报错啊 给的最新的不是0430那一版就不行啊 reactor.c:(.text0x254): relocation truncated to fit: R_X86_64_PC32 against symbol begin de…

Unity 材质系统优化(mesh相同,图片不同,但是可以将所有的图片合成一张图集)

今天提供一个Unity材质优化的思路&#xff0c;流程是这样的&#xff0c;模型的mesh相同只是图片不同&#xff0c;我想着能不能将所有的图片合成一张图集呢&#xff0c;于是我就试着在Blender里面开搞了&#xff0c;所有的mesh相同的模型&#xff0c;共用一个材质&#xff08;图…

分支结构相关

1.if 语句 结构&#xff1a; if 条件语句&#xff1a; 代码块 小练习&#xff1a; 使用random.randint()函数随机生成一个1~100之间的整数&#xff0c;判断是否是偶数 import random n random.randint(1,100) print(n) if n % 2 0:print(str(n) "是偶数") 2.else语…

Unity3d 游戏暂停(timeScale=0)引起的deltaTime关联的系列问题解决

问题描述 游戏暂停的功能是通过设置timeScale0实现的&#xff0c;不过在暂停游戏的时候&#xff0c;需要对角色进行预览和设置&#xff0c;为了实现这个功能&#xff0c;是通过鼠标控制相机的操作&#xff0c;为了使相机的操作丝滑&#xff0c;获取鼠标操作系数乘以Time.delta…

代码大模型揭秘:从下载到推理,全流程体验StarCoder

选择模型 模型榜单 大模型的发展日新月异&#xff0c;性能强劲的大模型不断涌现&#xff0c;可以实时关注开源大模型的榜单&#xff0c;选择合适自己的大模型 开源大模型榜单 开源代码大模型榜单 模型网站 目前主流的下载模型的网站就是 huggingface 全球社区&#xff0c;…

Python - 各种计算器合集【附源码】

计算器合集 一&#xff1a;极简版计算器二&#xff1a;简易版计算器三&#xff1a;不简易的计算器四&#xff1a;还可以计算器 一&#xff1a;极简版计算器 运行效果&#xff1a; import tkinter as tk import tkinter.messagebox win tk.Tk() win.title("计算器")…

Linux系统ubuntu20.04 无人机PX4 开发环境搭建(失败率很低)

Linux系统ubuntu20.04 无人机PX4 开发环境搭建 PX4固件下载开发环境搭建MAVROS安装安装地面站QGC PX4固件下载 PX4的源码处于GitHub&#xff0c;因为众所周知的原因git clone经常失败&#xff0c;此处从Gitee获取PX4源码和依赖模块。 git clone https://gitee.com/voima/PX4-…

python学习笔记-09

面向对象编程-中 面向对象三大特征&#xff1a;封装、继承、多态。 封装&#xff1a;把内容封装起来便于后面的使用。对于封装来讲&#xff0c;就是使用__init__方法将内容封装道对象中&#xff0c;然后通过对象直接或者self获取被封装的内容。 继承&#xff1a;子继承父的属…

悬浮翻译app免费怎么操作?看完这篇文章就知道了

#高考结束该出发看世界了# 高考的钟声已落&#xff0c;是时候开启探索世界的旅程了。无论是踏上旅途&#xff0c;观看视频&#xff0c;阅读书籍&#xff0c;还是浏览网页资料&#xff0c;我们都有机会拓宽视野。 然而&#xff0c;语言常常成为我们与世界沟通的障碍。好在&…

具身智能特点及实现路线

多模态——多功能的“小脑” 人类具有眼耳鼻舌身意&#xff0c;说明对于物理世界的充分感知和理解&#xff0c;是意识和智慧的来源。而传统AI更多的是被动观测&#xff0c;主要是“看”&#xff08;计算机视觉&#xff09;和“读”&#xff08;文本NLP&#xff09;&#xff0c…

Kubernetes容器运行时:Containerd vs Docke

容器化技术笔记 Kubernetes容器运行时&#xff1a;Containerd vs Docke - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this arti…

一文教你在centos 7.9中安装mysql5.7(超级详细)

##red## &#x1f534; 大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff0c;雄雄的小课堂。 一、前言 每当新来一个服务器之后&#xff0c;习惯性的都会安装一个宝塔面板&#xff0c;不为别的&#xff0c;就为了装环境方便点儿&#xff0c;比如常用的jdk,m…

C++初学者指南第一步---10.内存(基础)

C初学者指南第一步—10.内存&#xff08;基础&#xff09; 文章目录 C初学者指南第一步---10.内存&#xff08;基础&#xff09;1.内存模型1.1 纸上谈兵&#xff1a;C的抽象内存模型1.2 实践&#xff1a;内存的实际处理 2. 自动存储3.动态存储&#xff1a;std::vector3.1 动态内…

动态住宅代理IP:多账号矩阵管理的使用

如果您要处理多个在线帐户&#xff0c;选择正确的代理类型对于实现流畅的性能至关重要。但最适合这项工作的代理类型是什么&#xff1f; 为了更好地管理不同平台上的多个账户并优化成本&#xff0c;动态住宅代理IP通常作用在此。 一、什么是轮换代理&#xff1f; 轮换代理充当…

逆旅热闹如花盛放

热闹 未及十五&#xff0c;月亮的清辉已可穿透厚厚的云层铺撒人间。 几颗星星点缀着夜空&#xff0c;偶尔一架飞机闪烁着光芒。 很难得的晴夜。 近两个月以来的雨&#xff0c;像电影上的蒙太奇画帧&#xff0c;一幕接一幕&#xff0c;只是单调的灰色&#xff0c;困乏人心。 …