////////////////////////////////////////////////////////////////////////////////
// 
// CommandlineOptions.cc
//
//    produced: 04 Oct 1999 jr
//
////////////////////////////////////////////////////////////////////////////////

#include "CommandlineOptions.hh"

namespace topcom {

  // switches and parameters:
  bool           CommandlineOptions::_observe_seed                   = false;
  bool           CommandlineOptions::_observe_required_symmetries    = false;
  bool           CommandlineOptions::_verbose                        = false;
  bool           CommandlineOptions::_debug                          = false;
  bool           CommandlineOptions::_iterative_dfs                  = false;
  bool           CommandlineOptions::_preprocess_points              = false;
  bool           CommandlineOptions::_simpidx_symmetries             = false;
  bool           CommandlineOptions::_full_extension_check           = false;
  bool           CommandlineOptions::_no_extension_check             = false;
  bool           CommandlineOptions::_extension_check_first          = false;
  bool           CommandlineOptions::_memopt                         = false;
  bool           CommandlineOptions::_parallel_enumeration           = false;
  bool           CommandlineOptions::_workbuffercontrol              = true;
  bool           CommandlineOptions::_parallel_symmetries            = false;
  bool           CommandlineOptions::_use_random_order               = false;
  bool           CommandlineOptions::_use_volume_order               = false;
  bool           CommandlineOptions::_use_volumes                    = false;
  bool           CommandlineOptions::_use_gkz                        = false;
  bool           CommandlineOptions::_use_critelm_tables             = true;
  bool           CommandlineOptions::_use_switch_tables              = false;
  bool           CommandlineOptions::_use_classified_symmetries      = false;
  bool           CommandlineOptions::_use_naive_symmetries           = false;
  bool           CommandlineOptions::_check_triang                   = false;
  bool           CommandlineOptions::_check_symmetries               = false;
  bool           CommandlineOptions::_neighborcount                  = false;
  bool           CommandlineOptions::_input_chiro                    = false;
  bool           CommandlineOptions::_fine_only                      = false;
  bool           CommandlineOptions::_reduce_points                  = false;
  bool           CommandlineOptions::_dont_add_points                = false;
  bool           CommandlineOptions::_dont_change_card               = false;
  bool           CommandlineOptions::_output_triangs                 = false;
  bool           CommandlineOptions::_output_flips                   = false;
  bool           CommandlineOptions::_output_flipconnectivity        = false;
  bool           CommandlineOptions::_output_flipregularity          = false;
  bool           CommandlineOptions::_output_asy                     = false;
  bool           CommandlineOptions::_output_stats                   = false;
  bool           CommandlineOptions::_compute_all                    = false;
  bool           CommandlineOptions::_preprocess_chiro               = false;
  bool           CommandlineOptions::_check_flag                     = false;
  bool           CommandlineOptions::_check_regular                  = false;
  bool           CommandlineOptions::_check_regular_early            = false;
  bool           CommandlineOptions::_check_full                     = false;
  bool           CommandlineOptions::_check_unimodular               = false;
  bool           CommandlineOptions::_check_nonregular               = false;
  bool           CommandlineOptions::_check_nonsubregular            = false;
  bool           CommandlineOptions::_check_nonsupregular            = false;
  bool           CommandlineOptions::_check_nonregular_comp          = false;
  bool           CommandlineOptions::_check_possibly_nonregular_comp = false;
  bool           CommandlineOptions::_skip_heuristics                = false;
  bool           CommandlineOptions::_check_findregular              = false;
  bool           CommandlineOptions::_check_randomfindregular        = false;
  bool           CommandlineOptions::_require_point                  = false;
  bool           CommandlineOptions::_skip_orbitcount                = false;
  bool           CommandlineOptions::_ignore_symmetries              = false;
  bool           CommandlineOptions::_symmetries_are_affine          = false;
  bool           CommandlineOptions::_symmetries_are_isometric       = false;
  bool           CommandlineOptions::_output_heights                 = false;
  bool           CommandlineOptions::_output_gkzvecs                 = false;
  bool           CommandlineOptions::_use_soplex                     = false;
  bool           CommandlineOptions::_use_qsopt_ex                   = false;
  bool           CommandlineOptions::_dump_status                    = false;
  bool           CommandlineOptions::_read_status                    = false;
  parameter_type CommandlineOptions::_required_point                 = 0;
  size_type      CommandlineOptions::_report_frequency               = 100000UL;
  size_type      CommandlineOptions::_findregular_frequency          = 1;
  size_type      CommandlineOptions::_chirocache                     = 12582917UL;
  size_type      CommandlineOptions::_localcache                     = 12582917UL;
  size_type      CommandlineOptions::_no_of_simplices                = 0UL;
  size_type      CommandlineOptions::_max_no_of_simplices            = 0UL;
  size_type      CommandlineOptions::_dump_frequency                 = 10000000UL;
  size_type      CommandlineOptions::_min_nodebudget                 = 1UL;
  size_type      CommandlineOptions::_max_nodebudget                 = std::numeric_limits<size_type>::max();
  int            CommandlineOptions::_scale_nodebudget               = 100; // in percent
  int            CommandlineOptions::_no_of_threads                  = 1;
  int            CommandlineOptions::_min_workbuffersize             = std::max<int>(std::thread::hardware_concurrency() - 1, 1);
  int            CommandlineOptions::_max_workbuffersize             = 2 * _min_workbuffersize;
  int            CommandlineOptions::_dump_rotations                 = 2;
  int            CommandlineOptions::_no_of_symtables                = 1;
  const char*    CommandlineOptions::_input_file                     = 0;
  const char*    CommandlineOptions::_dump_file                      = "TOPCOM.dump";
  const char*    CommandlineOptions::_read_file                      = "TOPCOM.dump";
  const char*    CommandlineOptions::_asy_file                       = "TOPCOM_graphics.asy";
  const char*    CommandlineOptions::_stats_file                     = "TOPCOM_stats.txt";

  const char*    CommandlineOptions::_client                         = "TOPCOM unknown client";

  // auxiliary information implied by combinations of options:
  bool      CommandlineOptions::_admissibles_restricted     = false;
  bool      CommandlineOptions::_lp_solver_needed           = false;
  bool      CommandlineOptions::_regularity_checks_needed   = false;
  bool      CommandlineOptions::_full_inctable_needed       = false;
  bool      CommandlineOptions::_simpidx_table_needed       = false;
  bool      CommandlineOptions::_orbit_traversal_needed     = false;
  bool      CommandlineOptions::_points_simpidx_syms_needed = false;
  bool      CommandlineOptions::_multithreading_needed      = false;
  int       CommandlineOptions::_user_no_of_threads         = -1;

  //polymake:Poly CommandlineOptions::_polymakeobj;

