Browse Source

Optimizing original OVI & Switch for comparing minswap methods

main
Jan Erik Karuc 5 years ago
parent
commit
48a3b5a927
  1. 289
      src/storm/solver/helper/OptimisticValueIterationHelper.h

289
src/storm/solver/helper/OptimisticValueIterationHelper.h

@ -135,99 +135,222 @@ namespace storm {
SolverStatus status = SolverStatus::InProgress; SolverStatus status = SolverStatus::InProgress;
while (status == SolverStatus::InProgress && overallIterations < maxOverallIterations) { if(env.solver().ovi().useTerminationGuaranteedMinimumMethod()) {
while (status == SolverStatus::InProgress && overallIterations < maxOverallIterations) {
// Perform value iteration until convergence // Perform value iteration until convergence
++valueIterationInvocations; ++valueIterationInvocations;
auto result = valueIterationCallback(lowerX, auxVector, iterationPrecision, relative, overallIterations, maxOverallIterations); auto result = valueIterationCallback(lowerX, auxVector, iterationPrecision, relative, overallIterations, maxOverallIterations);
lastValueIterationIterations = result.iterations; lastValueIterationIterations = result.iterations;
overallIterations += result.iterations; overallIterations += result.iterations;
if (result.status != SolverStatus::Converged) {
if (result.status != SolverStatus::Converged) { status = result.status;
status = result.status;
} else {
bool intervalIterationNeeded = false;
currentVerificationIterations = 0;
if (relative) {
oviinternal::guessUpperBoundRelative(*lowerX, *upperX, relativeBoundGuessingScaler);
} else { } else {
oviinternal::guessUpperBoundAbsolute(*lowerX, *upperX, precision); bool intervalIterationNeeded = false;
} currentVerificationIterations = 0;
if (relative) {
bool cancelGuess = false; oviinternal::guessUpperBoundRelative(*lowerX, *upperX, relativeBoundGuessingScaler);
while (status == SolverStatus::InProgress && overallIterations < maxOverallIterations) { } else {
++overallIterations; oviinternal::guessUpperBoundAbsolute(*lowerX, *upperX, precision);
++currentVerificationIterations;
// Perform value iteration stepwise for lower bound and guessed upper bound
// Upper bound iteration
singleIterationCallback(upperX, auxVector, overallIterations);
// At this point,h auxVector contains the old values for the upper bound whereas upperX contains the new ones.
// Compare the new upper bound candidate with the old one
bool newUpperBoundAlwaysHigherEqual = true;
bool newUpperBoundAlwaysLowerEqual = true;
for (uint64_t i = 0; i < upperX->size(); ++i) {
if ((*upperX)[i] < (*auxVector)[i]) {
newUpperBoundAlwaysHigherEqual = false;
} else if ((*upperX)[i] != (*auxVector)[i]) {
newUpperBoundAlwaysLowerEqual = false;
//std::swap((*upperX)[i], (*auxVector)[i]);
}
} }
if (newUpperBoundAlwaysHigherEqual &! newUpperBoundAlwaysLowerEqual) { bool cancelGuess = false;
// All values moved up or stayed the same while (status == SolverStatus::InProgress && overallIterations < maxOverallIterations) {
// That means the guess for an upper bound is actually a lower bound ++overallIterations;
iterationPrecision = oviinternal::updateIterationPrecision(env, *auxVector, *upperX, relative, relevantValues); ++currentVerificationIterations;
// We assume to have a single fixed point. We can thus safely set the new lower bound, to the wrongly guessed upper bound // Perform value iteration stepwise for lower bound and guessed upper bound
// Set lowerX to the upper bound candidate // Upper bound iteration
std::swap(lowerX, upperX); singleIterationCallback(upperX, auxVector, overallIterations);
break; // At this point,h auxVector contains the old values for the upper bound whereas upperX contains the new ones.
} else if (newUpperBoundAlwaysLowerEqual &! newUpperBoundAlwaysHigherEqual) { // Compare the new upper bound candidate with the old one
// All values moved down or stayed the same and we have a maximum difference of twice the requested precision bool newUpperBoundAlwaysHigherEqual = true;
// We can safely use twice the requested precision, as we calculate the center of both vectors bool newUpperBoundAlwaysLowerEqual = true;
bool reachedPrecision; for (uint64_t i = 0; i < upperX->size(); ++i) {
if (relevantValues) { if ((*upperX)[i] < (*auxVector)[i]) {
reachedPrecision = storm::utility::vector::equalModuloPrecision(*lowerX, *upperX, relevantValues.get(), doublePrecision, relative); newUpperBoundAlwaysHigherEqual = false;
} else { } else if ((*upperX)[i] != (*auxVector)[i]) {
reachedPrecision = storm::utility::vector::equalModuloPrecision(*lowerX, *upperX, doublePrecision, relative); newUpperBoundAlwaysLowerEqual = false;
std::swap((*upperX)[i], (*auxVector)[i]);
}
} }
if (reachedPrecision) { if (newUpperBoundAlwaysHigherEqual &! newUpperBoundAlwaysLowerEqual) {
status = SolverStatus::Converged; // All values moved up or stayed the same
// That means the guess for an upper bound is actually a lower bound
iterationPrecision = oviinternal::updateIterationPrecision(env, *auxVector, *upperX, relative, relevantValues);
// We assume to have a single fixed point. We can thus safely set the new lower bound, to the wrongly guessed upper bound
// Set lowerX to the upper bound candidate
std::swap(lowerX, upperX);
break; break;
} else { } else if (newUpperBoundAlwaysLowerEqual &! newUpperBoundAlwaysHigherEqual) {
// From now on, we keep updating both bounds // All values moved down or stayed the same and we have a maximum difference of twice the requested precision
intervalIterationNeeded = true; // We can safely use twice the requested precision, as we calculate the center of both vectors
bool reachedPrecision;
if (relevantValues) {
reachedPrecision = storm::utility::vector::equalModuloPrecision(*lowerX, *upperX, relevantValues.get(), doublePrecision, relative);
} else {
reachedPrecision = storm::utility::vector::equalModuloPrecision(*lowerX, *upperX, doublePrecision, relative);
}
if (reachedPrecision) {
status = SolverStatus::Converged;
break;
} else {
// From now on, we keep updating both bounds
intervalIterationNeeded = true;
}
}
// At this point, the old upper bounds (auxVector) are not needed anymore.
// Check whether we tried this guess for too long
ValueType scaledIterationCount = storm::utility::convertNumber<ValueType>(currentVerificationIterations) * storm::utility::convertNumber<ValueType>(env.solver().ovi().getMaxVerificationIterationFactor());
if (!intervalIterationNeeded && scaledIterationCount >= storm::utility::convertNumber<ValueType>(lastValueIterationIterations)) {
cancelGuess = true;
// In this case we will make one more iteration on the lower bound (mainly to obtain a new iterationPrecision)
}
// Lower bound iteration (only if needed)
if (cancelGuess || intervalIterationNeeded || currentVerificationIterations > upperBoundOnlyIterations) {
singleIterationCallback(lowerX, auxVector, overallIterations);
// At this point, auxVector contains the old values for the lower bound whereas lowerX contains the new ones.
// Check whether the upper and lower bounds have crossed, i.e., the upper bound is smaller than the lower bound.
bool valuesCrossed = false;
for (uint64_t i = 0; i < lowerX->size(); ++i) {
if ((*upperX)[i] < (*lowerX)[i]) {
valuesCrossed = true;
break;
}
}
if (cancelGuess || valuesCrossed) {
// A new guess is needed.
iterationPrecision = oviinternal::updateIterationPrecision(env, *auxVector, *lowerX, relative, relevantValues);
break;
}
} }
} }
// At this point, the old upper bounds (auxVector) are not needed anymore. }
}
// Check whether we tried this guess for too long }
ValueType scaledIterationCount = storm::utility::convertNumber<ValueType>(currentVerificationIterations) * storm::utility::convertNumber<ValueType>(env.solver().ovi().getMaxVerificationIterationFactor()); else {
if (!intervalIterationNeeded && scaledIterationCount >= storm::utility::convertNumber<ValueType>(lastValueIterationIterations)) { while (status == SolverStatus::InProgress && overallIterations < maxOverallIterations) {
cancelGuess = true; // Perform value iteration until convergence
// In this case we will make one more iteration on the lower bound (mainly to obtain a new iterationPrecision) ++valueIterationInvocations;
auto result = valueIterationCallback(lowerX, auxVector, iterationPrecision, relative, overallIterations, maxOverallIterations);
lastValueIterationIterations = result.iterations;
overallIterations += result.iterations;
if (result.status != SolverStatus::Converged) {
status = result.status;
} else {
bool intervalIterationNeeded = false;
currentVerificationIterations = 0;
if (relative) {
oviinternal::guessUpperBoundRelative(*lowerX, *upperX, relativeBoundGuessingScaler);
} else {
oviinternal::guessUpperBoundAbsolute(*lowerX, *upperX, precision);
} }
bool cancelGuess = false;
// Lower bound iteration (only if needed) while (status == SolverStatus::InProgress && overallIterations < maxOverallIterations) {
if (cancelGuess || intervalIterationNeeded || currentVerificationIterations > upperBoundOnlyIterations) { ++overallIterations;
singleIterationCallback(lowerX, auxVector, overallIterations); ++currentVerificationIterations;
// At this point, auxVector contains the old values for the lower bound whereas lowerX contains the new ones. // Perform value iteration stepwise for lower bound and guessed upper bound
// Upper bound iteration
// Check whether the upper and lower bounds have crossed, i.e., the upper bound is smaller than the lower bound. singleIterationCallback(upperX, auxVector, overallIterations);
bool valuesCrossed = false; // At this point,h auxVector contains the old values for the upper bound whereas upperX contains the new ones.
for (uint64_t i = 0; i < lowerX->size(); ++i) { // Compare the new upper bound candidate with the old one
if ((*upperX)[i] < (*lowerX)[i]) { bool newUpperBoundAlwaysHigherEqual = true;
valuesCrossed = true; bool newUpperBoundAlwaysLowerEqual = true;
break; bool cancelOuterScan = false;
for (uint64_t i = 0; i < upperX->size() &! cancelOuterScan; ++i) {
if ((*upperX)[i] < (*auxVector)[i]) {
newUpperBoundAlwaysHigherEqual = false;
++i;
while (i < upperX->size()) {
if ((*upperX)[i] > (*auxVector)[i]) {
newUpperBoundAlwaysLowerEqual = false;
cancelOuterScan = true;
break;
}
++i;
}
} else if ((*upperX)[i] != (*auxVector)[i]) {
newUpperBoundAlwaysLowerEqual = false;
++i;
while (i < upperX->size()) {
if ((*upperX)[i] > (*auxVector)[i]) {
newUpperBoundAlwaysLowerEqual = false;
cancelOuterScan = true;
break;
}
++i;
}
} }
} }
if (newUpperBoundAlwaysHigherEqual &! newUpperBoundAlwaysLowerEqual) {
if (cancelGuess || valuesCrossed) { // All values moved up or stayed the same
// A new guess is needed. // That means the guess for an upper bound is actually a lower bound
iterationPrecision = oviinternal::updateIterationPrecision(env, *auxVector, *lowerX, relative, relevantValues); iterationPrecision = oviinternal::updateIterationPrecision(env, *auxVector, *upperX, relative, relevantValues);
// We assume to have a single fixed point. We can thus safely set the new lower bound, to the wrongly guessed upper bound
// Set lowerX to the upper bound candidate
std::swap(lowerX, upperX);
break; break;
} else if (newUpperBoundAlwaysLowerEqual &! newUpperBoundAlwaysHigherEqual) {
// All values moved down or stayed the same and we have a maximum difference of twice the requested precision
// We can safely use twice the requested precision, as we calculate the center of both vectors
bool reachedPrecision;
if (relevantValues) {
reachedPrecision = storm::utility::vector::equalModuloPrecision(*lowerX, *upperX, relevantValues.get(), doublePrecision, relative);
} else {
reachedPrecision = storm::utility::vector::equalModuloPrecision(*lowerX, *upperX, doublePrecision, relative);
}
if (reachedPrecision) {
status = SolverStatus::Converged;
break;
} else {
// From now on, we keep updating both bounds
intervalIterationNeeded = true;
}
}
// At this point, the old upper bounds (auxVector) are not needed anymore.
// Check whether we tried this guess for too long
ValueType scaledIterationCount = storm::utility::convertNumber<ValueType>(currentVerificationIterations) * storm::utility::convertNumber<ValueType>(env.solver().ovi().getMaxVerificationIterationFactor());
if (!intervalIterationNeeded && scaledIterationCount >= storm::utility::convertNumber<ValueType>(lastValueIterationIterations)) {
cancelGuess = true;
// In this case we will make one more iteration on the lower bound (mainly to obtain a new iterationPrecision)
}
// Lower bound iteration (only if needed)
if (cancelGuess || intervalIterationNeeded || currentVerificationIterations > upperBoundOnlyIterations) {
singleIterationCallback(lowerX, auxVector, overallIterations);
// At this point, auxVector contains the old values for the lower bound whereas lowerX contains the new ones.
// Check whether the upper and lower bounds have crossed, i.e., the upper bound is smaller than the lower bound.
bool valuesCrossed = false;
for (uint64_t i = 0; i < lowerX->size(); ++i) {
if ((*upperX)[i] < (*lowerX)[i]) {
valuesCrossed = true;
break;
}
}
if (cancelGuess || valuesCrossed) {
// A new guess is needed.
iterationPrecision = oviinternal::updateIterationPrecision(env, *auxVector, *lowerX, relative, relevantValues);
break;
}
} }
} }
} }

|||||||
100:0
Loading…
Cancel
Save