Exemple #1
0
void*
mps_caller (mps_context * s)
{
  if (!mps_context_has_errors (s))
    s->mpsolve_ptr (s);

  /* Call user defined callback if available */
  if (s->callback == NULL)
    return NULL;
  else
    return (*s->callback) (s, s->user_data);
}
Exemple #2
0
/**
 * @brief Call the real polynomial (or secular equation, or whatever) solver
 * and do the computation.
 *
 * The algorithm used must be selected before this call with <code>mps_select_algorithm</code>
 * and the data (the coefficients, or whatever the algorithm may require) should be provided
 * after that.
 *
 * Roots can then be obtained with the functions <code>mps_context_get_roots_*</code>
 *
 */
void
mps_mpsolve (mps_context * s)
{
#ifdef MPS_CATCH_FPE
  feenableexcept (FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW); 
#endif

  if (mps_context_has_errors (s))
    return;

  (*s->mpsolve_ptr) (s);
}
Exemple #3
0
void*
cleanup_context (mps_context * ctx, void * user_data)
{
  /* Check for errors */
  if (mps_context_has_errors (ctx))
    {
      mps_print_errors (ctx);
      return NULL;
    }

  /* Output the roots */
  mps_output (ctx);

#ifdef HAVE_GRAPHICAL_DEBUGGER
  if (logger_closed)
    gtk_main_quit ();
  else if (logger)
  {
    /* In the other case copy the approximation in the right place
     * so the logger can display them again. */
    int i = 0;
    mps_approximation ** approximations = malloc (sizeof (mps_approximation*) * ctx->n);

    for (i = 0; i < ctx->n; i++)
      approximations[i] = mps_approximation_copy (ctx, ctx->root[i]);

    mps_iteration_logger_set_roots (logger, approximations, ctx->n);
  }
#endif  

  /* Free used data */
  if (poly) 
    mps_polynomial_free (ctx, poly);
  mps_context_free (ctx);

  s = NULL;

  return NULL;
}
Exemple #4
0
int
main (int argc, char **argv)
{
#if HAVE_GRAPHICAL_DEBUGGER
  mps_boolean graphic_debug = false;
#endif

  /* Create a new status */
  s = mps_context_new ();

  /* Associate the SIGUSR1 signal to the mps_dump () function */
#ifndef __WINDOWS
  signal (SIGUSR1, status);
#endif

  /* Leave this value to -1 if not precision has been enforced
   * by the user. Otherwise, override the polynomial input
   * precision. */
  long int input_precision = -1;
  char * inline_poly = NULL;

  FILE *infile;

  /* Parse options */
  mps_opt *opt;
  mps_phase phase = no_phase;

  /* This will be true if the user has explicitely selected the algorithm, 
     otherwise we will be using our own heuristic. */
  mps_boolean explicit_algorithm_selection = false;

  opt = NULL;
  while ((mps_getopts (&opt, &argc, &argv, MPSOLVE_GETOPT_STRING)))
    {
      switch (opt->optchar)
        {
        case 'l':
          {
            FILE* logstr = fopen (opt->optvalue, "w");
            if (!logstr)
              mps_error (s, "Cannot open selected log file.");
            mps_context_set_log_stream (s, logstr);
          }
          break;

        case 'v':

#ifdef HAVE_CONFIG_H
          printf (PACKAGE_STRING "\n");
#else
          printf ("MPSolve 3.1.5\n");
#endif

          mps_context_free (s);
          exit (EXIT_SUCCESS);

	case 'r':
	  mps_context_select_starting_strategy (s, MPS_STARTING_STRATEGY_RECURSIVE);
	  break;

        case 'O':
          /* Select the desired output format */
          if (!opt->optvalue)
            {
              mps_error (s, "An argument is needed for option 'O'");
              break;
            }
          
          switch (*opt->optvalue)
            {
            case 'f':
              mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_FULL);
              break;
            case 'b':
              mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_BARE);
              break;
            case 'g':
              mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_GNUPLOT);
              if (*(opt->optvalue + 1) == 'f')
                {
                  mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_GNUPLOT_FULL);
                  s->gnuplot_format = "xyerrorbars";
                }
              else if (*(opt->optvalue + 1) == 'p')
                {
                  mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_GNUPLOT_FULL);
                  s->gnuplot_format = "points";
                }
              break;
            case 'v':
              mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_VERBOSE);
              break;
            case 'c':
              mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_COMPACT);
              break;
            default:
              mps_error (s, "The selected output format is not supported");
              break;
            }

          break;

            /* select search set */
          case 'S':
            switch (*opt->optvalue)
              {
              case 'a':
                s->output_config->search_set = MPS_SEARCH_SET_COMPLEX_PLANE;
                break;
              case 'r':
                s->output_config->search_set = MPS_SEARCH_SET_POSITIVE_REAL_PART;
                break;
              case 'l':
                s->output_config->search_set = MPS_SEARCH_SET_NEGATIVE_REAL_PART;
                break;
              case 'u':
                s->output_config->search_set = MPS_SEARCH_SET_POSITIVE_IMAG_PART;
                break;
              case 'd':
                s->output_config->search_set = MPS_SEARCH_SET_NEGATIVE_IMAG_PART;
                break;
              case 'i':
                s->output_config->search_set = MPS_SEARCH_SET_UNITARY_DISC;
                break;
              case 'o':
                s->output_config->search_set = MPS_SEARCH_SET_UNITARY_DISC_COMPL;
                break;
              case 'R':
                s->output_config->search_set = MPS_SEARCH_SET_REAL;
                break;
              case 'I':
                s->output_config->search_set = MPS_SEARCH_SET_IMAG;
                break;
              case 'U':
                s->output_config->search_set = MPS_SEARCH_SET_CUSTOM;
                break;
              default:
                mps_error (s, "Bad search set switch: ", opt->optvalue,
                           ", use a|r|l|u|d|i|o|R|I|U");
              }
            if (strlen (opt->optvalue) != 1)
              mps_error (s, "Bad set: ", opt->optvalue);
            break;

            /* select multiplicity */
          case 'M':
            switch (*opt->optvalue)
              {
              case '+':
                s->output_config->multiplicity = true;
                break;
              case '-':
                s->output_config->multiplicity = false;
                break;
              default:
                mps_error (s, "Bad multiplicity switch: ", opt->optvalue,
                           ", use +|-");
              }
            if (strlen (opt->optvalue) != 3)
              mps_error (s, "Bad multiplicity option: ", opt->optvalue);
            break;

            /* detection */
          case 'D':
            switch (*opt->optvalue)
              {
              case 'n':
                s->output_config->root_properties = MPS_OUTPUT_PROPERTY_NONE;
                break;
              case 'r':
                s->output_config->root_properties = MPS_OUTPUT_PROPERTY_REAL;
                break;
              case 'i':
                s->output_config->root_properties = MPS_OUTPUT_PROPERTY_IMAGINARY;
                break;
              case 'b':
                s->output_config->root_properties = MPS_OUTPUT_PROPERTY_REAL | 
                  MPS_OUTPUT_PROPERTY_IMAGINARY;
                break;
              default:
                mps_error (s, "Bad detection switch: ", opt->optvalue,
                           ", use n|r|i|b");
              }
            if (strlen (opt->optvalue) != 1)
              mps_error (s, "Bad detection option: ", opt->optvalue);
            break;

            /* I/O streams */
          case 'R':
            s->rtstr = fopen (opt->optvalue, "r");
            if (s->rtstr == NULL)
              mps_error (s, "Cannot open roots file: ", opt->optvalue);
            s->resume = true;
            break;

            /* Additional checks */
          case 'C':
            switch (*opt->optvalue)
              {
              case 'R':
                s->chkrad = true;
                break;
              case 'r':
                s->chkrad = false;
                break;
              default:
                mps_error (s, "Bad check switch: ", opt->optvalue,
                           ", use R|r");
              }
            if (strlen (opt->optvalue) != 1)
              mps_error (s, "Bad check option: ", opt->optvalue);
            break;

            
        case 'a':
	  explicit_algorithm_selection = true;
          switch (*opt->optvalue)
            {
            case 'u':
              mps_context_select_algorithm (s, MPS_ALGORITHM_STANDARD_MPSOLVE);
              break;
            case 's':
              mps_context_select_algorithm (s, MPS_ALGORITHM_SECULAR_GA);
              break;
            default:
              mps_error (s, "The selected algorithm is not supported");
              break;
            }
          break;
        case 'b':
          mps_context_set_jacobi_iterations (s, true);
          break;
	case 'c':
	  mps_context_set_crude_approximation_mode (s, true);
	  break;
        case 'o':
          mps_context_set_output_prec (s, (atoi (opt->optvalue)) * LOG2_10 + 1);
          break;
        case 'i':
          input_precision = atoi (opt->optvalue) * LOG2_10;
          break;
        case 'G':
          switch (*opt->optvalue)
            {
            case 'a':
              mps_context_set_output_goal (s, MPS_OUTPUT_GOAL_APPROXIMATE);
              break;
            case 'i':
              mps_context_set_output_goal (s, MPS_OUTPUT_GOAL_ISOLATE);
              break;
            case 'c':
              mps_context_set_output_goal (s, MPS_OUTPUT_GOAL_COUNT);
              break;
            default:
              mps_error (s, "The selected goal does not exists");
              break;
            }
          break;

        case 'p':
          inline_poly = strdup (opt->optvalue);
          break;

