Beispiel #1
0
Datei: f4.cpp Projekt: pzinn/M2
void F4GB::reorder_rows()
{
  //??? reorder rows in <mat> and <syz> simultaneously?

  int nrows = INTSIZE(mat->rows);
  int ncols = INTSIZE(mat->columns);
  coefficient_matrix::row_array newrows;
  VECTOR(long) rowlocs; // 0..nrows-1 of where row as been placed

  newrows.reserve(nrows);
  rowlocs.reserve(nrows);
  for (int r = 0; r < nrows; r++)
    rowlocs.push_back(-1);

  for (int c = 0; c < ncols; c++)
    {
      int oldrow = mat->columns[c].head;
      if (oldrow >= 0)
        {
          // Move the row into place
          int newrow = INTSIZE(newrows);
          newrows.push_back(mat->rows[oldrow]);
          rowlocs[oldrow] = newrow;
          mat->columns[c].head = newrow;
          if (mat->columns[c].head == oldrow)
            mat->columns[c].head = newrow;
        }

    }
  for (int r = 0; r < nrows; r++)
    if (rowlocs[r] < 0)
      newrows.push_back(mat->rows[r]);
  std::swap(mat->rows, newrows);
}
Beispiel #2
0
Datei: f4.cpp Projekt: pzinn/M2
void F4GB::new_GB_elements()
{
  /* After LU decomposition, loop through each
     row of the matrix.  If the corresponding
     lead term is not in the initial ideal (or, at least,
     wasn't) then insert GB element (and so update spairs, etc,
     but don't do auto_reduce...)

     If instead the lead term is not new, then keep track of this
     information somehow: place ... into a monheap...
  */

  /* If we can place the possible new elements first, or in a separate place, then
     we don't need to loop through all of these */

  for (int r=0; r<mat->rows.size(); r++)
    {
      if (is_new_GB_row(r)) {
        insert_syz(syz->rows[r], INTSIZE(gb));
        insert_gb_element(mat->rows[r]);
      } else {
        insert_syz(syz->rows[r]);
      }
    }
}
Beispiel #3
0
Datei: f4.cpp Projekt: pzinn/M2
void F4GB::process_column(int c)
{
  /* If this column has been handled before, return.
     Otherwise, find a GB element whose lead term
     divides this monomial, and either mark this colum
     as not an initial element, OR append a row
  */

  column_elem &ce = mat->columns[c];
  if (ce.head >= -1)
    return;
  int32_t which;
  bool found = lookup->find_one_divisor_packed(M, ce.monom, which);
  if (found)
    {
      packed_monomial n = next_monom;
      M->unchecked_divide(ce.monom, gb[which]->f.monoms, n);
      B.intern(1+M->monomial_size(n));
      next_monom = B.reserve(1+M->max_monomial_size());
      next_monom++;
      //M->set_component(which, n);
      ce.head = INTSIZE(mat->rows);
      load_row(n,which);
    }
  else
    ce.head = -1;
}
Beispiel #4
0
FreeModule *FreeModule::make_schreyer(const GBMatrix *m)
{
    const FreeModule *F = m->get_free_module();
    const PolynomialRing *R = F->get_ring()->cast_to_PolynomialRing();
    if (R == 0)
    {
        ERROR("expected a polynomial ring");
        return nullptr;
    }
    FreeModule *G = R->make_FreeModule();
    int rk = INTSIZE(m->elems);
    if (rk == 0) return G;

    for (int i=0; i<rk; i++)
    {
        int *deg = R->degree_monoid()->make_one();
        gbvector * v = m->elems[i];
        if (v != 0)
            R->get_gb_ring()->gbvector_multidegree(F, v, deg);
        G->append(deg);
    }

    G->schreyer = SchreyerOrder::create(m);

    return G;
}
Beispiel #5
0
/* Sorting a list of spairs */
void gbB::spairs_sort(int len, spair *&ps)
{
  if (ps == 0 || ps->next == 0) return;
  if (len <= 1) return;
  spairs a; // array of spair's
  spairs b; // these are the ones which are uncomputed, but whose lead_of_spoly is 0.
  a.reserve(len);
  for (spair *p = ps; p != 0; p=p->next)
    {
      if ((p->type > gbB::SPAIR_SKEW) || p->lead_of_spoly)
        a.push_back(p);
      else
        b.push_back(p);
    }

  SPolySorterB SP(R,F);
  QuickSorter<SPolySorterB>::sort(&SP,&a[0],a.size());

  int asize = INTSIZE(a);
  int bsize = INTSIZE(b);

  if (asize > 0)
    {
      ps = a[0];
      for (int i=1; i<asize; i++)
        a[i-1]->next = a[i];
    }
  else if (bsize > 0)
    {
      ps = b[0];
      //debugging// fprintf(stderr, "bsize is %d\n",bsize);
    }
  else
    {
      ps = 0;
      return;
    }

  if (asize > 0)
    a[asize-1]->next = (bsize > 0 ? b[0] : 0);
  if (bsize > 0)
    {
      for (int i=1; i<bsize; i++)
        b[i-1]->next = b[i];
      b[bsize-1]->next = 0;
    }
}
Beispiel #6
0
Datei: f4.cpp Projekt: pzinn/M2
void F4GB::insert_gb_element(row_elem &r)
{
  // Insert row as gb element.
  // Actions to do:
  //  translate row to a gbelem + poly
  //    set degrees as needed
  //  insert the monomial into the lookup table
  //  find new pairs associated to this new element

  int nslots = M->max_monomial_size();
  int nlongs = r.len * nslots;

  gbelem *result = new gbelem;
  result->f.len = r.len;

  // If the coeff array is null, then that means the coeffs come from the original array
  // Here we copy it over.

  result->f.coeffs = (r.coeffs ? r.coeffs : KK->copy_F4CoefficientArray(r.len, get_coeffs_array(r)));
  r.coeffs = 0;;

  result->f.monoms = Mem->allocate_monomial_array(nlongs);

  monomial_word *nextmonom = result->f.monoms;
  for (int i=0; i<r.len; i++)
    {
      M->copy(mat->columns[r.comps[i]].monom, nextmonom);
      nextmonom += nslots;
    }
  Mem->components.deallocate(r.comps);
  r.len = 0;
  result->deg = this_degree;
  result->alpha = static_cast<int>(M->last_exponent(result->f.monoms));
  result->minlevel = ELEM_MIN_GB; // MES: How do
                                  // we distinguish between ELEM_MIN_GB, ELEM_POSSIBLE_MINGEN?

  int which = INTSIZE(gb);
  gb.push_back(result);

  if (hilbert)
    {
      int x;
      int *exp = newarray_atomic(int, M->n_vars());
      M->to_intstar_vector(result->f.monoms, exp, x);
      hilbert->addMonomial(exp, x+1);
      deletearray(exp);
    }

  // now insert the lead monomial into the lookup table
  varpower_monomial vp = newarray_atomic(varpower_word, 2 * M->n_vars() + 1);
  M->to_varpower_monomial(result->f.monoms, vp);
  lookup->insert_minimal_vp(M->get_component(result->f.monoms), vp, which);
  deleteitem(vp);
  // now go forth and find those new pairs
  S->find_new_pairs(is_ideal);
}
Beispiel #7
0
Datei: f4.cpp Projekt: pzinn/M2
///////////////////////////////////////////////////
// Creation of the matrix over K //////////////////
///////////////////////////////////////////////////
int F4GB::new_column(packed_monomial m)
{
  // m is a packed monomial, unique via the hash table H, B.
  column_elem c;
  int next_column = INTSIZE(mat->columns);
  m[-1] = next_column;
  c.monom = m;
  c.head = -2;
  mat->columns.push_back(c);
  return next_column;
}
Beispiel #8
0
SchreyerOrder *SchreyerOrder::create(const GBMatrix *m)
{
#ifdef DEVELOPMENT
#warning "the logic in SchreyerOrder creation is WRONG!"
#endif
  int i;
  const FreeModule *F = m->get_free_module();
  const Ring *R = F->get_ring();
  const SchreyerOrder *S = F->get_schreyer_order();
  const PolynomialRing *P = R->cast_to_PolynomialRing();
  const Monoid *M = P->getMonoid();
  SchreyerOrder *result = new SchreyerOrder(M);
  int rk = INTSIZE(m->elems);
  if (rk == 0) return result;

  int *base = M->make_one();
  int *tiebreaks = newarray_atomic(int,rk);
  int *ties = newarray_atomic(int,rk);
  for (i=0; i<rk; i++)
    {
      gbvector *v = m->elems[i];
      if (v == NULL || S == NULL)
        tiebreaks[i] = i;
      else
        tiebreaks[i] = i + rk * S->compare_num(v->comp-1);
    }
  // Now sort tiebreaks in increasing order.
  std::sort<int *>(tiebreaks, tiebreaks+rk);
  for (i=0; i<rk; i++)
    ties[tiebreaks[i] % rk] = i;
  for (i=0; i<rk; i++)
    {
      gbvector *v = m->elems[i];
      if (v == NULL)
        M->one(base);
      else //if (S == NULL)
        M->copy(v->monom, base);
#ifdef DEVELOPMENT
#warning "Schreyer unencoded case not handled here"
#endif
#if 0
//       else
//      M->mult(v->monom, S->base_monom(i), base);
#endif
      result->append(ties[i], base);
    }

  intern_SchreyerOrder(result);
  M->remove(base);
  deletearray(tiebreaks);
  deletearray(ties);
  return result;
}
Beispiel #9
0
Datei: f4.cpp Projekt: pzinn/M2
void F4GB::gauss_reduce_linbox()
  // dumps the current matrix into a file in the linbox sparse matrix format
{
  // dump the matrix in a file
  char fname[30];
  sprintf(fname, "tmp.%i.matrix", this_degree);
  FILE* mfile = fopen(fname, "w");
  int nrows = INTSIZE(mat->rows);
  int ncols = INTSIZE(mat->columns);

  fprintf(mfile, "%i %i M\n", nrows, ncols);
  for (int i=0; i<nrows; i++)
    {
      row_elem &r = mat->rows[i];
      int *sparseelems = static_cast<int *>(r.coeffs);
      for (int j=0; j<r.len; j++) {
        fprintf(mfile, "%i %i %i\n",i+1,r.comps[j]+1,KK->coeff_to_int(*sparseelems++)); //is *sparseelems integer?
      }
    }
  fprintf(mfile, "0 0 0\n");
  fclose(mfile);
}
Beispiel #10
0
Datei: f4.cpp Projekt: pzinn/M2
void F4GB::show_new_rows_matrix()
{
  int ncols = INTSIZE(mat->columns);
  int nrows = 0;
  for (int nr=0; nr<mat->rows.size(); nr++)
    if (is_new_GB_row(nr)) nrows++;

  MutableMatrix *gbM = IM2_MutableMatrix_make(KK->get_ring(), nrows, ncols, false);

  int r = -1;
  for (int nr=0; nr<mat->rows.size(); nr++)
    if (is_new_GB_row(nr))
      {
        r++;
        row_elem &row = mat->rows[nr];
        ring_elem *rowelems = newarray(ring_elem, row.len);
        if (row.coeffs == 0)
          {
            if (row.monom == 0)
              KK->to_ringelem_array(row.len, gens[row.elem]->f.coeffs, rowelems);
            else
              KK->to_ringelem_array(row.len, gb[row.elem]->f.coeffs, rowelems);
          }
        else
          {
            KK->to_ringelem_array(row.len, row.coeffs, rowelems);
          }
        for (int i=0; i<row.len; i++)
          {
            int c = row.comps[i];
            gbM->set_entry(r,c,rowelems[i]);
          }
        deletearray(rowelems);
      }

  buffer o;
  gbM->text_out(o);
  emit(o.str());
}
Beispiel #11
0
Datei: f4.cpp Projekt: pzinn/M2
void F4GB::process_s_pair(spair *p)
{
  int c;

  switch (p->type) {
  case F4_SPAIR_SPAIR: {
    packed_monomial n = next_monom;
    M->unchecked_divide(p->lcm, gb[p->i]->f.monoms, n);
    B.intern(1+M->monomial_size(n));
    next_monom = B.reserve(1+M->max_monomial_size());
    next_monom++;

    load_row(n, p->i);
    c = mat->rows[mat->rows.size()-1].comps[0];

    if (mat->columns[c].head >= -1)
      n_lcmdups++;
    else {
      // In this situation, we load the other half as a reducer
      n = next_monom;
      M->unchecked_divide(p->lcm, gb[p->j]->f.monoms, n);
      B.intern(1+M->monomial_size(n));
      next_monom = B.reserve(1+M->max_monomial_size());
      next_monom++;
      load_row(n, p->j);

      mat->columns[c].head = INTSIZE(mat->rows)-1;
    }
    break;
  }
  case F4_SPAIR_GEN:
    load_gen(p->i);
    break;
  default:
    break;
  }
}
Beispiel #12
0
void gbB::auto_reduce_by(int id)
{
  /* Loop backwards while degree doesn't change */
  /* Don't change quotient ring elements */
  gbelem *me = gb[id];
  int a = me->gap;  // Only auto reduce those that are of the same degree
                      // and not a higher gap level
  for (int i= INTSIZE(gb)-1; i>=first_gb_element; i--)
    {
      if (i == id) continue;
      gbelem *g = gb[i];
      if (g->deg < me->deg) return;
      if (g->gap < a) continue;
      if (M2_gbTrace >= 10)
        {
          buffer o;
          o << "  auto reduce " << i << " by " << id;
          emit_line(o.str());
        }
      R->gbvector_auto_reduce(F, Fsyz,
                              g->g.f, g->g.fsyz, // these are modified
                              me->g.f, me->g.fsyz);
    }
}
Beispiel #13
0
// new code
void gbB::do_computation()
{
  ComputationStatusCode ret;
  spair *p;

  // initial state is STATE_NEWDEGREE

  if (stop_.always_stop) return; // don't change status

  if ((ret = computation_is_complete()) != COMP_COMPUTING)
    {
      set_status(ret);
      return;
    }

  if (M2_gbTrace == 15)
    {
      emit_line("[gb]");
    }
  else if (M2_gbTrace >= 1)
    {
      emit_wrapped("[gb]");
    }
  for (;;)
    {
      if (stop_.stop_after_degree && this_degree > stop_.degree_limit->array[0])
        {
          // Break out now if we don't have anything else to compute in this degree.
          set_status(COMP_DONE_DEGREE_LIMIT);
          return;
        }
      if (M2_gbTrace & PrintingDegree)
        {
        }

      switch(state) {

      case STATE_NEWPAIRS:
        // Loop through all of the new GB elements, and
        // compute spairs.  Start at np_i
        // np_i is initialized at the beginning, and also here.
            while (np_i < n_gb)
              {
                if (system_interrupted())
                  {
                    set_status(COMP_INTERRUPTED);
                    return;
                  }
                if (gb[np_i]->minlevel & ELEMB_MINGB)
                  update_pairs(np_i);
                np_i++;
              }
            state = STATE_NEWDEGREE;

      case STATE_NEWDEGREE:
        // Get the spairs and generators for the next degree

            if (S->n_in_degree == 0)
              {
                int old_degree = this_degree;
                npairs = spair_set_prepare_next_degree(this_degree); // sets this_degree
                if (old_degree < this_degree)
                  first_in_degree = INTSIZE(gb);
                complete_thru_this_degree = this_degree-1;
                if (npairs == 0)
                  {
                    state = STATE_DONE;
                    set_status(COMP_DONE);
                    return;
                  }
                if (stop_.stop_after_degree && this_degree > stop_.degree_limit->array[0])
                  {
                    set_status(COMP_DONE_DEGREE_LIMIT);
                    return;
                  }
                if (hilbert)
                  {
                    if (!hilbert->setDegree(this_degree))
                      {
                        if (error())
                          set_status(COMP_ERROR);
                        else
                          set_status(COMP_INTERRUPTED);
                        return;
                      }
                  }
              }
            if (M2_gbTrace == 15)
              {
                buffer o;
                o << "DEGREE " << this_degree;
                o << ", number of spairs = " << npairs;
                if (hilbert)
                  o << ", expected number in this degree = " << hilbert->nRemainingExpected();
                emit_line(o.str());
              }
            else if (M2_gbTrace >= 1)
              {
                buffer o;
                o << '{' << this_degree << '}';
                o << '(';
                if (hilbert)
                  o << hilbert->nRemainingExpected() << ',';
                o << npairs << ')';
                emit_wrapped(o.str());
              }
            ar_i = n_gb;
            ar_j = ar_i+1;
            state = STATE_SPAIRS;

      case STATE_SPAIRS:
      case STATE_GENS:
        // Compute the spairs for this degree

            while ((p = spair_set_next()) != 0)
              {
                process_spair(p);
                npairs--;
                n_pairs_computed++;

                if ((ret = computation_is_complete()) != COMP_COMPUTING)
                  {
                    set_status(ret);
                    return;
                  }

                if (system_interrupted())
                  {
                    set_status(COMP_INTERRUPTED);
                    return;
                  }
              }
            state = STATE_AUTOREDUCE;
            // or state = STATE_NEWPAIRS

      case STATE_AUTOREDUCE:
        // This is still possibly best performed when inserting a new element
        // Perform the necessary or desired auto-reductions
        while (ar_i < n_gb)
              {
                while (ar_j < n_gb)
                  {
                    if (system_interrupted())
                      {
                        set_status(COMP_INTERRUPTED);
                        return;
                      }
                    R->gbvector_auto_reduce(F, Fsyz,
                                            gb[ar_i]->g.f, gb[ar_i]->g.fsyz,
                                            gb[ar_j]->g.f, gb[ar_j]->g.fsyz);
                    ar_j++;
                  }
                ar_i++;
                ar_j = ar_i+1;
              }
            state = STATE_NEWPAIRS;
            break;

      case STATE_DONE:
        return;
      }
  }
}
Beispiel #14
0
void gbB::insert_gb(POLY f, gbelem_type minlevel)
{
  /* Reduce this element as far as possible.  This either removes content,
     makes it monic, or at least negates it so the lead coeff is positive. */
  ring_elem junk;

  //DEBUG BLOCK  int fwt;
  //  int fdeg = weightInfo->gbvector_weight(f.f, fwt);
  //  fprintf(stderr, "inserting GB element %d, thisdeg %d deg %d gap %d\n",
  //      gb.size(),
  //      this_degree,
  //      fdeg,
  //      fdeg-fwt);

  remainder(f,this_degree,false,junk);

  //  fdeg = weightInfo->gbvector_weight(f.f, fwt);
  //  fprintf(stderr, "    after remainder deg %d gap %d\n",
  //      fdeg,
  //      fdeg-fwt);

  stats_ngb++;


  // Complete hack for getting bug fix to get test/isSubset.m2 to work again for 1.3:
  // over ZZ, always make gb elements non reducers...

  gbelem *g = gbelem_make(f.f, f.fsyz, minlevel, this_degree);
  minimal_gb_valid = false;
  int me = INTSIZE(gb);
  gb.push_back(g);
  n_gb++;
  int x = g->g.f->comp;

  // In a encoded Schreyer order, the following line might miss subring elements.
  // But it at least won't be incorrect...
  if (R->get_flattened_monoid()->in_subring(1,g->g.f->monom))
    n_subring++;

  lookup->insert(g->lead, x, me);

  if (M2_gbTrace == 15)
    {
      buffer o;
      o << "    new ";
      gbelem_text_out(o, INTSIZE(gb)-1);
      emit_line(o.str());
    }
  else if (M2_gbTrace >= 5)
    {
      char s[100];
      buffer o;
      sprintf(s, "new-inserting element %d (minimal %d): ",me,minlevel);
      o << s;
      R->gbvector_text_out(o,F,g->g.f);
      emit_line(o.str()); o.reset();
      o << "                          syzygy : ";
      R->gbvector_text_out(o,Fsyz,g->g.fsyz);
      emit_line(o.str());
    }

  auto_reduce_by(me);

  if (hilbert)
    {
      bool is_last_elem = hilbert->addMonomial(g->lead, x);
      if (is_last_elem) flush_pairs();
    }
  else
    {
#ifdef DEVELOPMENT
#warning "todo: codimension stop condition"
#endif
      // codim test is set.  Compute the codimension now.
    }

  if (M2_gbTrace >= 10)
    {
      //      show();
    }
}
Beispiel #15
0
Datei: f4.cpp Projekt: pzinn/M2
void F4GB::do_spairs()
{
  if (hilbert && hilbert->nRemainingExpected() == 0)
    {
      if (M2_gbTrace >= 1)
        fprintf(stderr, "-- skipping degree...no elements expected in this degree\n");
      return;
    }
  reset_matrix();
  reset_syz_matrix();
  clock_t begin_time = clock();

  n_lcmdups = 0;
  make_matrix();

  if (M2_gbTrace >= 5) {
    fprintf(stderr, "---------\n");
    show_matrix();
    fprintf(stderr, "---------\n");
  }

  clock_t end_time = clock();
  clock_make_matrix += end_time - begin_time;
  double nsecs = static_cast<double>(end_time - begin_time);
  nsecs /= CLOCKS_PER_SEC;
  if (M2_gbTrace >= 2)
    fprintf(stderr, " make matrix time = %f\n", nsecs);

  if (M2_gbTrace >= 2)
    H.dump();

  begin_time = clock();
  gauss_reduce(true);
  end_time = clock();
  clock_gauss += end_time - begin_time;

  //  fprintf(stderr, "---------\n");
  //  show_matrix();
  //  fprintf(stderr, "---------\n");

  nsecs = static_cast<double>(end_time - begin_time);
  nsecs /= CLOCKS_PER_SEC;
  if (M2_gbTrace >= 2)
    {
      fprintf(stderr, " gauss time          = %f\n", nsecs);

      fprintf(stderr, " lcm dups            = %ld\n", n_lcmdups);
      if (M2_gbTrace >= 5)
        {
          fprintf(stderr, "---------\n");
          show_matrix();
          fprintf(stderr, "---------\n");
          show_syz_matrix();
          //  show_new_rows_matrix();
        }
    }
  new_GB_elements();
  int ngb = INTSIZE(gb);
  if (M2_gbTrace >= 1) {
    fprintf(stderr, " # GB elements   = %d\n", ngb);
    if (M2_gbTrace >= 5) show_gb_array(gb);
    if (using_syz)
      fprintf(stderr, " # syzygies      = %ld\n", static_cast<long>(syz_basis.size()));
    if (M2_gbTrace >= 5) show_syz_basis();
  }

  clear_matrix();
  clear_syz_matrix();
}
Beispiel #16
0
Datei: f4.cpp Projekt: pzinn/M2
void F4GB::tail_reduce()
{
  int nrows = INTSIZE(mat->rows);
  int ncols = INTSIZE(mat->columns);

  KK->dense_row_allocate(gauss_row, ncols);
  if (using_syz) KK->dense_row_allocate(syz_row, nrows);
  for (int i=nrows-1; i>=0; i--)
    {
      row_elem &r = mat->rows[i];
      if (r.len <= 1 || r.coeffs == 0) continue; // row reduced to zero, ignore it.
      // At this point, we should have an element to reduce
      bool anychange = false;
      KK->dense_row_fill_from_sparse(gauss_row, r.len, r.coeffs, r.comps);
      syz_dense_row_fill_from_sparse(i); // fill syz_row from row[i]
      int firstnonzero = r.comps[0];
      int first = (r.len == 1 ? ncols :  r.comps[1]);
      int last = r.comps[r.len-1];
      while (first <= last) {
        int pivotrow = mat->columns[first].head;
        if (pivotrow >= 0)
          {
            anychange = true;
            row_elem &pivot_rowelem = mat->rows[pivotrow]; // pivot_rowelems.coeffs is set at this point
            syzygy_row_record_reduction(pivotrow,
                                          KK->lead_coeff(r.coeffs), KK->lead_coeff(pivot_rowelem.coeffs));
            KK->dense_row_cancel_sparse(gauss_row, pivot_rowelem.len, pivot_rowelem.coeffs, pivot_rowelem.comps);
            int last1 = pivot_rowelem.comps[pivot_rowelem.len-1];
            if (last1 > last) last = last1;
          }
        else if (firstnonzero == ncols)
          firstnonzero = first;
        first = KK->dense_row_next_nonzero(gauss_row, first+1, last);
      };
      if (anychange)
        {
          Mem->components.deallocate(r.comps);
          KK->deallocate_F4CCoefficientArray(r.coeffs, r.len); // the coeff array is owned by the row here
          r.len = 0;
          KK->dense_row_to_sparse_row(gauss_row, r.len, r.coeffs, r.comps, firstnonzero, last);
          if (using_syz) {
            row_elem& s = syz->rows[i];
            if (s.len>0) // the opposite should not happen
              {
                int* scoeffs = static_cast<int *>(s.coeffs);
                Mem->coefficients.deallocate(scoeffs);
                Mem->components.deallocate(s.comps);
                s.len = 0;
              }
            syz_dense_row_to_sparse_row(syz->rows[i]);
            // the above line leaves syz_row zero
          }
        }
      else
        {
          KK->dense_row_clear(gauss_row, firstnonzero, last);
          KK->dense_row_clear(gauss_row, 0, INTSIZE(syz->columns)-1); //!!!lazy
        }
      if (r.len > 0)
        {
          syzygy_row_divide(i, static_cast<int*>(r.coeffs)[0]);
          KK->sparse_row_make_monic(r.len, r.coeffs);
        }
    }

  KK->dense_row_deallocate(gauss_row);
  if (using_syz) KK->dense_row_deallocate(syz_row);
}
Beispiel #17
0
Datei: f4.cpp Projekt: pzinn/M2
void F4GB::gauss_reduce(bool diagonalize)
  // This reduces the matrix to a triangular form
{
  // For each row which is a non-pivot row:
  //  note that the row must be reducible, since the lead term corresponds to an spair cancellation
  //   actually: not true: generators will often not be reducible...
  //  also each such row must be non-zero, for the same reason
  int nrows = INTSIZE(mat->rows);
  int ncols = INTSIZE(mat->columns);

  int n_newpivots = -1; // the number of new GB elements in this degree
  int n_zero_reductions = 0;
  if (hilbert)
    {
      n_newpivots = hilbert->nRemainingExpected();
      if (n_newpivots == 0) return;
    }

  KK->dense_row_allocate(gauss_row, ncols);
  if (using_syz) KK->dense_row_allocate(syz_row, nrows);
  for (int i=0; i<nrows; i++)
    {
      row_elem &r = mat->rows[i];
      if (r.len == 0) continue; // could happen once we include syzygies...
      int pivotcol = r.comps[0];
      int pivotrow = mat->columns[pivotcol].head;
      if (pivotrow == i) continue; // this is a pivot row, so leave it alone

      F4CoefficientArray rcoeffs = get_coeffs_array(r);
      n_pairs_computed++;
      KK->dense_row_fill_from_sparse(gauss_row, r.len, rcoeffs, r.comps);
      syz_dense_row_fill_from_sparse(i); // fill syz_row from row[i]

      int firstnonzero = ncols;
      int first = r.comps[0];
      int last = r.comps[r.len-1];
      do {
        pivotrow = mat->columns[first].head;
        if (pivotrow >= 0)
          {
            row_elem &pivot_rowelem = mat->rows[pivotrow];
            F4CoefficientArray pivot_coeffs = get_coeffs_array(pivot_rowelem);
            syzygy_row_record_reduction(pivotrow,
                                          KK->lead_coeff(rcoeffs), KK->lead_coeff(pivot_coeffs));
            n_reduction_steps++;
            KK->dense_row_cancel_sparse(gauss_row, pivot_rowelem.len, pivot_coeffs, pivot_rowelem.comps);
            int last1 = pivot_rowelem.comps[pivot_rowelem.len-1];
            if (last1 > last) last = last1;
          }
        else if (firstnonzero == ncols)
          firstnonzero = first;
        first = KK->dense_row_next_nonzero(gauss_row, first+1, last);
      } while (first <= last);
      if (r.coeffs) KK->deallocate_F4CCoefficientArray(r.coeffs, r.len);
      Mem->components.deallocate(r.comps);
      r.len = 0;
      KK->dense_row_to_sparse_row(gauss_row, r.len, r.coeffs, r.comps, firstnonzero, last);
      // the above line leaves gauss_row zero, and also handles the case when r.len is 0
      // it also potentially frees the old r.coeffs and r.comps
      if (using_syz) {
        row_elem& s = syz->rows[i];
        if (s.len>0) // the opposite should not happen
          {
            int* scoeffs = static_cast<int *>(s.coeffs);
            Mem->coefficients.deallocate(scoeffs);
            Mem->components.deallocate(s.comps);
            s.len = 0;
          }
        syz_dense_row_to_sparse_row(syz->rows[i]);
        // the above line leaves syz_row zero
      }
      if (r.len > 0)
        {
          syzygy_row_divide(i, static_cast<int*>(r.coeffs)[0]);
          KK->sparse_row_make_monic(r.len, r.coeffs);
          mat->columns[r.comps[0]].head = i;
          if (--n_newpivots == 0) break;
        }
      else
        n_zero_reductions++;
    }
  KK->dense_row_deallocate(gauss_row);
  if (using_syz) KK->dense_row_deallocate(syz_row);

  if (M2_gbTrace >= 3)
    fprintf(stderr, "-- #zeroreductions %d\n", n_zero_reductions);

  if (diagonalize)
    tail_reduce();
}
Beispiel #18
0
Datei: f4.cpp Projekt: pzinn/M2
void F4GB::reorder_columns()
{
  // Set up to sort the columns.
  // Result is an array 0..ncols-1, giving the new order.
  // Find the inverse of this permutation: place values into "ord" column fields.
  // Loop through every element of the matrix, changing its comp array.

  int nrows = INTSIZE(mat->rows);
  int ncols = INTSIZE(mat->columns);

  // sort the columns

  int *column_order = Mem->components.allocate(ncols);
  int *ord = Mem->components.allocate(ncols);

  ColumnsSorter C(M, mat);

  // Actual sort of columns /////////////////

#if 0
  //TODO: MES remove the code in this ifdef 0
  C.reset_ncomparisons();

  clock_t begin_time = clock();
  for (int i=0; i<ncols; i++)
    {
      column_order[i] = i;
    }

  if (M2_gbTrace >= 2)
    fprintf(stderr, "ncomparisons = ");

  QuickSorter<ColumnsSorter>::sort(&C, column_order, ncols);

  clock_t end_time = clock();
  if (M2_gbTrace >= 2)
    fprintf(stderr, "%ld, ", C.ncomparisons());
  double nsecs = (double)(end_time - begin_time)/CLOCKS_PER_SEC;
  clock_sort_columns += nsecs;
  if (M2_gbTrace >= 2)
    fprintf(stderr, " time = %f\n", nsecs);
#endif
  // STL version ///////////////

  C.reset_ncomparisons();

  clock_t begin_time0 = clock();
  for (int i=0; i<ncols; i++)
    {
      column_order[i] = i;
    }

  if (M2_gbTrace >= 2)
    fprintf(stderr, "ncomparisons = ");

  std::stable_sort(column_order, column_order+ncols, C);

  clock_t end_time0 = clock();
  if (M2_gbTrace >= 2)
    fprintf(stderr, "%ld, ", C.ncomparisons0());
  double nsecs0 = (double)(end_time0 - begin_time0)/CLOCKS_PER_SEC;
  clock_sort_columns += nsecs0;
  if (M2_gbTrace >= 2)
    fprintf(stderr, " time = %f\n", nsecs0);

  ////////////////////////////

  for (int i=0; i<ncols; i++)
    {
      ord[column_order[i]] = i;
    }

  // Now move the columns into position
  coefficient_matrix::column_array newcols;
  newcols.reserve(ncols);
  for (int i=0; i<ncols; i++)
    {
      long newc = column_order[i];
      newcols.push_back(mat->columns[newc]);
    }

  // Now reset the components in each row
  for (int r=0; r<nrows; r++)
    {
      row_elem &row = mat->rows[r];
      for (int i=0; i<row.len; i++)
        {
          int oldcol = row.comps[i];
          int newcol = ord[oldcol];
          row.comps[i] = newcol;
        }
      for (int i=1; i<row.len; i++)
        {
          if (row.comps[i] <= row.comps[i-1])
            {
              fprintf(stderr, "Internal error: array out of order\n");
              break;
            }

        }
    }

  std::swap(mat->columns, newcols);
  Mem->components.deallocate(column_order);
  Mem->components.deallocate(ord);
}