Sorry about that, hope I'm not too late!

John

On 8/12/07, William Stein <[EMAIL PROTECTED]> wrote:
>
> On 8/12/07, John Cremona <[EMAIL PROTECTED]> wrote:
> > Attached are some files for mwrank which have had minor modifications
> > (for the purpose of making the saturation part of mwrank more
> > efficient).  No changes to interface required, just replace th
> > existing files with these.
> >
> > arith.h
> > parifact.cc
> > mwprocs.cc
> > saturate.cc
> > descent.cc
> >
> > My enhancements to simon_two_descent() are not ready yet.
>
> Unfortunately you accidentally typed "descent.vv" somewhere when
> making the attachment, so I didn't get the new version of descent.cc.
> Please resend.  Thanks.
>
> William
>
> >
>


-- 
John Cremona

--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-devel@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://sage.scipy.org/sage/ and http://modular.math.washington.edu/sage/
-~----------~----~----~----~------~----~------~--~---

// descent.cc: implementation of classes rank12 and two_descent
//////////////////////////////////////////////////////////////////////////
//
// Copyright 1990-2005 John Cremona
// 
// This file is part of the mwrank package.
// 
// mwrank is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version.
// 
// mwrank is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// 
// You should have received a copy of the GNU General Public License
// along with mwrank; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 
//////////////////////////////////////////////////////////////////////////
 

// rank12 is a common base for separate classes rank1 and rank2 (for
// computing rank via general 2-descent and descent via 2-isogeny
// repectively); class two_descent is a user interface to these

#include "compproc.h"
#include "points.h"
#include "mwprocs.h"
#include "mquartic.h"
#include "descent.h"
#include "mrank1.h"
#include "mrank2.h"

#define PRE_SATURATION_SEARCH_LIMIT 8

// Constructor:
//
// sel is selmer_only switch
// firstlim is bound on |x|+|z|
// secondlim is bound on log max {|x|,|z| }, i.e. logarithmic
// n_aux only relevant for general 2-descent when 2-torsion trivial
// n_aux=-1 causes default to be used (depends on method)
// second_descent only relevant for descent via 2-isogeny

two_descent::two_descent(Curvedata* ec, 
	      int verb, int sel, 
	      long firstlim, long secondlim, 
	      long n_aux, int second_descent)
  :verbose(verb), selmer_only(sel), mwbasis(ec,verb>2)
  {
    two_torsion_exists = (two_torsion(*ec).size()>1) ;
    if(two_torsion_exists) 
      r12=new rank2(ec,verb,sel,firstlim,secondlim,second_descent);
    else
      r12=new rank1(ec,verb,sel,firstlim,secondlim,n_aux);
    success=r12->ok();
    rank = r12->getrank();
    selmer_rank = r12->getselmer();
    certain=r12->getcertain();
  }

void two_descent::report_rank() const
{
  if(!success) {cout << "Failed to compute rank\n"; return;}
  if(selmer_only)
    {
      cout << "selmer-rank = " << selmer_rank << endl;
    }
  else
    {
      if(certain) 
	cout << "Rank = " << rank << endl;
      else 
	{
	  if(two_torsion_exists)
	    cout<< rank << " <= rank <= " << selmer_rank << endl;
	  else
	    cout<< rank << " <= rank <= selmer-rank = " << selmer_rank << endl;
	}   
    } 
}

void two_descent::saturate(long sat_bd)
{

// Do a quick search for points on the curve before processing points
  bigfloat hlim=to_bigfloat(PRE_SATURATION_SEARCH_LIMIT);
  bigfloat oldreg=mwbasis.regulator();
  if(verbose) cout <<"Searching for points (bound = "<<hlim<<")..." << flush;
  mwbasis.search(hlim);
  if(verbose) cout<<"done:"<<endl;
  long search_rank=mwbasis.getrank();
  bigfloat newreg=mwbasis.regulator();
  if(verbose) cout<<"  found points of rank "<<search_rank
		  <<"\n  and regulator "<<mwbasis.regulator()<<endl;
  
  if(verbose) cout <<"Processing points found during 2-descent..." << flush;
  mwbasis.process(r12->getgens(),0); // no saturation yet
  if(verbose) cout <<"done:"<<endl;
  rank = mwbasis.getrank();
  if(verbose) 
    {
      if(rank>search_rank) cout << "2-descent increases rank to "<<rank<<", ";
      if(rank<search_rank) cout << "2-descent only finds rank lower bound of "<<rank<<", ";
      cout <<"  now regulator = "<<mwbasis.regulator()<<endl;
    }
  sat_bound=sat_bd; // store for reporting later
  if(sat_bd==0) 
    {
      fullmw=0;
      if(verbose) cout <<"No saturation being done" << endl;
    }
  else
    {
      /*
// Do a quick search for points on the curve before trying to saturate
      bigfloat hlim=to_bigfloat(PRE_SATURATION_SEARCH_LIMIT);
      bigfloat oldreg=mwbasis.regulator();
      if(verbose) cout <<"Searching for points (bound = "<<hlim<<")..." << flush;
      mwbasis.search(hlim);
      if(verbose) cout<<"done"<<flush;
      bigfloat newreg=mwbasis.regulator();
      bigint ind = Iround(sqrt(oldreg/newreg));
      if(verbose)
	{
	  if(ind>1) cout<<" -- gained index "<<ind;
	  cout<<endl;
	  cout <<"Regulator (after searching) = "<<mwbasis.regulator()<<"\n";
	}
      */
// Now saturate
      if(verbose) cout <<"Saturating (bound = "<<sat_bd<<")..." << flush;
      bigint index; vector<long> unsat;
      int sat_ok = mwbasis.saturate(index,unsat,sat_bd,1);
      // The last parameter 1 says not to bother with 2-saturation!
      if(verbose) cout <<"done:"<<endl;

// Report outcome
      if(verbose)
	{
	  if(index>1) 
	    {
	      cout <<"  *** saturation increased group by index "<<index<<endl;
	      cout <<"  *** regulator is now "<<mwbasis.regulator()<<endl;
	    }
	  else cout << "  points were already saturated."<<endl;
	}
      if(!sat_ok) 
	{
	  cout << "*** saturation possibly incomplete at primes " << unsat << "\n";
	}
      rank = mwbasis.getrank();
      fullmw=sat_ok; // (rank==0);
    }
}