#ifndef DISABLE_DEBUG
        case 'd':
          mps_context_add_debug_domain (s, MPS_DEBUG_INFO);
          
          if (!opt->optvalue)
            break;

          /* If debugging was enabled, parse debug_level */
          while (*opt->optvalue)
            {         
              char output[255];
              switch (*opt->optvalue++)
                {
                case 't':
                  mps_context_add_debug_domain (s, MPS_DEBUG_TRACE);
                  break;
                case 'a':
                  mps_context_add_debug_domain (s, MPS_DEBUG_APPROXIMATIONS);
                  break;
                case 'c':
                  mps_context_add_debug_domain (s, MPS_DEBUG_CLUSTER);
                  break;
                case 'i':
                  mps_context_add_debug_domain (s, MPS_DEBUG_IMPROVEMENT);
                  break;
                case 'w':
                  mps_context_add_debug_domain (s, MPS_DEBUG_TIMINGS);
                  break;
                case 'o':
                  mps_context_add_debug_domain (s, MPS_DEBUG_IO);
                  break;
                case 'm':
                  mps_context_add_debug_domain (s, MPS_DEBUG_MEMORY);
                  break;
                case 'f':
                  mps_context_add_debug_domain (s, MPS_DEBUG_FUNCTION_CALLS);
                  break;
                case 'p':
                  mps_context_add_debug_domain (s, MPS_DEBUG_PACKETS);
                  break;
                case 'r':
                  mps_context_add_debug_domain (s, MPS_DEBUG_REGENERATION);
                  break;
                default:
                  sprintf (output, "Unrecognized debug option: %c", *(opt->optvalue - 1));
                  mps_error (s, output);
                  break;
                }
            }
          break;
