華電北風吹
最後修改日期:2015/8/6
如果只有一些線性約束,想把所有的可行解都輸出出來怎麼辦?
例如下面的小例子:
約束條件為|a
1x1+
a2x2
+a3x
3+..
.+an
xn−b|m1
=<=m1m2=
<=m2
… mn
=<=mn
最簡單的方法肯定是把所有的點根據超矩形約束條件遍歷一遍,然後把與到超平面距離滿足約數的點輸出。
我寫了個小例子,如下,迴圈把所有的可行解個數輸出。
__author__ = 'zhengyi'
defmainfunc
(m0,m,x):
if len(m)>0:
k1=m0[0]
k2=m[0]
for i in range(k1,k2+1):
t=x.copy()
mainfunc(m0[1::],m[1::],t)
else:
if distance(x)<=e:
print(x)
defdistance
(x):
result=map(lambda x,y:x*y,a,x)
return abs(sum(result)-b)
a=[20,30]
b=90
m=[5,5]
m0=[2,0]
e=20
x=mainfunc(m0,m,x)**執行結果為:
[2, 1]
[2, 2]
[3, 1]
[4, 0]
[4, 1]
[5, 0]
但是當特徵個數增大的時候,這個計算時間會特別大。因為,計算時間複雜度是theta(mn
)。其中m為每個特徵的取值範圍,n為特徵維數。
考慮到即使你知道那個解是可行解,把所有的解輸出也需要迴圈n次。因此如果想要減少計算量,貌似只能減少在無用解上的計算次數。這時候我們可以考慮先在可行解內部獲取乙個初始點,然後以這個初始點為中心,在可行解空間中向外圍搜尋,直到到達可行解邊界。
這樣做需要考慮搜尋方向問題。比較好的一點是,由線性約束的可行解構成的空間肯定是乙個凸空間。因此可以想到以下兩種搜尋策略:
1、根據特徵遞迴迴圈(這裡有缺陷,就是如果不讓下層特徵對上層特徵進行搜尋的話,需要保證當前特徵搜尋路徑是最寬的,這個就很麻煩了)
2、根據空間的外方向,逐層外擴(這也是下面**採用的思想)
__author__ = 'zhengyi'
defmainfunc
(x,d):
flag=true
for i in range(0,len(d)):
x[i]+=d[i]
if x[i]or x[i]>m[i]:
return
if d[i]!=0
and flag:
flag=false
if flag:
return
if distance(x)>e:
return
print(x)
mainfunc(x.copy(),d.copy())
for i in range(0,len(d)):
if d[i]!=0:
td=d.copy()
td[i]=0
mainfunc(x.copy(),td)
defdistance
(x):
result=map(lambda x,y:x*y,a,x)
return abs(sum(result)-b)
a=[20,30]
b=90
m=[5,5]
m0=[2,0]
e=20
x=[2,2]
print(x)
d=[-1
for i in range(0,len(a))]
k=pow(3,len(a))
for i in range(1,k):
td=d.copy()
j=0while i>0:
td[j]+=i%3
i//=3
j+=1
mainfunc(x.copy(),td)**輸出結果:
[2, 2]
[2, 1]
[3, 1]
[4, 0]
[5, 0]
[4, 1]
但是這個演算法的複雜度仍舊是theta(3^n),因為每一維都有3中選擇,共同構成的空間外方向數目就是3n
−1種。這樣的搜尋策略能夠保證搜尋一直在可行解內部搜尋,**計算效率比較高,這是我目前想到的最好的方法,歡迎對這個問題感興趣的有想法的朋友一起討論。
補充:
第二種方法需要在可行解內找乙個初始點,由於這個問題不是主要問題,可以由隨便指定乙個優化函式,然後利用單純形法得到乙個初始解。在這裡我為了方便,使用lingo得到乙個初始解。
lingo**如下:
model:
sets:
s/1.
.20/:a,x,m0,m;
endsets
data:
a=20,30,15,17,20,20,20,20,30,15,17,20,20,20,20,30,15,17,20,20;
m=5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5;
m0=2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;
enddata
@abs(@sum(s(i):a(i)*x(i))-1000)<100;
@for(s(i):m0(i)i));
@for(s(i):x(i)i));
@for(s(i):@gin(x(i)));
end**1的非遞迴形式:
__author__ = 'zhengyi'
defdistance
(x):
result=map(lambda x,y:x*y,a,x)
return abs(sum(result)-b)
a=[20,30]
b=90
m=[5,5]
m0=[2,0]
e=20
k=len(a)
totalnum=1
original=m0.copy()
rangelist=[0
for i in range(0,k)]
for i in range(0,k):
rangelist[i]=m[i]-m0[i]+1
totalnum*=rangelist[i]
for i in range(0,totalnum):
s=original.copy()
p=0while i>0:
s[p]=original[p]+i%(rangelist[p])
i=i//(rangelist[p])
p+=1
if distance(s)<=e:
print(s)作為對比,放乙個相似問題的解法
參考**:
#include
#include
using
namespace
std;
int main(int argc, char* argv)
else}}
}}}}
cout
<< count << endl;
getchar();
return
0;}
Scipy空間 計算凸包(convexHull
凸包 數學上指,在實向量空間v中的一組點x的凸包或凸包絡是包含x的最小凸集。通俗的來說就是包圍一組散點的最小凸邊形。在scipy.spatial 中計算凸包的函式,scipy中convexhull輸入的引數可以是m2的點座標。其返回值的屬性.verticess是所有凸輪廓點在散點 m2 中的索引值。...
把Gmail空間當磁碟使用
把gmail空間當磁碟使用 by webleon 今天早上 zheng 那裡看到了這個神奇的軟體,可以把gmail的1000m空間作為乙個虛擬磁碟來使用。當然,你可以像操作硬碟一樣,在這個磁碟中進行複製貼上等工作,非常方便。乙個多月前,richard jones就提出了 gmailfs 的概念,並開...
如何把資料匯入不同的表空間
使用者unlimited tablespace許可權 這樣就可以匯入到使用者預設表空間 sql create user bjbbs identified by passwd 2 default tablespace bjbbs 3 temporary tablespace temp 4 user c...