📄 snepsolver.m
字号:
function L=snepsolver(W,e)
%------------------------------------------
%input: W--polynomial system
% e--a small tolerance
%output:
% P--the table of dimensions of projection and prolongtion matrices
% M--the multiplication matrices
% L--the solutions of polyonmial system
%-------------------------------------------
format long
P=zeros(10);
W=pre_prolongtion(W);%将初给的多项式系统化为齐次,使各个多项式的最高次相等,且为原多项式系统的最高次数
deg=ldeg(W);
n=size(W,2)-2;
A=W;
flag=0;
for j=1:10
%for语句得到多项式系统A经过若干次prolongtion和projection算子得到的维数表P
if j==1
B=A;
else
B=prolongtion(A,j-1);
end
s=ldeg(B);
C=convert(B);
[U,S,V]=svd(C);
rank=ndim(S,e);
m=size(V,2);
t=0;
for i=1:j+deg
if i==1
P(i,j)=size(V,1)-rank;
else
t=t+kdeg(s,n);
D=V(t+1:m,rank+1:m);
[U,S,F]=svd(D);
P(i,j)=ndim(S,e);
s=s-1;
end
if i>=2&&j>=2&&P(i-1,j-1)==P(i,j)&&P(i-1,j-1)==P(i,j-1)
%此时多项式系统对合
k=j-1;
flag=1;
end
end
if flag==1
break;
end
end
P, %输出prolongtion和projection算子得到的维数表P
for i=k:-1:1
if P(i,k)==P(i+1,k)&&P(i,k)==P(i+1,k+1)
break;
end
end
l=i; %在维数表P中选出满足对合条件的最小的k(prolongtion次数),,,以及在这个k下最大的l(projection次数)
dim=P(i,k);
if k==1
B=A;
else
B=prolongtion(A,k-1);
end
C=convert(B);
[U,S,V]=svd(C);
rank=ndim(S,e);
m=size(V,2);
D=V(m-gsum(deg+k-l,n)+1:m,rank+1:m); %D为对合的approximate spanning set子矩阵
E=V(m-gsum(deg+k-l-1,n)+1:m,rank+1:m); %E为将D再进行一次projection得到approximate spanning set子矩阵
max=m-rank;
Q=app_basis(E,dim,max,e);
DD=zeros(size(D,1),dim);
EE=zeros(size(E,1),dim);
for i=1:dim
DD(:,i)=D(:,Q(1,i)); %将D,E利用app_basis随机数筛选基而得到的满足对合条件的approximate basis DD,EE
EE(:,i)=E(:,Q(1,i));
end
[U,S,V]=svd(EE);
P=zeros(dim);
for i=1:dim %for语句得到各个multiplication matrix M,及multiplication matrix的线性组合T
P(i,i)=1/S(i,i);
end
G=U(:,1:dim);
X=grlex(deg+k-l,n);
T=zeros(dim);
for i=1:n
s=1;
N=zeros(gsum(deg+k-l-1,n),size(V,2));
for j=1:gsum(deg+k-l,n)
if X(j,i)>0
N(s,:)=DD(j,:);
s=s+1;
end
end
M=G'*N*V*P;
M, %输出各个multiplication matrix M
T=T+((-1)^i)*M;
end
[V,Y]=eig(T);
R=G*V;
L=zeros(n,dim);
for i=1:n %利用multiplication matrix的线性组合T的特征向量计算出多项式系统的solutions L,输出solutions L
L(i,:)=R(size(R,1)-n+i-1,:)./R(size(R,1),:);
end
%--------------------------------------------
function A=pre_prolongtion(W)
%将初给的多项式系统化为齐次,使各个多项式的最高次相等,且为原多项式系统的最高次数
format long
Q=size(W,1);
n=size(W,2)-2;
m=W(Q,n+1);
F=zeros(m,2);
q=0;
max=0;
s=1;
for i=1:Q %for语句统计出各个多项式的项数和最高次
sum=0;
for j=1:n
sum=sum+W(i,j);
end
if W(i,n+1)==s
q=q+1;
if sum>max
max=sum;
end
else
F(s,1)=q;
F(s,2)=max;
q=1;
max=sum;
s=s+1;
end
end
F(s,1)=q;
F(s,2)=max;
for i=1:m
if F(i,2)>max
max=F(i,2);
end
end
sum=0;
for i=1:m
sum=sum+F(i,1)*kdeg(max-F(i,2),n);
end
A=zeros(sum,n+2);
sum=0;
p=0;
flag=0;
for i=1:m %for语句完成对各个多项式的延拓,使其最高次相等
D=rlex(max-F(i,2),n);
for j=1:kdeg(max-F(i,2),n)
for t=1:F(i,1)
p=p+1;
A(p,1:n)=W(sum+t,1:n)+D(j,:);
A(p,n+1)=flag+j;
A(p,n+2)=W(sum+t,n+2);
end
end
sum=sum+F(i,1);
flag=flag+kdeg(max-F(i,2),n);
end
%--------------------------------------------------
function B=prolongtion(A,k)
%对多项式系统A进行k次prolongtion算子延拓
format long
flag=0;
Q=size(A,1);
n=size(A,2)-2;
m=A(Q,n+1);
q=Q;
B=zeros(Q*gsum(k,n),n+2);
B(1:Q,:)=A;
for i=1:k
D=rlex(i,n);
for j=1:kdeg(i,n)
flag=flag+1;
for t=1:Q
q=q+1;
B(q,1:n)=A(t,1:n)+D(j,:);
B(q,n+1)=A(t,n+1)+flag*m;
B(q,n+2)=A(t,n+2);
end
end
end
%-------------------------------------------------
function clum=app_basis(E,dim,max,e)
%将对合的approximate spanning set子矩阵E利用随机数筛选出一组approximate basis
B=zeros(size(E,1),dim);
clum=sort(ceil(max*rand(1,dim)));
for i=1:dim
B(:,i)=E(:,clum(1,i));
end
[U,S,V]=svd(B);
while ndim(S,e)~=dim
clum=sort(ceil(max*rand(1,dim)));
for i=1:dim
B(:,i)=E(:,clum(1,i));
end
[U,S,V]=svd(B);
end
%-------------------------------------------------
function d=ndim(A,e)
%计算SVD分解的核空间的近似维数
r=size(A,1);
l=size(A,2);
if r>l
min=l;
else
min=r;
end
d=0;
for i=1:min
if A(i,i)>=e
d=d+1;
end
end
%---------------------------------------------------
function C=convert(B)
%将延拓后的多项式系统B的指标矩阵转化为系数矩阵
format long
Q=size(B,1);
n=size(B,2)-2;
deg=ldeg(B);
q=Q;
C=zeros(B(q,n+1),gsum(deg,n));
for i=1:q
w=B(i,n+1);
E=grlex(deg,n);
for j=1:gsum(deg,n)
b=E(j,:)-B(i,1:n);
a=b.*b;
s=0;
for t=1:n
s=s+a(t);
end
if s==0
v=j;
break;
end
end
C(w,v)=B(i,n+2);
end
C=flipud(C);
%-----------------------------------------------
function l=gsum(k,n)
%计算n个未知数的所有次数不超过k次的单项式的总数
l=0;
for i=0:k
l=l+kdeg(i,n);
end
%----------------------------------------------
function g=grlex(k,n)
%n个未知数的所有次数不超过k次的单项式分次字典序的指标列表(从高到低)
sum=0;
for i=0:k
sum=sum+kdeg(i,n);
end
g=zeros(sum,n);
r=1;
for i=k:-1:0
g(r:r+kdeg(i,n)-1,1:n)=rlex(i,n);
r=r+kdeg(i,n);
end
%----------------------------------------------
function output=rlex(k,n)
%n个未知数的所有k次单项式分次字典序的指标列表(从高到低)
output=zeros(kdeg(k,n),n);
q=1;
if n==1
output=k;
else
for p=k:-1:0
r=kdeg(k-p,n-1);
output(q:q+r-1,2:n)=rlex(k-p,n-1);
output(q:q+r-1,1)=p;
q=q+r;
end
end
%-----------------------------------------------
function s=ldeg(A)
%计算多项式系统A的最高次数
Q=size(A,1);
n=size(A,2)-2;
s=0;
for i=1:Q
sum=0;
for j=1:n
sum=sum+A(i,j);
end
if sum>s
s=sum;
end
end
%-----------------------------------------------
function c=cdeg(a,b)
%计算组合数
if a<=b
c=1;
for e=1:b
c=c*e;
end
for f=1:b-a
c=c/f;
end
for g=1:a
c=c/g;
end
else
c=0;
end
%--------------------------------------------
function d=kdeg(k,n)
%计算n个未知数的k次单项式的总数
if k>0
d=0;
for i=1:k
d=d+cdeg(i-1,k-1)*cdeg(i,n);
end
else
d=1;
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -