为遵守法规,银行需要确保其持有的资金中至少90%(或其他固定比例)是“干净的”。
如果货币在“干净”帐户中,则被认为是干净的。如果帐户中的所有资金均来自可验证来源,则被视为“干净”。
银行可以强制将钱从无法验证的来源退还给客户,以增加“干净”钱的比例,以符合法规要求。问题是要确定银行需要返还的最低金额以符合规定。
Account Verif NonVerif Divi Clean NotClean
1 889.77 157.01 5.67 0 1046.78
2 907.88 160.21 5.67 0 1068.09
3 1187.18 209.5 5.67 0 1396.68
4 918.12 162.02 5.67 0 1080.14
5 1721.88 303.86 5.67 0 2025.74
6 828.17 276.05 3.00 0 1104.22
7 1127.6 375.86 3.00 0 1503.46
8 1177.13 392.37 3.00 0 1569.5
9 801.81 267.27 3.00 0 1069.08
10 741.9 247.3 3.00 0 989.2
11 0 1468.11 0.00 0 1468.11
12 0 853.66 0.00 0 853.66
13 2354.81 0 -1.00 2354.81 0
14 2267.1 0 -1.00 2267.1 0
15 2238.3 0 -1.00 2238.3 0
16 2188.66 0 -1.00 2188.66 0
17 2167.85 0 -1.00 2167.85 0
18 2166.1 0 -1.00 2166.1 0
19 2165.59 0 -1.00 2165.59 0
20 2163.84 0 -1.00 2163.84 0
21 2145.43 0 -1.00 2145.43 0
22 2117.76 0 -1.00 2117.76 0
23 1320.26 0 -1.00 1320.26 0
24 1299.99 0 -1.00 1299.99 0
25 1241.02 0 -1.00 1241.02 0
26 1237.36 0 -1.00 1237.36 0
27 1208.74 0 -1.00 1208.74 0
28 1114.58 0 -1.00 1114.58 0
29 1048.63 0 -1.00 1048.63 0
30 1010.92 0 -1.00 1010.92 0
31 971.1 0 -1.00 971.1 0
32 874.95 0 -1.00 874.95 0
33 832.01 0 -1.00 832.01 0
34 825.72 0 -1.00 825.72 0
TOTAL 45262.16 4873.22 34960.72 15174.66
在上面的示例中,银行持有的总金额为34960.72 + 15174.66 = 50135.38;无需进行任何清洗,只有69.7%(34960.72 / 50135.38 = 0.697 ...)被认为是清洗的,因此银行需要清洗以符合规定。
如果银行清理了前两个帐户,则银行持有的总金额将为50135.38-157.01-160.21 = 49818.16,清洁货币将为34960.72 + 889.77 + 907.88 = 36758.37;清洁货币的比例将是36758.37 / 49818.16 = 73.7%。
在上面的示例中,Div = Verif / NonVerif(“ Verif”为值,“ NonVerif”为“ Weight”,以查看提供最佳比率的项来选择它们);示例中的列表按Div降序排序。天真的方法是按顺序选择要清理的帐户,直到银行遵守规定为止。
我当时正在考虑使用Avikalp Srivastava here建议的方法:因此将Verif(值)视为权重,将NonVerif(成本)视为值;然后使用常规的背包问题解决方法来查找在Verif保持> = 90%*(银行持有的总金额)时可以消除的最大成本;问题是,当您向背包中添加不干净的物品时,银行持有的总金额会减少,因为银行正在将这笔钱退还给客户(这样,随着更多物品的添加,背包会变小吗?)。蛮力导致显示的数据出现内存溢出。我实际上试图解决这个问题数小时,而没有找到答案。也许背包问题解决方法不是解决此问题的正确方法(?)
天真的方法足以满足我的目的,但我仍然想了解如何正确解决它。
答案 0 :(得分:1)
一个想法可能是对目标未验证量进行二进制搜索以返回。然后,对于每个这样的候选人,运行一个背包,其中那个候选人是最大权重,每个未验证的金额都是权重,要最大化的值是帐户中的可验证金额。 (当然,我们只需要查询未验证资金的帐户即可。)
答案 1 :(得分:1)
注意:此方法基于我在上面的注释中的理解。如果我的理解有误,我将进行编辑。
这是一种基于整数线性规划(ILP)的方法。
I
是所有帐户的集合,而让I_c
和I_n
分别是干净帐户和非干净帐户的集合。 V[i]
和NV[i]
为帐户i
的可验证资金和不可验证资金。 r
为必须清理的资金比例(例如90%)。 (这些是参数-模型的输入。)
x[i] = 1
,让i
为i
中的I_n
,否则为0
。 (我们不会清除I_c
中的帐户。)(这是一个二进制决策变量-模型将为其设置值的变量。)
那么ILP是:
minimize sum {i in I_n} NV[i] * x[i]
subject to sum {i in I_c} V[i] + sum {i in I_n} V[i] * x[i] >=
r * (sum {i in I} (NV[i] + V[i]) - sum {i in I_n} NV[i] * x[i]))
x[i] in {0,1} for all i in I_n
目标函数使清洗的总资金最小化。 (对于i
中的每个I_n
,如果我们清洗帐户,那么我们将清除NV[i]
的金额。)第一个约束条件是,总清洗货币必须至少为0.9总金额中的总金额:总净额是原始净额(sum {i in I_c} V[i]
)加上新净额(sum {i in I_n} V[i] * x[i]
);总金额等于原始总金额(已验证并未经验证)减去已清理的资金。第二个约束只是说所有x[i]
变量必须是二进制的。
在实现方面,您当然可以在Excel / Solver中解决此问题。 (我怀疑您所获得的非线性是因为您编写约束的方式更像是
sum {i in I_c} V[i] + sum {i in I_n} V[i] * x[i] / (sum {i in I} (NV[i] + V[i]) - sum {i in I_n} NV[i] * x[i])) >= r
这是非线性的。)您还可以使用Python / PuLP
或任意数量的其他线性编程包。