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 ];
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(¤t_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); } }
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(¤t_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_; }