//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;
}
//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;
}
Exemple #3
0
//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);
	}
}