//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
DAF::LightsOutSolver::Solve(const std::vector<bool>& kvectorStateMatrix, std::vector<bool>& vbOptimalSolutionMatrix)
{
    const std::size_t kuDimension = _uDimension * _uDimension;
    for (const std::vector<bool>& vbBasisVector : _vvbGameMatrixNullSpaceBasis )
    {
        if ( VectorVectorScalarProduct(kuDimension, vbBasisVector, kvectorStateMatrix) )
            return false;
    }
    
    const std::vector<bool> kvectorBasicSolutionMatrix = MatrixVectorProduct(kuDimension, _vbElementaryOperationMatrix, kvectorStateMatrix);
    
    const std::size_t kuNullSpaceBasisDimension = _vvbGameMatrixNullSpaceBasis.size();
    for (std::size_t uNullSpaceBasisIndex = 0; uNullSpaceBasisIndex < kuNullSpaceBasisDimension; ++uNullSpaceBasisIndex)
    {
        if ( VectorVectorScalarProduct(kuDimension, _vvbGameMatrixNullSpaceBasis[uNullSpaceBasisIndex], kvectorStateMatrix) )
            return false;
    }
    
    std::size_t kuOptimalSolutionMoveCount = kuDimension;
    std::vector<bool> vbGameMatrixNullSpaceBasisCombination(kuNullSpaceBasisDimension, false);
    for (;;)
    {
        std::vector<bool> vbCurrentSolutionMatrix = kvectorBasicSolutionMatrix;
        for (std::size_t uNullSpaceBasisIndex = 0; uNullSpaceBasisIndex < kuNullSpaceBasisDimension; ++uNullSpaceBasisIndex)
        {
            if ( vbGameMatrixNullSpaceBasisCombination[uNullSpaceBasisIndex] )
                vbCurrentSolutionMatrix = VectorVectorSum(kuDimension, vbCurrentSolutionMatrix, _vvbGameMatrixNullSpaceBasis[uNullSpaceBasisIndex]);
        }
        
        const std::size_t kuCurrentSolutionMoveCount = std::count(vbCurrentSolutionMatrix.begin(), vbCurrentSolutionMatrix.end(), true);
        if ( kuCurrentSolutionMoveCount < kuOptimalSolutionMoveCount )
        {
            vbOptimalSolutionMatrix = vbCurrentSolutionMatrix;
            kuOptimalSolutionMoveCount = kuCurrentSolutionMoveCount;
        }
        
        std::size_t uCombinationIndex = 0;
        for (; uCombinationIndex < kuNullSpaceBasisDimension; ++uCombinationIndex)
        {
            if ( ! vbGameMatrixNullSpaceBasisCombination[uCombinationIndex] )
            {
                vbGameMatrixNullSpaceBasisCombination[uCombinationIndex] = true;
                break;
            }
            
            vbGameMatrixNullSpaceBasisCombination[uCombinationIndex] = false;
        }
        
        if ( uCombinationIndex == kuNullSpaceBasisDimension )
            break;
    }
    
    return true;
}
예제 #2
0
void CSysMatrix::ComputeILUPreconditioner(const CSysVector & vec, CSysVector & prod, CGeometry *geometry, CConfig *config) {
  
  unsigned long index, index_;
  double *Block_ij, *Block_jk;
  long iPoint, jPoint, kPoint;
  unsigned short iVar;
  
  /*--- Copy block matrix, note that the original matrix
   is modified by the algorithm---*/
  
  for (iPoint = 0; iPoint < nPoint; iPoint++) {
    for (index = row_ptr[iPoint]; index < row_ptr[iPoint+1]; index++) {
      jPoint = col_ind[index];
      Block_ij = GetBlock(iPoint, jPoint);
      SetBlock_ILUMatrix(iPoint, jPoint, Block_ij);
    }
    for (iVar = 0; iVar < nVar; iVar++) {
      prod[iPoint*nVar+iVar] = vec[iPoint*nVar+iVar];
    }
  }
  
  /*--- Transform system in Upper Matrix ---*/
  
  for (iPoint = 1; iPoint < nPoint; iPoint++) {
    
    for (index = row_ptr[iPoint]; index < row_ptr[iPoint+1]; index++) {
      
      jPoint = col_ind[index];
      
      if (jPoint < iPoint) {
        
        Block_ij = GetBlock_ILUMatrix(iPoint, jPoint);
        InverseDiagonalBlock_ILUMatrix(jPoint, block_inverse);
        MatrixMatrixProduct(Block_ij, block_inverse, block_weight);
        
        for (index_ = row_ptr[jPoint]; index_ < row_ptr[jPoint+1]; index_++) {
          kPoint = col_ind[index_];
          Block_jk = GetBlock_ILUMatrix(jPoint, kPoint);
          if (kPoint >= jPoint) {
            MatrixMatrixProduct(Block_jk, block_weight, block);
            SubtractBlock_ILUMatrix(iPoint, kPoint, block);
          }
        }
        
        MatrixVectorProduct(block_weight, &prod[jPoint*nVar], aux_vector);
        
        for (iVar = 0; iVar < nVar; iVar++)
          prod[iPoint*nVar+iVar] -= aux_vector[iVar];
        
      }
      
    }
  }
  
  /*--- MPI Parallelization ---*/
  
  SendReceive_Solution(prod, geometry, config);
  
  /*--- Backwards substitution ---*/
  
  InverseDiagonalBlock_ILUMatrix((nPoint-1), block_inverse);
  MatrixVectorProduct(block_inverse, &prod[(nPoint-1)*nVar], aux_vector);
  
  for (iVar = 0; iVar < nVar; iVar++)
    prod[ (nPoint-1)*nVar + iVar] = aux_vector[iVar];
  
  for (iPoint = nPoint-2; iPoint >= 0; iPoint--) {
    
    for (iVar = 0; iVar < nVar; iVar++) sum_vector[iVar] = 0.0;
    
    for (index = row_ptr[iPoint]; index < row_ptr[iPoint+1]; index++) {
      
      jPoint = col_ind[index];
      
      
      Block_ij = GetBlock_ILUMatrix(iPoint, jPoint);
      
      if (jPoint >= iPoint+1) {
        
        MatrixVectorProduct(Block_ij, &prod[jPoint*nVar], aux_vector);
        
        for (iVar = 0; iVar < nVar; iVar++) sum_vector[iVar] += aux_vector[iVar];
        
      }
      
    }
    
    for (iVar = 0; iVar < nVar; iVar++) prod[iPoint*nVar+iVar] = (prod[iPoint*nVar+iVar]-sum_vector[iVar]);
    
    InverseDiagonalBlock_ILUMatrix(iPoint, block_inverse);
    MatrixVectorProduct(block_inverse, &prod[iPoint*nVar], aux_vector);
    
    for (iVar = 0; iVar < nVar; iVar++) prod[iPoint*nVar+iVar] = aux_vector[iVar];
    
    if (iPoint == 0) break;
    
  }
  
  /*--- MPI Parallelization ---*/
  
  SendReceive_Solution(prod, geometry, config);
  
}