예제 #1
0
void F4Reducer::classicReducePolySet(
  const std::vector< std::unique_ptr<Poly> >& polys,
  const PolyBasis& basis,
  std::vector< std::unique_ptr<Poly> >& reducedOut
) {
  if (polys.size() <= 1) {
    if (tracingLevel >= 2)
      std::cerr << "F4Reducer: Using fall-back reducer for "
                << polys.size() << " polynomials.\n";
    mFallback->classicReducePolySet(polys, basis, reducedOut);
    return;
  }

  reducedOut.clear();

  MATHICGB_ASSERT(!polys.empty());
  if (tracingLevel >= 2)
    std::cerr << "F4Reducer: Reducing " << polys.size() << " polynomials.\n";

  SparseMatrix reduced;
  QuadMatrix::Monomials monomials;
  {
    QuadMatrix qm(ring());
    {
      if (mType == OldType) {
        F4MatrixBuilder builder(basis, mMemoryQuantum);
        for (const auto& poly : polys)
          builder.addPolynomialToMatrix(*poly);
        builder.buildMatrixAndClear(qm);
      } else {
        F4MatrixBuilder2 builder(basis, mMemoryQuantum);
        for (const auto& poly : polys)
          builder.addPolynomialToMatrix(*poly);
        builder.buildMatrixAndClear(qm);
      }
    }
    MATHICGB_LOG_INCREMENT_BY(F4MatrixRows, qm.rowCount());
    MATHICGB_LOG_INCREMENT_BY(F4MatrixTopRows, qm.topLeft.rowCount());
    MATHICGB_LOG_INCREMENT_BY(F4MatrixBottomRows, qm.bottomLeft.rowCount());
    MATHICGB_LOG_INCREMENT_BY(F4MatrixEntries, qm.entryCount());
    saveMatrix(qm);
    reduced = F4MatrixReducer(basis.ring().charac()).
      reducedRowEchelonFormBottomRight(qm);
    monomials = std::move(qm.rightColumnMonomials);
    for (auto& mono : qm.leftColumnMonomials)
      monoid().freeRaw(mono.castAwayConst());
  }

  if (tracingLevel >= 2 && false)
    std::cerr << "F4Reducer: Extracted " << reduced.rowCount()
              << " non-zero rows\n";

  for (SparseMatrix::RowIndex row = 0; row < reduced.rowCount(); ++row) {
    auto p = make_unique<Poly>(basis.ring());
    reduced.rowToPolynomial(row, monomials, *p);
    reducedOut.push_back(std::move(p));
  }
  for (auto& mono : monomials)
    monoid().freeRaw(mono.castAwayConst());
}
예제 #2
0
void SchreyerFrame::show(int len) const
{
  std::cout << "#levels=" << mFrame.mLevels.size() << " currentLevel=" << currentLevel() << std::endl;
  for (int i=0; i<mFrame.mLevels.size(); i++)
    {
      auto& myframe = level(i);
      auto& myorder = schreyerOrder(i);
      if (myframe.size() == 0) continue;
      std::cout << "--- level " << i << " ------" << std::endl;
      for (int j=0; j<myframe.size(); j++)
        {
          std::cout << "    " << j << " " << myframe[j].mDegree 
                    << " (" << myframe[j].mBegin << "," << myframe[j].mEnd << ") " << std::flush;
          std::cout << "(size:" << myframe[j].mSyzygy.len << ") [";
          monoid().showAlpha(myorder.mTotalMonom[j]);
          std::cout << "  " << myorder.mTieBreaker[j] << "] ";
          if (len == 0 or myframe[j].mSyzygy.len == 0)
            monoid().showAlpha(myframe[j].mMonom);
          else
            display_poly(stdout, ring(), myframe[j].mSyzygy);
          std::cout << std::endl;
        }
    }
  showMemoryUsage();
}
예제 #3
0
void SigPolyBasis::lowBaseDivisorsSlow(
  std::vector<size_t>& divisors,
  size_t maxDivisors,
  size_t newGenerator) const
{
  MATHICGB_ASSERT(newGenerator < size());

  divisors.clear();
  divisors.reserve(maxDivisors + 1);

  auto sigNew = signature(newGenerator);
  for (size_t i = 0; i < newGenerator; ++i) {
    auto sigi = signature(i);

    if (monoid().component(sigi) != monoid().component(sigNew))
      continue;
    if (!monoid().divides(sigi, sigNew))
      continue;
    for (size_t j = 0; j <= divisors.size(); ++j) {
      if (j == divisors.size()) {
        divisors.push_back(i);
        break;
      }
      if (ratioCompare(i, divisors[j]) == GT) {
        divisors.insert(divisors.begin() + j, i);
        break;
      }
    }
    if (divisors.size() > maxDivisors)
      divisors.pop_back();
    MATHICGB_ASSERT(divisors.size() <= maxDivisors);
  }
  MATHICGB_ASSERT(divisors.size() <= maxDivisors);
}
예제 #4
0
void SigPolyBasis::displayFancy
  (std::ostream& out, const Processor& processor) const
{
  mathic::ColumnPrinter pr;
  auto& indexOut = pr.addColumn(false) << "Index\n";
  auto& sigOut = pr.addColumn(false) << "sig\n";
  auto& polyOut = pr.addColumn() << "poly\n";
  pr.repeatToEndOfLine('-');

  auto sig = monoid().alloc();
  for (size_t i = 0; i < mBasis.size(); i++) {
    indexOut << i << '\n';

    monoid().copy(*mSignatures[i], *sig);
    processor.postprocess(sig);

    if (monoid().isIdentity(*sig))
      MathicIO<>().writeComponent(monoid(), *sig, out);
    else
      MathicIO<>().writeMonomial(monoid(), true, *sig, out);
    sigOut << '\n';

    MathicIO<>().writePoly(mBasis.poly(i), false, polyOut);
    polyOut << '\n';
  }
  out << pr;
}
예제 #5
0
파일: res-f4.cpp 프로젝트: DanGrayson/M2
// processMonomialProduct
//     m is a monomial, component is ignored (it determined the possible n's
//     being used here)
//     n is a monomial at level 'mThisLevel-1'
//     compute their product, and return the column index of this product
//       or -1, if the monomial is not needed.
//     additionally: the product monomial is inserted into the hash table
//     and column array (if it is not already there).
// caveats: this function is only to be used during construction
//     of the coeff matrices.  It uses mThisLevel.
//
// If the ring has skew commuting variables, then result_sign_if_skew is set to
// 0, 1, or -1.
ComponentIndex F4Res::processMonomialProduct(res_const_packed_monomial m,
                                             res_const_packed_monomial n,
                                             int& result_sign_if_skew)
{
  result_sign_if_skew = 1;
  auto x = monoid().get_component(n);
  auto& p = mFrame.level(mThisLevel - 2)[x];
  if (p.mBegin == p.mEnd) return -1;

  int* thisMonom = mMonomSpace2.allocate(1 + monoid().max_monomial_size());
  thisMonom++; // so thisMonom[-1] exists, but is not part of the monomial, as far as
  monoid().unchecked_mult(m, n, thisMonom);
  monoid().set_component(x, thisMonom);

  if (ring().isSkewCommutative())
    {
      result_sign_if_skew = monoid().skew_mult_sign(ring().skewInfo(), m, n);
      if (result_sign_if_skew == 0)
        {
          mMonomSpace2.popLastAlloc(thisMonom-1); // we did not need this monomial!
          return -1;
        }
    }
  return processCurrentMonomial(thisMonom);
}
예제 #6
0
 void postprocess(MonoRef mono) const {
   if (needToReverseComponents())
     reverseComponent(mono);
   if (hasSchreyerMultipliers()) {
     MATHICGB_ASSERT(monoid().divides(moduleAdjustment(mono), mono));
     monoid().divideInPlace(moduleAdjustment(mono), mono);
   }
 }
