//Return a list of data points //Each should take the data average value of each continuous observable //Each should represent one combination of possible discrete values vector<DataPoint*> PhaseSpaceBoundary::GetDiscreteCombinations() const { if( storedCombinationID == uniqueID && !StoredCombinations.empty() ) { return StoredCombinations; } while( !StoredCombinations.empty() ) { if( StoredCombinations.back() != NULL ) delete StoredCombinations.back(); StoredCombinations.pop_back(); } //Calculate all possible combinations of discrete observables vector<string> thisAllNames = this->GetAllNames(); vector<vector<double> > discreteValues; vector<string> discreteNames, continuousNames; vector<vector<double> > discreteCombinations = StatisticsFunctions::DiscreteCombinations( &thisAllNames, this, discreteNames, continuousNames, discreteValues ); (void) continuousNames; //Create the data points to return vector<DataPoint*> newDataPoints; DataPoint* tempPoint = this->GetMidPoint(); if( tempPoint == NULL ) return newDataPoints; for( unsigned int combinationIndex = 0; combinationIndex < discreteCombinations.size(); ++combinationIndex ) { DataPoint* templateDataPoint = new DataPoint( *tempPoint ); //Output the discrete values for this combination for( unsigned int discreteIndex = 0; discreteIndex < discreteNames.size(); ++discreteIndex ) { //Set the data point Observable* oldValue = templateDataPoint->GetObservable( discreteNames[discreteIndex] ); Observable* newValue = new Observable( oldValue->GetName(), discreteCombinations[combinationIndex][discreteIndex], oldValue->GetUnit() ); templateDataPoint->SetObservable( discreteNames[discreteIndex], newValue ); delete newValue; } newDataPoints.push_back( templateDataPoint ); } delete tempPoint; StoredCombinations = newDataPoints; storedCombinationID = uniqueID; return newDataPoints; }
//Returns whether a point is within the boundary bool PhaseSpaceBoundary::IsPointInBoundary( DataPoint * TestDataPoint, bool silence ) { for (unsigned int nameIndex = 0; nameIndex < allNames.size(); ++nameIndex ) { //Check if test Observable exists in the DataPoint Observable * testObservable = TestDataPoint->GetObservable( allNames[nameIndex], silence ); if ( testObservable->GetUnit() == "NameNotFoundError" ) { cerr << "Observable \"" << allNames[nameIndex] << "\" expected but not found" << endl; return false; } else { //Check if the Observable fits if ( !allConstraints[nameIndex]->CheckObservable(testObservable) ) { return false; } else if( allConstraints[nameIndex]->IsDiscrete() ) { vector<double> temp_vec = allConstraints[nameIndex]->GetValues(); for( unsigned int i=0; i< temp_vec.size(); ++i ) { if( fabs( testObservable->GetValue() - temp_vec[i] ) < DOUBLE_TOLERANCE_PHASE ) { Observable* temp = new Observable( testObservable->GetName(), temp_vec[i], testObservable->GetUnit() ); TestDataPoint->SetObservable( testObservable->GetName(), temp ); delete temp; } } } } } //Point is within the boundary return true; }
//Constructor with correct argument MakeFoam::MakeFoam( IPDF * InputPDF, PhaseSpaceBoundary * InputBoundary, DataPoint * InputPoint ) : finishedCells(), centerPoints(), centerValues(), cellIntegrals(), integratePDF(InputPDF) { //Make the container to hold the possible cells queue<PhaseSpaceBoundary*> possibleCells; PhaseSpaceBoundary* firstCell = InputBoundary; possibleCells.push(firstCell); //Make a list of observables to integrate over vector<string> doIntegrate, dontIntegrate; vector<string> pdfDontIntegrate = InputPDF->GetDoNotIntegrateList(); StatisticsFunctions::DoDontIntegrateLists( InputPDF, InputBoundary, &(pdfDontIntegrate), doIntegrate, dontIntegrate ); //Continue until all possible cells have been examined while ( !possibleCells.empty() ) { //Remove the next possible cell PhaseSpaceBoundary* currentCell = possibleCells.front(); possibleCells.pop(); //Set up the histogram storage vector< vector<double> > histogramBinHeights, histogramBinMiddles, histogramBinMaxes; double normalisation = 0.0; for (unsigned int observableIndex = 0; observableIndex < doIntegrate.size(); ++observableIndex ) { vector<double> binHeights, binMiddles, binMaxes; IConstraint * temporaryConstraint = currentCell->GetConstraint( doIntegrate[observableIndex] ); double minimum = temporaryConstraint->GetMinimum(); double delta = ( temporaryConstraint->GetMaximum() - minimum ) / (double)HISTOGRAM_BINS; //Loop over bins for (int binIndex = 0; binIndex < HISTOGRAM_BINS; ++binIndex ) { binHeights.push_back(0.0); binMiddles.push_back( minimum + ( delta * ( binIndex + 0.5 ) ) ); binMaxes.push_back( minimum + ( delta * ( binIndex + 1.0 ) ) ); } histogramBinHeights.push_back(binHeights); histogramBinMiddles.push_back(binMiddles); histogramBinMaxes.push_back(binMaxes); } //MC sample the cell, make projections, sort of for (int sampleIndex = 0; sampleIndex < MAXIMUM_SAMPLES; ++sampleIndex ) { //Create a data point within the current cell DataPoint samplePoint( InputPoint->GetAllNames() ); for (unsigned int observableIndex = 0; observableIndex < doIntegrate.size(); ++observableIndex ) { //Generate random values to explore integrable observables IConstraint * temporaryConstraint = currentCell->GetConstraint( doIntegrate[observableIndex] ); samplePoint.SetObservable( doIntegrate[observableIndex], temporaryConstraint->CreateObservable() ); } for (unsigned int observableIndex = 0; observableIndex < dontIntegrate.size(); ++observableIndex ) { //Use given values for unintegrable observables Observable * temporaryObservable = new Observable( *(InputPoint->GetObservable( dontIntegrate[observableIndex] )) ); samplePoint.SetObservable( dontIntegrate[observableIndex], temporaryObservable ); delete temporaryObservable; } //Evaluate the function at this point double sampleValue = InputPDF->Evaluate( &samplePoint ); normalisation += sampleValue; //Populate the histogram for (unsigned int observableIndex = 0; observableIndex < doIntegrate.size(); ++observableIndex ) { double observableValue = samplePoint.GetObservable( doIntegrate[observableIndex] )->GetValue(); for ( int binIndex = 0; binIndex < HISTOGRAM_BINS; ++binIndex ) { if ( observableValue < histogramBinMaxes[observableIndex][unsigned(binIndex)] ) { histogramBinHeights[observableIndex][unsigned(binIndex)] += sampleValue; break; } } } } //Normalise the histograms for (unsigned int observableIndex = 0; observableIndex < doIntegrate.size(); ++observableIndex ) { for ( int binIndex = 0; binIndex < HISTOGRAM_BINS; ++binIndex ) { histogramBinHeights[observableIndex][unsigned(binIndex)] /= normalisation; } } //Find the maximum gradient vector<double> midPoints; string maximumGradientObservable, unit; double maximumGradient=0.; double lowPoint=0.; double splitPoint=0.; double highPoint=0.; for (unsigned int observableIndex = 0; observableIndex < doIntegrate.size(); ++observableIndex ) { //Find the size of the cell in this observable IConstraint * temporaryConstraint = currentCell->GetConstraint( doIntegrate[observableIndex] ); double cellMaximum = temporaryConstraint->GetMaximum(); double cellMinimum = temporaryConstraint->GetMinimum(); //Store the mid point double observableMiddle = cellMinimum + ( ( cellMaximum - cellMinimum ) / 2.0 ); midPoints.push_back(observableMiddle); for ( int binIndex = 1; binIndex < HISTOGRAM_BINS; ++binIndex ) { double gradient = abs( histogramBinHeights[observableIndex][ unsigned(binIndex - 1) ] - histogramBinHeights[observableIndex][unsigned(binIndex)] ); //Update maximum if ( ( observableIndex == 0 && binIndex == 1 ) || gradient > maximumGradient ) { maximumGradient = gradient; maximumGradientObservable = doIntegrate[observableIndex]; unit = temporaryConstraint->GetUnit(); highPoint = cellMaximum; splitPoint = ( histogramBinMiddles[observableIndex][ unsigned(binIndex - 1) ] + histogramBinMiddles[observableIndex][unsigned(binIndex)] ) / 2.0; lowPoint = cellMinimum; } } } //If the maximum gradient is within tolerance, the cell is finished if ( maximumGradient < MAXIMUM_GRADIENT_TOLERANCE ) { //Store the finished cell finishedCells.push_back(currentCell); //Create a data point at the center of the current cell DataPoint* cellCenter = new DataPoint( InputPoint->GetAllNames() ); for (unsigned int observableIndex = 0; observableIndex < doIntegrate.size(); ++observableIndex ) { //Use the mid points for the integrable values Observable * temporaryObservable = cellCenter->GetObservable( doIntegrate[observableIndex] ); Observable* temporaryObservable2 = new Observable( temporaryObservable->GetName(), midPoints[observableIndex], temporaryObservable->GetUnit() ); cellCenter->SetObservable( doIntegrate[observableIndex], temporaryObservable2 ); delete temporaryObservable2; } for (unsigned int observableIndex = 0; observableIndex < dontIntegrate.size(); ++observableIndex ) { //Use given values for unintegrable observables Observable * temporaryObservable = new Observable( *(InputPoint->GetObservable( dontIntegrate[observableIndex] )) ); cellCenter->SetObservable( dontIntegrate[observableIndex], temporaryObservable ); delete temporaryObservable; } //Store the center point centerPoints.push_back(cellCenter); } else { //Create two cells to replace the current cell PhaseSpaceBoundary* daughterCell1 = new PhaseSpaceBoundary( currentCell->GetAllNames() ); PhaseSpaceBoundary* daughterCell2 = new PhaseSpaceBoundary( currentCell->GetAllNames() ); for (unsigned int observableIndex = 0; observableIndex < doIntegrate.size(); ++observableIndex ) { IConstraint * temporaryConstraint = currentCell->GetConstraint( doIntegrate[observableIndex] ); if ( doIntegrate[observableIndex] == maximumGradientObservable ) { //Split the cells on the observable with the greatest gradient daughterCell1->SetConstraint( doIntegrate[observableIndex], lowPoint, splitPoint, unit ); daughterCell2->SetConstraint( doIntegrate[observableIndex], splitPoint, highPoint, unit ); } else { //Copy the continuous constraint (if it can be integrated, it must be continuous) daughterCell1->SetConstraint( doIntegrate[observableIndex], temporaryConstraint->GetMinimum(), temporaryConstraint->GetMaximum(), temporaryConstraint->GetUnit() ); daughterCell2->SetConstraint( doIntegrate[observableIndex], temporaryConstraint->GetMinimum(), temporaryConstraint->GetMaximum(), temporaryConstraint->GetUnit() ); } } for (unsigned int observableIndex = 0; observableIndex < dontIntegrate.size(); ++observableIndex ) { IConstraint * temporaryConstraint = currentCell->GetConstraint( dontIntegrate[observableIndex] ); if ( temporaryConstraint->IsDiscrete() ) { //Copy the discrete constraint daughterCell1->SetConstraint( dontIntegrate[observableIndex], temporaryConstraint->GetValues(), temporaryConstraint->GetUnit() ); daughterCell2->SetConstraint( dontIntegrate[observableIndex], temporaryConstraint->GetValues(), temporaryConstraint->GetUnit() ); } else { //Copy the continuous constraint daughterCell1->SetConstraint( dontIntegrate[observableIndex], temporaryConstraint->GetMinimum(), temporaryConstraint->GetMaximum(), temporaryConstraint->GetUnit() ); daughterCell2->SetConstraint( dontIntegrate[observableIndex], temporaryConstraint->GetMinimum(), temporaryConstraint->GetMaximum(), temporaryConstraint->GetUnit() ); } } //Add the two new cells to the possibles possibleCells.push(daughterCell1); possibleCells.push(daughterCell2); } //Make sure you don't exceed the maximum number of cells if ( int(finishedCells.size() + possibleCells.size()) >= MAXIMUM_CELLS ) { cout << "MakeFoam warning: maximum cells reached with " << possibleCells.size() << " unexplored" << endl; //Dump out any possible cells into finished, without any further examination while ( !possibleCells.empty() ) { //Move the cell from "possible" to "finished" PhaseSpaceBoundary* temporaryCell = possibleCells.front(); possibleCells.pop(); finishedCells.push_back(temporaryCell); //Create a data point at the center of the current cell DataPoint* cellCenter = new DataPoint( InputPoint->GetAllNames() ); for (unsigned int observableIndex = 0; observableIndex < doIntegrate.size(); ++observableIndex ) { //Calculate the cell mid point IConstraint * temporaryConstraint = temporaryCell->GetConstraint( doIntegrate[observableIndex] ); double midPoint = temporaryConstraint->GetMinimum() + ( ( temporaryConstraint->GetMaximum() - temporaryConstraint->GetMinimum() ) / 2 ); //Use the mid points for the integrable values Observable * temporaryObservable = cellCenter->GetObservable( doIntegrate[observableIndex] ); Observable* temporaryObservable2 = new Observable( temporaryObservable->GetName(), midPoint, temporaryObservable->GetUnit() ); cellCenter->SetObservable( doIntegrate[observableIndex], temporaryObservable2 ); delete temporaryObservable2; } for (unsigned int observableIndex = 0; observableIndex < dontIntegrate.size(); ++observableIndex ) { //Use given values for unintegrable observables Observable * temporaryObservable = new Observable( *(InputPoint->GetObservable( dontIntegrate[observableIndex] )) ); cellCenter->SetObservable( dontIntegrate[observableIndex], temporaryObservable ); delete temporaryObservable; } //Store the center point centerPoints.push_back(cellCenter); } //Exit the foam loop break; } } //Now all the cells have been made! //Make a numerical integrator for the function RapidFitIntegrator cellIntegrator( InputPDF, true ); //Find the function value at the center of each cell, and the integral of the function over the cell for (unsigned int cellIndex = 0; cellIndex < finishedCells.size(); ++cellIndex ) { //Integrate the cell double integral = cellIntegrator.Integral( InputPoint, finishedCells[cellIndex] ); cellIntegrals.push_back(integral); //Evaluate the function at the center of the cell double value = InputPDF->Evaluate( centerPoints[cellIndex] ); centerValues.push_back(value); } }