src/cmr/camion.c
/**
 * \brief Signs a given matrix.
 */
\brief Signs a given matrix.
\ brief Signs a given matrix .
static
CMR_ERROR sign(
  CMR* cmr,                     
  CMR_CHRMAT* matrix,           
  bool change,                  
  bool* pisCamionSigned,        
  CMR_SUBMAT** psubmatrix,      
  CMR_CAMION_STATISTICS* stats  
)
{
  assert(cmr);
  assert(matrix);
  assert(!psubmatrix || !*psubmatrix);
  size_t numComponents;
  CMR_ONESUM_COMPONENT* components = NULL;
  assert(CMRchrmatIsTernary(cmr, matrix, NULL));
#if defined(CMR_DEBUG)
  CMRdbgMsg(0, "sign:\n");
  CMRchrmatPrintDense(cmr, matrix, stdout, '0', true);
#endif 
  CMR_CALL( decomposeOneSum(cmr, (CMR_MATRIX*) matrix, sizeof(char), sizeof(char), &numComponents, &components, NULL, NULL,
    NULL, NULL) );
  if (pisCamionSigned)
    *pisCamionSigned = true;
  for (int comp = 0; comp < numComponents; ++comp)
  {
    CMR_SUBMAT* compSubmatrix = NULL;
    CMRdbgMsg(2, "-> Component %d of size %dx%d\n", comp, components[comp].matrix->numRows,
      components[comp].matrix->numColumns);
    char modified;
    CMR_CALL( CMRcomputeCamionSignSequentiallyConnected(cmr, (CMR_CHRMAT*) components[comp].matrix,
      (CMR_CHRMAT*) components[comp].transpose, change, &modified,
      (psubmatrix && !*psubmatrix) ? &compSubmatrix : NULL) );
    CMRdbgMsg(2, "-> Component %d yields: %c\n", comp, modified ? modified : '0');
    if (modified == 0)
    {
      assert(compSubmatrix == NULL);
      continue;
    }
    if (pisCamionSigned)
      *pisCamionSigned = false;
    if (compSubmatrix)
    {
      assert(psubmatrix && !*psubmatrix);
      for (size_t r = 0; r < compSubmatrix->numRows; ++r)
        compSubmatrix->rows[r] = components[comp].rowsToOriginal[compSubmatrix->rows[r]];
      for (size_t c = 0; c < compSubmatrix->numColumns; ++c)
        compSubmatrix->columns[c] = components[comp].columnsToOriginal[compSubmatrix->columns[c]];
      CMRsortSubmatrix(cmr, compSubmatrix);
      *psubmatrix = compSubmatrix;
    }
    if (!change)
    {
      CMRdbgMsg(2, "Aborting early because we don't change the matrix.\n");
      break;
    }
    assert(modified == 'm' || modified == 't');
    bool copyTranspose = modified == 't';
    CMR_CHRMAT* sourceMatrix = copyTranspose ?
      (CMR_CHRMAT*) components[comp].transpose :
      (CMR_CHRMAT*) components[comp].matrix;
    for (size_t sourceRow = 0; sourceRow < sourceMatrix->numRows; ++sourceRow)
    {
      size_t sourceFirst = sourceMatrix->rowSlice[sourceRow];
      size_t sourceBeyond = sourceMatrix->rowSlice[sourceRow + 1];
      for (size_t  sourceEntry = sourceFirst; sourceEntry < sourceBeyond; ++sourceEntry)
      {
        size_t sourceColumn = sourceMatrix->entryColumns[sourceEntry];
        size_t compRow = copyTranspose ? sourceColumn : sourceRow;
        size_t compColumn = copyTranspose ? sourceRow : sourceColumn;
        size_t row = components[comp].rowsToOriginal[compRow];
        size_t column = components[comp].columnsToOriginal[compColumn];
        CMRdbgMsg(4, "Searching entry for row %d and column %d.\n", row, column);
        size_t lower = matrix->rowSlice[row];
        size_t upper = matrix->rowSlice[row + 1];
        while (lower < upper)
        {
          size_t entry = (lower + upper) / 2;
          size_t searchColumn = matrix->entryColumns[entry];
          if (column < searchColumn)
            upper = entry;
          else if (column > searchColumn)
            lower = entry + 1;
          else
          {
            CMRdbgMsg(4, "Original matrix entry %d (%d) is replaced by source matrix entry %d (%d).\n", entry,
              matrix->entryValues[entry], sourceEntry, sourceMatrix->entryValues[sourceEntry]);
            matrix->entryValues[entry] = sourceMatrix->entryValues[sourceEntry];
            break;
          }
        }
        assert(lower < upper);
      }
    }
  }
#if defined(CMR_DEBUG)
  if (pisCamionSigned && !*pisCamionSigned && change)
  {
    CMRdbgMsg(0, "Modified original matrix:\n");
    CMRchrmatPrintDense(cmr, matrix, stdout, ' ', true);
  }
#endif 
  for (int c = 0; c < numComponents; ++c)
  {
    CMRchrmatFree(cmr, (CMR_CHRMAT**) &components[c].matrix);
    CMRchrmatFree(cmr, (CMR_CHRMAT**) &components[c].transpose);
    CMRfreeBlockArray(cmr, &components[c].rowsToOriginal);
    CMRfreeBlockArray(cmr, &components[c].columnsToOriginal);
  }
  CMRfreeBlockArray(cmr, &components);
  return CMR_OKAY;
}
static CMR_ERROR sign ( CMR * cmr , CMR_CHRMAT * matrix , bool change , bool * pisCamionSigned , CMR_SUBMAT * * psubmatrix , CMR_CAMION_STATISTICS * stats ) { assert ( cmr ) ; assert ( matrix ) ; assert ( ! psubmatrix || ! * psubmatrix ) ; size_t numComponents ; CMR_ONESUM_COMPONENT * components = NULL ; assert ( CMRchrmatIsTernary ( cmr , matrix , NULL ) ) ; #if defined ( CMR_DEBUG ) CMRdbgMsg ( 0 , " \n " ) ; CMRchrmatPrintDense ( cmr , matrix , stdout , ' ' , true ) ; #endif CMR_CALL ( decomposeOneSum ( cmr , ( CMR_MATRIX * ) matrix , sizeof ( char ) , sizeof ( char ) , & numComponents , & components , NULL , NULL , NULL , NULL ) ) ; if ( pisCamionSigned ) * pisCamionSigned = true ; for ( int comp = 0 ; comp < numComponents ; ++ comp ) { CMR_SUBMAT * compSubmatrix = NULL ; CMRdbgMsg ( 2 , " \n " , comp , components [ comp ] . matrix -> numRows , components [ comp ] . matrix -> numColumns ) ; char modified ; CMR_CALL ( CMRcomputeCamionSignSequentiallyConnected ( cmr , ( CMR_CHRMAT * ) components [ comp ] . matrix , ( CMR_CHRMAT * ) components [ comp ] . transpose , change , & modified , ( psubmatrix && ! * psubmatrix ) ? & compSubmatrix : NULL ) ) ; CMRdbgMsg ( 2 , " \n " , comp , modified ? modified : ' ' ) ; if ( modified == 0 ) { assert ( compSubmatrix == NULL ) ; continue ; } if ( pisCamionSigned ) * pisCamionSigned = false ; if ( compSubmatrix ) { assert ( psubmatrix && ! * psubmatrix ) ; for ( size_t r = 0 ; r < compSubmatrix -> numRows ; ++ r ) compSubmatrix -> rows [ r ] = components [ comp ] . rowsToOriginal [ compSubmatrix -> rows [ r ] ] ; for ( size_t c = 0 ; c < compSubmatrix -> numColumns ; ++ c ) compSubmatrix -> columns [ c ] = components [ comp ] . columnsToOriginal [ compSubmatrix -> columns [ c ] ] ; CMRsortSubmatrix ( cmr , compSubmatrix ) ; * psubmatrix = compSubmatrix ; } if ( ! change ) { CMRdbgMsg ( 2 , " \n " ) ; break ; } assert ( modified == ' ' || modified == ' ' ) ; bool copyTranspose = modified == ' ' ; CMR_CHRMAT * sourceMatrix = copyTranspose ? ( CMR_CHRMAT * ) components [ comp ] . transpose : ( CMR_CHRMAT * ) components [ comp ] . matrix ; for ( size_t sourceRow = 0 ; sourceRow < sourceMatrix -> numRows ; ++ sourceRow ) { size_t sourceFirst = sourceMatrix -> rowSlice [ sourceRow ] ; size_t sourceBeyond = sourceMatrix -> rowSlice [ sourceRow + 1 ] ; for ( size_t sourceEntry = sourceFirst ; sourceEntry < sourceBeyond ; ++ sourceEntry ) { size_t sourceColumn = sourceMatrix -> entryColumns [ sourceEntry ] ; size_t compRow = copyTranspose ? sourceColumn : sourceRow ; size_t compColumn = copyTranspose ? sourceRow : sourceColumn ; size_t row = components [ comp ] . rowsToOriginal [ compRow ] ; size_t column = components [ comp ] . columnsToOriginal [ compColumn ] ; CMRdbgMsg ( 4 , " \n " , row , column ) ; size_t lower = matrix -> rowSlice [ row ] ; size_t upper = matrix -> rowSlice [ row + 1 ] ; while ( lower < upper ) { size_t entry = ( lower + upper ) / 2 ; size_t searchColumn = matrix -> entryColumns [ entry ] ; if ( column < searchColumn ) upper = entry ; else if ( column > searchColumn ) lower = entry + 1 ; else { CMRdbgMsg ( 4 , " \n " , entry , matrix -> entryValues [ entry ] , sourceEntry , sourceMatrix -> entryValues [ sourceEntry ] ) ; matrix -> entryValues [ entry ] = sourceMatrix -> entryValues [ sourceEntry ] ; break ; } } assert ( lower < upper ) ; } } } #if defined ( CMR_DEBUG ) if ( pisCamionSigned && ! * pisCamionSigned && change ) { CMRdbgMsg ( 0 , " \n " ) ; CMRchrmatPrintDense ( cmr , matrix , stdout , ' ' , true ) ; } #endif for ( int c = 0 ; c < numComponents ; ++ c ) { CMRchrmatFree ( cmr , ( CMR_CHRMAT * * ) & components [ c ] . matrix ) ; CMRchrmatFree ( cmr , ( CMR_CHRMAT * * ) & components [ c ] . transpose ) ; CMRfreeBlockArray ( cmr , & components [ c ] . rowsToOriginal ) ; CMRfreeBlockArray ( cmr , & components [ c ] . columnsToOriginal ) ; } CMRfreeBlockArray ( cmr , & components ) ; return CMR_OKAY ; }
\brief Signs a given matrix.
\ brief Signs a given matrix .
/**< \ref CMR environment. */ /**< Matrix \f$ M \f$. */ /**< Whether the signs of \f$ M \f$ shall be modified. */ /**< Pointer for storing whether \f$ M \f$ was already [Camion-signed](\ref camion). */ /**< Pointer for storing a non-camion submatrix (may be \c NULL). */ /**< Statistics for the computation (may be \c NULL). */ /* CMR_DEBUG */ /* Decompose into 1-connected components. */ /* If we found a submatrix for the first time: */ /* Translate component indices to indices of whole matrix and sort them again. */ /* As we don't modify, we can abort early. */ /* Either the matrix or its transposed was modified. */ /* We have to copy the changes back to the original matrix. */ /* Perform binary search in row of original matrix to find the column. */ /* CMR_DEBUG */ /* Clean-up */