Playlist::FavoredRandomTrackNavigator::planOne()
{
    DEBUG_BLOCK

    if ( m_plannedItems.isEmpty() && !allItemsList().isEmpty() )
    {
        int avoidRecentlyPlayedSize = AVOID_RECENTLY_PLAYED_MAX;    // Start with being very picky.

        // Don't over-constrain ourself:
        //   - Keep enough headroom to be unpredictable.
        //   - Make sure that 'chooseRandomItem()' doesn't need to find a needle in a haystack.
        avoidRecentlyPlayedSize = qMin( avoidRecentlyPlayedSize, allItemsList().size() / 2 );

        QSet<quint64> avoidSet = getRecentHistory( avoidRecentlyPlayedSize );

        QList<qreal> weights = rowWeights( avoidSet );

        // Choose a weighed random row.
        if( !weights.isEmpty() )
        {
            qreal totalWeight = 0.0;
            foreach ( qreal weight, weights )
                totalWeight += weight;

            qreal randomCumulWeight = ( KRandom::random() / qreal( RAND_MAX ) ) * totalWeight;

            int row = 0;
            qreal rowCumulWeight = weights[ row ];
            while ( randomCumulWeight > rowCumulWeight + 0.0000000001 )
                rowCumulWeight += weights[ ++row ];
Beispiel #2
0
void Utilities::loadFVFile(FVParser &parser,
        Dataset *result) {
    check(NULL != result, "Utilities::loadFVFile() result is null");

    list<FVParserToken> current_vector;
    double totalWeight = 0.0;
    vector<double> rowWeights(result->numRows());

    int largestDimensionSeen = 0;

    while (parser.nextLine(&current_vector)) {
        unsigned int point = parser.currentLineNumber() - 1;
        if (point >= result->numRows()) {
            check(false, "Utilities::loadFVFile() more vectors than expected "
                    "(loading vector " + toString((int)(point + 1)) + " when expecting " 
                    + toString((int)(result->numRows())) + ")");
        }

        // normalize the vector
        double sumVector = 0.0;
        list<FVParserToken>::iterator i;
        for (i = current_vector.begin(); i != current_vector.end(); i++) {
            sumVector += i->value;
            if (i->dimension > largestDimensionSeen) { largestDimensionSeen = i->dimension; }
        }

        rowWeights[point] = sumVector;
        totalWeight += sumVector;

        for (i = current_vector.begin(); i != current_vector.end(); i++) {
            if (i->dimension > (int)result->numCols() || i->dimension < 1) {
                check(i->dimension <= (int)result->numCols(),
                    "Utilities::loadFVFile() expecting only " +
                    toString((int)result->numCols()) +
                    " dimensions, but found dimension " +
                    toString((int)i->dimension));
                check(i->dimension >= 1,
                    "Utilities::loadFVFile() dimension < 1");
            }
            // put the value in the destination dataset (switching to 0-offset
            // and normalizing by the total vector sum)
            (*result)[point][i->dimension - 1] = i->value / sumVector;
        }
    }
    check(parser.currentLineNumber() == (int)result->numRows(),
            "Utilities::loadFVFile() the number of vectors loaded "
            "disagrees with the number specified (expected " +
            toString((int)result->numRows()) + " but loaded " +
            toString(parser.currentLineNumber()) + ")");

    check(largestDimensionSeen == (int)result->numCols(),
            "Utilities::loadFVFile() the number of dimensions loaded "
            "disagrees with the number specified (expected " +
            toString((int)result->numCols()) + " but loaded " +
            toString((int)largestDimensionSeen) + ")");

    // normalize the weights and put them in the dataset
    for (unsigned int row = 0; row < result->numRows(); row++) {
        result->setWeight(row, rowWeights[row] / totalWeight);
    }
}
Beispiel #3
0
void Utilities::loadAndProjectFVFile(FVParser &parser, 
                                     const Dataset &projection, 
                                     Dataset *result) {
    check(NULL != result, "Utilities::loadAndProjectFVFile() result is null");
    check(projection.numCols() == (*result).numCols(),
            "Utilities::loadAndProjectFVFile() dimensions are wrong");

    result->fill(0.0);

    list<FVParserToken> current_vector;
    double totalWeight = 0.0;
    vector<double> rowWeights(result->numRows());
    int numProjectedColumns = projection.numCols();
    int numProjectedRows = projection.numRows();
    int largestDimensionSeen = 0;

    while (parser.nextLine(&current_vector)) {
        int point = parser.currentLineNumber() - 1;
        if (point >= (int)result->numRows()) {
            check(false, "Utilities::loadAndProjectFVFile() more vectors than expected "
                    "(loading vector " + toString(point + 1) + " when expecting " 
                    + toString((int)result->numRows()) + ")");
        }

        // normalize the vector
        double sumVector = 0.0;
        list<FVParserToken>::iterator i;
        for (i = current_vector.begin(); i != current_vector.end(); i++) {
            sumVector += i->value;
        }

        rowWeights[point] = sumVector;
        totalWeight += sumVector;

        // multiply the row we just pulled from the parser by *each column*
        // of the projection matrix to obtain the row in the result.

        // fill the resulting vector with zeros
        (*result)[point].fill(0.0);

        // over all original dimensions (columns of the original vector, rows of
        // the projection matrix)
        for (i = current_vector.begin(); i != current_vector.end(); i++) { 
            int dim = i->dimension;
            double val = i->value / sumVector;
            if (dim > largestDimensionSeen) { largestDimensionSeen = dim; }
            if (dim < 1 || dim > numProjectedRows) {
                check(dim >= 1, "Utilities::loadAndProjectFVFile() dimension < 1");
                check(dim <= numProjectedRows,
                    "Utilities::loadAndProjectFVFile() expecting only " +
                    toString((int)numProjectedRows) +
                    " dimensions, but found dimension " +
                    toString((int)dim));
            }

            // project the row
            for (int projCol = 0; projCol < numProjectedColumns; projCol++) {
                // note that dimension is changed to be offset 0
                (*result)[point][projCol] += val * projection[dim - 1][projCol];
            }
        }
    }
    check(parser.currentLineNumber() == (int)result->numRows(),
            "Utilities::loadAndProjectFVFile() the number of vectors loaded "
            "disagrees with the number specified (expected " +
            toString((int)result->numRows()) + " but loaded " +
            toString((int)parser.currentLineNumber()) + ")");

    check(largestDimensionSeen == (int)numProjectedRows,
            "Utilities::loadAndProjectFVFile() the number of dimensions loaded "
            "disagrees with the number specified (expected " +
            toString((int)numProjectedRows) + " but loaded " +
            toString((int)largestDimensionSeen) + ")");

    // normalize the weights and put them in the dataset
    for (unsigned int row = 0; row < result->numRows(); row++) {
        result->setWeight(row, rowWeights[row] / totalWeight);
    }
}
AmesosBTFGlobal_LinearProblem::NewTypeRef
AmesosBTFGlobal_LinearProblem::
operator()( OriginalTypeRef orig )
{
  origObj_ = &orig;

  // Extract the matrix and vectors from the linear problem
  OldRHS_ = Teuchos::rcp( orig.GetRHS(), false );
  OldLHS_ = Teuchos::rcp( orig.GetLHS(), false );
  OldMatrix_ = Teuchos::rcp( dynamic_cast<Epetra_CrsMatrix *>( orig.GetMatrix() ), false );
	
  int nGlobal = OldMatrix_->NumGlobalRows(); 
  int n = OldMatrix_->NumMyRows();

  // Check if the matrix is on one processor.
  int myMatProc = -1, matProc = -1;
  int myPID = OldMatrix_->Comm().MyPID();
  int numProcs = OldMatrix_->Comm().NumProc();

  const Epetra_BlockMap& oldRowMap = OldMatrix_->RowMap();

  // Get some information about the parallel distribution.
  int maxMyRows = 0;
  std::vector<int> numGlobalElem( numProcs );
  OldMatrix_->Comm().GatherAll(&n, &numGlobalElem[0], 1);
  OldMatrix_->Comm().MaxAll(&n, &maxMyRows, 1);

  for (int proc=0; proc<numProcs; proc++) 
  {
    if (OldMatrix_->NumGlobalNonzeros() == OldMatrix_->NumMyNonzeros())
      myMatProc = myPID;
  }

  OldMatrix_->Comm().MaxAll( &myMatProc, &matProc, 1 );

  Teuchos::RCP<Epetra_CrsMatrix> serialMatrix;
  Teuchos::RCP<Epetra_Map> serialMap;	
  if( oldRowMap.DistributedGlobal() && matProc == -1) 
  {
    // The matrix is distributed and needs to be moved to processor zero.
    // Set the zero processor as the master.
    matProc = 0;
    serialMap = Teuchos::rcp( new Epetra_Map( Epetra_Util::Create_Root_Map( OldMatrix_->RowMap(), matProc ) ) );
    
    Epetra_Import serialImporter( *serialMap, OldMatrix_->RowMap() );
    serialMatrix = Teuchos::rcp( new Epetra_CrsMatrix( Copy, *serialMap, 0 ) );
    serialMatrix->Import( *OldMatrix_, serialImporter, Insert );
    serialMatrix->FillComplete();
  }
  else {
    // The old matrix has already been moved to one processor (matProc).
    serialMatrix = OldMatrix_;
  }

  if( debug_ )
  {
    cout << "Original (serial) Matrix:\n";
    cout << *serialMatrix << endl;
  }

  // Obtain the current row and column orderings
  std::vector<int> origGlobalRows(nGlobal), origGlobalCols(nGlobal);
  serialMatrix->RowMap().MyGlobalElements( &origGlobalRows[0] );
  serialMatrix->ColMap().MyGlobalElements( &origGlobalCols[0] );
  
  // Perform reindexing on the full serial matrix (needed for BTF).
  Epetra_Map reIdxMap( serialMatrix->RowMap().NumGlobalElements(), serialMatrix->RowMap().NumMyElements(), 0, serialMatrix->Comm() );
  Teuchos::RCP<EpetraExt::ViewTransform<Epetra_CrsMatrix> > reIdxTrans =
    Teuchos::rcp( new EpetraExt::CrsMatrix_Reindex( reIdxMap ) );
  Epetra_CrsMatrix newSerialMatrix = (*reIdxTrans)( *serialMatrix );
  reIdxTrans->fwd();
  
  // Compute and apply BTF to the serial CrsMatrix and has been filtered by the threshold
  EpetraExt::AmesosBTF_CrsMatrix BTFTrans( threshold_, upperTri_, verbose_, debug_ );
  Epetra_CrsMatrix newSerialMatrixBTF = BTFTrans( newSerialMatrix );
  
  rowPerm_ = BTFTrans.RowPerm();
  colPerm_ = BTFTrans.ColPerm();
  blockPtr_ = BTFTrans.BlockPtr();
  numBlocks_ = BTFTrans.NumBlocks();
 
  if (myPID == matProc && verbose_) {
    bool isSym = true;
    for (int i=0; i<nGlobal; ++i) {
      if (rowPerm_[i] != colPerm_[i]) {
        isSym = false;
        break;
      }
    }
    std::cout << "The BTF permutation symmetry (0=false,1=true) is : " << isSym << std::endl;
  }
  
  // Compute the permutation w.r.t. the original row and column GIDs.
  std::vector<int> origGlobalRowsPerm(nGlobal), origGlobalColsPerm(nGlobal);
  if (myPID == matProc) {
    for (int i=0; i<nGlobal; ++i) {
      origGlobalRowsPerm[i] = origGlobalRows[ rowPerm_[i] ];
      origGlobalColsPerm[i] = origGlobalCols[ colPerm_[i] ];
    }
  }
  OldMatrix_->Comm().Broadcast( &origGlobalRowsPerm[0], nGlobal, matProc );
  OldMatrix_->Comm().Broadcast( &origGlobalColsPerm[0], nGlobal, matProc );

  // Generate the full serial matrix that imports according to the previously computed BTF.
  Epetra_CrsMatrix newSerialMatrixT( Copy, newSerialMatrixBTF.RowMap(), 0 );
  newSerialMatrixT.Import( newSerialMatrix, *(BTFTrans.Importer()), Insert );
  newSerialMatrixT.FillComplete();
  
  if( debug_ )
  {
    cout << "Original (serial) Matrix permuted via BTF:\n";
    cout << newSerialMatrixT << endl;
  }

  // Perform reindexing on the full serial matrix (needed for balancing).
  Epetra_Map reIdxMap2( newSerialMatrixT.RowMap().NumGlobalElements(), newSerialMatrixT.RowMap().NumMyElements(), 0, newSerialMatrixT.Comm() );
  Teuchos::RCP<EpetraExt::ViewTransform<Epetra_CrsMatrix> > reIdxTrans2 =
    Teuchos::rcp( new EpetraExt::CrsMatrix_Reindex( reIdxMap2 ) );
  Epetra_CrsMatrix tNewSerialMatrixT = (*reIdxTrans2)( newSerialMatrixT );
  reIdxTrans2->fwd();

  Teuchos::RCP<Epetra_Map> balancedMap;
  
  if (balance_ == "linear") {
    
    // Distribute block somewhat evenly across processors
    std::vector<int> rowDist(numProcs+1,0);
    int balRows = nGlobal / numProcs + 1;
    int numRows = balRows, currProc = 1;
    for ( int i=0; i<numBlocks_ || currProc < numProcs; ++i ) {
      if (blockPtr_[i] > numRows) {
	rowDist[currProc++] = blockPtr_[i-1];
	numRows = blockPtr_[i-1] + balRows;
      }      
    }
    rowDist[numProcs] = nGlobal;
   
    // Create new Map based on this linear distribution.
    int numMyBalancedRows = rowDist[myPID+1]-rowDist[myPID];

    NewRowMap_ = Teuchos::rcp( new Epetra_Map( nGlobal, numMyBalancedRows, &origGlobalRowsPerm[ rowDist[myPID] ], 0, OldMatrix_->Comm() ) );
    // Right now we do not explicitly build the column map and assume the BTF permutation is symmetric!
    //NewColMap_ = Teuchos::rcp( new Epetra_Map( nGlobal, nGlobal, &colPerm_[0], 0, OldMatrix_->Comm() ) );
    
    if ( verbose_ ) 
      std::cout << "Processor " << myPID << " has " << numMyBalancedRows << " rows." << std::endl;    
    //balancedMap = Teuchos::rcp( new Epetra_Map( nGlobal, numMyBalancedRows, 0, serialMatrix->Comm() ) );
  }
  else if (balance_ == "isorropia") {
	
    // Compute block adjacency graph for partitioning.
    std::vector<double> weight;
    Teuchos::RCP<Epetra_CrsGraph> blkGraph;
    EpetraExt::BlockAdjacencyGraph adjGraph;
    blkGraph = adjGraph.compute( const_cast<Epetra_CrsGraph&>(tNewSerialMatrixT.Graph()), 
							numBlocks_, blockPtr_, weight, verbose_);
    Epetra_Vector rowWeights( View, blkGraph->Map(), &weight[0] );
    
    // Call Isorropia to rebalance this graph.
    Teuchos::RCP<Epetra_CrsGraph> balancedGraph =
      Isorropia::Epetra::create_balanced_copy( *blkGraph, rowWeights );
    
    int myNumBlkRows = balancedGraph->NumMyRows();    
    
    //std::vector<int> myGlobalElements(nGlobal);
    std::vector<int> newRangeElements(nGlobal), newDomainElements(nGlobal);
    int grid = 0, myElements = 0;
    for (int i=0; i<myNumBlkRows; ++i) {
      grid = balancedGraph->GRID( i );
      for (int j=blockPtr_[grid]; j<blockPtr_[grid+1]; ++j) {
	newRangeElements[myElements++] = origGlobalRowsPerm[j];
	//myGlobalElements[myElements++] = j;
      }
    }

    NewRowMap_ = Teuchos::rcp( new Epetra_Map( nGlobal, myElements, &newRangeElements[0], 0, OldMatrix_->Comm() ) );
    // Right now we do not explicitly build the column map and assume the BTF permutation is symmetric!
    //NewColMap_ = Teuchos::rcp( new Epetra_Map( nGlobal, nGlobal, &colPerm_[0], 0, OldMatrix_->Comm() ) );
    //balancedMap = Teuchos::rcp( new Epetra_Map( nGlobal, myElements, &myGlobalElements[0], 0, serialMatrix->Comm() ) );

    if ( verbose_ ) 
      std::cout << "Processor " << myPID << " has " << myElements << " rows." << std::endl;
  }
  
  // Use New Domain and Range Maps to Generate Importer
  //for now, assume they start out as identical
  Epetra_Map OldRowMap = OldMatrix_->RowMap();
  Epetra_Map OldColMap = OldMatrix_->ColMap();
  
  if( debug_ )
  {
    cout << "New Row Map\n";
    cout << *NewRowMap_ << endl;
    //cout << "New Col Map\n";
    //cout << *NewColMap_ << endl;
  }

  // Generate New Graph
  // NOTE:  Right now we are creating the graph, assuming that the permutation is symmetric!
  // NewGraph_ = Teuchos::rcp( new Epetra_CrsGraph( Copy, *NewRowMap_, *NewColMap_, 0 ) );
  NewGraph_ = Teuchos::rcp( new Epetra_CrsGraph( Copy, *NewRowMap_, 0 ) );
  Importer_ = Teuchos::rcp( new Epetra_Import( *NewRowMap_, OldRowMap ) );
  Importer2_ = Teuchos::rcp( new Epetra_Import( OldRowMap, *NewRowMap_ ) );
  NewGraph_->Import( OldMatrix_->Graph(), *Importer_, Insert );
  NewGraph_->FillComplete();

  if( debug_ )
  {
    cout << "NewGraph\n";
    cout << *NewGraph_;
  }

  // Create new linear problem and import information from old linear problem
  NewMatrix_ = Teuchos::rcp( new Epetra_CrsMatrix( Copy, *NewGraph_ ) );
  NewMatrix_->Import( *OldMatrix_, *Importer_, Insert );
  NewMatrix_->FillComplete();

  NewLHS_ = Teuchos::rcp( new Epetra_MultiVector( *NewRowMap_, OldLHS_->NumVectors() ) );
  NewLHS_->Import( *OldLHS_, *Importer_, Insert );
  
  NewRHS_ = Teuchos::rcp( new Epetra_MultiVector( *NewRowMap_, OldRHS_->NumVectors() ) );
  NewRHS_->Import( *OldRHS_, *Importer_, Insert );

  if( debug_ )
  {
    cout << "New Matrix\n";
    cout << *NewMatrix_ << endl;
  }

  newObj_ = new Epetra_LinearProblem( &*NewMatrix_, &*NewLHS_, &*NewRHS_ );

  return *newObj_;
}