Valence of sparse matrix over Z or Zp.
#include <iostream>
int main (int argc, char **argv)
{
commentator().
setMaxDetailLevel (-1);
commentator().
setMaxDepth (-1);
commentator().
setReportStream (std::cerr);
if (argc < 2 || argc > 4) {
std::cerr << "Usage: smithvalence <matrix-file-in-supported-format> [-ata|-aat|valence] [coprime]" << std::endl;
std::cerr << " Optional parameters valence and coprime are integers." << std::endl;
std::cerr << " Prime factors of valence will be used for local computation." << std::endl;
std::cerr << " coprime will be used for overall rank computation." << std::endl;
return -1;
}
std::ifstream input (argv[1]);
if (!input) { std::cerr << "Error opening matrix file " << argv[1] << std::endl; return -1; }
Givaro::ZRing<Integer> ZZ;
typedef SparseMatrix<Givaro::ZRing<Integer> > Blackbox;
Blackbox A (ms);
input.close();
std::cout << "A is " << A.rowdim() << " by " << A.coldim() << std::endl;
Givaro::ZRing<Integer>::Element val_A;
Givaro::Timer chrono; chrono.start();
if (argc >= 3) {
if (strcmp(argv[2],"-ata") == 0) {
std::cout <<
"A^T A is " << C.
rowdim() <<
" by " << C.
coldim() << std::endl;
valence(val_A, C);
}
else if (strcmp(argv[2],"-aat") == 0) {
std::cout <<
"A A^T is " << C.
rowdim() <<
" by " << C.
coldim() << std::endl;
valence(val_A, C);
}
else {
std::cout << "Suppose primes are contained in " << argv[2] << std::endl;
}
}
else {
if (A.rowdim() != A.coldim()) {
std::cerr << "Valence works only on square matrices, try either to change the dimension in the matrix file, or to compute the valence of A A^T or A^T A, via the -aat or -ata options." << std::endl;
exit(0);
}
else
valence (val_A, A);
}
std::cout << "Valence is " << val_A << std::endl;
std::vector<integer> Moduli;
std::vector<size_t> exponents;
Givaro::IntFactorDom<> FTD;
typedef std::pair<integer,unsigned long> PairIntRk;
std::vector< PairIntRk > smith;
if (argc >= 4) {
}
while ( gcd(val_A,coprimeV) > 1 ) {
FTD.nextprimein(coprimeV);
}
if (argc >= 4) {
std::cout << "Suppose " << argv[3] << " is coprime with Smith form" << std::endl;
}
std::cout << "integer rank: " << std::endl;
unsigned long coprimeR; LRank(coprimeR, argv[1], coprimeV);
smith.push_back(PairIntRk(coprimeV, coprimeR));
std::cout << "Some factors (5000 factoring loop bound): ";
FTD.set(Moduli, exponents, val_A, 5000);
std::vector<size_t>::const_iterator eit=exponents.begin();
for(std::vector<integer>::const_iterator mit=Moduli.begin();
mit != Moduli.end(); ++mit,++eit)
std::cout << *mit << '^' << *eit << ' ';
std::cout << std::endl;
std::vector<integer> SmithDiagonal(coprimeR,
integer(1));
for(std::vector<integer>::const_iterator mit=Moduli.begin();
mit != Moduli.end(); ++mit) {
unsigned long r; LRank(r, argv[1], *mit);
smith.push_back(PairIntRk(*mit, r));
for(size_t i=r; i < coprimeR; ++i)
SmithDiagonal[i] *= *mit;
}
eit=exponents.begin();
std::vector<PairIntRk>::const_iterator sit=smith.begin();
for( ++sit; sit != smith.end(); ++sit, ++eit) {
if (sit->second != coprimeR) {
std::vector<size_t> ranks;
ranks.push_back(sit->second);
size_t effexp;
if (*eit > 1) {
PRank(ranks, effexp, argv[1], sit->first, *eit, coprimeR);
}
else {
PRank(ranks, effexp, argv[1], sit->first, 2, coprimeR);
}
if (ranks.size() == 1) ranks.push_back(coprimeR);
if (effexp < *eit) {
for(size_t expo = effexp<<1; ranks.back() < coprimeR; expo<<=1) {
PRankInteger(ranks, argv[1], sit->first, expo, coprimeR);
}
} else {
for(size_t expo = (*eit)<<1; ranks.back() < coprimeR; expo<<=1) {
PRank(ranks, effexp, argv[1], sit->first, expo, coprimeR);
if (ranks.size() < expo) {
std::cerr << "It seems we need a larger prime power, it will take longer ..." << std::endl;
PRankInteger(ranks, argv[1], sit->first, expo, coprimeR);
}
}
}
std::vector<size_t>::const_iterator rit=ranks.begin();
for(++rit; rit!= ranks.end(); ++rit) {
if ((*rit)>= coprimeR) break;
for(size_t i=(*rit); i < coprimeR; ++i)
SmithDiagonal[i] *= sit->first;
}
}
}
size_t num=0;
for( std::vector<integer>::const_iterator dit=SmithDiagonal.begin();
dit != SmithDiagonal.end(); ++dit) {
if (*dit == si) ++num;
else {
if (num > 0)
std::cerr << '[' << si << ',' << num << "] ";
num=1;
si = *dit;
}
}
std::cerr << '[' << si << ',' << num << "] " << std::endl;
chrono.stop();
std::cerr << chrono << std::endl;
return 0;
}