32 throw std::runtime_error(
"NoProposal.setState was called, but this class is not actually supposed to be used.");
36 template<
typename Model,
typename Proposal>
40 template<
typename Model,
typename Proposal>
41 void tune(RunBase<Model, Proposal>& run, AcceptanceRateTuner::param_type& parameters);
43 template<
typename Model,
typename Proposal>
44 void tune(RunBase<Model, Proposal>& run, ExpectedSquaredJumpDistanceTuner::param_type& parameters);
46 template<
typename Model,
typename Proposal>
47 void tune(RunBase<Model, Proposal>& run, SimpleExpectedSquaredJumpDistanceTuner::param_type& parameters);
50 template<
typename Model,
typename Proposal>
54 unsigned long numberOfSamples = 1000,
55 unsigned long numberOfChains = 1) :
56 markovChainType(markovChainType),
57 numberOfChains(numberOfChains),
58 numberOfSamples(numberOfSamples) {
64 unsigned long numberOfSamples = 1000,
65 unsigned long numberOfChains = 1) :
67 markovChainType(markovChainType),
68 numberOfChains(numberOfChains),
69 numberOfSamples(numberOfSamples) {
74 unsigned long numberOfSamples = 1000,
75 unsigned long numberOfChains = 1) :
76 m_proposal(m_proposal),
77 numberOfChains(numberOfChains),
78 numberOfSamples(numberOfSamples) {
84 unsigned long numberOfSamples = 1000,
85 unsigned long numberOfChains = 1) :
87 m_proposal(m_proposal),
88 numberOfChains(numberOfChains),
89 numberOfSamples(numberOfSamples) {
141 data = std::make_shared<Data>(problem.dimension);
143 if (!isRandomGeneratorInitialized) {
144 isRandomGeneratorInitialized =
true;
146 for (
unsigned long i = 0; i < numberOfChains; ++i) {
153 if (startingPoints.size() < numberOfChains) {
154 Eigen::VectorXd defaultStartingPoint;
155 if (!problem.useStartingPoint && startingPoints.size() == 0) {
156 #if defined(HOPS_GUROBI_FOUND) || defined(HOPS_CLP_FOUND)
168 "No default starting point was provided in problem and no "
169 "LP solver is available for computing the Chebyshev center, "
170 "can thus not intialize missing starting points.");
172 }
if (problem.useStartingPoint) {
173 defaultStartingPoint = problem.startingPoint;
175 defaultStartingPoint = startingPoints.back();
179 for (
unsigned long i = startingPoints.size(); i < numberOfChains; ++i) {
180 startingPoints.push_back(defaultStartingPoint);
185 Eigen::MatrixXd roundingTransformation;
187 roundingTransformation =
191 if (!roundingTransformation.isLowerTriangular()) {
192 throw std::runtime_error(
"Error while rounding starting point, check code.");
197 m_markovChains.resize(numberOfChains);
198 for (
unsigned long i = 0; i < numberOfChains; ++i) {
199 if (problem.unround) {
200 if constexpr(std::is_same<Proposal, NoProposal>::value) {
205 problem.unroundingTransformation,
206 problem.unroundingShift,
209 m_proposal.setState(startingPoints[i]);
211 problem.unroundingTransformation,
212 problem.unroundingShift,
215 }
else if (useRounding) {
216 Eigen::VectorXd roundedStartingPoint = roundingTransformation.triangularView<Eigen::Lower>().solve(startingPoints[i]);
217 if constexpr(std::is_same<Proposal, NoProposal>::value) {
219 Eigen::MatrixXd(problem.A * roundingTransformation),
221 roundedStartingPoint,
222 roundingTransformation,
223 Eigen::VectorXd(Eigen::VectorXd::Zero(problem.dimension)),
226 m_proposal.setState(roundedStartingPoint);
228 roundingTransformation,
229 Eigen::VectorXd(Eigen::VectorXd::Zero(problem.dimension)),
233 if constexpr(std::is_same<Proposal, NoProposal>::value) {
240 m_proposal.setState(startingPoints[i]);
241 m_markovChains[i] = std::move(
242 MarkovChainFactory::createMarkovChain<Eigen::MatrixXd, Eigen::VectorXd, Model, Proposal>(m_proposal,
248 m_markovChains[i]->clearHistory();
249 m_markovChains[i]->reserveStateRecords(maxRepetitions * numberOfSamples);
266 data->linkWithChains(m_markovChains);
267 data->setDimension(problem.dimension);
269 isInitialized =
true;
276 sample(numberOfSamples, thinning);
282 void sample(
unsigned long numberOfSamples,
unsigned long thinning = 1) {
283 if (!isInitialized) {
288 double convergenceStatistics = 0;
290 #pragma omp parallel for
291 for (
unsigned long i = 0; i < numberOfChains; ++i) {
292 m_markovChains[i]->draw(randomNumberGenerators[i], numberOfSamples, thinning);
296 if (sampleUntilConvergence && numberOfChains >= 2) {
302 }
while(sampleUntilConvergence &&
304 (convergenceStatistics > convergenceThreshold || std::isnan(convergenceStatistics)) &&
311 std::shared_ptr<Data> data =
nullptr;
315 bool isInitialized =
false;
316 bool isRandomGeneratorInitialized =
false;
320 std::vector<std::shared_ptr<hops::MarkovChain>> m_markovChains;
321 std::vector<hops::RandomNumberGenerator> randomNumberGenerators;
323 std::vector<Eigen::VectorXd> startingPoints;
325 unsigned long numberOfChains = 1;
326 unsigned long numberOfSamples = 1000;
327 unsigned long thinning = 1;
329 bool useRounding =
false;
331 bool sampleUntilConvergence =
false;
332 double convergenceThreshold = 1.05;
333 unsigned long maxRepetitions = 1;
336 double fisherWeight = 0.5;
338 double randomSeed = 0;
346 template <
typename Model>
349 template<
typename Model,
typename Proposal>
351 this->isInitialized =
false;
352 this->problem = problem;
355 template<
typename Model,
typename Proposal>
361 template<
typename Model,
typename Proposal>
363 this->isInitialized =
false;
364 this->startingPoints = startingPoints;
367 template<
typename Model,
typename Proposal>
369 return startingPoints;
373 template<
typename Model,
typename Proposal>
375 this->isInitialized =
false;
376 this->markovChainType = markovChainType;
379 template<
typename Model,
typename Proposal>
381 return markovChainType;
385 template<
typename Model,
typename Proposal>
387 this->isInitialized =
false;
388 this->numberOfChains = numberOfChains;
391 template<
typename Model,
typename Proposal>
393 return numberOfChains;
397 template<
typename Model,
typename Proposal>
399 this->numberOfSamples = numberOfSamples;
402 template<
typename Model,
typename Proposal>
404 return numberOfSamples;
408 template<
typename Model,
typename Proposal>
410 this->thinning = thinning;
413 template<
typename Model,
typename Proposal>
419 template<
typename Model,
typename Proposal>
421 this->isInitialized =
false;
422 this->useRounding = useRounding;
425 template<
typename Model,
typename Proposal>
427 return this->useRounding;
431 template<
typename Model,
typename Proposal>
433 this->isInitialized =
false;
434 this->stepSize = stepSize;
437 template<
typename Model,
typename Proposal>
443 template<
typename Model,
typename Proposal>
445 this->isInitialized =
false;
446 this->fisherWeight = fisherWeight;
449 template<
typename Model,
typename Proposal>
455 template<
typename Model,
typename Proposal>
457 this->isInitialized =
false;
458 this->isRandomGeneratorInitialized =
false;
459 this->randomSeed = randomSeed;
462 template<
typename Model,
typename Proposal>
468 template<
typename Model,
typename Proposal>
470 this->sampleUntilConvergence = sampleUntilConvergence;
473 template<
typename Model,
typename Proposal>
475 return this->sampleUntilConvergence;
479 template<
typename Model,
typename Proposal>
481 this->convergenceThreshold = convergenceThreshold;
484 template<
typename Model,
typename Proposal>
486 return convergenceThreshold;
490 template<
typename Model,
typename Proposal>
492 this->maxRepetitions = maxRepetitions;
493 if (this->isInitialized) {
494 for (
unsigned long i = 0; i < numberOfChains; ++i) {
495 m_markovChains[i]->reserveStateRecords(maxRepetitions * numberOfSamples);
500 template<
typename Model,
typename Proposal>
502 return maxRepetitions;
506 template<
typename Model,
typename Proposal>
511 template<
typename Model,
typename Proposal>
513 if (!run.isInitialized) {
517 double tunedStepSize, deltaAcceptanceRate;
518 Eigen::MatrixXd data, posterior;
521 double time = std::chrono::duration_cast<std::chrono::milliseconds>(
522 std::chrono::high_resolution_clock::now().time_since_epoch()
528 run.randomNumberGenerators,
533 time = std::chrono::duration_cast<std::chrono::milliseconds>(
534 std::chrono::high_resolution_clock::now().time_since_epoch()
538 for (
size_t i = 0; i < run.m_markovChains.size(); ++i) {
546 run.stepSize = tunedStepSize;
547 unsigned long totalNumberOfTuningSamples =
552 run.data->setTuningMethod(
"ThompsonSamplingESJD");
553 run.data->setTotalNumberOfTuningSamples(totalNumberOfTuningSamples);
554 run.data->setTunedStepSize(tunedStepSize);
555 run.data->setTunedObjectiveValue(deltaAcceptanceRate);
556 run.data->setTotalTuningTimeTaken(time);
558 run.data->setTuningData(data);
559 run.data->setTuningPosterior(posterior);
562 template<
typename Model,
typename Proposal>
564 if (!run.isInitialized) {
568 double tunedStepSize, maximumExpectedSquaredJumpDistance;
569 Eigen::MatrixXd data, posterior;
572 double time = std::chrono::duration_cast<std::chrono::milliseconds>(
573 std::chrono::high_resolution_clock::now().time_since_epoch()
577 maximumExpectedSquaredJumpDistance,
579 run.randomNumberGenerators,
584 time = std::chrono::duration_cast<std::chrono::milliseconds>(
585 std::chrono::high_resolution_clock::now().time_since_epoch()
589 for (
size_t i = 0; i < run.m_markovChains.size(); ++i) {
597 run.stepSize = tunedStepSize;
598 unsigned long totalNumberOfTuningSamples =
603 run.data->setTuningMethod(
"ThompsonSamplingAcceptanceRate");
604 run.data->setTotalNumberOfTuningSamples(totalNumberOfTuningSamples);
605 run.data->setTunedStepSize(tunedStepSize);
606 run.data->setTunedObjectiveValue(maximumExpectedSquaredJumpDistance);
607 run.data->setTotalTuningTimeTaken(time);
609 run.data->setTuningData(data);
610 run.data->setTuningPosterior(posterior);
613 template<
typename Model,
typename Proposal>
615 if (!run.isInitialized) {
619 double tunedStepSize, maximumExpectedSquaredJumpDistance;
620 Eigen::MatrixXd data, posterior;
623 double time = std::chrono::duration_cast<std::chrono::milliseconds>(
624 std::chrono::high_resolution_clock::now().time_since_epoch()
628 maximumExpectedSquaredJumpDistance,
630 run.randomNumberGenerators,
633 time = std::chrono::duration_cast<std::chrono::milliseconds>(
634 std::chrono::high_resolution_clock::now().time_since_epoch()
638 for (
size_t i = 0; i < run.m_markovChains.size(); ++i) {
646 run.stepSize = tunedStepSize;
647 unsigned long totalNumberOfTuningSamples =
652 run.data->setTuningMethod(
"GridSearchESJD");
653 run.data->setTotalNumberOfTuningSamples(totalNumberOfTuningSamples);
654 run.data->setTunedStepSize(tunedStepSize);
655 run.data->setTunedObjectiveValue(maximumExpectedSquaredJumpDistance);
656 run.data->setTotalTuningTimeTaken(time);
658 run.data->setTuningData(data);
659 run.data->setTuningPosterior(posterior);
663 #endif // HOPS_RUN_HPP