예제 #7
0
SchreyerFrame::PreElement* SchreyerFrame::createQuotientElement(res_packed_monomial m1, res_packed_monomial m)
{
  PreElement* vp = mPreElements.allocate();
  vp->vp = mVarpowers.reserve(mMaxVPSize);
  monoid().quotient_as_vp(m1, m, vp->vp);
  vp->degree = monoid().degree_of_vp(vp->vp);
  int len = static_cast<int>(res_varpower_monomials::length(vp->vp));
  mVarpowers.intern(len);
  return vp;
}
예제 #8
0
void SigPolyBasis::display(std::ostream& out) const {
  for (size_t i = 0; i < mBasis.size(); i++) {
    out << i << " ";
    // This is needed for compatibility with old tests.
    // todo: change the tests so this isn't necessary.
    if (monoid().isIdentity(*mSignatures[i]))
      MathicIO<>().writeComponent(monoid(), *mSignatures[i], out);
    else
      MathicIO<>().writeMonomial(monoid(), true, *mSignatures[i], out);
    out << "  ";
    MathicIO<>().writePoly(mBasis.poly(i), false, out);
    out << '\n';
  }
}
예제 #9
0
SigPolyBasis::~SigPolyBasis()
{
  MATHICGB_ASSERT(mBasis.size() == mSignatures.size());
  MATHICGB_ASSERT(mBasis.size() == mSigLeadRatio.size());

  for (size_t i = 0; i < mBasis.size(); i++) {
    if (!mSignatures[i].isNull())
      monoid().freeRaw(*mSignatures[i]);
    if (!mSigLeadRatio[i].isNull())
      monoid().freeRaw(*mSigLeadRatio[i]);
  }
  for (size_t i = 0; i < mSignatureLookup.size(); ++i)
    delete mSignatureLookup[i];
  mBasis.ring().freeMonomial(mTmp);
}
예제 #10
0
 ConstMonoRef moduleAdjustment(ConstMonoRef mono) const {
   MATHICGB_ASSERT(hasSchreyerMultipliers());
   const auto component = monoid().component(mono);
   MATHICGB_ASSERT(component < componentCount());
   MATHICGB_ASSERT(mSchreyerMultipliers.size() == componentCount());
   return *mSchreyerMultipliers[component];
 }
