快速算法,精确查找二元矩阵中的 k 列,使这些列的总和为 1-向量

2024-02-16

假设我有一个 (M x N) 二进制矩阵,其中 M 和 N 都可以很大。我想精确地找到 k 列(k 相对较小,比如小于 10),这样这 k 列的总和就是 1 向量(所有元素均为 1)。一种解决方案就足够了。有没有快速的算法?

例如,处理矩阵的算法

1 0 0
1 0 0
1 1 0
0 1 1

k=2 时应返回第 0 列和第 2 列,但如果 k=1 或 k=3 则不应报告任何解。

我尝试过两种方法:

  1. 慢速组合方法,我尝试所有(N 选择 k)组合并找到总和为 1-向量的组合。这需要 O(N^k) 时间,这显然是可怕的。
  2. 递归方法,速度更快,但在最坏情况下仍然需要 O(N^k) 时间。 Python代码如下:
import numpy as np

def recursiveFn(mat, col_used_bool, col_sum_to_date, cols_to_go):
    N = len(mat)
    if cols_to_go == 1:
        col_unused = 1 - col_sum_to_date
        if list(col_unused) in [list(i) for i in mat]:
            return (True, [col_unused])
        else:
            return (False, None)
    for col_id in range(N):
        if col_used_bool[col_id]:
            continue
        if 2 not in mat[col_id]+col_sum_to_date:
            col_used_bool[col_id] = True
            x = recursiveFn(mat, col_used_bool, mat[col_id]+col_sum_to_date, cols_to_go-1)
            col_used_bool[col_id] = False
            if x[0]:
                return (True, x[1] + [mat[col_id]])
    return (False, None)

exMat = [[1,1,1,0],[0,0,1,1],[0,0,0,1]] #input by colums
exMat = [np.asarray(i) for i in exMat]
k = 2
output = recursiveFn(mat = exMat, col_used_bool = [False for i in exMat], 
    col_sum_to_date = np.asarray([0 for i in exMat[0]]), cols_to_go = k)
print(output[1])
### prints this : [array([0, 0, 0, 1]), array([1, 1, 1, 0])]

我对这两种方法都不满意,我觉得存在更智能、更快的算法。非常感谢您的帮助。这是我在 StackOverflow 上的第一篇文章,所以如果我在某个地方失礼了,请对我温和一些!