#endif

#if HAVE_GRAPHICAL_DEBUGGER
        case 'x':
          graphic_debug = true;
          break;
#endif          

	case 's':
	  if (opt->optvalue == NULL)
	    {
	      mps_error (s, "You need to specify a valid file with -s");
	      break;
	    }
	  else
	    {
	      s->rtstr = fopen (opt->optvalue, "r");
	      if (! s->rtstr)
		{
		  mps_error (s, "Cannot open the given file: %s", opt->optvalue);
		  break;
		}
	      else
		{
		  mps_context_select_starting_strategy (s, MPS_STARTING_STRATEGY_FILE);
		}
	    }
	  break;

        case 't':
          switch (opt->optvalue[0])
            {
            case 'f':
              phase = float_phase;
              break;
            case 'd':
              phase = dpe_phase;
              break;
            default:
              usage (s, argv[0]);
            }
          break;

        case 'j':
          mps_thread_pool_set_concurrency_limit (s, NULL, atoi (opt->optvalue));
          s->n_threads = atoi (opt->optvalue);
          break;
        default:
          usage (s, argv[0]);
          break;
        }
    }

#if HAVE_GRAPHICAL_DEBUGGER
  if (graphic_debug)
  {
    /* Init GTK only if graphic debug is requested. In all other case is unnecessary
     * and will waste computational time that is likely to bias benchmarks. */
    gtk_init (&argc, &argv);

    logger = mps_iteration_logger_new ();
    mps_iteration_logger_set_mps_context (logger, s);

    g_signal_connect (GTK_WIDGET (logger), "delete_event", 
       G_CALLBACK (on_iteration_logger_destroy), NULL);

    gtk_widget_show_all (GTK_WIDGET (logger));
  }