예제 #11
0
void SchreyerFrame::setSchreyerOrder(int lev)
{
  auto& myframe = level(lev);
  auto& myorder = schreyerOrder(lev);
  myorder.mTieBreaker.resize(myframe.size());
  if (lev == 0)
    {
      for (long i=0; i<myorder.mTieBreaker.size(); i++)
        myorder.mTieBreaker[i] = i;
      return;
    }

  auto& prevframe = level(lev-1);
  auto& prevorder = schreyerOrder(lev-1);
  long* tiebreakers = new long[myframe.size()];
  
  for (long i=0; i<myframe.size(); i++)
    {
      long comp = monoid().get_component(myframe[i].mMonom);
      tiebreakers[i] = i + myframe.size() * prevorder.mTieBreaker[comp];
    }
  std::stable_sort(tiebreakers, tiebreakers + myframe.size());

  
  for (long i=0; i<myframe.size(); i++)
    {
      myorder.mTieBreaker[tiebreakers[i] % myframe.size()] = i;
    }
  delete [] tiebreakers;
}
예제 #12
0
size_t SigPolyBasis::ratioRank(ConstMonoRef ratio) const {
  MATHICGB_ASSERT(mUseRatioRank);
  const size_t index = size();
  if (index == 0)
    return 0; // any value will do as there is nothing to compare to
  auto& sigLeadRatioNonConst =
    const_cast<std::vector<MonoPtr>&>(mSigLeadRatio);

  sigLeadRatioNonConst.push_back(ratio.castAwayConst());
  auto pos = mRatioSorted.lower_bound(index);
  sigLeadRatioNonConst.pop_back();

  if (pos == mRatioSorted.end()) {
    MATHICGB_ASSERT
      (ratioRank(*mRatioSorted.rbegin()) < std::numeric_limits<Rank>::max());
    return std::numeric_limits<Rank>::max();
  } else {
    if (monoid().equal(ratio, sigLeadRatio(*pos)))
      return ratioRank(*pos);
    MATHICGB_ASSERT(ratioRank(*pos) > 0);
#ifdef MATHICGB_DEBUG
    if (pos != mRatioSorted.begin()) {
      auto prev = pos;
      --prev;
      MATHICGB_ASSERT(ratioRank(*pos) - 1 > ratioRank(*prev));
    }
#endif
    return ratioRank(*pos) - 1;
  }
}
예제 #13
0
RegExp::RegExp(char* expression) {
	this->operations.reserve(64);
	this->transducers.reserve(64);
	this->expression = expression;
	
	for (ui i = 0; i < strlen(expression); i++) {
		switch(expression[i]) {
			case '<': {
					char* input = read_word(i);
					char* output = read_word(++i);
					i+=2;
					ui weight = read_number(i);
					Monoid monoid(input, output, weight);
					this->transducers.push_back(new Transducer(monoid));
				}
				break;
			case '|':
				this->operations.push_back(UNION);
				break;
			case '*':
				this->operations.push_back(STAR);
				break;
			case '.':
				this->operations.push_back(CONCAT);
				break;
		}
	}
}
예제 #14
0
파일: res-f4.cpp 프로젝트: DanGrayson/M2
// new_m is a monomial that we have just created.  There are several
// things that can happen:
//  (1) new_m is already in the hash table (as is).
//       i.e. we have already processed this monomial.
//       in this case new_m[-1] is the index of the divisor for this monomial
//       (possibly -1).
//  (2) new_m is a newly seen monomial in this degree.
//       insert it into the hash table as a seen monomial
//       we set the divisor for new_m: either -1 or some index
//       If there is no divisor, return -1.
//       If there is: create a row, and push onto the mReducers list.
//    (2A)
ComponentIndex F4Res::processCurrentMonomial(res_packed_monomial thisMonom)
{
  res_packed_monomial new_m;  // a pointer to a monomial we are visiting
  if (mHashTable.find_or_insert(thisMonom, new_m))
    {
      // we did not need the monomial. So pop it.
      mMonomSpace2.popLastAlloc(thisMonom-1);
      return static_cast<ComponentIndex>(
                                         new_m[-1]);  // monom exists, don't save monomial space
    }

  // At this point thisMonom has been inserted.  We keep it.

  thisMonom = mMonomSpace2.allocate(1 + monoid().max_monomial_size());
  thisMonom++; // so thisMonom[-1] exists, but is not part of the monomial, as far as
  
  bool has_divisor = findDivisor(new_m, thisMonom);
  if (!has_divisor)
    {
      mMonomSpace2.popLastAlloc(thisMonom-1);
      new_m[-1] = -1;  // no divisor exists
      return -1;
    }

  ComponentIndex thiscol = static_cast<ComponentIndex>(mColumns.size());
  new_m[-1] = thiscol;  // this is a HACK: where we keep the divisor
  mColumns.push_back(new_m);

  Row row;
  row.mLeadTerm = thisMonom;
  mReducers.push_back(row);

  return thiscol;
}
예제 #15
0
파일: res-f4.cpp 프로젝트: gblanco92/M2
void F4Res::debugOutputReducers()
{
  auto end = mReducers.cend();
  for (auto i=mReducers.cbegin(); i != end; ++i)
    {
      monoid().showAlpha((*i).mLeadTerm);
      std::cout << std::endl;
    }
}
예제 #16
0
void ResPolyRing::memUsage(const poly& f, long& nterms, long& bytes_used, long& bytes_alloc) const
{
  long sz = 0;
  sz = f.len * sizeof(FieldElement);
  sz += f.len * monoid().max_monomial_size() * sizeof(monomial_word);
  nterms += f.len;
  bytes_used += sz;
  bytes_alloc += sz;
}
예제 #17
0
파일: res-f4.cpp 프로젝트: gblanco92/M2
void F4Res::debugOutputColumns()
{
  auto end = mColumns.cend();
  for (auto i=mColumns.cbegin(); i != end; ++i)
    {
      monoid().showAlpha((*i));
      std::cout << std::endl;
    }
}
예제 #18
0
MonomialCounter::MonomialCounter(const ResMonoid& M)
  : mIgnoreMonomials(new ResMonomialsIgnoringComponent(M)),
    mAllMonomials(mIgnoreMonomials),
    mNumAllMonomials(0),
    mNextMonom(nullptr),
    mMonoid(M)
{
  // start out mNextMonom
  mNextMonom = mMonomSpace.reserve(monoid().max_monomial_size());
}
예제 #19
0
size_t SigPolyBasis::regularReducerSlow(
  ConstMonoRef sig,
  ConstMonoRef term
) const {
  monomial m = ring().allocMonomial();
  const size_t stop = size();
  for (size_t be = 0; be < stop; ++be) {
    if (!monoid().divides(leadMono(be), term))
      continue;
    monoid().divide(leadMono(be), term, m);
    monoid().multiplyInPlace(signature(be), m);
    if (monoid().lessThan(m, sig)) {
      ring().freeMonomial(m);
      return be;
    }
  }
  ring().freeMonomial(m);
  return static_cast<size_t>(-1);
}
예제 #20
0
파일: res-f4.cpp 프로젝트: gblanco92/M2
void F4Res::resetMatrix(int lev, int degree)
{
  mThisLevel = lev;
  mThisDegree = degree;
  mNextReducerToProcess = 0;

  // mNextMonom[-1] is the reducer corresponding to this monomial
  mNextMonom = mMonomSpace.reserve(1+monoid().max_monomial_size());
  mNextMonom++;
}
예제 #21
0
파일: res-f4.cpp 프로젝트: BertiniM2/M2
void F4Res::loadRow(Row& r)
{
  //  std::cout << "loadRow: " << std::endl;

  r.mCoeffs = resGausser().allocateCoefficientVector();

  //  monoid().showAlpha(r.mLeadTerm);
  //  std::cout << std::endl;
  int skew_sign;  // will be set to 1, unless ring().isSkewCommutative() is
                  // true, then it can be -1,0,1.
  // however, if it is 0, then "val" below will also be -1.
  long comp = monoid().get_component(r.mLeadTerm);
  auto& thiselement = mFrame.level(mThisLevel - 1)[comp];
  // std::cout << "  comp=" << comp << " mDegree=" << thiselement.mDegree << "
  // mThisDegree=" << mThisDegree << std::endl;
  if (thiselement.mDegree == mThisDegree)
    {
      // We only need to add in the current monomial
      // fprintf(stdout, "USING degree 0 monomial\n");
      ComponentIndex val =
          processMonomialProduct(r.mLeadTerm, thiselement.mMonom, skew_sign);
      if (val < 0) fprintf(stderr, "ERROR: expected monomial to live\n");
      r.mComponents.push_back(val);
      if (skew_sign > 0)
        mRing.resGausser().pushBackOne(r.mCoeffs);
      else
        {
          // Only happens if we are in a skew commuting ring.
          ring().resGausser().pushBackMinusOne(r.mCoeffs);
        }
      return;
    }
  auto& p = thiselement.mSyzygy;
  auto end = poly_iter(mRing, p, 1);
  auto i = poly_iter(mRing, p);
  for (; i != end; ++i)
    {
      ComponentIndex val =
          processMonomialProduct(r.mLeadTerm, i.monomial(), skew_sign);
      // std::cout << "  monom: " << val << " skewsign=" << skew_sign << "
      // mColumns.size=" << mColumns.size() << std::endl;
      if (val < 0) continue;
      r.mComponents.push_back(val);
      if (skew_sign > 0)
        mRing.resGausser().pushBackElement(
            r.mCoeffs, p.coeffs, i.coefficient_index());
      else
        {
          // Only happens if we are in a skew commuting ring.
          mRing.resGausser().pushBackNegatedElement(
              r.mCoeffs, p.coeffs, i.coefficient_index());
        }
    }
}
예제 #22
0
bool SigPolyBasis::isSingularTopReducibleSlow(
  const Poly& poly,
  ConstMonoRef sig
) const {
  if (poly.isZero())
    return false;

  monomial multiplier = ring().allocMonomial();
  const size_t genCount = size();
  const auto polyLead = poly.leadMono();
  for (size_t i = 0; i < genCount; ++i) {
    if (!monoid().divides(leadMono(i), polyLead))
      continue;
    monoid().divide(leadMono(i), polyLead, multiplier);
    if (monoid().compare(sig, multiplier, signature(i)) == EQ)
      return true;
  }
  ring().freeMonomial(multiplier);
  return false;
}
예제 #23
0
파일: res-f4.cpp 프로젝트: gblanco92/M2
// processMonomialProduct
//     m is a monomial, component is ignored (it determined the possible n's being used here)
//     n is a monomial at level 'mThisLevel-1'
//     compute their product, and return the column index of this product
//       or -1, if the monomial is not needed.
//     additionally: the product monomial is inserted into the hash table
//     and column array (if it is not already there).
// caveats: this function is only to be used during construction 
//     of the coeff matrices.  It uses mThisLevel.
//
// If the ring has skew commuting variables, then result_sign_if_skew is set to 0, 1, or -1.
ComponentIndex F4Res::processMonomialProduct(packed_monomial m, packed_monomial n, int& result_sign_if_skew)
{
  result_sign_if_skew = 1;
  auto x = monoid().get_component(n);
  auto& p = mFrame.level(mThisLevel-2)[x];
  if (p.mBegin == p.mEnd) return -1;

  monoid().unchecked_mult(m,n,mNextMonom);
  // the component is wrong, after this operation, as it adds components
  // So fix that:
  monoid().set_component(x, mNextMonom);

  if (ring().isSkewCommutative())
    {
      result_sign_if_skew = monoid().skew_mult_sign(ring().skewInfo(), m, n);
      if (result_sign_if_skew == 0)
        return -1;
    }
  return processCurrentMonomial();
}
예제 #24
0
파일: res-f4.cpp 프로젝트: gblanco92/M2
/// findDivisor
//    m: monomial at level mThisLevel-1
//    result: monomial at level mThisLevel, IF true is returned
//  returns true if 'm' == inG(result), for some (unique) 'result'.
bool F4Res::findDivisor(packed_monomial m, packed_monomial result)
{
  // get component of m
  // find the range of monomials to check
  // for each of these, check divisibility in turn
  //   if one works, then return true, and set result.
  long comp = monoid().get_component(m); // component is an index into level mLevel-2
  auto& elem = mFrame.level(mThisLevel-2)[comp];
  auto& lev = mFrame.level(mThisLevel-1);
  for (auto j=elem.mBegin; j<elem.mEnd; ++j)
    {
      // Check divisibility of m by this element
      packed_monomial pj = lev[j].mMonom;
      if (monoid().divide(m, pj, result)) // this sets the component to be 0
        {
          monoid().set_component(j, result); // this sets component correctly
          return true;
        }
    }
  return false;
}
예제 #25
0
void SchreyerFrame::insertBasic(int lev, res_packed_monomial monom, int degree)
{
  // if lev >= 2, then level(lev-1)[comp].(mBegin,mEnd) is set separately.
  auto& myframe = level(lev);
  long idx = myframe.size();
  myframe.emplace_back(FrameElement(monom,degree));
  auto& myelem = myframe[idx];

  // The rest of this code simply sets the total monomial for the Schreyer order
  // and should be moved out of here. (MES 3 Feb 2016)
  auto& myorder = schreyerOrder(lev);
  auto myTotalMonom = monomialBlock().allocate(monoid().max_monomial_size());
  if (lev > 0)
    {
      auto& prevlevel = level(lev-1);
      auto& prevorder = schreyerOrder(lev-1);
      long comp = monoid().get_component(myelem.mMonom);
      monoid().unchecked_mult(myelem.mMonom, prevorder.mTotalMonom[comp], myTotalMonom);
      monoid().set_component(monoid().get_component(prevorder.mTotalMonom[comp]), myTotalMonom);
    }
  else
    {
      monoid().copy(myelem.mMonom, myTotalMonom);
    }
  myorder.mTotalMonom.push_back(myTotalMonom);
}
예제 #26
0
 /// Replaces basis element at index with the given new polynomial. The lead
 /// term of the new polynomial must be the same as the previous one.
 /// This is useful for auto-tail-reduction.
 void replaceSameLeadTerm(size_t index, std::unique_ptr<Poly> newValue) {
   MATHICGB_ASSERT(index < size());
   MATHICGB_ASSERT(!retired(index));
   MATHICGB_ASSERT(newValue.get() != nullptr);
   MATHICGB_ASSERT(!newValue->isZero());
   MATHICGB_ASSERT
     (monoid().equal(leadMono(index), newValue->leadMono()));
   mMonoLookup->remove(leadMono(index));
   delete mEntries[index].poly;
   mEntries[index].poly = newValue.release();
   mMonoLookup->insert(leadMono(index), index);    
   MATHICGB_ASSERT(mEntries[index].poly != nullptr);
 }
