I用大写字母表示矩阵,用小写字母表示向量。
我需要解向量v
的以下线性不等式组:
min(rv - (u + Av), v - s) = 0
其中0
是一个零向量。在
其中r
是标量,u
和{A
是矩阵。在
定义z = v-s
,B=rI - A
,q=-u + Bs
,我可以将前面的问题重写为linear complementarity problem,并希望使用LCP解算器,例如来自openopt
:
或者,在矩阵表示法中:
z'(Bz+q) = 0
z >= 0
Bz + q >= 0
问题是我的方程组太庞大了。要创建A
,我
scipy.sparse.diags
创建四个矩阵A11
,A12
,A21
,A22
A = scipy.sparse.bmat([[A11, A12], [A21, A22]])
A
不是对称的,因此一些有效的QP
问题的转换是行不通的)openopt.LCP
显然不能处理稀疏矩阵:当我运行这个程序时,我的计算机崩溃了。通常,A.todense()
将导致内存错误。类似地,compecon-python
也不能解决稀疏矩阵的LCP
问题。在
有什么替代的LCP
实现适合这个问题?在
我真的不认为对于一个一般的“解决LCP的工具”问题需要样本数据,但无论如何,我们开始吧
from numpy.random import rand
from scipy import sparse
n = 3000
r = 0.03
A = sparse.diags([-rand(n)], [0])
s = rand(n,).reshape((-1, 1))
u = rand(n,).reshape((-1, 1))
B = sparse.eye(n)*r - A
q = -u + B.dot(s)
q.shape
Out[37]: (3000, 1)
B
Out[38]:
<3000x3000 sparse matrix of type '<class 'numpy.float64'>'
with 3000 stored elements in Compressed Sparse Row format>
还有一些建议:
openopt.LCP
我的矩阵崩溃了,我假设在继续之前它会将矩阵转换为稠密的compecon-python
完全失败,有一些错误,它显然需要稠密矩阵,并且没有稀疏性的退步B
不是半正定的,所以我不能把线性互补问题(LCP)重新表述为凸二次问题(QP)
这个问题有一个非常有效的(线性时间)解决方案,尽管它需要一些讨论。。。在
Zeroth:澄清问题/LCP
根据评论中的澄清,@FooBar说原始问题是元素方面的
min
;我们需要找到一个z
(或v
),这样正如@FooBar正确指出的,有效的重新参数化将导致LCP。然而,下面我展示了一个更简单、更有效的解决原始问题的方法(通过利用原始问题中的结构),而不需要LCP。为什么这应该更容易?注意,LCP在
z
(Bz+q)'z中有一个二次项,但是原始问题没有(只有线性项Bz+q和z)。下面我将利用这个事实。在首先:简化
有一个重要但关键的细节在很大程度上简化了这个问题:
这有着巨大的影响。具体地说,这不是一个单一的大的问题,而是一个非常小的问题(确切地说是2D)的大数问题。注意,这个
A
矩阵的块对角结构在所有后续操作中都保持不变。每一个后续的运算都是矩阵向量乘法或内积。这意味着这个程序实际上是在z
(或v
)变量对中的可分离的。在具体来说,假设每个块}只在等式和术语中出现在中,而不会出现在其他地方。因此,该问题可分为
A11,...
的大小为n
,大小为n
。然后批判性地注意到z_1
和{n
问题,每个问题都是二维的。因此,我将在以后解决2D问题,并且您可以在n
上序列化或并行化,而不需要稀疏矩阵或大opt包。在第二:二维问题的几何结构
假设我们有二维的元素问题,即:
因为在我们的设置中
^{pr2}$B
现在是2x2,这个问题几何对应于我们可以手动枚举的四个标量不等式(我将它们命名为a1、a2、z1、z2):这代表一个(可能是空的)多面体,也就是二维空间中四个半空间的交集。在
第三:解决二维问题
(编辑:为了清楚起见,更新了这一点)
那么2D问题具体是什么呢?我们想要找到一个
z
,其中一个解决方案(虽然不是完全不同,但并不重要):如果实现了其中之一,我们就有了一个解:z,其中z和Bz+q的元素最小值是0向量。如果这四个都不能实现,那么这个问题是不可行的,我们将宣布不存在这样的
z
。在第一种情况发生在a1,a2的交点正或正中。只需选择解z=B^-1q,并检查它是否是元素非负的。如果是,则返回
B^-1q
(注意,即使B不是psd,我假设它是可逆的/满秩的)。所以:第二种情况(与第一种情况不完全不同)发生在a1、a2的交点在任何地方但包含原点时。换句话说,当Bz+q>;0表示z=0时。当q为元素正时发生这种情况。所以:
第三种情况为z1=0,可以代入a2表示当z2=-q2/B22时a2=0。z2必须大于等于0,因此-q2/B22>;=0。a1也必须是>;=0,用z1和z2代替值,得到-B22/B12*q2+q1>;=0。所以:
第四步与第三步相同,但是交换1和2。所以:
最后第五种情况是当问题不可行时。当上述条件都不满足时会发生这种情况。所以:
最后:将各部分组合起来
求解每一个二维问题都是一对简单/高效/平凡的线性解并进行比较。每个都将返回一对数字或
None
。然后对所有的n
2D问题做同样的处理,并连接向量。如果有没有,这个问题是不可行的(全部没有)。否则,你有你的答案。在基于AMPLPY
正如@denfromufa指出的,有一个}。然而,
AMPL
接口到PATH
解算器。他建议使用Pyomo
,因为它是开源的,能够处理{Pyomo
结果是缓慢和乏味的工作。我最终在cython中编写了自己的接口到PATH
解算器,并希望在某个时候发布它,但目前它没有输入卫生设施,速度快而且脏,而且我看不到时间来处理它。在现在,我可以分享一个使用python扩展
AMPL
的答案。它不如PATH
的直接接口快:对于我们要解决的每个LCP
,它都会创建一个(临时)模型文件,运行AMPL
,并收集输出。这有点快又脏,但我觉得我至少应该报告几个月来提出这个问题以来的部分结果。在相关问题 更多 >
编程相关推荐