Main Page   Namespace List   Class Hierarchy   Compound List   File List   Header Files   Sources   Namespace Members   Compound Members   File Members  

mapper.cpp

00001 //$Header: /home/ben/Mapper/c++/RCS/mapper.cpp,v 6.14 2002/07/09 23:03:15 ben Exp $
00002 // Copyright Benedict Adamson 2002.
00003 // This file is part of Mapper.
00004 
00005 // Mapper is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 
00010 // Mapper is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 
00015 // You should have received a copy of the GNU General Public License
00016 // along with Mapper; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00029 #include <cassert>
00030 #include <cmath>
00031 #include <cstdlib>
00032 #include <fstream>
00033 #include <unistd.h>
00034 #include <vector>
00035 
00036 #include <framework/LocalFileInputSource.hpp>
00037 #include <framework/StdInInputSource.hpp>
00038 #include <util/PlatformUtils.hpp>
00039 #include <util/XMLString.hpp>
00040 
00041 #include "MapDataDocument.h"
00042 #include "MapperErrorHandler.h"
00043 #include "assoc.h"
00044 #include "curve.h"
00045 #include "minimise.h"
00046 #include "total_energy_function.h"
00047 
00048 
00049 
00054 namespace status {
00055    enum code {
00056       OK = 0,
00057       error = 1
00058    };
00059 }
00060 
00061 
00062 namespace {
00063 
00083    void solve(
00084       total_energy_function &e,
00085       vector<double> &p, //input, output
00086       const double ftol,
00087       unsigned max_iter,
00088       unsigned &iter, //output
00089       double &fmin //output
00090       )
00091       {
00092          {//preconditions:
00093             assert( p.size() );
00094             assert( 0.0 < ftol && ftol < 1 );
00095             assert( 0 <  max_iter );
00096          };
00097          unsigned iter1;
00098          if( ftol < 1E-3 && 4 <= max_iter ){
00099             //find an approximate solution first,
00100             //before solving to the fine tolerance.
00101             const double ftol1 = 10.0 * ftol;
00102             const unsigned max_iter1 = max_iter/2;
00103             e.set_tol( ftol1 );
00104             solve(
00105                e,
00106                p,
00107                ftol1, max_iter1,
00108                iter1, fmin
00109                );
00110          }else
00111             iter1 = 0;
00112          ;
00113          unsigned max_iter2 = max_iter2 = max_iter - iter1;
00114          unsigned iter2;
00115          e.set_tol( ftol );
00116          minimise::Fletcher_Reeves_Polak_Ribere(
00117             e,
00118             p,
00119             ftol, 2U, max_iter2,
00120             iter2, fmin
00121             );
00122          iter = iter1 + iter2;
00123          {//postconditions:
00124             assert( iter <= max_iter );
00125             //assert( fmin == f(p) || iter == max_iter); within rounding error.
00126          };
00127       }
00128    
00129 }
00130 
00131 
00132 
00142 int main(
00143    int argc,
00144    char **argv
00145    )
00146 {
00147    const char *my_name = argv[0];
00148    {//initialisation
00149       try{ //Initialise Xerces
00150          XMLPlatformUtils::Initialize();
00151       }catch( const XMLException &toCatch ){
00152          cerr << my_name << ":error: during initialization\n";
00153          return status::error;
00154       };
00155    };
00156    MapperErrorHandler error_handler( my_name );
00157    //Initialise command-line options
00158    const char *input_file = 0; //0 indicates stdin.
00159    const char *output_file = 0; //0 indicates stdout.
00160    double ftol = 1E-8;
00161    unsigned max_iter = 0U;
00162    {//process the command line arguments
00163       int c;
00164       while( (c = getopt( argc, argv, "f:i:o:" )) != -1 ){
00165          switch( c ){
00166             case 'o':
00167                output_file = optarg;
00168                break;
00169             case 'f':{
00170                char *end;
00171                ftol = strtod( optarg, &end );
00172                if( *end || ftol <= 0.0 || 1.0 <= ftol ){
00173                   error_handler.badOptionArgument( 'f', optarg );
00174                   ftol = 1E-8;
00175                };
00176                break;}
00177             case 'i':{
00178                char *end;
00179                unsigned long i;
00180                i = strtoul( optarg, &end, 10 );
00181                if( *end ){
00182                   error_handler.badOptionArgument( 'i', optarg );
00183                   i = 0;
00184                };
00185                max_iter = i;
00186                break;}
00187             case '?':
00188                error_handler.error( "unrecognised command-line option" );
00189                break; //Give the compiler a break
00190 #ifndef NDEBUG
00191             default: //unexpected
00192                abort();
00193                break; //Give the compiler a break
00194 #endif
00195          };
00196       };
00197       if( optind == argc-1 ) //file given
00198          input_file = argv[optind];
00199       else if( optind == argc ) //no file given
00200             ; //OK
00201       else{ //several files given
00202          error_handler.error( "too many files" );
00203       };
00204       if( error_handler.errors ){//usage error(s)
00205          XMLPlatformUtils::Terminate();
00206          return status::error;
00207       };
00208    };
00209 
00210    MapDataDocument doc;
00211 
00212    {//read input file
00213      InputSource *source;
00214      if( input_file )
00215        source = new LocalFileInputSource(
00216           XMLString::transcode(input_file)
00217           );
00218      else
00219         source = new StdInInputSource;
00220      ;
00221      doc.read( *source, error_handler );
00222      delete source;
00223      if( error_handler.errors ){//error(s) during parsing
00224         XMLPlatformUtils::Terminate();
00225         return status::error;
00226      };
00227    };
00228 
00229    unsigned n_constraints;
00230    {//report on and check input data
00231       const unsigned n_points = doc.named_points().size();
00232       const unsigned n_curves = doc.curves().size();
00233       const unsigned n_fixed_points = doc.fixed_points().size();
00234       n_constraints = doc.constraints().size();
00235       assert( n_fixed_points <= n_points );
00236       cerr << n_points << " points, "
00237            << n_fixed_points << " fixed points, "
00238            << n_curves << " curves, "
00239            << n_constraints << " constraints\n";
00240       if( n_fixed_points < 2 )
00241          error_handler.warning( "fewer than 2 fixed points" );
00242       ;
00243       if( n_constraints == 0 )
00244          error_handler.warning( "no constraints" );
00245       ;
00246       if( n_constraints < (n_points-n_fixed_points)  )
00247          error_handler.warning(
00248             "fewer constraints than named moveable points"
00249             );
00250       ;
00251    };
00252 
00253    if( 0 < max_iter ){//calculation
00254       total_energy_function e( ftol );
00255       const set< vector2 * > ps( doc.all_points() );
00256       const vector< vector2 * > pv( ps.begin(), ps.end() );
00257       assoc( e, pv, doc.fixed_points(), doc.constraints() );
00258       try{//calculate point positions
00259          const unsigned n = e.n_vars();
00260          if( n && n_constraints ){
00261             vector<double> p(n);
00262             p = e.current_var(); //use any hints provided
00263             unsigned iter;
00264             double fmin;
00265             solve(
00266                e,
00267                p,
00268                ftol, max_iter,
00269                iter, fmin
00270                );
00271             e.move_points( p );
00272             cerr << iter << " iterations, "
00273                  << fmin << " total energy\n";
00274             if( max_iter <= iter )
00275                error_handler.warning( "iteration limit reached" );
00276             ;
00277          };
00278       }catch( ... ){
00279          error_handler.error( "during minimisation" );
00280       };
00281       if( error_handler.errors ){//error(s) during minimisation
00282          XMLPlatformUtils::Terminate();
00283          return status::error;
00284       };
00285    };
00286 
00287    try{//output
00288       if( output_file ){
00289          ofstream file(output_file);
00290          doc.write( file, ftol );
00291       }else
00292          doc.write( cout, ftol );
00293       ;
00294    }catch( ... ){
00295       error_handler.unexpectedError();
00296 #ifndef NDEBUG
00297       abort();
00298 #endif
00299    };
00300 
00301    XMLPlatformUtils::Terminate();
00302    if( error_handler.errors ){
00303       return status::error;
00304    }else
00305       return status::OK;
00306    ;
00307 }
00308 

Generated at Sun Jul 14 20:38:10 2002 for Mapper by doxygen 1.0.0 written by Dimitri van Heesch, © 1997-1999