예제 #27
0
void MonomialCounter::accountForMonomial(res_const_packed_monomial mon)
{
  // First copy monomial
  // Then call find_or_insert
  // If not there, increment number of monomials
  // If there: intern monomial

  monoid().copy(mon, mNextMonom);
  res_packed_monomial not_used;
  if (mAllMonomials.find_or_insert(mNextMonom, not_used))
    {
      // true, means that it was already there
      // nothing needs to be done
    }
  else
    {
      // false: new monomial
      mNumAllMonomials++;
      mMonomSpace.intern(monoid().monomial_size(mNextMonom));
      mNextMonom = mMonomSpace.reserve(monoid().max_monomial_size());      
    }
}
예제 #28
0
void SchreyerFrame::insertLevelZero(res_packed_monomial monom, int degree, int maxdeglevel0)
{
  //  return insertBasic(0, monom, degree);

  auto& myframe = level(0);
  long idx = myframe.size();
  myframe.emplace_back(FrameElement(monom,degree));
  auto& myelem = myframe[idx];

  auto& myorder = schreyerOrder(0);
  auto myTotalMonom = monomialBlock().allocate(monoid().max_monomial_size());
  // Create the total monomial.  It is monom * (firstvar)^(maxdeglevel0-degree)
#if 0
  long comp;
  ntuple_monomial exp = new int[monoid().n_vars()];
  to_exponent_vector(monom, exp, comp);
  exp[0] += (maxdeglevel0 - XXXX);
  from_exponent_vector(exp, comp, monom); // XXXX not correct, I think.
#endif
  monoid().copy(myelem.mMonom, myTotalMonom);
  myorder.mTotalMonom.push_back(myTotalMonom);
}
예제 #29
0
파일: res-f4.cpp 프로젝트: BertiniM2/M2
// new_m is a monomial that we have just created.  There are several
// things that can happen:
//  (1) new_m is already in the hash table (as is).
//       i.e. we have already processed this monomial.
//       in this case new_m[-1] is the index of the divisor for this monomial
//       (possibly -1).
//  (2) new_m is a newly seen monomial in this degree.
//       insert it into the hash table as a seen monomial
//       we set the divisor for new_m: either -1 or some index
//       If there is no divisor, return -1.
//       If there is: create a row, and push onto the mReducers list.
//    (2A)
ComponentIndex F4Res::processCurrentMonomial()
{
  res_packed_monomial new_m;  // a pointer to a monomial we are visiting
  if (mHashTable.find_or_insert(mNextMonom, new_m))
    return static_cast<ComponentIndex>(
        new_m[-1]);  // monom exists, don't save monomial space

  // intern the monomial just inserted into the hash table
  mMonomSpace.intern(1 + monoid().monomial_size(mNextMonom));

  // leave room for the next monomial.  This might be set below.
  mNextMonom = mMonomSpace.reserve(1 + monoid().max_monomial_size());
  mNextMonom++;

  bool has_divisor = findDivisor(new_m, mNextMonom);
  if (!has_divisor)
    {
      new_m[-1] = -1;  // no divisor exists
      return -1;
    }

  mMonomSpace.intern(1 + monoid().monomial_size(mNextMonom));

  ComponentIndex thiscol = static_cast<ComponentIndex>(mColumns.size());
  new_m[-1] = thiscol;  // this is a HACK: where we keep the divisor
  mColumns.push_back(new_m);

  Row row;
  row.mLeadTerm = mNextMonom;
  mReducers.push_back(row);

  // Now we increment mNextMonom, for the next time
  mNextMonom = mMonomSpace.reserve(1 + monoid().max_monomial_size());
  mNextMonom++;

  return thiscol;
}
예제 #30
0
long SchreyerFrame::computeIdealQuotient(int lev, long begin, long elem)
{
  ///  std::cout << "computeIdealQuotient(" << lev << "," << begin << "," << elem << ")" << std::endl;
  // Returns the number of elements added
  res_packed_monomial m = monomial(lev, elem); 
  std::vector<PreElement*> elements;
  if (ring().isSkewCommutative())
    {
      auto skewvars = new int[ring().monoid().n_vars()];
      int a = ring().monoid().skew_vars(ring().skewInfo(), m, skewvars);
      // std::cout << "adding " << a << " syz from skew" << std::endl;
      for (int i=0; i<a; ++i)
        {
          PreElement* vp = mPreElements.allocate();
          vp->vp = mVarpowers.reserve(mMaxVPSize);
          monoid().variable_as_vp(skewvars[i], vp->vp); 
          vp->degree = monoid().degree_of_vp(vp->vp);         
          int len = static_cast<int>(res_varpower_monomials::length(vp->vp));
          mVarpowers.intern(len);

          elements.push_back(vp);
        }
      delete [] skewvars;
    }
  for (long i=begin; i<elem; i++)
    elements.push_back(createQuotientElement(monomial(lev,i), m));
  typedef ResF4MonomialLookupTableT<int32_t> MonomialLookupTable;
  MonomialLookupTable montab(monoid().n_vars());

#if 0
  std::cout << "  #pre elements = " << elements.size() << std::endl;
  for (auto i=elements.begin(); i != elements.end(); ++i)
    {
      varpower_monomials::elem_text_out(stdout, (*i)->vp);
      fprintf(stdout, "\n");
    }
#endif
  PreElementSorter C;
  std::stable_sort(elements.begin(), elements.end(), C);

  long n_elems = 0;
  for (auto i = elements.begin(); i != elements.end(); ++i)
    {
      int32_t not_used;
      bool inideal = montab.find_one_divisor_vp(0, (*i)->vp, not_used);
      if (inideal) continue;
      // Now we create a res_packed_monomial, and insert it into 'lev+1'
      montab.insert_minimal_vp(0, (*i)->vp, 0);
      res_packed_monomial monom = monomialBlock().allocate(monoid().max_monomial_size());
      monoid().from_varpower_monomial((*i)->vp, elem, monom);
      // Now insert it into the frame
      insertBasic(currentLevel(), monom, (*i)->degree + degree(currentLevel()-1, monoid().get_component(monom)));
      n_elems++;
    }
  //std::cout << "  returns " << n_elems << std::endl;
  return n_elems;
}