Python 指定边界数矩阵的生成算法
我试图生成一个7行4列的数字矩阵。每一行的总和必须为100,每一列必须在最小和最大范围(如下规定)之间有一个均匀的排列(如果允许) 目标:Python 指定边界数矩阵的生成算法,python,algorithm,numpy,optimization,Python,Algorithm,Numpy,Optimization,我试图生成一个7行4列的数字矩阵。每一行的总和必须为100,每一列必须在最小和最大范围(如下规定)之间有一个均匀的排列(如果允许) 目标: C1 C2 C3 C4 sum range 1 low 100 ^ 2 .. | 3 .. | 4 ..
C1 C2 C3 C4 sum range
1 low 100 ^
2 .. |
3 .. |
4 .. |
5 .. |
6 .. |
7 high _
c1_high = 98
c1_low = 75
c2_high = 15
c2_low = 6
c3_high = 8
c3_low = 2
c4_low = 0.05
c4_high =0.5
除此之外,我需要每行的排列尽可能线性,尽管用二阶多项式拟合数据的直线就足够了(r^2值>0.98)
我目前正尝试使用以下sudocode执行此操作:
import pandas as pd
import numpy as np
from sklearn.utils import shuffle
c1_high = 98
c1_low = 75
c2_high = 15
c2_low = 6
c3_high = 8
c3_low = 2
c4_low = 0.05
c4_high =0.5
def matrix_gen(): #generates matrix within min and max values
container =[]
d={}
offset = np.linspace(0.05,1,9)
c1= np.linspace(c1_low, c1_high, 7)
c2= np.linspace(c2_low, c2_high, 7)
c3= np.linspace(c3_low, c3_high, 7)
c4= np.linspace(c4_low, c4_high, 7)
for i in np.arange(7):
d["row{0}".format(i)]=[item[i] for item in [c1,c2,c3,c4]]
df =pd.DataFrame(d)
df.loc[4,:] = df.iloc[0,:][::-1].values
df1 = df.drop(0)
df1.loc[5,:] = df1.sum(axis=0)
new_name = df1.index[-1]
df1 = df1.rename(index={new_name: 'sum'})
return df1
m = matrix_gen()
print(m)
输出:
下一个功能:
def shuf(): # attempts at shuffling the values around such that the 'sum' row is as close to 100 as possible.
df = matrix_gen()
df1 = df[1:4]
count =0
while True:
df1 = shuffle(df1)
df1.loc[5,:] = df1.sum(axis=0)
for i in df1.loc[5].values:
if 98<= i <=100:
print('solution')
return df1
else:
count+=1
print(count)
continue
opt = shuf()
print(opt)
def shuf():#尝试对值进行混洗,使“sum”行尽可能接近100。
df=矩阵_gen()
df1=df[1:4]
计数=0
尽管如此:
df1=洗牌(df1)
df1.loc[5,:]=df1.sum(轴=0)
对于df1.loc[5]中的i,值:
如果98我认为一个有趣的方法是使用优化模型
有序值
让x(i,j)成为你想要填充的矩阵。然后我们有:
sum(j, x(i,j)) = 100 ∀i
L(j) ≤ x(i,j) ≤ U(j) ∀i,j
x(i,j) = x(i-1,j) + step(j) + deviation(i,j)
special cases:
x(1,j) = L(j) + deviation(1,j)
and x(m,j) = U(j) + deviation(m,j)
step(j) ≥ 0
minimize sum((i,j), deviation(i,j)^2 )
这是一个二次规划问题。可以用绝对偏差代替平方偏差。在这种情况下,您有一个LP
可以对模型进行优化,使平方相对误差最小化
这与所谓的矩阵平衡(通常用于经济建模的一种统计技术)有点相关
无序值
在上面的例子中,我假设必须对值进行排序。现在我明白情况并非如此。我调整了模型以如下方式处理此问题。首先是对结果的概述
输入数据为:
---- 17 PARAMETER LO
c1 80.000, c2 5.000, c3 0.500, c4 0.050
---- 17 PARAMETER UP
c1 94.000, c2 14.000, c3 5.000, c4 0.500
警告:请注意,海报已更改此数据。我的答案是使用更改前的原始LO和UP值
该模型分为三个步骤:
(1) 在不遵守行和约束的情况下填充完全组织的矩阵。这可以在模型之外完成。我只生成了:
---- 53 PARAMETER init initial matrix
c1 c2 c3 c4 rowsum
r1 80.000 5.000 0.500 0.050 85.550
r2 82.333 6.500 1.250 0.125 90.208
r3 84.667 8.000 2.000 0.200 94.867
r4 87.000 9.500 2.750 0.275 99.525
r5 89.333 11.000 3.500 0.350 104.183
r6 91.667 12.500 4.250 0.425 108.842
r7 94.000 14.000 5.000 0.500 113.500
即从lo(j)
到up(j)
的步骤相等
(2) 第二步是排列列中的值,以获得与行和非常匹配的解决方案。这使得:
---- 53 VARIABLE y.L after permutation
c1 c2 c3 c4 rowsum
r1 94.000 5.000 0.500 0.125 99.625
r2 82.333 12.500 4.250 0.500 99.583
r3 89.333 8.000 2.000 0.200 99.533
r4 87.000 9.500 2.750 0.275 99.525
r5 84.667 11.000 3.500 0.350 99.517
r6 91.667 6.500 1.250 0.050 99.467
r7 80.000 14.000 5.000 0.425 99.425
---- 53 VARIABLE x.L final values
c1 c2 c3 c4 rowsum
r1 94.374 5.001 0.500 0.125 100.000
r2 82.747 12.503 4.250 0.500 100.000
r3 89.796 8.004 2.000 0.200 100.000
r4 87.469 9.506 2.750 0.275 100.000
r5 85.142 11.007 3.501 0.350 100.000
r6 92.189 6.510 1.251 0.050 100.000
r7 80.561 14.012 5.002 0.425 100.000
---- 53 VARIABLE d.L deviations
c1 c2 c3 c4
r1 0.374 0.001 1.459087E-5 1.459087E-7
r2 0.414 0.003 9.542419E-5 9.542419E-7
r3 0.462 0.004 2.579521E-4 2.579521E-6
r4 0.469 0.006 4.685327E-4 4.685327E-6
r5 0.475 0.007 7.297223E-4 7.297223E-6
r6 0.522 0.010 0.001 1.123123E-5
r7 0.561 0.012 0.002 1.587126E-5
这已经非常接近,并保持“完美”的传播
(3) 通过添加偏差稍微更改值,使行和正好为100。最小化相对偏差的平方和。这使得:
---- 53 VARIABLE y.L after permutation
c1 c2 c3 c4 rowsum
r1 94.000 5.000 0.500 0.125 99.625
r2 82.333 12.500 4.250 0.500 99.583
r3 89.333 8.000 2.000 0.200 99.533
r4 87.000 9.500 2.750 0.275 99.525
r5 84.667 11.000 3.500 0.350 99.517
r6 91.667 6.500 1.250 0.050 99.467
r7 80.000 14.000 5.000 0.425 99.425
---- 53 VARIABLE x.L final values
c1 c2 c3 c4 rowsum
r1 94.374 5.001 0.500 0.125 100.000
r2 82.747 12.503 4.250 0.500 100.000
r3 89.796 8.004 2.000 0.200 100.000
r4 87.469 9.506 2.750 0.275 100.000
r5 85.142 11.007 3.501 0.350 100.000
r6 92.189 6.510 1.251 0.050 100.000
r7 80.561 14.012 5.002 0.425 100.000
---- 53 VARIABLE d.L deviations
c1 c2 c3 c4
r1 0.374 0.001 1.459087E-5 1.459087E-7
r2 0.414 0.003 9.542419E-5 9.542419E-7
r3 0.462 0.004 2.579521E-4 2.579521E-6
r4 0.469 0.006 4.685327E-4 4.685327E-6
r5 0.475 0.007 7.297223E-4 7.297223E-6
r6 0.522 0.010 0.001 1.123123E-5
r7 0.561 0.012 0.002 1.587126E-5
步骤(2)和(3)必须在优化模型内:它们必须同时执行,以获得经验证的最佳解决方案
数学模型可以如下所示:
该模型使用Cplex或Gurobi等解算器,在几秒钟内解出经验证的全局最优解
我认为这是一个非常可爱的模型(好吧,我知道这真是个书呆子)。置换用置换矩阵P(二进制值)建模。这使得该模型成为MIQP(混合整数二次规划)模型。它可以很容易地线性化:在目标中使用绝对值而不是正方形。经过适当的重新计算,我们得到了一个线性MIP模型。有很多软件可以处理这个问题。这包括可从Python调用的库和包
注:我可能不应该在目标中除以init(I,j)
,而是除以init
矩阵中的列平均值。除以y(i,j)
将是最好的,但这将导致另一个非线性 您的数字足够小,可以使用智能暴力方法
我使用两种方法来量化和最小化与“干净”等距值的偏差(linspace(低、高、7)
)<代码>“abserr”表示平方差,而“relerr”
表示平方误差除以平方净值。最后我还检查了corrcoefs,但我从未见过低于99.8%的任何东西
下面的代码首先查找错误最小的干净值。这只需要几秒钟,因为我们使用以下技巧:
- 将4列拆分为两对
- 每对有7个!相对排列,一个可管理的数字,即使平方(每对一个因数)
- 计算这些(7!)^2次洗牌并对其求和
- 为了不必迭代对之间的所有相对洗牌,我们观察到,如果两组对和按相反顺序排列,则总误差最小化。对于
和“abserr”
“relerr”
solve
,它在最小化relerr
时包含一个小的不准确度,另一个是经过修正的版本改进的\u solve
。他们经常会找到不同的解决方案,但在100多个随机问题中,只有一个会导致改进的\u solve
产生非常小的错误
对几个例子的回答:
OP的例子:
((75, 98), (6, 15), (2, 8), (0.05, 0.5))
solve relerr improved_solve relerr
table: table:
76.14213 15.22843 8.12183 0.50761 76.14213 15.22843 8.12183 0.50761
79.02431 13.53270 7.01696 0.42603 79.02431 13.53270 7.01696 0.42603
81.83468 11.87923 5.93961 0.34648 81.83468 11.87923 5.93961 0.34648
84.57590 10.26644 4.88878 0.26888 84.57590 10.26644 4.88878 0.26888
87.25048 8.69285 3.86349 0.19317 87.25048 8.69285 3.86349 0.19317
89.86083 7.15706 2.86282 0.11928 89.86083 7.15706 2.86282 0.11928
92.40924 5.65771 1.88590 0.04715 92.40924 5.65771 1.88590 0.04715
avgerr: avgerr:
0.03239 0.03239
corrcoefs: corrcoefs:
0.99977 0.99977 0.99977 0.99977 0.99977 0.99977 0.99977 0.99977
将某些列升序或降序排序不是最佳的示例:
((11, 41), (4, 34), (37, 49), (0.01, 23.99))
请注意,解算器会找到不同的解,但错误是相同的
solve relerr improved_solve relerr
table: table:
10.89217 18.81374 46.53926 23.75483 11.00037 24.00080 49.00163 15.99720
26.00087 9.00030 49.00163 15.99720 16.00107 19.00127 45.00300 19.99467
31.00207 4.00027 45.00300 19.99467 25.74512 13.86276 36.63729 23.75483
16.00000 29.00000 43.00000 12.00000 35.99880 8.99970 46.99843 8.00307
20.99860 33.99773 40.99727 4.00640 41.00000 4.00000 43.00000 12.00000
40.99863 13.99953 36.99877 8.00307 20.99860 33.99773 40.99727 4.00640
36.35996 24.23998 39.38996 0.01010 31.30997 29.28997 39.38996 0.01010
avgerr: avgerr:
0.00529 0.00529
corrcoefs: corrcoefs:
0.99993 0.99994 0.99876 0.99997 0.99989 0.99994 0.99877 0.99997
这就是问题所在,改进的\u solve
实际上胜过了遗留的solve
:
((36.787862883725872, 43.967159949544317),
(40.522239654303483, 47.625869880574164),
(19.760537036548321, 49.183056694462799),
(45.701873101046154, 48.051424087501672))
solve relerr improved_solve relerr
table: table:
21.36407 23.53276 28.56241 26.54076 20.25226 26.21874 27.07599 26.45301
22.33545 24.52391 26.03695 27.10370 21.53733 26.33278 25.10656 27.02333
23.33149 25.54022 23.44736 27.68093 22.90176 26.45386 23.01550 27.62888
24.35314 26.58266 20.79119 28.27301 24.35314 26.58266 20.79119 28.27301
25.40141 27.65226 18.06583 28.88050 25.90005 26.71994 18.42047 28.95953
26.47734 28.75009 15.26854 29.50403 27.55225 26.86656 15.88840 29.69279
27.58205 29.87728 12.39644 30.14424 29.32086 27.02351 13.17793 30.47771
avgerr: avgerr:
0.39677 0.39630
corrcoefs: corrcoefs:
0.99975 0.99975 0.99975 0.99975 0.99847 0.99847 0.99847 0.99847
代码:
如果从另一端开始:生成一个se