  void CommandlineOptions::init(const int argc, const char** argv) {
        
    // write TOPCOM header with version information:
    MessageStreams::forced().print_topcomheader();

    // first check whether any verbose/debug output is wanted:
    for (int i = 1; i < argc; ++i) {
      if (strcmp(argv[i], "-d") == 0) {
	_debug = true;
	MessageStreams::verbose().activate(std::cerr);
	MessageStreams::debug().activate(std::cerr);
	MessageStreams::verbose() << "evaluating commandline options for debug output ..." << std::endl;
	
	MessageStreams::verbose() << " -d                  : debug output activated" << std::endl;
      }
      else if (strcmp(argv[i], "-v") == 0) {
	_verbose = true;
	MessageStreams::verbose().activate(std::cerr);

	MessageStreams::verbose() << "evaluating commandline options for verbose output ..." << std::endl;
	MessageStreams::verbose() << " -v                  : verbose output activated" << std::endl;
      }
    }    

    // set default symmetry handling method depending on client:
    if ((strstr(argv[0], "chiro2circuits") != 0)
	|| (strstr(argv[0], "chiro2ncircuits") != 0)
	|| (strstr(argv[0], "chiro2cocircuits") != 0)
	|| (strstr(argv[0], "chiro2ncocircuits") != 0)
	|| (strstr(argv[0], "points2circuits") != 0)
	|| (strstr(argv[0], "points2ncircuits") != 0)
	|| (strstr(argv[0], "points2cocircuits") != 0)
	|| (strstr(argv[0], "points2ncocircuits") != 0)
	) {
      _use_switch_tables = true;
      _use_critelm_tables = false;
      _use_naive_symmetries = false;
      _use_classified_symmetries = false;
    }

    else if ((strstr(argv[0], "chiro2placingtriang") != 0)
	     || (strstr(argv[0], "chiro2finetriang") != 0)
	     || (strstr(argv[0], "chiro2triangs") != 0)
	     || (strstr(argv[0], "chiro2ntriangs") != 0)
	     || (strstr(argv[0], "chiro2alltriangs") != 0)
	     || (strstr(argv[0], "chiro2nalltriangs") != 0)
	     || (strstr(argv[0], "chiro2allfinetriangs") != 0)
	     || (strstr(argv[0], "chiro2nallfinetriangs") != 0)
	     || (strstr(argv[0], "chiro2finetriangs") != 0)
	     || (strstr(argv[0], "chiro2nfinetriangs") != 0)
	     || (strstr(argv[0], "chiro2mintriang") != 0)
	     || (strstr(argv[0], "points2placingtriang") != 0)
	     || (strstr(argv[0], "points2finetriang") != 0)
	     || (strstr(argv[0], "points2triangs") != 0)
	     || (strstr(argv[0], "points2ntriangs") != 0)
	     || (strstr(argv[0], "points2alltriangs") != 0)
	     || (strstr(argv[0], "points2nalltriangs") != 0)
	     || (strstr(argv[0], "points2allfinetriangs") != 0)
	     || (strstr(argv[0], "points2nallfinetriangs") != 0)
	     || (strstr(argv[0], "points2finetriangs") != 0)
	     || (strstr(argv[0], "points2nfinetriangs") != 0)
	     || (strstr(argv[0], "points2mintriang") != 0)
	     ) {
      _use_critelm_tables = true;
      _use_switch_tables = false;
      _use_naive_symmetries = false;
      _use_classified_symmetries = false;
    }

    MessageStreams::verbose() << "Evaluating further Commandline Options ..." << std::endl;

    for (int i = 1; i < argc; ++i) {

      // print usage message:
      if ((strcmp(argv[i], "--help") == 0) || (strcmp(argv[i], "-h") == 0)) {
	MessageStreams::result() << "--help or -h: \t help requested:" << std::endl;

	MessageStreams::result() << "usage:" << std::endl;
	MessageStreams::result() << argv[0] << " [options]" << std::endl;
	MessageStreams::result() << "where the input is read from stdin" << std::endl;
	MessageStreams::result() << "and the output is written to stdout." << std::endl;
	MessageStreams::result() << std::endl;

	MessageStreams::result() << "options concerning input/output from files:" << std::endl;
	MessageStreams::result() << "-i [filename]        : read input from [filename] instead of stdin." << std::endl;
	MessageStreams::result() << "--symmetries         : observe symmetries of the configuration in the input file (default)." << std::endl;
	MessageStreams::result() << "--nosymmetries       : ignore symmetries of the configuration." << std::endl;
	MessageStreams::result() << "--triangsymmetries   : observe symmetries required for triangulations in the input file." << std::endl;
	MessageStreams::result() << "--notriangsymmetries : ignore symmetries required for triangulations (default)." << std::endl;
	MessageStreams::result() << "--triangseed         : observe the seed in the input file" << std::endl;
	MessageStreams::result() << "--notriangseed       : ignore the seed in the input file (default)" << std::endl;
	MessageStreams::result() << std::endl;

	MessageStreams::result() << "options concerning output of information:" << std::endl;
	MessageStreams::result() << "-h or --help         : print this help message" << std::endl;
	MessageStreams::result() << "-v                   : write verbose information to stderr." << std::endl;
	MessageStreams::result() << "--reportfrequency [n]: report every [n]th generated object." << std::endl;
	MessageStreams::result() << "-d                   : write debug information to stderr." << std::endl;
	MessageStreams::result() << "--heights            : write height vectors for triangulations to stdout (only with --regular)." << std::endl;
	MessageStreams::result() << "--gkzvecs            : write GKZ vectors for triangulations to stdout." << std::endl;
	MessageStreams::result() << "--flips              : write flips as pairs of triangulation IDs to stdout." 
		  << std::endl;
	MessageStreams::result() << "--flipconnectivity   : write flip-connectivity information as sequence of triangulations and flips to stdout." 
		  << std::endl;
	MessageStreams::result() << "--flipregularity     : add flip-regularity information to flip output." << std::endl;
	MessageStreams::result() << "--asy                : write asymptote graphics commands into file (in rank-3 triangulations, points are drawn as well)."
		  << std::endl;
	MessageStreams::result() << "--stats              : write some statistics into file."
		  << std::endl;
	MessageStreams::result() << std::endl;
     
	MessageStreams::result() << "options for checking input:" << std::endl;
	MessageStreams::result() << "--checktriang        : check any given triangulations for correctness." << std::endl;
	MessageStreams::result() << "--checksymmetries    : check the given symmetry generators for correctness." << std::endl;
	MessageStreams::result() << std::endl;

	MessageStreams::result() << "options for reporting properties of discovered triangulations:" << std::endl;
	MessageStreams::result() << "--flipdeficiency     : report flip deficiency in triangulations to stderr." << std::endl;
	MessageStreams::result() << "--findregular        : check for regularity and exit if regular." << std::endl;
	MessageStreams::result() << std::endl;

	MessageStreams::result() << "options concerning which triangulations are output (no influence on exploration):" << std::endl;
	MessageStreams::result() << "--noorbitcount       : skip the enumaration of orbits (total number of objects is unavailable)" << std::endl;
	MessageStreams::result() << "--cardinality [n]    : count/output only triangulations of cardinality [n]." << std::endl;
	MessageStreams::result() << "--maxcardinality [n] : count/output only triangulations of cardinality at most [n]." << std::endl;
	MessageStreams::result() << "--flag               : count/output only triangulations that are flag, i.e., all min. non-faces are edges." << std::endl;
	MessageStreams::result() << "--nonregular         : count/output only non-regular triangulations." << std::endl;
	MessageStreams::result() << "--nonsubregular      : count/output only non-greedy-subregular triangulations." << std::endl;
	MessageStreams::result() << "--nonsupregular      : count/output only non-greedy-supregular triangulations." << std::endl;
	MessageStreams::result() << "--nonregularcomp     : count/output only triangulations whose flip-graph component is non-regular." << std::endl;
	MessageStreams::result() << "--possnonregularcomp : count/output only triangulations whose flip-graph component might possibly be non-regular." << std::endl;
	MessageStreams::result() << "--randomfindregular  : count/output only triangulations that could be flipped randomly to a regular triangulation." << std::endl;
	MessageStreams::result() << "--skipheuristics     : skip heuristics in all flip-graph explorations (immediate BFS)." << std::endl;
	MessageStreams::result() << "--unimodular         : count/output only unimodular triangulations (reduces symmetries to isometric ones; correct only if there is a unimodular simplex)." << std::endl;
	MessageStreams::result() << "--requirepoint [k]   : allow only simplices containing point [k]." << std::endl;
	MessageStreams::result() << std::endl;

	MessageStreams::result() << "options concerning which triangulations are explored:" << std::endl;
	MessageStreams::result() << "--regular            : consider only regular triangulations" << std::endl;
	MessageStreams::result() << "--regularearly       : consider only regular partial triangulations (implies --regular)" << std::endl;
	MessageStreams::result() << "--full               : consider only full triangulations (using all elements)" << std::endl;
	MessageStreams::result() << "--noinsertion        : while flipping, never add a point unused in the seed triangulation." << std::endl;
	MessageStreams::result() << "--reducepoints       : while flipping, try to reduce the set of used points." << std::endl;
	MessageStreams::result() << "--keepcard           : never change the cardinality of triangulations by flipping." << std::endl;
	MessageStreams::result() << std::endl;

	MessageStreams::result() << "options concerning symmetries:" << std::endl;
	MessageStreams::result() << "--affinesymmetries   : assume that given symmetries are affine." << std::endl;
	MessageStreams::result() << "--isometricsymmetries: assume that given symmetries are isometric." << std::endl;
	MessageStreams::result() << std::endl;

	MessageStreams::result() << "options for dumping and reading the status of an interrupted computation:" << std::endl;
	MessageStreams::result() << "--dump               : dump status of previous computation into file" << std::endl;
	MessageStreams::result() << "--dumpfile [filename]: set dump base file name to [filename] (default: TOPCOM.dump; implies --dump)" << std::endl;
	MessageStreams::result() << "--dumpfrequency [n]  : dump each [n]th completed BFS round (default: 1; implies --dump)" << std::endl;
	MessageStreams::result() << "--dumprotations [n]  : dump into [n] rotating files (default: 2; implies --dump)" << std::endl;
	MessageStreams::result() << "--read               : read status of previous computation from file" << std::endl;
	MessageStreams::result() << "--readfile [filename]: set dump file name to read to [filename] (default: TOPCOM.dump; implies --read)" << std::endl;
	MessageStreams::result() << std::endl;
      

	MessageStreams::result() << "options concerning internal behaviour:" << std::endl;
	MessageStreams::result() << "--iterativedfs       : use an iterative version for depth-first search." << std::endl;
	MessageStreams::result() << "--recursivedfs       : use an recursive version for depth-first search." << std::endl;
	MessageStreams::result() << "--memopt             : try to reduce memory consumption." << std::endl;
	MessageStreams::result() << "--usegkz             : use GKZ vectors as a finger print in symmetry handling (only for points with isometric symmetries)." << std::endl;
	MessageStreams::result() << "--usenaivesymmetries : use naive full scan of all symmetries for symmetry handling." << std::endl;
	MessageStreams::result() << "--usecritelmtables   : use critical-element tables for symmetry handling (default for triangulations)." << std::endl;
	MessageStreams::result() << "--useswitchtables    : use Jordan-Joswig-Kastner switch tables for symmetry handling (default for (co-)circuits)." << std::endl;
	MessageStreams::result() << "--usesymmetrytables  : use tables of classified symmetries for symmetry handling." << std::endl;
	MessageStreams::result() << "--symtables [n]      : use [n] symtables for preprocessing symmetries." << std::endl;
	MessageStreams::result() << "--preprocesschiro    : preprocess the chirotope (default for points2[n]alltriangs)." << std::endl;
	MessageStreams::result() << "--preprocesspoints   : heuristically transform points (only relevant for (co)circuit enumeration)." << std::endl;
	MessageStreams::result() << "--simpidxsymmetries  : preprocess a representation of the symmetry group on simplex indices (only relevant for triangulation enumeration)." << std::endl;
	MessageStreams::result() << "--userandomorder     : sort simplices in preprocessed index table randomly (only for points with isometric symmetries)." << std::endl;
	MessageStreams::result() << "--usevolumeorder     : sort simplices in preprocessed index table by volume (only for points with isometric symmetries)." << std::endl;
	MessageStreams::result() << "--usevolumes         : use volumes to check extendability of partial triangulations (only for points with isometric symmetries)." << std::endl;
	MessageStreams::result() << "--fullextensioncheck : put more effort in the check of extendability of a partial triangulation." << std::endl;
	MessageStreams::result() << "--noextensioncheck   : skip the check of extendability of a partial triangulation." << std::endl;
	MessageStreams::result() << "--extensioncheckfirst: check extendability prior to symmetry." << std::endl;
	MessageStreams::result() << "--chirocache [n]     : set the chirotope cache to [n] elements." << std::endl;
	MessageStreams::result() << "--localcache [n]     : set the cache for local data to [n] elements ." << std::endl;
	MessageStreams::result() << "--qsopt_ex           : use QSopt_ex for regularity checks." << std::endl;
	MessageStreams::result() << "--soplex             : use soplex for regularity checks." << std::endl;
	MessageStreams::result() << std::endl;

	MessageStreams::result() << "options concerning multi-threading:" << std::endl;
	MessageStreams::result() << "--parallelenumeration: use multiple threads for enumeration." << std::endl;
	MessageStreams::result() << "--workbuffercontrol  : control interrupt of workers by size of the current workbuffer." << std::endl;
	MessageStreams::result() << "--nodebudgeting      : control interrupt of workers by node budget." << std::endl;
	MessageStreams::result() << "--parallelsymmetries : use multiple threads for symmetry checks." << std::endl;
	MessageStreams::result() << "--threads [n]        : use [n] threads (if possible)." << std::endl;      
	MessageStreams::result() << "--minnodebudget [n]  : let each thread process at least [n] nodes (to avoid multi-threading overhead)." << std::endl;      
	MessageStreams::result() << "--maxnodebudget [n]  : let each thread process at most [n] nodes (to avoid thread starving)." << std::endl;      
	MessageStreams::result() << "--scalenodebudget [n]: scale the default node budget by [n] percent (n integer)" << std::endl;      
	MessageStreams::result() << "--minworkbuffer [n]  : (unused) try to keep the work buffer above [n] work packages (to balance overhead and thread starving)." << std::endl;      
	MessageStreams::result() << "--maxworkbuffer [n]  : (unused) try to keep the work buffer below [n] work packages (to balance overhead and thread starving)." << std::endl;      
	MessageStreams::result() << std::endl;
	exit(0);
      }

      // output options:
      else if (strcmp(argv[i], "-i") == 0) {
	++i;
	if (argc >i) {
	  _input_file = argv[i];
	}
	FILE* f = freopen(_input_file, "r", stdin);

	MessageStreams::verbose() << " -i                  : input read from " << _input_file << std::endl;
      }
      else if (strcmp(argv[i], "--nosymmetries") == 0) {
	_ignore_symmetries = true;

	MessageStreams::verbose() << "--nosymmetries       : ignoring symmetries activated" << std::endl;
      }
      else if (strcmp(argv[i], "--symmetries") == 0) {
	_ignore_symmetries = false;

	MessageStreams::verbose() << "--symmetries         : observing symmetries activated" << std::endl;
      }
      else if (strcmp(argv[i], "--notriangsymmetries") == 0) {
	_observe_required_symmetries = false;

	MessageStreams::verbose() << "--notriangsymmetries : ignoring symmetries required for triangulations activated" << std::endl;
      }
      else if (strcmp(argv[i], "--triangsymmetries") == 0) {
	_observe_required_symmetries = true;

	MessageStreams::verbose() << "--triangsymmetries   : observing symmetries required for triangulations activated" << std::endl;
      }
      else if (strcmp(argv[i], "--notriangseed") == 0) {
	_observe_seed = false;

	MessageStreams::verbose() << "--notriangseed       : ignoring seed from input activated" << std::endl;
      }
      else if (strcmp(argv[i], "--triangseed") == 0) {
	_observe_seed = true;

	MessageStreams::verbose() << "--triangseed         : observing seed from input activated" << std::endl;
      }
      else if (strcmp(argv[i], "-v") == 0) {
	_verbose = true;

	MessageStreams::verbose() << " -v                  : verbose output activated" << std::endl;
      }
      else if (strcmp(argv[i], "--reportfrequency") == 0) {
	++i;
	if (argc > i) {
	  _report_frequency = (size_type)atol(argv[i]);
	  _verbose = true;

	  MessageStreams::verbose() << "--reportfrequency    : report every " << _report_frequency << "th new found object (implies '-v' = verbose)" << std::endl;
	}
      }
      else if (strcmp(argv[i], "-d") == 0) {
	_debug = true;

	MessageStreams::verbose() << " -d                  : debug output activated" << std::endl;
      }
      else if (strcmp(argv[i], "--heights") == 0) {
	_output_heights = true;

	MessageStreams::verbose() << "--heights            : output of defining heights activated" << std::endl;
      }
      else if (strcmp(argv[i], "--gkzvecs") == 0) {
	_output_gkzvecs = true;

	MessageStreams::verbose() << "--gkzvecs            : output of GKZ vectors activated" << std::endl;
      }

      else if (strcmp(argv[i], "--flips") == 0) {
	_output_flips = true;

	MessageStreams::verbose() << "--flips              : output of flips activated" << std::endl;
      }
      else if (strcmp(argv[i], "--flipconnectivity") == 0) {
	_output_flipconnectivity = true;

	MessageStreams::verbose() << "--flipconnectivity   : output of flip-connectivity information activated" << std::endl;
      }
      else if (strcmp(argv[i], "--flipregularity") == 0) {
	_output_flipregularity = true;

	MessageStreams::verbose() << "--flipregularity     : add flip-regularity information activated" << std::endl;
      }
      else if (strcmp(argv[i], "--asy") == 0) {
	_output_asy = true;

	MessageStreams::verbose() << "--asy                : write graphics output (in rank-3 triangulations, points are drawn as well)" << std::endl;
      }
      else if (strcmp(argv[i], "--asyfile") == 0) {
	++i;
	if (argc > i) {
	  _asy_file = argv[i];
	  _output_asy = true;

	  MessageStreams::verbose() << "--asyfile            : graphics output to file " << _asy_file << std::endl;
	}
      }
      else if (strcmp(argv[i], "--stats") == 0) {
	_output_stats = true;

	MessageStreams::verbose() << "--stats              : write statistics output" << std::endl;
      }
      else if (strcmp(argv[i], "--statsfile") == 0) {
	++i;
	if (argc > i) {
	  _stats_file = argv[i];
	  _output_stats = true;

	  MessageStreams::verbose() << "--statsfile          : statistics output to file " << _stats_file << std::endl;
	}
      }

      // options for checking input:
      else if (strcmp(argv[i], "--checktriang") == 0) {
	_check_triang = true;

	MessageStreams::verbose() << "--checktriang        : check seed triangulation activated" << std::endl;
      }
      else if (strcmp(argv[i], "--checksymmetries") == 0) {
	_check_symmetries = true;

	MessageStreams::verbose() << "--checksymmetries    : check symmetry generators activated" << std::endl;
      }

      // options for reporting properties of discovered triangulations:
      else if (strcmp(argv[i], "--flipdeficiency") == 0) {
	_neighborcount = true;

	MessageStreams::verbose() << "--flipdeficiency     : search for flip deficiency activated" << std::endl;
      }
      else if (strcmp(argv[i], "--findregular") == 0) {
	if (_check_regular) {
	  MessageStreams::verbose() << "--findregular cannot be used with --regular, ignoring --findregular." << std::endl;
	}
	else {
	  _check_regular = false;
	  _check_findregular = true;
	  
	  MessageStreams::verbose() << "--findregular        : exit at first regular triangulation in flip-graph activated" << std::endl;
	}
      }

      // options concerning which triangulations are output (no influence on exploration):
      else if (strcmp(argv[i], "--cardinality") == 0) {
	++i;
	if (argc > i) {
	  _no_of_simplices = (size_type)atol(argv[i]);
	}

	MessageStreams::verbose() << "--cardinality        : restrict to triangulations with " << _no_of_simplices << " simplices" << std::endl;
      }

      else if (strcmp(argv[i], "--maxcardinality") == 0) {
	++i;
	if (argc > i) {
	  _max_no_of_simplices = (size_type)atol(argv[i]);
	}

	MessageStreams::verbose() << "--maxcardinality     : restrict to triangulations with at most " << _max_no_of_simplices << " simplices" << std::endl;
      }

      else if (strcmp(argv[i], "--flag") == 0) {
	_check_flag = true;

	MessageStreams::verbose() << "--flag               : check for flag triangulations activated" << std::endl;
      }

      else if (strcmp(argv[i], "--nonregular") == 0) {
	_check_nonregular = true;

	MessageStreams::verbose() << "--nonregular         : search for non-regular triangulations activated" << std::endl;
      }

      else if (strcmp(argv[i], "--nonsubregular") == 0) {
	_check_nonsubregular = true;

	MessageStreams::verbose() << "--nonsubregular      : search for non-greedy-subregular triangulations activated" << std::endl;
      }

      else if (strcmp(argv[i], "--nonsupregular") == 0) {
	_check_nonsupregular = true;

	MessageStreams::verbose() << "--nonsupregular      : search for non-greedy-supregular triangulations activated" << std::endl;
      }

      else if (strcmp(argv[i], "--nonregularcomp") == 0) {
	_check_nonregular_comp = true;

	MessageStreams::verbose() << "--nonregularcomp     : search for non-regular flip-graph component activated" << std::endl;
      }

      else if (strcmp(argv[i], "--possnonregularcomp") == 0) {
	_check_possibly_nonregular_comp = true;

	MessageStreams::verbose() << "--possnonregularcomp : search for possibly non-regular flip-graph component activated" << std::endl;
      }

      else if (strcmp(argv[i], "--randomfindregular") == 0) {
	_check_randomfindregular = true;

	MessageStreams::verbose() << "--randomfindregular  : search for regular triangulation by random-direction flipping" << std::endl;
      }

      else if (strcmp(argv[i], "--skipheuristics") == 0) {
	_skip_heuristics = true;

	MessageStreams::verbose() << "--skipheuristics     : skip heuristics in all flip-graph explorations (immediate BFS)" << std::endl;
      }

      else if (strcmp(argv[i], "--unimodular") == 0) {
	_check_unimodular = true;

	MessageStreams::verbose() << "--unimodular         : restrict to unimodular triangulations (assumes isometric symmetries; correct only if there is a unimodular simplex)" << std::endl;
      }

      else if (strcmp(argv[i], "--requirepoint") == 0) {
	++i;
	if (argc > i) {
	  _require_point = true;
	  _required_point = (parameter_type)atol(argv[i]);
	}

	MessageStreams::verbose() << "--requirepoint [k]   : allow only simplices containing point " << _required_point << std::endl;
      }

      // options concerning which triangulations are explored:
      else if (strcmp(argv[i], "--regular") == 0) {
	if (_check_findregular) {
	  MessageStreams::verbose() << "--regular cannot be used with --findregular, ignoring --regular." << std::endl;
	}
	else {
	  _check_findregular = false;
	  _check_regular = true;

	  MessageStreams::verbose() << "--regular            : check for regular triangulations activated" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--regularearly") == 0) {
	_check_regular = true;
	_check_regular_early = true;

	MessageStreams::verbose() << "--regularearly       : check for regular partial triangulations activated" << std::endl;
      }
      else if (strcmp(argv[i], "--full") == 0) {
	_check_full = true;
	
	MessageStreams::verbose() << "--full               : check for full triangulations activated" << std::endl;
      }
      else if (strcmp(argv[i], "--noinsertion") == 0) {
	_dont_add_points = true;

	MessageStreams::verbose() << "--noinsertion        : while flipping, never add a point unused in the seed triangulation activated" << std::endl;
      }
      else if (strcmp(argv[i], "--reducepoints") == 0) {
	_reduce_points = true;

	MessageStreams::verbose() << "--reducepoints       : while flipping, try to reduce the set of used points activated" << std::endl;
      }
      else if (strcmp(argv[i], "--keepcard") == 0) {
	_dont_change_card = true;

	MessageStreams::verbose() << "--keepcard           : never change cardinality of triangulations by flipping activated" << std::endl;
      }

      // options concerning symmetries:
      else if (strcmp(argv[i], "--affinesymmetries") == 0) {
	_symmetries_are_affine = true;

	MessageStreams::verbose() << "--affinesymmetries   : assumption that symmetries are affine activated" << std::endl;
      }
      else if (strcmp(argv[i], "--isometricsymmetries") == 0) {
	_symmetries_are_isometric = true;

	MessageStreams::verbose() << "--isometricsymmetries: assumption that symmetries are isometric activated" << std::endl;
      }
      else if (strcmp(argv[i], "--noorbitcount") == 0) {
	_skip_orbitcount = true;

	MessageStreams::verbose() << "--noorbitcount       : skipping traversal of orbits activated" << std::endl;
      }

      // options concerning internals:
      else if (strcmp(argv[i], "--preprocesspoints") == 0) {
	_preprocess_points = true;

	MessageStreams::verbose() << "--preprocesspoints   : heuristics preprocessing of point matrix activated" << std::endl;
      }
      else if (strcmp(argv[i], "--preprocesschiro") == 0) {
	_preprocess_chiro = true;

	MessageStreams::verbose() << "--preprocesschiro    : preprocessing of chirotope activated" << std::endl;
      }
      else if (strcmp(argv[i], "--simpidxsymmetries") == 0) {
	_simpidx_symmetries = true;

	MessageStreams::verbose() << "--simpidxsymmetries  : preprocessing of a representation of the symmetry group on simplex indices activated" << std::endl;
      }
      else if (strcmp(argv[i], "--userandomorder") == 0) {
	_use_random_order = true;

	MessageStreams::verbose() << "--userandomorder     : sort simplices in preprocessed index table randomly" << std::endl;
      }
      else if (strcmp(argv[i], "--usevolumeorder") == 0) {
	_use_volume_order = true;

	MessageStreams::verbose() << "--usevolumeorder     : sort simplices in preprocessed index table by volume" << std::endl;
      }
      else if (strcmp(argv[i], "--usevolumes") == 0) {
	_use_volumes = true;

	MessageStreams::verbose() << "--usevolumes         : use volumes to check extendability of partial triangulations" << std::endl;
      }
      else if (strcmp(argv[i], "--fullextensioncheck") == 0) {
	_full_extension_check = true;

	MessageStreams::verbose() << "--fullextensioncheck : full extension check for partial triangulations activated" << std::endl;
      }
      else if (strcmp(argv[i], "--noextensioncheck") == 0) {
	_no_extension_check = true;

	MessageStreams::verbose() << "--noextensioncheck   : skip extension check for partial triangulations activated" << std::endl;
      }
      else if (strcmp(argv[i], "--extensioncheckfirst") == 0) {
	_extension_check_first = true;

	MessageStreams::verbose() << "--extensioncheckfirst: extension check prior to symmetry check activated" << std::endl;
      }
      else if (strcmp(argv[i], "--iterativedfs") == 0) {
	_iterative_dfs = true;

	MessageStreams::verbose() << "--iterativedfs       : iterative versions for depth-first search activated" << std::endl;
      }
      else if (strcmp(argv[i], "--recursivedfs") == 0) {
	_iterative_dfs = false;

	MessageStreams::verbose() << "--recursivedfs       : recursive versions for depth-first search activated" << std::endl;
      }
      else if (strcmp(argv[i], "--memopt") == 0) {
	_memopt = true;

	MessageStreams::verbose() << "--memopt             : higher memory efficiency activated" << std::endl;
      }
      else if (strcmp(argv[i], "--parallelenumeration") == 0) {
	_parallel_enumeration = true;
	_no_of_threads = std::max<int>(std::thread::hardware_concurrency() - 1, 1);

	MessageStreams::verbose() << "--parallelenumeration: multi-threading for enumeration activated" << std::endl;
      }
      else if (strcmp(argv[i], "--workbuffercontrol") == 0) {
	_workbuffercontrol = true;

	MessageStreams::verbose() << "--workbuffercontrol  : control of worker interrupt by work buffer activated" << std::endl;
      }
      else if (strcmp(argv[i], "--nodebudgeting") == 0) {
	_workbuffercontrol = false;

	MessageStreams::verbose() << "--nodebudgeting      : control of worker interrupt by node budget" << std::endl;
      }
      else if (strcmp(argv[i], "--parallelsymmetries") == 0) {
	if (!_ignore_symmetries) {
	  _parallel_symmetries = true;
	  _no_of_threads = std::max<int>(std::thread::hardware_concurrency() - 1, 1);

	  MessageStreams::verbose() << "--parallelsymmetries : multi-threading for symmetry checks activated" << std::endl;
	}
	else {
	  MessageStreams::verbose() << "--parallelsymmetries : multi-threading for symmetry checks ingnored because of --nosymmetries" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--threads") == 0) {
	++i;
	if (argc > i) {
	  _user_no_of_threads = std::max<int>(1, (size_type)atol(argv[i]));

	  MessageStreams::verbose() << "--threads            : no of threads set to " << _user_no_of_threads << " threads" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--minnodebudget") == 0) {
	++i;
	if (argc > i) {
	  _min_nodebudget = std::max<int>(1, (size_type)atol(argv[i]));

	  MessageStreams::verbose() << "--minnodebudget      : min node budget set to " << _min_nodebudget << " nodes" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--maxnodebudget") == 0) {
	++i;
	if (argc > i) {
	  _max_nodebudget = std::max<int>(1, (size_type)atol(argv[i]));

	  MessageStreams::verbose() << "--maxnodebudget      : max node budget set to " << _max_nodebudget << " nodes" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--scalenodebudget") == 0) {
	++i;
	if (argc > i) {
	  _scale_nodebudget = std::max<int>(1, (size_type)atol(argv[i]));

	  MessageStreams::verbose() << "--scalenodebudget    : scaling factor of node budget set to " << _scale_nodebudget << " percent" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--minworkbuffer") == 0) {
	++i;
	if (argc > i) {
	  _min_workbuffersize = std::max<int>(1, (size_type)atol(argv[i]));

	  MessageStreams::verbose() << "--minworkbuffer      : min work buffer size set to " << _min_workbuffersize << " work packages" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--maxworkbuffer") == 0) {
	++i;
	if (argc > i) {
	  _max_workbuffersize = std::max<int>(1, (size_type)atol(argv[i]));

	  MessageStreams::verbose() << "--maxworkbuffer      : max work buffer size set to " << _max_workbuffersize << " work packages" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--usegkz") == 0) {
	_use_gkz = true;

	MessageStreams::verbose() << "--usegkz             : use GKZ vectors as a finger print in symmetry handling (only for points with isometric symmetries)." << std::endl;
      }
      else if (strcmp(argv[i], "--usenaivesymmetries") == 0) {
	_use_naive_symmetries = true;
	_use_switch_tables = false;
	_use_critelm_tables = false;
	_use_classified_symmetries = false;

	MessageStreams::verbose() << "--usenaivesymmeries  : use of naive full scan of all symmetries for symmetry handling activated" << std::endl;
      }
      else if (strcmp(argv[i], "--usecritelmtables") == 0) {
	_use_critelm_tables = true;
	_use_switch_tables = false;
	_use_naive_symmetries = false;
	_use_classified_symmetries = false;

	MessageStreams::verbose() << "--usecritelmtables   : use of critical-element tables activated" << std::endl;
      }
      else if (strcmp(argv[i], "--useswitchtables") == 0) {
	_use_switch_tables = true;
	_use_critelm_tables = false;
	_use_naive_symmetries = false;
	_use_classified_symmetries = false;

	MessageStreams::verbose() << "--useswitchtables    : use of Jordan-Joswig-Kastner switch tables activated" << std::endl;
      }
      else if (strcmp(argv[i], "--usesymmetrytables") == 0) {
	_use_classified_symmetries = true;
	_use_switch_tables = false;
	_use_critelm_tables = false;
	_use_naive_symmetries = false;

	MessageStreams::verbose() << "--usesymmetrytables  : use of tables of classified symmetries for symmetry handling activated" << std::endl;
      }
      else if (strcmp(argv[i], "--symtables") == 0) {
	++i;
	if (argc > i) {
	  _no_of_symtables = std::max<int>(1, (size_type)atol(argv[i]));

	  MessageStreams::verbose() << "--symtables          : no of symmetry tables set to " << _no_of_symtables << " entries" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--chirocache") == 0) {
	++i;
	if (argc > i) {
	  _chirocache = (size_type)atol(argv[i]);

	  MessageStreams::verbose() << "--chirocache         : cache for lazy chirotope set to " << _chirocache << " elements" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--localcache") == 0) {
	++i;
	if (argc > i) {
	  _localcache = (size_type)atol(argv[i]);

	  MessageStreams::verbose() << "--localcache         : cache for local data set to " << _localcache << " elements" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--dumpfrequency") == 0) {
	++i;
	if (argc > i) {
	  _dump_frequency = (size_type)atol(argv[i]);
	  _dump_status = true;

	  MessageStreams::verbose() << "--dumpfrequency      : dump every " << _dump_frequency << "th processed object (implies --dump)" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--dumprotations") == 0) {
	++i;
	if (argc > i) {
	  _dump_rotations = (size_type)atol(argv[i]);
	  _dump_status    = true;

	  MessageStreams::verbose() << "--dumprotations      : rotate dump into " << _dump_rotations << " many dump files (implies --dump)" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--dumpfile") == 0) {
	++i;
	if (argc > i) {
	  _dump_file = argv[i];
	  _dump_status = true;

	  MessageStreams::verbose() << "--dumpfile           : dump to file " << _dump_file << " (implies --dump)" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--dump") == 0) {
	_dump_status = true;

	MessageStreams::verbose() << "--dump               : dump status of computation into file activated" << std::endl;
      }
      else if (strcmp(argv[i], "--readfile") == 0) {
	++i;
	if (argc > i) {
	  _read_file = argv[i];
	  _read_status = true;

	  MessageStreams::verbose() << "--readfile           : read from file " << _read_file << " (implies --read)" << std::endl;
	}
      }
      else if (strcmp(argv[i], "--read") == 0) {
	_read_status = true;

	MessageStreams::verbose() << "--read               : read status from file" << std::endl;
      }
      else if (strcmp(argv[i], "--soplex") == 0) {
#ifdef HAVE_LIBSOPLEX      
	_use_soplex = true;

	MessageStreams::verbose() << "--soplex             : soplex activated" << std::endl;
#else
	MessageStreams::verbose() << "--soplex             : ignored (soplex support was not configured for this binary)" << std::endl;
#endif
      }
      else if (strcmp(argv[i], "--qsoptex") == 0) {
#ifdef HAVE_LIBQSOPTEX     
	_use_qsopt_ex = true;

	MessageStreams::verbose() << "--qsoptex            : QSopt_ex activated" << std::endl;
#else
	MessageStreams::verbose() << "--qsoptex            : ignored (QSOpt_ex support was not configured for this binary)" << std::endl;
#endif
      }

      // some options that are not documented:
      else if (strcmp(argv[i], "-A") == 0) {
	_compute_all = true;
      }
      else if (strcmp(argv[i], "-C") == 0) {
	_input_chiro = true;
      }
      else if (strcmp(argv[i], "-F") == 0) {
	_fine_only = true;
      }
      else if (strcmp(argv[i], "-O") == 0) {
	_output_triangs = true;
      }
      else if (strcmp(argv[i], "-E") == 0) {
	_output_flips = true;
      }
      else {
	MessageStreams::verbose() << "unknown option " << argv[i] << " - exiting" << std::endl;
	exit(1);
      }
    }

    // collect information that should not depend on order of options:
    if (_user_no_of_threads > 0) {
      _no_of_threads = _user_no_of_threads;
    }
    _min_workbuffersize = _no_of_threads;

    if ((_no_of_simplices > 0) && (_max_no_of_simplices > 0)) {
      _max_no_of_simplices = 0;

      MessageStreams::verbose() << "--maxcardinality [n] : ignored because it conflicts with --cardinality [n]" << std::endl;
    }

    // sanity checks:

    if (_read_status) {
      if (!std::filesystem::exists(_read_file)) {
	MessageStreams::verbose() << "--read[file]         : ignored because file " << _read_file << " not found" << std::endl;
	_read_status = false;
      }
    }

    if (!((strstr(argv[0], "points2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2mintriang") == 0))) {
      _simpidx_table_needed = true;
    }
    
    if (_require_point) {
      if ((strstr(argv[0], "points2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2mintriang") == 0)
	  &&
	  (strstr(argv[0], "points2triangs") == 0)
	  &&
	  (strstr(argv[0], "points2ntriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2mintriang") == 0)
	  &&
	  (strstr(argv[0], "chiro2triangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2ntriangs") == 0)) {
	MessageStreams::verbose() << "--requirepoint [k]   : ignored because unsupported by " << argv[0] << std::endl;
	_require_point = false;
	_required_point = 0;
      }
    }

    // check for combinations of commandline options that do not make sense for a client:
    if (_parallel_symmetries && _ignore_symmetries) {

      // if symmetries are ignored, there is no point in parallel processing symmetries:
      _parallel_symmetries = false;
      MessageStreams::verbose() << "--parallelsymmetries : ignored because of --nosymmetries" << std::endl;
    }

    if (_use_gkz && !_symmetries_are_isometric) {
      
      // gkz is not invariant w.r.t. non-isometric symmetries:
      MessageStreams::verbose() << "--usegkz             : ignored because it requires --isometricsymmetries" << std::endl;
      _use_gkz = false;
    }
    
    if (_use_volumes && !_symmetries_are_isometric) {

      // volume is not invariant w.r.t. non-isometric symmetries:
      MessageStreams::verbose() << "--usevolumes         : ignored because it requires --isometricsymmetries" << std::endl;
      _use_volumes = false;
    }

    if (_use_volume_order && !_symmetries_are_isometric) {

      // volume is not invariant w.r.t. non-isometric symmetries:
      MessageStreams::verbose() << "--usevolumeorder     : ignored because it requires --isometricsymmetries" << std::endl;
      _use_volume_order = false;
    }

    if (_simpidx_symmetries && _memopt) {
      MessageStreams::verbose() << "--simpidxsymmetries  : ignored because it conflicts with --memopt" << std::endl;
      _simpidx_symmetries = false;
    }
    	
    if (_use_switch_tables) {
      if ((strstr(argv[0], "check") == 0)
	  &&
	  (strstr(argv[0], "points2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2mintriang") == 0)
	  &&
	  (strstr(argv[0], "points2ncircuits") == 0)
	  &&
	  (strstr(argv[0], "points2ncocircuits") == 0)
	  &&
	  (strstr(argv[0], "points2circuits") == 0)
	  &&
	  (strstr(argv[0], "points2cocircuits") == 0)
	  &&
	  (strstr(argv[0], "chiro2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2mintriang") == 0)
	  &&
	  (strstr(argv[0], "chiro2ncircuits") == 0)
	  &&
	  (strstr(argv[0], "chiro2ncocircuits") == 0)
	  &&
	  (strstr(argv[0], "chiro2circuits") == 0)
	  &&
	  (strstr(argv[0], "chiro2cocircuits") == 0)) {
	MessageStreams::verbose() << "--useswitchtables    : ignored because unsupported by " << argv[0] << std::endl;
	_use_switch_tables = false;
      }
            
      else if (!_simpidx_symmetries) {
	if ((strstr(argv[0], "check") == 0)
	    &&
	    (strstr(argv[0], "points2ncircuits") == 0)
	    &&
	    (strstr(argv[0], "points2ncocircuits") == 0)
	    &&
	    (strstr(argv[0], "points2circuits") == 0)
	    &&
	    (strstr(argv[0], "points2cocircuits") == 0)
	    &&
	    (strstr(argv[0], "chiro2ncircuits") == 0)
	    &&
	    (strstr(argv[0], "chiro2ncocircuits") == 0)
	    &&
	    (strstr(argv[0], "chiro2circuits") == 0)
	    &&
	    (strstr(argv[0], "chiro2cocircuits") == 0)) {
	  MessageStreams::verbose() << "--useswitchtables    : ignored because it requires --simpidxsymmetries for " << argv[0] << std::endl;
	  _use_switch_tables = false;
	}
      }

      else if (_parallel_symmetries) {
	
	// switch tables do not support parallel symmetry processing:
	_parallel_symmetries = false;
	MessageStreams::verbose() << "--parallelsymmetries : ignored because it conflicts with --useswitchtables" << std::endl;
      }
    }
    
    if (_output_asy) {
      if ((strstr(argv[0], "points2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2mintriang") == 0)
	  &&
	  (strstr(argv[0], "points2ncircuits") == 0)
	  &&
	  (strstr(argv[0], "points2ncocircuits") == 0)
	  &&
	  (strstr(argv[0], "points2circuits") == 0)
	  &&
	  (strstr(argv[0], "points2cocircuits") == 0)) {
	MessageStreams::verbose() << "--asy                : ignored because unsupported by " << argv[0] << std::endl;
	_output_asy = false;
      }
    }

    if (_dump_status) {
      if ((strstr(argv[0], "points2ntriangs") == 0)
	  &&
	  (strstr(argv[0], "points2triangs") == 0)
	  &&
	  (strstr(argv[0], "points2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2mintriang") == 0)
	  &&
	  (strstr(argv[0], "chiro2ntriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2triangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2mintriang") == 0)
	  &&
	  (strstr(argv[0], "points2ncircuits") == 0)
	  &&
	  (strstr(argv[0], "points2ncocircuits") == 0)
	  &&
	  (strstr(argv[0], "points2circuits") == 0)
	  &&
	  (strstr(argv[0], "points2cocircuits") == 0)) {
	MessageStreams::verbose() << "--dump               : ignored because unsupported by " << argv[0] << std::endl;
	_dump_status = false;
      }
    }
    
    if (_observe_required_symmetries) {
      if ((strstr(argv[0], "points2ntriangs") == 0)
	  &&
	  (strstr(argv[0], "points2triangs") == 0)
	  &&
	  (strstr(argv[0], "points2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2mintriang") == 0)
	  &&
	  (strstr(argv[0], "chiro2ntriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2triangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2mintriang") == 0)
	  &&
	  (strstr(argv[0], "points2prettyprint") == 0)
	  &&
	  (strstr(argv[0], "points2gale") == 0)) {
	MessageStreams::verbose() << "--triangsymmetries   : ignored because unsupported by " << argv[0] << std::endl;
	_observe_required_symmetries = false;
      }
    }
    
    if (_observe_seed) {
      if ((strstr(argv[0], "points2ntriangs") == 0)
	  &&
	  (strstr(argv[0], "points2triangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2ntriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2triangs") == 0)
	  &&
	  (strstr(argv[0], "points2flips") == 0)
	  &&
	  (strstr(argv[0], "points2nflips") == 0)
	  &&
	  (strstr(argv[0], "points2prettyprint") == 0)
	  &&
	  (strstr(argv[0], "points2gale") == 0)) {
	MessageStreams::verbose() << "--triangseed         : ignored because unsupported by " << argv[0] << std::endl;
	_observe_seed = false;
      }
    }
    
    if (_parallel_enumeration) {
      if ((strstr(argv[0], "points2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2mintriang") == 0)
	  &&
	  (strstr(argv[0], "chiro2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2mintriang") == 0)
	  &&
	  (strstr(argv[0], "points2circuits") == 0)
	  &&
	  (strstr(argv[0], "points2cocircuits") == 0)
	  &&
	  (strstr(argv[0], "points2ncircuits") == 0)
	  &&
	  (strstr(argv[0], "points2ncocircuits") == 0)) {
	MessageStreams::verbose() << "--parallelenumeration: ignored because unsupported by " << argv[0] << std::endl;
	_parallel_enumeration = false;
      }
    }
    if (_parallel_enumeration) {
      if ((strstr(argv[0], "points2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2mintriang") == 0)
	  &&
	  (strstr(argv[0], "chiro2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "chiro2mintriang") == 0)
	  &&
	  (strstr(argv[0], "points2circuits") == 0)
	  &&
	  (strstr(argv[0], "points2cocircuits") == 0)
	  &&
	  (strstr(argv[0], "points2ncircuits") == 0)
	  &&
	  (strstr(argv[0], "points2ncocircuits") == 0)) {
	MessageStreams::verbose() << "--parallelenumeration: ignored because unsupported by " << argv[0] << std::endl;
	_parallel_enumeration = false;
      }
    }

    if (_parallel_symmetries && _parallel_enumeration) {
      MessageStreams::verbose() << "--parallelsymmetries : ignored because it conflicts with --parallelenumeration" << std::endl;
    }

    if (_check_possibly_nonregular_comp) {
      if (_check_nonregular_comp || _check_nonsubregular || _check_nonsupregular || _check_nonregular || _check_regular) {
      	MessageStreams::verbose() << "--possnonregularcomp : ignored beause other present regularity checks have higher priority" << std::endl;
	_check_possibly_nonregular_comp = false;
      }
    }
    if (_check_nonregular_comp) {
      if (_check_nonsubregular || _check_nonsupregular || _check_nonregular || _check_regular) {
      	MessageStreams::verbose() << "--nonregularcomp   : ignored beause other present regularity checks have higher priority" << std::endl;
	_check_nonregular_comp = false;
      }
    }
    else {
      if (_check_nonsubregular || _check_nonsupregular) {
	if (_check_nonregular || _check_regular) {
	  if (_check_nonsubregular) {
	    MessageStreams::verbose() << "--nonsubregular    : ignored beause other present regularity checks have higher priority" << std::endl;
	    _check_nonsubregular = false;
	  }
	  if (_check_nonsupregular) {
	    MessageStreams::verbose() << "--nonsupregular    : ignored beause other present regularity checks have higher priority" << std::endl;
	    _check_nonsupregular = false;
	  }
	}
      }
      else {
	if (_check_nonregular) {
	  if (_check_regular) {
	    MessageStreams::verbose() << "--nonregular       : ignored beause other present regularity checks have higher priority" << std::endl;
	    _check_nonregular = false;
	  }
	}
      }
    }
    
    if (_check_regular_early) {
      if ((strstr(argv[0], "points2alltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2allfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nalltriangs") == 0)
	  &&
	  (strstr(argv[0], "points2nallfinetriangs") == 0)
	  &&
	  (strstr(argv[0], "points2mintriang") == 0)) {
	MessageStreams::verbose() << "--regularearly       : ignored because unsupported by " << argv[0] << std::endl;
	_check_regular_early = false;
      }
    }

    if (_check_regular_early && !_symmetries_are_affine) {
      MessageStreams::verbose() << "--regularearly       : ignored because it requires --affinesymmetries" << std::endl;
      _check_regular_early = false;
    }
    
    if (_use_qsopt_ex && _parallel_enumeration) {
      MessageStreams::verbose() << "--parallelenumeration: ignored because qsopt_ex is not thread-safe" << std::endl;
      _parallel_enumeration = false;
    }

    if (_output_heights && (!_check_regular) && (!_check_findregular) && (!_check_randomfindregular) && (strstr(argv[0], "checkregularity") == 0)) {
      MessageStreams::verbose() << "--heights            : ignored because " << argv[0] << " requires --regular or --findregular for heights output" << std::endl;
      _output_heights = false;
    }

    if (
	!_skip_orbitcount // if option is chosen, no orbit is ever traversed
	&&
	(
	 (_check_regular || _check_nonregular || _check_nonsubregular || _check_nonsupregular || _check_nonregular_comp || _check_possibly_nonregular_comp)
	 &&
	 (!_symmetries_are_affine)
	 ) // non-invariant regularity
	) {
      _orbit_traversal_needed = true;
    }

    if (_parallel_enumeration || _parallel_symmetries) {
      _multithreading_needed = true;
    }
    
    if ((_check_unimodular && !_symmetries_are_isometric)
	||
	((_check_unimodular || _check_full) && (_check_findregular || _check_randomfindregular
						|| _check_nonregular_comp || _check_possibly_nonregular_comp
						|| _check_nonsubregular || _check_nonsupregular))
	||
	_require_point
	||
	_observe_required_symmetries) {
      _admissibles_restricted = true;
    }

    if (_check_regular
	|| _check_regular_early
	|| _check_nonregular
	|| _check_nonsubregular
	|| _check_nonsupregular
	|| _check_nonregular_comp
	|| _check_possibly_nonregular_comp
	|| _check_findregular
	|| _check_randomfindregular
	|| _output_flipregularity
	) {
      _regularity_checks_needed = true;
      _lp_solver_needed = true;
    }

    if (_check_nonsubregular
	|| _check_nonsupregular
	|| _check_nonregular_comp
	|| _check_possibly_nonregular_comp
	|| _check_findregular
	|| _check_randomfindregular
	) {
      _points_simpidx_syms_needed = true;
      _full_inctable_needed = true;
    }

    _client = argv[0];
    MessageStreams::verbose() << "... done." << std::endl;
  }

}; // namespace topcom

// eof CommandlineOptions.cc
