算法简化债务的加权有向图(Algorithm to simplify a weighted dire

2019-08-18 08:50发布

我一直在使用一个小python脚本我写来管理债务之中我的室友。 它的工作原理,但也有一些缺失的功能,其中之一是简化了不必要的复杂债务结构。 例如,如果满足下列加权有向图表示一些人和箭头表示它们之间的债务(爱丽丝欠鲍勃$ 20和$查理5鲍勃欠查理$ 10等):

很显然,这个图应该被简化为下图:

有没有在$ 10没有道理做它的方式从Alice到Bob,然后由鲍勃查理如果Alice可以只把它给查理直接。

的目标,然后,在一般情况下是采取债务图和简化它(即产生具有相同的节点,但是不同边缘一个新的图),使得

  1. 无节点在国内外享有很高的指向它的边缘(没有无用的钱转手)
  2. 所有节点,因为他们在原来的图形做(这是在哪里的钱揣进条款相同)相同的“流”过他们。

通过“流”,我指的是所有输入减去所有的输出值(是有这个技术术语?我不是图论专家)。 因此,在上面的例子中,对每个节点的流的值是:

  • 鲍勃:+10
  • 爱丽丝:-25
  • 查理:+15

你可以看到,第一和第二图形必须通过每个节点相同的流量,所以这是一个很好的解决方案。 还有一些其他的容易情况下,例如,任何周期可通过去除具有最低值的边缘,并从所有其它边缘减去其值被简化。

这个:

应简化成这样:

我无法想象,没有人研究过这个问题; 我只是不知道搜索什么条款,以找到它(再次,而不是图论专家)信息。 我一直在找了几个小时也没有用,所以我的问题是:什么是会产生根据上述指定任何加权有向图的条件简化(新图)的算法?

Answer 1:

简单的算法

您可以在O(n)的多少钱谁是期望得到或支付找到。 所以,你可以简单地创建两个列表,一个是借方和其他信贷,再平衡两个列表的头,直到它们是空的。 从你的第一个例子:

  • 初始状态:借记:(A:25),信用:(B:15,C:10)
  • 第一事务,A:15 - > B:借:(A:10),信用:(C:10)
  • 第二次交易,A:10 - > C:借:(),信用:()

该交易定义图形的边缘。 对于参与的N个人,将有至多n-1交易=边缘。 在开始的时候,两个列表的总长度为n。 在每个步骤中,列表(借方/贷方)中至少一方获得一个短,并且在最后两个列表中消失一次。

问题是,在一般情况下,这个图并不一定是类似原来的图形,其中,因为我知道你的意图,是一个要求。 (是吗?有些情况下的最佳解决方案包括增加新的边缘的情况下,想象由于C中的相同数额的钱一由于B和B,A应该直接支付C,但这种优势并不是债务的图。)

成交少

如果目标只是构建一个等价的图形,你可以搜索债权人和debitor列表(如上面的部分)为完全匹配,或者用于信贷和一个人的借记卡(或其他方式轮比赛的情况下)。 寻找装箱 。 对于其他情况下,你有没有其他的选择,而不是分裂的流动,但上面连简单的算法产生具有少一个边缘之外还有有关人员的图形 - 最多。

编辑 :感谢j_random_hacker的指出与小于n-1边缘的解决方案是可能的当且仅当有一群人的债项总额另一组人的信用相匹配的人:那么,这个问题可以分成两个子问题与的n-2个边缘用于交易图的总成本。 不幸的是, 子集和问题是NP难问题。

甲流的问题?

或许,这也可以转化为一个最小费用流问题 。 如果你想只是为了简化您的原始图,您构建它的流动中,边容量是原来的金额借记/贷记的。 所述debitors作为流入节点(通过其用于所有debitors具有等于它们的总容量的债务的边缘的连接器节点),债权人用作流出节点(具有类似的连接节点)。

如果你希望尽量减少交易数量,你会更喜欢保持“大”的交易,降低了“小”的。 因此,每个边的成本可以被建模为在该边缘上的流动的倒数。



Answer 2:

这里是一个学术文件,其中很详细调查这个问题。 还存在用于在第8部分朝向端部的不同算法的一些示例代码。

费尔赫夫,T.(2004)。 高效率地解决多重债务:邀请计算科学。 信息学教育,3(1),105-126。



Answer 3:

其实我已经在完全相同的情况下,你遇到了这个问题:)

我认为krlmlr的各种解决方案不太准确解决问题。 我有一个思考如何解决究竟它(在最小边缘感),但在此期间,实际的选择解决问题的方法就是去创造一个新的人, 史蒂夫

  1. 史蒂夫实际上不是一个人。 史蒂夫仅仅是一个桶,与附加了一张纸。
  2. 每个人都在计算净量,他们欠(或者被拖欠,如果是负的),并将其写入一张纸,沿着他们的名字。
  3. 任何人的净头寸是他们欠的钱给了,货币净额史蒂夫时,他们就可以了,划掉他们的名字。
  4. 人人网,其立场是,他们被拖欠的钱花费的钱从史蒂夫,当他们看到史蒂夫有它,划掉他们的名字。

如果谁欠的钱一个人不能支付所有的这一次,他们可以给史蒂夫他们目前能够负担得起,并借此金额折抵他们的名字,由于总的身影。 同样,如果你欠的钱比史蒂夫目前在手,你可以采取一切的他目前拥有的资金,并采取量离总欠反对你的名字。

如果每个人都同意在开始支付史蒂夫只有全款,然后每隔净奥尔使得只有一个存款,并且每一个净欠人做完全一个撤回(虽然这可能需要在史蒂夫多次检查,看他是否目前有足够的手上的现金)。 关于史蒂夫的好处是,他总是左右,而从来都不是太忙理清财务状况。 不幸的是,他很容易上当,所以爱丽丝,鲍勃和查理需要已经彼此信任不占他的便宜。



文章来源: Algorithm to simplify a weighted directed graph of debts