vector<Point> two_descent::getbasis(Curvedata* CD_orig, 
				    const bigint& u, const bigint& r, 
				    const bigint& s, const bigint& t)
{
  vector<Point>plist=mwbasis.getbasis();
  for (int i=0; i<rank; i++)
    { 
      plist[i] = shift(plist[i],CD_orig,u,r,s,t,1);
    }
  return plist;
}

void two_descent::show_gens(int change,
			    Curvedata* CD_orig, 
			    const bigint& u, const bigint& r, 
			    const bigint& s, const bigint& t)
{
  if(change&&verbose&&(rank>0)) 
    cout<<"Transferring points back to original curve "
	<<(Curve)(*CD_orig)<<"\n";
  vector<Point>plist=mwbasis.getbasis();
  if(change)
    plist = getbasis(CD_orig,u,r,s,t);
      
  cout<<endl;
  for (int i=0; i<rank; i++)
    { 
      Point P = plist[i];
      cout << "Generator "<<(i+1)<<" is "<<P<<"; ";
      cout << "height "<<height(P);
      if(!P.isvalid()) cout<<" --warning: NOT on curve!";
      cout<<endl;
    }
  cout<<endl;
  cout << "Regulator = "<<mwbasis.regulator()<<endl<<endl;
}

void two_descent::show_result_status()
{
  if(certain)
    {
      if(fullmw)
	{
	  cout << "The rank and full Mordell-Weil basis have been determined unconditionally.\n";
	}
      else
	{		
	  cout << "The rank has been determined unconditionally.\n";
	  if(rank>0)
	    {
	      cout << "The basis given is for a subgroup of full rank of the Mordell-Weil group\n";
	      cout << " (modulo torsion), possibly of index greater than 1\n";
	      if(sat_bound>0)
		cout << " (but not divisible by any prime less than "
		     <<sat_bound<<" unless listed above).\n";
	    }
	  cout<<endl;
	}
    }
  else // not certain of the rank
    {
      cout << "The rank has not been completely determined, \n";
      cout << "only a lower bound of "<<rank
	   <<" and an upper bound of "<<selmer_rank<<".\n";
      cout<<endl;
      if(fullmw)
	{
	  if(rank>0)
	    {
	      cout << "If the rank is equal to the lower bound, the basis given ";
	      cout << "is for the full Mordell-Weil group (modulo torsion).\n";
	    }
	}
      else
	{
	  if(rank>0)
	    {
	      cout << "Even if the lower bound is strict, ";
	      cout << "the basis given is for a subgroup of the Mordell-Weil group\n ";
	      cout << " (modulo torsion), possibly of index greater than 1.\n";
	    }
	  cout<<endl;
	}
    }
}

void two_descent::pari_output(int change,
			      Curvedata* CD_orig, 
			      const bigint& u, const bigint& r, 
			      const bigint& s, const bigint& t)
{
  vector<Point>plist=mwbasis.getbasis();
  if(change)
    plist = getbasis(CD_orig,u,r,s,t);
  cout<<"[["<<rank;
  if(rank<selmer_rank)  cout<<","<<selmer_rank;
  cout<<"],[";
  for(int i=0; i<rank; i++)
    {
      if(i) cout<<",";
      output_pari(cout,plist[i]);
    }
  cout<<"]]\n";
}

//////////////////////////////////////////////////////////////////
//Some old obsolete code for crude saturation
//////////////////////////////////////////////////////////////////

#if(0) // code now obsolete since we have done a proper saturation...
      if(do_infinite_descent&&(srank>0))
	{
	  fullmw=1;  // but may be reset to 0 below...
// Compute the height up to which to search
	  ht_c = height_constant(CD);
	  if(verbose) 
	    cout << "Height Constant = " << ht_c << "\n";
	  maxht=0;
	  for (i=0; i<plist.size(); i++)
	    { 
	      ht  = height(plist[i]);
	      if(ht>maxht) maxht=ht;
	    }
	  if(verbose)
	    cout<<"\nMax height = "<<maxht<<endl;
	  if(rank==1) maxht/=9;  // in this case the index is at least 3
	  hlim = maxht+ht_c;
	  if(verbose)
	    cout<<"Bound on naive height of extra generators = "<<hlim<<endl;
	  long hlimc = opt.get_hlimc();
	  if((hlimc>=0) && (hlimc<hlim))
	    {
	      fullmw=0;
	      hlim = hlimc;
	      if(verbose)
		cout << "Only searching up to height " << hlim << endl;
	    }
	  else
	    if((hlimc<0) && (MAX_HEIGHT<hlim))
	      {
		fullmw=0;
		hlim = MAX_HEIGHT;
		if(verbose)
		  cout << "Only searching up to height "<<MAX_HEIGHT<<"\n";
	      }
// Do the extra search
	  mwbasis.search(hlim, SEARCH_METHOD,0);
	  rank = mwbasis.getrank();
	  if(verbose)
	    cout<<"After point search, rank of points found is "<<rank<<endl;
	}
      else
	if(verbose)
	  cout<<"After descent, rank of points found is "<<rank<<endl;

// End  of extra search for points
#endif // obsolete code

Reply via email to