Todo for branch res-2018, created 9 March 2018.

1. Allow FastNonminimal resolutions to assume we have the GB. DONE

2. Allow these to work with multi-gradings, as well as inhomogenoeus.
    PARTLY DONE: nonminimal resolution works.
    TODO: minimal multi-graded betti numbers

    How best to do this?

    plan:
      . have a unique set of degrees in the resolution: a MonomialCollection, or something like that.
      . change all betti displays to be multi-graded.
      . degree ptr --> heft degree function, is essential.
      .
      . replace mDegree with a "const int *" degree pointer.  Call it something good.
        requires changes in: show, getBounds (remove this?).
        need a way of collecting what needs to be done, ordering it.
        setBettiDisplays
        getBettiFrame
        insertBasic
          and calls to it from computeIdealQuotient (need to compute new degree, and uniquify it).
        resetMatrix
    functions which currently deal with degrees.  Note that construction of syzygies doesn't need to go down to multidegrees.
      OR: does it?? It might make the matrices constructed much smaller, and therefore easier to compute.
      minimalBettiNumbers
      inseetBasic
      insertLevelZero
      insertLevelOne
      getBounds
      computeSyzygies
      computeRanks: needs to change.  Needs a way to get all degrees at this (heft,level).
      fillInSyzygies: change slanted_degree to a UniquifiedDegree.
      computeRank: change slanted_degree to a UniquifiedDegree.

    smaller changes to do first:
      . change use of MemoryBlock to memtailor.
      . add in MemoryCollection: collection of degrees. 
    
    
    
3. stash the nonminimal res, in a different location. What functions actually use nonminimal resolutions. DONE

4. allow QQ as an actual coefficient ring.  Actually, allow any
  coefficient ring, as long as we are given a monic Groebner basis for
  it.
  
5. modules are not working correctly: there is a mismatch of monomial orders.  How best to fix this? DONE

6. nonminimal --> minimal resolution.  How best to do this?  e.g. use zig-zag idea of Frank?

7. fix NonminimalComplexes package.

8. schreyerName functionality, in the engine?

9. sparse rank computation?

