You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
427 lines
12 KiB
427 lines
12 KiB
#include <iostream>
|
|
#include <ginac/ginac.h>
|
|
#include <vector>
|
|
#include <cstdlib>
|
|
#include <ctime>
|
|
#include <chrono>
|
|
#include <cstdio>
|
|
using namespace std;
|
|
using namespace GiNaC;
|
|
|
|
const symbol & get_symbol(const string & s)
|
|
{
|
|
static map<string, symbol> directory;
|
|
map<string, symbol>::iterator i = directory.find(s);
|
|
if (i != directory.end())
|
|
return i->second;
|
|
else
|
|
return directory.insert(make_pair(s, symbol(s))).first->second;
|
|
}
|
|
// #define CREATE_VARIABLE_NAME(index) a##index
|
|
symbol x("x"), y("y"), z("z"),w("w");
|
|
symbol s("s"), t("t");
|
|
symbol a("a"), b("b"), c("c"), d("d");
|
|
static int deg;
|
|
vector<ex> f(4);
|
|
int get_idx(int i,int j){
|
|
return i*deg+j;
|
|
}
|
|
//组合数来生成计算minor
|
|
void generateCombination(vector<int>& candidates, int start, int p, vector<int>& combination, vector<vector<int>>& result) {
|
|
if (p == 0) {
|
|
result.push_back(combination);
|
|
return;
|
|
}
|
|
|
|
for (int i = start; i < candidates.size(); ++i) {
|
|
combination.push_back(candidates[i]);
|
|
generateCombination(candidates, i + 1, p - 1, combination, result);
|
|
combination.pop_back();
|
|
}
|
|
}
|
|
|
|
vector<vector<int> > getCombinations(int k, int p) {
|
|
vector<vector<int> > result;
|
|
vector<int> candidates;
|
|
for (int i = 0; i < k; ++i) {
|
|
candidates.push_back(i);
|
|
}
|
|
|
|
vector<int> combination;
|
|
generateCombination(candidates, 0, p - 1, combination, result);
|
|
return result;
|
|
}
|
|
matrix random_matrix(int n,int m,int k){
|
|
matrix cur(n,m);
|
|
int rem;//
|
|
if(k>10)
|
|
rem=2;
|
|
else
|
|
rem=10;
|
|
for(int i=0;i<n;i++)
|
|
for(int j=0;j<m;j++)
|
|
cur(i,j)=rand()%rem;
|
|
return cur;
|
|
}
|
|
ex KKS(matrix N,int p,int k)
|
|
{
|
|
srand(time(0));
|
|
matrix U1=random_matrix(p-1,p,k);
|
|
matrix U2=random_matrix(p-1,p,k);
|
|
matrix V1=random_matrix(k,p-1,k);
|
|
matrix V2=random_matrix(k,p-1,k);
|
|
matrix curU1=U1.mul(N);
|
|
matrix curU2=U2.mul(N);
|
|
matrix resU1=curU1.mul(V1);
|
|
matrix resU2=curU2.mul(V2);
|
|
// cout<<resU1<<endl;
|
|
// cout<<"....."<<endl;
|
|
// cout<<resU2<<endl;
|
|
// return 1;
|
|
ex g1=determinant(resU1);
|
|
// cout<<"123"<<endl;
|
|
ex g2=determinant(resU2);
|
|
return gcd(g1,g2);
|
|
}
|
|
vector<ex> factor_parser(ex f,parser &reader){
|
|
vector<ex> ans;
|
|
if(!is_a<mul>(f))
|
|
{
|
|
ans.push_back(f);
|
|
return ans;
|
|
}
|
|
int cnt=0;
|
|
string cur="";
|
|
int i=0;
|
|
stringstream ss;
|
|
ss<<f;
|
|
string curs;
|
|
getline(ss,curs);
|
|
while(i<curs.size()){// * ( )
|
|
if(curs[i]=='*'){
|
|
if(cnt==0)
|
|
{
|
|
ans.push_back(reader(cur));
|
|
cur="";
|
|
}
|
|
else
|
|
cur+=curs[i];
|
|
}
|
|
else if(curs[i]=='('){
|
|
cur+=curs[i];
|
|
cnt++;
|
|
}
|
|
else if(curs[i]==')'){
|
|
cur+=curs[i];
|
|
cnt--;
|
|
}
|
|
else
|
|
cur+=curs[i];
|
|
i++;
|
|
}
|
|
ans.push_back(reader(cur));
|
|
return ans;
|
|
}
|
|
void checktime(auto &st){
|
|
auto ed=std::chrono::high_resolution_clock::now();
|
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(ed-st);
|
|
st=ed;
|
|
std::cout << duration.count() << " ms" << std::endl;
|
|
}
|
|
int main()
|
|
{
|
|
freopen("a.out","w",stdout);
|
|
auto st = std::chrono::high_resolution_clock::now();
|
|
symtab table;
|
|
table["s"] = s;
|
|
table["t"] = t;
|
|
parser reader(table);
|
|
// random
|
|
//Ex 4.6
|
|
//Cone
|
|
f[0]=reader("-t*(-s^2 + 1)");
|
|
f[1]=reader("2*s*t");
|
|
f[2]=reader(" t*(s^2 + 1)");
|
|
f[3]=reader(" s^2 + 1");
|
|
//Ex 4.2
|
|
// f[0]=reader("(2*t^2 - 6*t + 4)*s^2 + 4*(t - 1)*s + 1");
|
|
// f[1]=reader(" -2*(t^2 - 3*t + 1)*s^2 + (4*t - 2)*s");
|
|
// f[2]=reader(" (t^2 - 4*t + 3)*s^2 - 2*(t - 1)^2 * s");
|
|
// f[3]=1;
|
|
// f[0]=(2*pow(t,2)-6*t+4)*pow(s,2)+4*(t-1)*s+1;
|
|
// f[1]=-2*(pow(t,2)-3*t+1)*pow(s,2)+(4*t-2)*s;
|
|
// f[2]=(pow(t,2)-4*t+3)*pow(s,2)-2*pow((t-1),2)*s;
|
|
// f[3]=1;
|
|
|
|
// Ex 6.1 Correct!
|
|
// f[0]=s+3+t;
|
|
// f[1]=1+t*s*s+t;
|
|
// f[2]=s*s-3*s+2*s*t+1;
|
|
// f[3]=s+s*t+3*t;
|
|
//Ex 6.2 Correct!
|
|
// f[0]=s*s+t;
|
|
// f[1]=t*(s*s+1)+s*s+1;
|
|
// f[2]=-s*s*s+2*s*s*t+s*s+1;
|
|
// f[3]=t*(s*s*s+3)+1;
|
|
//Ex 6.3
|
|
// f[0]=-pow(s,3)*(t*t-1);
|
|
// f[1]=(s+2)*s*t;
|
|
// f[2]=-pow(t,3)*(pow(s,2)-4);
|
|
// f[3]=pow(s,3);
|
|
//Ex 6.4
|
|
// f[0]=reader("4*s^3 + s*t^2 + 4*s^2 - 12*s*t + t^2 + s + 1");
|
|
// f[1]=reader("4*s^4 + s^2*t^2 + s^2 + 6*t");
|
|
// f[2]=reader("6*t^2");
|
|
// f[3]=reader("4*s^2 + t^2 + 1");
|
|
//Ex 6.5
|
|
// f[0]=reader("4*s^3 + s*t^2 + 4*s^2 - 12*s*t + t^2 + s + 1");
|
|
// f[1]=reader("4*s^4 + s^2*t^2 + s^2 + 6*t");
|
|
// f[2]=reader("6*t^2");
|
|
// f[3]=reader("4*s^2 + t^2 + 1");
|
|
for(int i=0;i<4;i++)
|
|
cout<<f[i]<<endl;
|
|
cout<<".........."<<endl;
|
|
int d1=-10,d2=-10;
|
|
for(int i=0;i<f.size();i++){
|
|
d1=max(d1,f[i].degree(s));
|
|
d2=max(d2,f[i].degree(t));
|
|
}
|
|
// cout<<d1<<" "<<d2<<endl;
|
|
int v1,v2;
|
|
if(d1>=d2)//保证ex4.2是3,1,理论上应该是>=
|
|
v1=d1-1,v2=2*d2-1;//s v1,t v2
|
|
else
|
|
v1=2*d1-1,v2=d2-1;
|
|
// cout<<v1<<' '<<v2<<endl;
|
|
deg=2*d1*d2;
|
|
//basefunc of moving planes, also matrix
|
|
vector<ex> basefunc;
|
|
|
|
//O(2*d1*d2)
|
|
for(int i=0;i<=v2;i++)
|
|
{
|
|
for(int j=0;j<=v1;j++){
|
|
basefunc.push_back(pow(s,j)*pow(t,i));
|
|
}
|
|
}
|
|
// for(int i=0;i<deg;i++)
|
|
// cout<<basefunc[i]<<endl;
|
|
|
|
vector<ex> matbasefunc;//存储乘后的结果,用来解线性方程组
|
|
lst matbasefunc_lst;
|
|
//O((d2+v2)*(d2+v2)) 近似于 O(d1*d2)
|
|
for(int i=0;i<=(d2+v2);i++)
|
|
for(int j=0;j<=(d1+v1);j++)
|
|
{
|
|
matbasefunc.push_back(pow(s,j)*pow(t,i));
|
|
matbasefunc_lst.append(pow(s,j)*pow(t,i));
|
|
}
|
|
//生成用来求解的未知数变量
|
|
//O(d1*d2)
|
|
vector<ex> matvar;
|
|
for(int i=0;i<4;i++)
|
|
for(int j=0;j<2*d1*d2;j++){
|
|
string cur="a";
|
|
cur=cur+to_string(get_idx(i,j));
|
|
matvar.push_back(get_symbol(cur));
|
|
}
|
|
lst eqns={};
|
|
lst vars={};
|
|
|
|
//添加到vars当中
|
|
for(int i=0;i<matvar.size();i++)
|
|
vars.append(matvar[i]);
|
|
vector<ex> l;
|
|
for(int i=0;i<4;i++)
|
|
{
|
|
ex cur=0;
|
|
for(int j=0;j<deg;j++)
|
|
{
|
|
int idx=get_idx(i,j);
|
|
cur=cur+matvar[idx]*basefunc[j];
|
|
}
|
|
l.push_back(cur);
|
|
}
|
|
//多维的分离系数存在问题,不能直接使用coeff
|
|
ex mulres=0;
|
|
for(int i=0;i<4;i++)
|
|
mulres=mulres+l[i]*f[i];
|
|
mulres=expand(mulres);
|
|
// cout<<mulres<<endl;
|
|
mulres.collect(matbasefunc_lst,true);//collect也不好用,并不能按照规定合并,合并之后的结果包含a1*s*t+a2*s*t
|
|
//因此需要使用map累加所有的同类项
|
|
// cout<<mulres<<endl;
|
|
int cnt=0;
|
|
map<ex,ex,ex_is_less> mp;//ex不支持比较,声明map的时候必须像这样声明
|
|
for (const auto& term : mulres) {//遍历多项式中的每一项
|
|
ex cur;
|
|
//coeff无法求两个symbol对应的度数,因此需要用除法来求解
|
|
int curd1=term.degree(s),curd2=term.degree(t);
|
|
ex pl=pow(s,curd1)*pow(t,curd2);
|
|
cur=quo(term,pl,x);//计算商
|
|
if(mp.find(pl)!=mp.end())
|
|
mp[pl]=mp[pl]+cur;
|
|
else
|
|
mp[pl]=cur;
|
|
// cout<<cur<<"......"<<term<<endl;
|
|
// eqns.append(cur==0);
|
|
}
|
|
for(auto &i:mp){
|
|
eqns.append(i.second==0);
|
|
// cout<<i.second<<endl;
|
|
// cnt++;
|
|
}
|
|
// cout<<cnt<<endl;
|
|
// checktime(st);
|
|
ex ans=lsolve(eqns,vars);//存储答案
|
|
// checktime(st);
|
|
// cout<<ans<<endl;
|
|
//判断自由变量
|
|
vector<ex> freevar;
|
|
for (int i=0;i<matvar.size();i++)
|
|
{
|
|
if(lhs(ans[i])==rhs(ans[i]))
|
|
freevar.push_back(lhs(ans[i]));
|
|
}
|
|
//计算这一向量空间的基,也就是计算无穷组解组成的向量空间的基
|
|
//最多有 自由变量+1个基(1是自由变量全0的时候,不过有可能自由变量全0的时候解为0向量,需要特判)
|
|
lst cureqns=eqns;
|
|
for(int j=0;j<freevar.size();j++)
|
|
{
|
|
cureqns.append(freevar[j]==0);
|
|
}
|
|
ex curans=lsolve(cureqns,vars);
|
|
int flag=0;
|
|
for(int i=0;i<matvar.size();i++){
|
|
if(rhs(curans[i])!=0)
|
|
flag=1;
|
|
}
|
|
// checktime(st);
|
|
int p=2*d1*d2,k;//p*k维矩阵
|
|
//特判k的大小
|
|
if(flag==1)
|
|
{
|
|
k=freevar.size()+1;
|
|
}
|
|
else
|
|
k=freevar.size();
|
|
matrix M(p,k);//全0,从0开始计算idx
|
|
matrix N(p,k);//直接求,不做替换
|
|
// cout<<M<<endl;
|
|
//如果为1,则要加入答案当中
|
|
vector<ex> ff;
|
|
ff.push_back(x);
|
|
ff.push_back(y);
|
|
ff.push_back(z);
|
|
ff.push_back(w);
|
|
if(flag==1)
|
|
{
|
|
for(int i=0;i<4;i++)
|
|
{
|
|
for(int j=0;j<2*d1*d2;j++)
|
|
{
|
|
ex varans=rhs(curans[get_idx(i,j)]);
|
|
if(varans!=0)//取出答案
|
|
{
|
|
M(j,p-1)=M(j,p-1)+varans*ff[i];
|
|
N(j,p-1)=N(j,p-1)+varans*f[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// cout<<p<<" "<<k<<endl;
|
|
|
|
for(int i=0;i<freevar.size();i++){
|
|
lst cureqns=eqns;
|
|
for(int j=0;j<freevar.size();j++)
|
|
{
|
|
if(j!=i)
|
|
cureqns.append(freevar[j]==0);
|
|
}
|
|
cureqns.append(freevar[i]==1);
|
|
ex curans=lsolve(cureqns,vars);
|
|
for(int ii=0;ii<4;ii++)
|
|
{
|
|
for(int j=0;j<2*d1*d2;j++)
|
|
{
|
|
ex varans=rhs(curans[get_idx(ii,j)]);
|
|
if(varans!=0)//取出答案
|
|
{
|
|
N(j,i)=N(j,i)+varans*f[ii];
|
|
M(j,i)=M(j,i)+varans*ff[ii];
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
// checktime(st);
|
|
int testflag;
|
|
testflag=0;
|
|
if(testflag)
|
|
{ ex H=0;
|
|
vector<ex> ni;//用于存储所有可能的minor
|
|
//计算H,相当于计算矩阵所有可能的p-1 *p-1维度的minor,然后求解GCD
|
|
//先递归找到所有的列组合
|
|
vector<vector<int> > combinations = getCombinations(k, p);
|
|
// matrix calmat=ex_to<matrix>(sub_matrix(N,0,p-2,0,p-2));
|
|
// cout<<determinant(calmat)<<endl;
|
|
for(int i=0;i<p;i++)
|
|
{
|
|
for(auto &nums:combinations)
|
|
{
|
|
//由于不支持选取不连续的几行几列,并且reduce去除矩阵的某行某列时必须同时提供行列
|
|
//先构建一个p*p的矩阵,p行是为了构建完矩阵后删除某一行,因此需要对应的多加一列
|
|
//因为最后一列是全0列,直接删就行
|
|
matrix curmat(p,p);
|
|
for(int j=0;j<nums.size();j++)
|
|
{
|
|
int col=nums[j];//选取出某一列
|
|
for(int k=0;k<p;k++){
|
|
curmat(k,j)=N(k,col);
|
|
}
|
|
}
|
|
matrix calmat=ex_to<matrix>(reduced_matrix(curmat,i,p-1));
|
|
ni.push_back(determinant(calmat));
|
|
}
|
|
cout<<i<<endl;
|
|
}
|
|
//求解GCD,即H
|
|
for(int i=0;i<ni.size();i++)
|
|
{
|
|
if(i==0)
|
|
H=ni[0];
|
|
else
|
|
H=gcd(H,ni[i]);
|
|
}
|
|
H=expand(H);
|
|
//对H因式分解
|
|
cout<<H<<endl;
|
|
cout<<"..........."<<endl;
|
|
ex curh=factor(H);
|
|
cout<<curh<<endl;
|
|
cout<<"-------------"<<endl;
|
|
}
|
|
//尝试先不带入xyzw的表达式,来加速,但是发现带入后计算的更快??可能存在消项
|
|
//因为在计算GCD的时候先带入表达式再计算GCD和先计算GCD再带入表达式求出结果完全一样
|
|
ex quickH=KKS(N,p,k);
|
|
quickH=expand(quickH);
|
|
quickH=factor(quickH);
|
|
// lst factors=ex_to<lst>(factor(quickH));
|
|
cout<<quickH<<endl;
|
|
cout<<"..........."<<endl;
|
|
// checktime(st);
|
|
vector<ex> h=factor_parser(quickH,reader);
|
|
for(auto &i:h)
|
|
if(!is_a<numeric>(i))//skip numeric
|
|
cout<<i<<endl;
|
|
|
|
//ALG2
|
|
vector<int> order;
|
|
for(auto &i:h){//处理每一个h
|
|
int s_deg=i.degree(s);
|
|
int t_deg=i.degree(t);
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|