#endif

  if (mps_context_has_errors (s))
    {
      mps_print_errors (s);
      return EXIT_FAILURE;
    }

  if (argc > 2)
    usage (s, argv[0]);

  /* If no file is provided use standard input */
  if (inline_poly)
    {
      // poly = mps_parse_inline_poly_from_string (s, inline_poly);
      mps_abstract_input_stream * stream = 
       (mps_abstract_input_stream *) mps_memory_file_stream_new (inline_poly);
      poly = mps_monomial_yacc_parser (s, stream);

      if (mps_context_has_errors (s))
       {
         mps_print_errors (s);
         return EXIT_FAILURE;
       }

      free (inline_poly);
    }
  else
    {
      if (argc == 1)
        infile = stdin;
      else
        infile = fopen (argv[1], "r");

      if (!infile)
        {
          mps_error (s, "Cannot open input file for read, aborting.");
          mps_print_errors (s);
          return EXIT_FAILURE;
        }

      /* Parse the input stream and if a polynomial is given as output, 
       * allocate also a secular equation to be used in regeneration */
       poly = mps_parse_stream (s, infile);
     }

  if (!poly)
    {
      mps_error (s, "Error while parsing the polynomial, aborting.");
      mps_print_errors (s);
      return EXIT_FAILURE;
    }
  else
    mps_context_set_input_poly (s, poly);

  /* Override input precision if needed */
  if (input_precision >= 0)
    mps_polynomial_set_input_prec (s, poly, input_precision);

  /* Perform some heuristic for the algorithm selection, but only if the user
   * hasn't explicitely selected one. */
  if (! explicit_algorithm_selection)
    {
      mps_context_select_algorithm (s, (MPS_IS_MONOMIAL_POLY (poly) && 
					MPS_DENSITY_IS_SPARSE (poly->density)) ? 
				    MPS_ALGORITHM_STANDARD_MPSOLVE : MPS_ALGORITHM_SECULAR_GA );
    }

  /* Close the file if it's not stdin */
  if (argc == 2 && ! inline_poly)
    fclose (infile);

  /* Select the starting phase according to user input */
  mps_context_set_starting_phase (s, phase);

  /* Solve the polynomial */
  #if HAVE_GRAPHICAL_DEBUGGER
  if (graphic_debug)
  {
    mps_mpsolve_async (s, cleanup_context, NULL);
    gtk_main ();
  }
  else
  {
  #endif
    mps_mpsolve (s);
    cleanup_context (s, NULL);
  #if HAVE_GRAPHICAL_DEBUGGER
  }
  #endif

}
Exemple #5
0
/**
 * @brief Main routine of the program that implements the algorithm
 * in the standard polynomial version.
 *
 * The program is divided into many parts
 * - Check the correctness of data, scale coefficients if
 *   needed, and select cases: the variable <code>which_case</code> is
 *   <code>'f'</code> or <code>'d'</code>  according to float or dpe case.
 * - Call msolve or dsolve according to the value of which_case.
 * - Allocate MP variables mfpc, mroot, drad (if needed).
 * - Start MPsolve loop
 *   - prepare data according to the current precision
 *      and to the data_type (density/sparsity/user)
 *   - Call msolve with the current precision
 * - check for termination
 */