10.    Sparse matrices:
   format: array of rows (or columns), each row:
    a. std::vector of column positions.
    b. a CoefficientVector
   operations:
    add: easy enough: addInPlace(pos1, coeffs1, pos2, coeff2): changes pos1, coeffs1. 
    sub: same
    transpose:
    nonzeroInRow, nonzeroInColumn
    submatrix
    iterators?

    lead_row
    get_entry
    set_entry
    interchange_rows
    interchange_columns

    mat-arith:
      is_zero: need to be able to check size of a column (can do directly from position vector)
      is_equal: need to check equality of two columns (check pos vectors first, then check equality of coeff vectors.
      scalarMultInPlace: scalar mult(a, coeff vector).  remember that some elements can become zero!
        how to handle that?
      negateInPlace
      addInPlace
      subtractInPlace
      transpose:
        this needs to be done directly by knowledge of ring.
        loop through all elements, append elements

    mat-elemops:
      lead_row
      interchange_rows: need to resort coeff vector according to pos vector?
      interchange_columns: easy
      scale_row: need to scale specific element of coeff array
      scale_column: scale all elems of coeff array
      divide: similar
      row_op: pain to write.
      column_op: basically sort 2 position lists, correspond coeff vectors. combine when positions match.
      2x2 ops: similar.
      dot_product
      row_permute
      column_permute: don't need to involve base ring.
      insert_rows: don't need to involve base ring.

   what operations are needed on coeff vectors:
     permute elements and position vector.
     mult r-th element by a scalar.
     mult entire vector by a scalar.
     add-merge: pos1,coeff1, pos2,coeff2. (pivot-add)
     remove a range of elements
     vector of indices, coeff vector --> new coeff vector. (permute, delete, setFromSubmatrix).
     set entry
     make monic
     transpose matrix.
     concatenate
    
    rank
    determinant
    inverse
    rowReducedEchelonForm
    mult
    nullSpace
    solveLinear
    solveInvertible
    rankProfile
    LU
    addMultipleTo (C += A*B)
    subtractMultipleTo (C -= A*B)

    mat-util: display, concatenate matrices.
    

    
Strategy 4 or 5 or 4.1
  Do NOT require that the module be graded.
  Place somewhere else:
    M.cache.RawNonminimalResComputation
  and then in the chain complex, place it somewhere?  I think not! Or, maybe, we do.
  
Strategy=>5:
  assume that the input is a cokernel module of a matrix whose columns form a GB.
    i.e. don't compute the GB.
  
  
to get working with arbitrary multi-gradings:
  res-f4-m2-interface.cpp:
    1. Determine what minimalBetti should do (well, in presence of DegreeLimit...)
    2. setDegreeZeroMap: needs to take a multi-degree
    3. rank: need to determine all the (multi)degrees one needs to do.
    4. to_M2_freemodule: need to keep somehow all of these modules.
     one easy way: the frame could keep the multi-degree.  This would help with all of these points.
  what about in the algorithm itself? It seems that other than placing the multi-degree in, nothing else is needed.
    creation of the frame?
    knowing what level,degree to do next?
    doing that one
  minimal_betti (res-f4-computation.cpp): calls minimalBettiNumbers    
What about inhomogeneous input?
  minimalBetti: no longer valid, should give an error.
  degreeZeroMap: gives an error?
  rank: same
  what else gives an error?
  
to_M2_MutableMatrix: the ring K needs to be checked!!!

maybe: another function for minimalBettiNumber, for a specific degree?
  It would reuse computation so it doesn't do extra work?
  what does "computeRank" do?  what is the 'status' bit...
    fillInSyzygies: need a function about what degrees are less than a given one:
      i.e. difference is the degree of a monomial in the ring.
      this might be computationally a pain, so another option: just do all up to heft-1 first.
      what is best here?
mComputationStatus: might need a hash table?
The frame should keep a hash table of the multi-degrees
  then mComputationStatus will have keys: (level,multi-degree).      
  

pseudo-code:

start_computation: (this is for determining the actual maps in a nonminimal res)
  computeFrame()
  computeSyzygies(sldeg,lev)

minimalBettiNumbers:
  computeFrame()
  for some(sldeg,lev) do computeRank(sldeg,lev) (this also changes betti display)

computeFrame():
  call computeNextLevel() for each level in turn
  set state of the computation
  
computeNextLevel():
  add in all ideal quotient elements at this level.
  set schreyer order for this level.
  
setSchreyerOrder(lev):
    schreyerOrder(lev-1) -- should alreday be set?
    schreyerOrder(lev).mTieBreaker -- this one is set by this routine
    schreyerOrder(lev).mTotalMonom -- is set earlier: in insertBasic.

computeSyzygies(sldeg,lev):

res-moninfo-dense:
  format [hashval, comp, w1, w2, ..., wr, e1, ..., en]
  notice: hash value does NOT involve the component.
  Change to allow weight vector(s)
  do we really need the hash values in the monomials?  Not sure...
  write several versions of compare_schreyer: one which includes revlex, and weight vectors.

-- res_comp (res-a1):

each level: vector of res_term's.  Way to sort them.
each (level,degree); need a way to go through all of these, and to sort them.
each element includes:
    monomial lookup table (for which monomials?)
    (level, degree)
    leadterm
    syzygy itself.
    indicator if this is a minimal syzygy element. (SYZ_MINIMAL, SYZ_NOT_MINIMAL, SYZ_NOT_NEEDED, SYZ_NOT_COMPUTED)
reduce syzygy:


Actually: assume we already have a sorted Schreyer frame.
  only thing: which is the better sort order: first by degrere, or by block?
  by degree makes sense, but then we need to know which monomials go with which element.
  There seems to be much in res_pair that is not needed?
    next?  not needed if we keep this as a vector?
    next_compare? used to compute Schreyer order compare #'s.
    mi2 -- not used!!
    next_mi -- not used!
    second?  do we really need this??  Probably not.
    me: do we need this ever? it is really an index in.