(如果有兴趣的话我也在 Math Stack Exchange 上问了同样的问题 https://math.stackexchange.com/q/3727899/801803,但我不太关心算法效率,而更关心数学技巧。)


我的第一次尝试是整数规划 https://en.wikipedia.org/wiki/Integer_programming使用可用的高性能求解器之一(例如Cbc https://github.com/coin-or/Cbc).

假设一些稀疏性在你的发生矩阵中,这些将非常有效并且非常普遍(侧面约束/适应)。它们也是完整的,并且可能能够证明不可行。

一个简单的公式如下:

Instance

c0 c1 c2
1  0  0  r0
1  0  0  r1
1  1  0  r2
0  1  1  r3

IP:

minimize(0)        # constant objective | pure feasibility problem

sum(c_i) = k       # target of columns chosen

r0 = 1 = c0        # r0 just showing the origin of the constraint; no real variable!
r1 = 1 = c0
r2 = 1 = c0 + c1
r3 = 1 = c1 + c2

c_i in {0, 1}      # all variables are binary

也许可以通过额外的不等式(例如派系不等式(冲突图 -> 最大派系))来加强这个公式,但不确定这是否有帮助。好的求解器会做类似的事情动态地正在生成cuts.

有很多理论可供参考。一个关键字是精确覆盖 https://en.wikipedia.org/wiki/Exact_cover或所有非常相似的包装/覆盖问题。

简单的代码示例:

import cvxpy as cp
import numpy as np

data = np.array([[1, 0, 0],
                 [1, 0, 0],
                 [1, 1, 0],
                 [0, 1, 1]])

def solve(k, data):
  c = cp.Variable(data.shape[1], boolean=True)

  con = [data * c == 1,
         cp.sum(c) == k,
         c >= 0,
         c <= 1]

  obj = cp.Minimize(0)
  
  problem = cp.Problem(obj, con)
  problem.solve(verbose=True, solver=cp.GLPK_MI)

  if(problem.status == 'optimal'):
    return np.where(np.isclose(c.value, 1.0) == True)[0]
  else:
    assert problem.status == 'infeasible'
    return None

print(solve(2, data))
print(solve(1, data))
print(solve(3, data))

# [0 2]
# None
# None

Remarks:

  • The code uses cvxpy which is very powerful, but lacks some advanced integer-programming support
    • 唯一易于使用的非商业求解器是GLPK,这非常好,但通常无法与Cbc
    • cvxpy 的代数用法与一些接口决策一起导致不寻常的变量边界作为约束此处表述
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

快速算法,精确查找二元矩阵中的 k 列,使这些列的总和为 1-向量 的相关文章

  • 如何生成给定范围内的回文数列表?

    假设范围是 1 X 120 这是我尝试过的 gt gt gt def isPalindrome s check if a number is a Palindrome s str s return s s 1 gt gt gt def ge
  • 如何收集列表、字典等中重复计算的结果(或制作修改每个元素的列表的副本)?

    There are a great many existing Q A on Stack Overflow on this general theme but they are all either poor quality typical
  • 导入错误:没有名为 _ssl 的模块

    带 Python 2 7 的 Ubuntu Maverick 我不知道如何解决以下导入错误 gt gt gt import ssl Traceback most recent call last File
  • Python 多处理示例不起作用

    我正在尝试学习如何使用multiprocessing但我无法让它发挥作用 这是代码文档 http docs python org 2 library multiprocessing html from multiprocessing imp
  • 如何在Windows上模拟socket.socketpair

    标准Python函数套接字 套接字对 https docs python org 3 library socket html socket socketpair不幸的是 它在 Windows 上不可用 从 Python 3 4 1 开始 我
  • 为什么这个算法的Big-O复杂度是O(n^2)?

    我知道这个算法的大O复杂度是O n 2 但我不明白为什么 int sum 0 int i 1 j n n while i lt j sum 即使我们设定了j n n一开始 我们在每次迭代期间递增 i 并递减 j 因此最终的迭代次数不应该比n
  • SQL Alchemy 中的 NULL 安全不等式比较?

    目前 我知道如何表达 NULL 安全的唯一方法 SQL Alchemy 中的比较 其中与 NULL 条目的比较计算结果为 True 而不是 NULL 是 or field None field value 有没有办法在 SQL Alchem
  • 为 pandas 数据透视表中的每个值列定义 aggfunc

    试图生成具有多个 值 列的数据透视表 我知道我可以使用 aggfunc 按照我想要的方式聚合值 但是如果我不想对两列求和或求平均值 而是想要一列的总和 同时求另一列的平均值 该怎么办 那么使用 pandas 可以做到这一点吗 df pd D
  • __del__ 真的是析构函数吗?

    我主要用 C 做事情 其中 析构函数方法实际上是为了销毁所获取的资源 最近我开始使用python 这真的很有趣而且很棒 我开始了解到它有像java一样的GC 因此 没有过分强调对象所有权 构造和销毁 据我所知 init 方法对我来说在 py
  • 总和不小于 key 的数组的最小子集

    给定一个数组 假设为非负整数 我们需要找到最小长度子集 使得元素之和不小于 K K 是作为输入提供的另一个整数 是否有可能找到时间复杂度为 O n n 的大 oh 的解决方案 我目前的想法是这样的 我们可以在 O n log n 中对数组进
  • 运行多个 scrapy 蜘蛛的正确方法

    我只是尝试使用在同一进程中运行多个蜘蛛新的 scrapy 文档 http doc scrapy org en 1 0 topics practices html但我得到 AttributeError CrawlerProcess objec
  • python pandas 中的双端队列

    我正在使用Python的deque 实现一个简单的循环缓冲区 from collections import deque import numpy as np test sequence np array range 100 2 resha
  • 求先递增后递减列表的最大值和最小值

    我尝试用谷歌搜索这个问题 但没有取得太大成功 我确信这个问题或类似问题有一个技术名称 但我似乎找不到答案 给定一个列表L整数 即严格递增 然后严格递减 找到该列表的最大值和最小值 例如 L可能 1 2 3 4 5 4 3 2 or 2 4
  • Pandas Dataframe 中 bool 值的条件前向填充

    问题 如何转发 fill boolTruepandas 数据框中的值 如果是当天的第一个条目 True 到一天结束时 请参阅以下示例和所需的输出 Data import pandas as pd import numpy as np df
  • Python:尝试检查有效的电话号码

    我正在尝试编写一个接受以下格式的电话号码的程序XXX XXX XXXX并将条目中的任何字母翻译为其相应的数字 现在我有了这个 如果启动不正确 它将允许您重新输入正确的数字 然后它会翻译输入的原始数字 我该如何解决 def main phon
  • 从 pygame 获取 numpy 数组

    我想通过 python 访问我的网络摄像头 不幸的是 由于网络摄像头的原因 openCV 无法工作 Pygame camera 使用以下代码就像魅力一样 from pygame import camera display camera in
  • 为美国东部以外地区的 Cloudwatch 警报发送短信?

    AWS 似乎没有为美国东部以外的 SNS 主题订阅者提供 SMS 作为协议 我想连接我的 CloudWatch 警报并在发生故障时接收短信 但无法将其发送到 SMS YES 经过一番挖掘后 我能够让它发挥作用 它比仅仅选择一个主题或输入闹钟
  • 检查所有值是否作为字典中的键存在

    我有一个值列表和一本字典 我想确保列表中的每个值都作为字典中的键存在 目前我正在使用两组来确定字典中是否存在任何值 unmapped set foo set bar keys 有没有更Pythonic的方法来测试这个 感觉有点像黑客 您的方
  • glpk.LPX 向后兼容性?

    较新版本的glpk没有LPXapi 旧包需要它 我如何使用旧包 例如COBRA http opencobra sourceforge net openCOBRA Welcome html 与较新版本的glpk 注意COBRA适用于 MATL
  • Python:元类属性有时会覆盖类属性?

    下面代码的结果让我感到困惑 class MyClass type property def a self return 1 class MyObject object metaclass MyClass a 2 print MyObject

随机推荐

  • 比较 R 中的时间

    我有两列 例如 A 和 B 时间格式为 HH MM A B 00 00 06 00 str A 和 str B 给出 字符 我想做一个比较 例如 Comment lt ifelse hour part A lt hour part B De
  • Asp.Net System.Web.Routing 不会路由 URL,除非最后有 .aspx

    我的路由有一个奇怪的问题 我有一个现有网站 我正在尝试将其添加到其中 它有效 但前提是 aspx 位于 URL 末尾 如果我删除 aspx 则会出现错误 找不到资源 我创建了一个快速测试网站并将代码复制到其中 它工作得很好 两者之间的代码是
  • Photoshop 文本工具在文本开头添加标点符号[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我在使用 Photoshop 时遇到了一个奇怪的问题 当我使用文字工具时 我可以正常键入字母 但是当我键入任何标点符号时 它会添加到文本的
  • PG::ConnectionBad:致命:用户“用户名”错误的对等身份验证失败

    当我尝试使用 User connection 或 generic table connection 连接到我的 pg 数据库时 出现此错误 PG ConnectionBad 致命 用户 用户名 的对等身份验证失败 我仔细检查了我的datab
  • 我应该如何将 redux 与不会重用的嵌套子组件一起使用?

    我正在开发一个具有许多子组件的组件 其中一些子组件嵌套了五层 我对使用 redux 感兴趣 因为它的优点是在公共状态原子中拥有单一的事实来源 我不明白的是智能 愚蠢组件的推荐 并将提供者置于主要组件之上 并通过道具传递所有内容 如果我这样做
  • gae 样板文档

    在为 App Engine 寻找一个好的社交登录包时 我尝试了 gae boilerplate 但我发现除了自述文件之外没有任何文档 我认为这根本不够 我有很多问题 其中包括 样板文件应该用作库还是根据需要下载并修改 样板应该如何更新 每个
  • Python yaml:ModuleNotFoundError

    我在 conda 中创建了一个新环境并在那里安装了 yaml conda list grep yaml yaml 0 1 7 had09818 2 但我无法导入它 python c import yaml Traceback most re
  • 如何构建微服务前端

    Let s say I have a dozen microservices I am wondering where should the front end go Let s say front end is HTML Javascri
  • 迭代时修改 Java8 流中的对象

    在 Java8 流中 我可以修改 更新其中的对象吗 例如 List
  • 如何纠正错误“从创建它的线程以外的线程访问”?

    下面的代码给了我下面的错误 我想我需要 InvokeRequired 但我不明白我该如何使用 跨线程操作无效 从创建它的线程以外的线程访问控制 listBox1 代码 using System Collections Generic usi
  • Eclipse 中不同的断点图标有何含义?

    在 Eclipse 中使用断点时 我有时会注意到它们有不同的图标 注释 左侧栏上的标记 有时它只是一个蓝色的球 有时上面有一个复选标记 有时它是十字形的 所有这些注释是什么意思 蓝色球 常规断点 活动 可能设置了命中计数 空球 即白色 断点
  • 使用 QuickCheck 测试一元法则

    是否有用于测试的库或工具laws https wiki haskell org Monad laws自定义 monad 的 我目前的黑客尝试是这样的 Define Arbitrary1 如同Eq1 Show1 etc 定义一个包装的辅助类型
  • laravel 私有通道和 laravel-echo-server 的身份验证问题

    我在 Laravel 5 5 中使用 laravel echo server 以及 Redis 和 vuejs 通过 websockets 广播事件 通过公共渠道 它工作正常 并且事件可以正确广播到客户端 但是当我将其更改为私有通道时 即使
  • 如何检查 Star Basic 中损坏的内部链接?

    我正在为 LibreOffice Writer 创建一个基本宏来检查损坏的内部链接 简而言之 生成所有锚点的列表 循环浏览文档 查找内部超链接 如果内部超链接不在锚点列表中 则打开它进行编辑 然后停止 我的代码有一些未解决的问题 withi
  • 语句包含 OUTPUT 子句但没有 INTO 子句错误

    我有一个触发器 它使用同一插入记录的身份主键 MessageId 的值更新插入的字段 RootId 之一 仅当插入记录的 RootId 字段为 0 时才应进行更新 触发器看起来像这样 ALTER TRIGGER dbo Trigger Ro
  • Google App Engine 应用程序可能消耗的最大内存是多少?

    最大金额是多少local记忆 notMemcache Google App 引擎应用程序的每个实例都可以使用吗 我找不到任何关于GAE 配额页面 http code google com appengine docs quotas html
  • Linq to SQL - 基础列长度

    我使用 Linq to SQL 一段时间了 我发现它非常有用且易于使用 对于我过去使用过的其他 ORM 工具 从数据库填充的实体对象通常有一个属性 指示数据库中基础数据列的长度 这在数据绑定情况下非常有用 例如 您可以在文本框上设置 Max
  • 如果我单击一个单元格,则需要在 Gsheet 中捕获电子邮件或姓名

    如果有人单击 Ay 列复选框 则需要在不同的列单元格中捕获他 她的电子邮件 您并不总是能够访问用户 唯一可以在单击上工作的触发器是 onSelectionChange 这是一个简单的触发器 这意味着它不能执行任何需要权限的操作 而 Sess
  • 如何创建空列表的列表

    如果之前已经回答过这个问题 我深表歉意 但我在这里找不到类似的问题 我对 Python 还很陌生 我想要创建的内容如下 list1 list2 results list1 list2 这段代码工作得非常好 但我想知道是否有一种更快的方法可以
  • 快速算法,精确查找二元矩阵中的 k 列,使这些列的总和为 1-向量

    假设我有一个 M x N 二进制矩阵 其中 M 和 N 都可以很大 我想精确地找到 k 列 k 相对较小 比如小于 10 这样这 k 列的总和就是 1 向量 所有元素均为 1 一种解决方案就足够了 有没有快速的算法 例如 处理矩阵的算法 1