MPS_PRIVATE void
mps_standard_mpsolve (mps_context * s)
{
  int i, nzc;
  char which_case;
  mps_boolean d_after_f, computed;

#ifndef DISABLE_DEBUG
  clock_t *my_timer = mps_start_timer ();
#endif

  mps_allocate_data (s);

  if (s->DOLOG)
    s->debug_level |= MPS_DEBUG_TRACE;

  /* == 1 ==  Setup variables, i.e. copy coefficients
     into dpr, dpc and similar. */
  mps_setup (s);

  s->lastphase = no_phase;
  computed = false;
  s->over_max = false;

  /* == 2 ==  Resume from pre-computed roots */
  if (s->resume)
    {
      mps_error (s, "Resume not supported yet");
#ifndef DISABLE_DEBUG
      mps_stop_timer (my_timer);
#endif
      return;
    }

  /* == 3 ==  Check data and get starting phase */
  if (s->skip_float)
    which_case = 'd';
  else
    which_case = 'f';

  /* This variable is true if we need a dpe phase after the
   * float phase */
  d_after_f = false;

  /* Check if a dpe phase is needed and deflate polynomial */
  mps_check_data (s, &which_case);

  /* Check for errors in check data */
  if (mps_context_has_errors (s))
    {
#ifndef DISABLE_DEBUG
      mps_stop_timer (my_timer);
#endif
      return;
    }

  rdpe_set_2dl (s->eps_out, 1.0, -s->output_config->prec);

  if (s->DOLOG)
    fprintf (s->logstr, "Which_case = %c, skip_float= %d\n", which_case,
             s->skip_float);

  /* == 4 ==  Float phase */
  if (which_case == 'f')
    {
      if (s->DOLOG)
        fprintf (s->logstr, "Float phase ...\n");
      mps_fsolve (s, &d_after_f);
      s->lastphase = float_phase;

      if (s->DOLOG)
        mps_dump (s);

      computed = mps_check_stop (s);
      if (computed && s->output_config->goal != MPS_OUTPUT_GOAL_APPROXIMATE)
        goto exit_sub;
      /* stop for COUNT and ISOLATE goals */
    }

  /* == 5 ==  DPE phase */
  if (which_case == 'd' || d_after_f)
    {                           /* DPE phase */
      if (s->DOLOG)
        fprintf (s->logstr, "DPE phase ...\n");
      /* If we are arriving from a float phase copy the floating points
       * roots approximations in the DPE root approximations. */
      if (d_after_f)
        for (i = 0; i < s->n; i++)
          {
            rdpe_set_d (s->root[i]->drad, s->root[i]->frad);
            cdpe_set_x (s->root[i]->dvalue, s->root[i]->fvalue);
          }
      s->lastphase = dpe_phase;
      mps_dsolve (s, d_after_f);

      if (s->DOLOG)
        mps_dump (s);

      computed = mps_check_stop (s);
      if (computed && s->output_config->goal != MPS_OUTPUT_GOAL_APPROXIMATE)
        goto exit_sub;
    }

  /* == 6 ==   Allocate MP variables mfpc, mroot, drad, mfppc, mfppc1
   * (the real input case is not implemented yet ) */
  MPS_DEBUG (s, "Starting MP phase");

  s->lastphase = mp_phase;

  /* ==== 6.1 initialize mp variables */
  mps_mp_set_prec (s, 2 * DBL_MANT_DIG);

  /* Prepare data according to the current working precision */
  mps_prepare_data (s, s->mpwp);

  /* ==== 6.2 set initial values for mp variables */
  for (i = 0; i < s->n; i++)
    {
      if (which_case == 'd' || d_after_f)
        mpc_set_cdpe (s->root[i]->mvalue, s->root[i]->dvalue);
      else
        {
          mpc_set_cplx (s->root[i]->mvalue, s->root[i]->fvalue);
          rdpe_set_d (s->root[i]->drad, s->root[i]->frad);
        }
    }
  if (computed && s->output_config->goal == MPS_OUTPUT_GOAL_APPROXIMATE)
    {
      MPS_DEBUG (s, "Exiting since the approximation are computed and the goal is MPS_OUTPUT_GOAL_APPROXIMATE");
      goto exit_sub;
    }

  MPS_DEBUG (s, "s->mpwp = %ld, s->mpwp_max = %ld", s->mpwp, s->mpwp_max);
  MPS_DEBUG (s, "s->input_config->prec = %ld", s->active_poly->prec);

  /* == 7 ==  Start MPSolve loop */
  s->mpwp = mps_context_get_minimum_precision (s);

  /* Poor man GMP - machine precision detection. We need that min_prec is contained
   * in the interval [ DBL_MANT_DIG , 2 * DBL_MANT_DIG ]. This is probably true on most
   * architectures with the instruction above, but we want to be sure. */
  while (s->mpwp < DBL_MANT_DIG)
    s->mpwp <<= 1;
  while (s->mpwp > 2 * DBL_MANT_DIG)
    s->mpwp >>= 1;

  while (!computed && s->mpwp < s->mpwp_max)
    {
      s->mpwp *= 2;

      if (s->mpwp > s->mpwp_max)
        {
          s->mpwp = s->mpwp_max;
          s->over_max = true;
        }

      if (s->DOLOG)
        fprintf (s->logstr, "MAIN: mp_loop: mpwp=%ld\n", s->mpwp);

      /* == 7.1 ==   prepare data according to the current precision */
      mps_mp_set_prec (s, s->mpwp);
      mps_prepare_data (s, s->mpwp);

      /* == 7.2 ==   Call msolve with the current precision */
      if (s->DOLOG)
        fprintf (s->logstr, "MAIN: now call msolve nclust=%ld\n", s->clusterization->n);
      mps_msolve (s);
      s->lastphase = mp_phase;

      /* if (s->DOLOG) dump(logstr); */

      if (s->DOLOG)
        {                       /* count isolated zeros */
          nzc = 0;
          for (i = 0; i < s->n; i++)
            {
              if (s->root[i]->status == MPS_ROOT_STATUS_ISOLATED ||
                  s->root[i]->status == MPS_ROOT_STATUS_APPROXIMATED)
                nzc++;
            }
          fprintf (s->logstr, "MAIN: isolated %d roots\n", nzc);
          fprintf (s->logstr, "MAIN: after msolve check stop\n");
        }

      /* == 7.3 ==  Check the stop condition */
      computed = mps_check_stop (s);
      mps_mmodify (s, true);

      /* == 7.4 ==  reset the status vector */
      for (i = 0; i < s->n; i++)
        if (s->root[i]->status == MPS_ROOT_STATUS_NEW_CLUSTERED)
          s->root[i]->status = MPS_ROOT_STATUS_CLUSTERED;
    }

  /* == 8 ==  Check for termination */
  if (!computed)
    {
      if (s->over_max)
        {
          s->over_max = true;
          /* mps_error (s, "Reached the maximum working precision"); */
          MPS_DEBUG (s, "Reached the maximum working precision");
          goto exit_sub;
        }
      else
        {
          /* mps_warn (s, "Reached the input precision"); */
          MPS_DEBUG (s, "Reached the input precision");
          goto exit_sub;
        }
    }

exit_sub:

  /* == 9 ==  Check inclusion disks */
  if (computed && s->clusterization->n < s->n)
    if (!mps_inclusion (s))
      {
        mps_error (s, "Unable to compute inclusion disks");
        return;
      }

  /* == 10 ==  Refine roots */
  if (computed && !s->over_max && s->output_config->goal == MPS_OUTPUT_GOAL_APPROXIMATE)
    {
      s->lastphase = mp_phase;
      mps_improve (s);
    }

  /* == 11 == Check inclusions */
  /* This step is disabled since it cause problems with the lar* kind of polynomials. 
   * To be re-enabled a careful check of the necessary precision to avoid NULL DERIVATIVE
   * warnings should be implemented. 
   * if (s->active_poly->prec > 0)
   *   mps_validate_inclusions (s);
   */

  /* == 12 ==  Restore to highest used precision */
  if (s->lastphase == mp_phase)
    mps_restore_data (s);

#ifndef DISABLE_DEBUG
  {
    unsigned long time = mps_stop_timer (my_timer);
    MPS_DEBUG (s, "Total time using MPSolve: %lu ms", time);
  }
#endif

  /* Finally copy the roots ready for output */
  mps_copy_roots (s);
}