Browse Source

Splitted VectorSet in header/source file which caused certain minor changes in its interface. Fixed some issues in the Markov automaton parser and made it substantially faster by dropping sscanf. This however introduces other limitations that need to be addressed in the future.

Former-commit-id: 44eb4aabc9
tempestpy_adaptions
dehnert 11 years ago
parent
commit
f35ac73547
  1. 2
      src/counterexamples/MILPMinimalLabelSetGenerator.h
  2. 6
      src/counterexamples/SMTMinimalCommandSetGenerator.h
  3. 91
      src/parser/MarkovAutomatonSparseTransitionParser.cpp
  4. 2
      src/storage/MaximalEndComponentDecomposition.cpp
  5. 282
      src/storage/VectorSet.cpp
  6. 253
      src/storage/VectorSet.h

2
src/counterexamples/MILPMinimalLabelSetGenerator.h

@ -1312,7 +1312,7 @@ namespace storm {
// (4.5) Read off result from variables. // (4.5) Read off result from variables.
storm::storage::VectorSet<uint_fast64_t> usedLabelSet = getUsedLabelsInSolution(environmentModelPair.first, environmentModelPair.second, variableInformation); storm::storage::VectorSet<uint_fast64_t> usedLabelSet = getUsedLabelsInSolution(environmentModelPair.first, environmentModelPair.second, variableInformation);
usedLabelSet.insert(choiceInformation.knownLabels.begin(), choiceInformation.knownLabels.end());
usedLabelSet.insert(choiceInformation.knownLabels);
// Display achieved probability. // Display achieved probability.
std::pair<uint_fast64_t, double> initialStateProbabilityPair = getReachabilityProbability(environmentModelPair.first, environmentModelPair.second, labeledMdp, variableInformation); std::pair<uint_fast64_t, double> initialStateProbabilityPair = getReachabilityProbability(environmentModelPair.first, environmentModelPair.second, labeledMdp, variableInformation);

6
src/counterexamples/SMTMinimalCommandSetGenerator.h

@ -228,7 +228,7 @@ namespace storm {
// If the state is initial, we need to add all the choice labels to the initial label set. // If the state is initial, we need to add all the choice labels to the initial label set.
if (initialStates.get(currentState)) { if (initialStates.get(currentState)) {
initialLabels.insert(choiceLabeling[currentChoice].begin(), choiceLabeling[currentChoice].end());
initialLabels.insert(choiceLabeling[currentChoice]);
initialCombinations.insert(choiceLabeling[currentChoice]); initialCombinations.insert(choiceLabeling[currentChoice]);
} }
@ -246,7 +246,7 @@ namespace storm {
// If the choice can reach a target state directly, we add all the labels to the target label set. // If the choice can reach a target state directly, we add all the labels to the target label set.
if (canReachTargetState) { if (canReachTargetState) {
targetLabels.insert(choiceLabeling[currentChoice].begin(), choiceLabeling[currentChoice].end());
targetLabels.insert(choiceLabeling[currentChoice]);
targetCombinations.insert(choiceLabeling[currentChoice]); targetCombinations.insert(choiceLabeling[currentChoice]);
} }
} }
@ -1513,7 +1513,7 @@ namespace storm {
// Restrict the given MDP to the current set of labels and compute the reachability probability. // Restrict the given MDP to the current set of labels and compute the reachability probability.
modelCheckingClock = std::chrono::high_resolution_clock::now(); modelCheckingClock = std::chrono::high_resolution_clock::now();
commandSet.insert(relevancyInformation.knownLabels.begin(), relevancyInformation.knownLabels.end());
commandSet.insert(relevancyInformation.knownLabels);
storm::models::Mdp<T> subMdp = labeledMdp.restrictChoiceLabels(commandSet); storm::models::Mdp<T> subMdp = labeledMdp.restrictChoiceLabels(commandSet);
storm::modelchecker::prctl::SparseMdpPrctlModelChecker<T> modelchecker(subMdp, new storm::solver::GmmxxNondeterministicLinearEquationSolver<T>()); storm::modelchecker::prctl::SparseMdpPrctlModelChecker<T> modelchecker(subMdp, new storm::solver::GmmxxNondeterministicLinearEquationSolver<T>());
LOG4CPLUS_DEBUG(logger, "Invoking model checker."); LOG4CPLUS_DEBUG(logger, "Invoking model checker.");

91
src/parser/MarkovAutomatonSparseTransitionParser.cpp

@ -43,29 +43,14 @@ namespace storm {
// Record that the current source was the last source. // Record that the current source was the last source.
lastsource = source; lastsource = source;
char actionNameBuffer[20];
#ifdef WINDOWS
int length = sscanf_s(buf, "%20s\n", actionNameBuffer, 20);
#else
int length = sscanf(buf, "%20s\n", actionNameBuffer);
#endif
// If the number of arguments filled is not one, there was an error.
if (length != 1) {
LOG4CPLUS_ERROR(logger, "Parsing error.");
throw storm::exceptions::WrongFormatException() << "Parsing error.";
} else {
// If the action name was parsed successfully, we need to move by the corresponding number of characters.
buf += strlen(actionNameBuffer);
}
// Depending on the action name, the choice is either a probabilitic one or a markovian one. // Depending on the action name, the choice is either a probabilitic one or a markovian one.
bool isMarkovianChoice = false; bool isMarkovianChoice = false;
if (strcmp(actionNameBuffer, "!") == 0) {
if (buf[0] == '!') {
isMarkovianChoice = true; isMarkovianChoice = true;
} else { } else {
isMarkovianChoice = false; isMarkovianChoice = false;
} }
++buf;
if (isMarkovianChoice) { if (isMarkovianChoice) {
if (stateHasMarkovianChoice) { if (stateHasMarkovianChoice) {
@ -89,33 +74,21 @@ namespace storm {
// At this point, we need to check whether there is an additional successor or we have reached the next choice for the same or a different state. // At this point, we need to check whether there is an additional successor or we have reached the next choice for the same or a different state.
do { do {
// Now parse the next symbol to see whether there is another target state for the current choice
// or not.
char star[1];
#ifdef WINDOWS
length = sscanf_s(buf, "%1s\n", star, 1);
#else
length = sscanf(buf, "%1s\n", star);
#endif
// If the number of arguments filled is not one, there was an error.
if (length == EOF) {
// If the end of the file was reached, we need to abort and check whether we are in a legal state.
if (buf[0] == '\0') {
if (!hasSuccessorState) { if (!hasSuccessorState) {
LOG4CPLUS_ERROR(logger, "Premature end-of-file. Expected at least one successor state for state " << source << " under action " << actionNameBuffer << ".");
throw storm::exceptions::WrongFormatException() << "Premature end-of-file. Expected at least one successor state for state " << source << " under action " << actionNameBuffer << ".";
LOG4CPLUS_ERROR(logger, "Premature end-of-file. Expected at least one successor state for state " << source << ".");
throw storm::exceptions::WrongFormatException() << "Premature end-of-file. Expected at least one successor state for state " << source << ".";
} else { } else {
// If there was at least one successor for the current choice, this is legal and we need to move on. // If there was at least one successor for the current choice, this is legal and we need to move on.
encounteredEOF = true; encounteredEOF = true;
} }
} else if (length != 1) {
LOG4CPLUS_ERROR(logger, "Parsing error.");
throw storm::exceptions::WrongFormatException() << "Parsing error.";
} else if (strcmp(star, "*") == 0) {
} else if (buf[0] == '*') {
// We need to record that we found at least one successor state for the current choice. // We need to record that we found at least one successor state for the current choice.
hasSuccessorState = true; hasSuccessorState = true;
// As we have encountered a "*", we know that there is an additional successor state for the current choice. // As we have encountered a "*", we know that there is an additional successor state for the current choice.
buf += strlen(star);
++buf;
// Now we need to read the successor state and check if we already saw a higher state index. // Now we need to read the successor state and check if we already saw a higher state index.
target = checked_strtol(buf, &buf); target = checked_strtol(buf, &buf);
@ -165,7 +138,7 @@ namespace storm {
// If we have skipped some states, we need to insert self-loops if requested. // If we have skipped some states, we need to insert self-loops if requested.
if (source > lastsource + 1) { if (source > lastsource + 1) {
if (fixDeadlocks) { if (fixDeadlocks) {
for (uint_fast64_t index = lastsource + 1; index < source; ++source) {
for (uint_fast64_t index = lastsource + 1; index < source; ++index) {
result.nondeterministicChoiceIndices[index] = currentChoice; result.nondeterministicChoiceIndices[index] = currentChoice;
result.transitionMatrix.addNextValue(currentChoice, index, 1); result.transitionMatrix.addNextValue(currentChoice, index, 1);
++currentChoice; ++currentChoice;
@ -184,25 +157,9 @@ namespace storm {
// Record that the current source was the last source. // Record that the current source was the last source.
lastsource = source; lastsource = source;
char actionNameBuffer[20];
#ifdef WINDOWS
int length = sscanf_s(buf, "%20s\n", actionNameBuffer, 20);
#else
int length = sscanf(buf, "%20s\n", actionNameBuffer);
#endif
// If the number of arguments filled is not one, there was an error.
if (length != 1) {
LOG4CPLUS_ERROR(logger, "Parsing error.");
throw storm::exceptions::WrongFormatException() << "Parsing error.";
} else {
// If the action name was parsed successfully, we need to move by the corresponding number of characters.
buf += strlen(actionNameBuffer);
}
// Depending on the action name, the choice is either a probabilitic one or a markovian one. // Depending on the action name, the choice is either a probabilitic one or a markovian one.
bool isMarkovianChoice = false; bool isMarkovianChoice = false;
if (strcmp(actionNameBuffer, "!") == 0) {
if (buf[0] == '!') {
isMarkovianChoice = true; isMarkovianChoice = true;
// Mark the current state as a Markovian one. // Mark the current state as a Markovian one.
@ -219,33 +176,17 @@ namespace storm {
// At this point, we need to check whether there is an additional successor or we have reached the next choice for the same or a different state. // At this point, we need to check whether there is an additional successor or we have reached the next choice for the same or a different state.
do { do {
// Now parse the next symbol to see whether there is another target state for the current choice
// or not.
char star[1];
#ifdef WINDOWS
length = sscanf_s(buf, "%1s\n", star, 1);
#else
length = sscanf(buf, "%1s\n", star);
#endif
// If the number of arguments filled is not one, there was an error.
if (length == EOF) {
if (!hasSuccessorState) {
LOG4CPLUS_ERROR(logger, "Premature end-of-file. Expected at least one successor state for state " << source << " under action " << actionNameBuffer << ".");
throw storm::exceptions::WrongFormatException() << "Premature end-of-file. Expected at least one successor state for state " << source << " under action " << actionNameBuffer << ".";
} else {
// If there was at least one successor for the current choice, this is legal and we need to move on.
// If the end of the file was reached, we need to abort and check whether we are in a legal state.
if (buf[0] == '\0') {
// Under the assumption that the currently open choice has at least one successor (which is given after the first run)
// we may legally stop reading here.
encounteredEOF = true; encounteredEOF = true;
}
} else if (length != 1) {
LOG4CPLUS_ERROR(logger, "Parsing error.");
throw storm::exceptions::WrongFormatException() << "Parsing error.";
} else if (strcmp(star, "*") == 0) {
} else if (buf[0] == '*') {
// We need to record that we found at least one successor state for the current choice. // We need to record that we found at least one successor state for the current choice.
hasSuccessorState = true; hasSuccessorState = true;
// As we have encountered a "*", we know that there is an additional successor state for the current choice. // As we have encountered a "*", we know that there is an additional successor state for the current choice.
buf += strlen(star);
++buf;
// Now we need to read the successor state and check if we already saw a higher state index. // Now we need to read the successor state and check if we already saw a higher state index.
target = checked_strtol(buf, &buf); target = checked_strtol(buf, &buf);

2
src/storage/MaximalEndComponentDecomposition.cpp

@ -94,7 +94,7 @@ namespace storm {
// Now erase the states that have no option to stay inside the MEC with all successors. // Now erase the states that have no option to stay inside the MEC with all successors.
mecChanged |= !statesToRemove.empty(); mecChanged |= !statesToRemove.empty();
std::vector<uint_fast64_t> statesToRemoveList = statesToRemove.getSetIndicesList(); std::vector<uint_fast64_t> statesToRemoveList = statesToRemove.getSetIndicesList();
scc.erase(storm::storage::VectorSet<uint_fast64_t>(statesToRemoveList.begin(), statesToRemoveList.end()));
scc.erase(storm::storage::VectorSet<uint_fast64_t>(statesToRemoveList));
// Now check which states should be reconsidered, because successors of them were removed. // Now check which states should be reconsidered, because successors of them were removed.
statesToCheck.clear(); statesToCheck.clear();

282
src/storage/VectorSet.cpp

@ -0,0 +1,282 @@
#include "src/storage/VectorSet.h"
namespace storm {
namespace storage {
template<typename ValueType>
VectorSet<ValueType>::VectorSet() : data(), dirty(false) {
// Intentionally left empty.
}
template<typename ValueType>
VectorSet<ValueType>::VectorSet(uint_fast64_t size) : data(), dirty(false) {
data.reserve(size);
}
template<typename ValueType>
VectorSet<ValueType>::VectorSet(std::vector<ValueType> const& data) : data(data), dirty(true) {
ensureSet();
}
template<typename ValueType>
VectorSet<ValueType>::VectorSet(std::set<ValueType> const& data) : dirty(false) {
this->data.reserve(data.size());
for (auto const& element : data) {
this->data.push_back(element);
}
}
template<typename ValueType>
VectorSet<ValueType>::VectorSet(uint_fast64_t from, uint_fast64_t to) : dirty(false) {
data.reserve(to - from);
for (uint_fast64_t element = from; element < to; ++element) {
data.push_back(element);
}
}
template<typename ValueType>
VectorSet<ValueType>::VectorSet(VectorSet const& other) : dirty(false) {
other.ensureSet();
data = other.data;
}
template<typename ValueType>
VectorSet<ValueType>& VectorSet<ValueType>::operator=(VectorSet<ValueType> const& other) {
data = other.data;
dirty = other.dirty;
return *this;
}
template<typename ValueType>
VectorSet<ValueType>::VectorSet(VectorSet<ValueType>&& other) : data(std::move(other.data)), dirty(std::move(other.dirty)) {
// Intentionally left empty.
}
template<typename ValueType>
VectorSet<ValueType>& VectorSet<ValueType>::operator=(VectorSet&& other) {
data = std::move(other.data);
dirty = std::move(other.dirty);
return *this;
}
template<typename ValueType>
bool VectorSet<ValueType>::operator==(VectorSet<ValueType> const& other) const {
ensureSet();
if (this->size() != other.size()) return false;
return std::equal(data.begin(), data.end(), other.begin());
}
template<typename ValueType>
bool VectorSet<ValueType>::operator<(VectorSet<ValueType> const& other) const {
ensureSet();
if (this->size() < other.size()) return true;
if (this->size() > other.size()) return false;
for (auto it1 = this->begin(), it2 = other.begin(); it1 != this->end(); ++it1, ++it2) {
if (*it1 < *it2) return true;
if (*it1 > *it2) return false;
}
return false;
}
template<typename ValueType>
bool VectorSet<ValueType>::operator>(VectorSet<ValueType> const& other) const {
ensureSet();
if (this->size() > other.size()) return true;
if (this->size() < other.size()) return false;
for (auto it1 = this->begin(), it2 = other.begin(); it1 != this->end(); ++it1, ++it2) {
if (*it1 > *it2) return true;
if (*it1 < *it2) return false;
}
return false;
}
template<typename ValueType>
void VectorSet<ValueType>::ensureSet() const {
if (dirty) {
std::sort(data.begin(), data.end());
data.erase(std::unique(data.begin(), data.end()), data.end());
dirty = false;
}
}
template<typename ValueType>
bool VectorSet<ValueType>::contains(ValueType const& element) const {
ensureSet();
return std::binary_search(data.begin(), data.end(), element);
}
template<typename ValueType>
bool VectorSet<ValueType>::subsetOf(VectorSet<ValueType> const& other) const {
ensureSet();
other.ensureSet();
return std::includes(other.begin(), other.end(), data.begin(), data.end());
}
template<typename ValueType>
bool VectorSet<ValueType>::supersetOf(VectorSet<ValueType> const& other) const {
ensureSet();
return other.subsetOf(*this);
}
template<typename ValueType>
VectorSet<ValueType> VectorSet<ValueType>::intersect(VectorSet<ValueType> const& other) {
ensureSet();
other.ensureSet();
VectorSet result;
std::set_intersection(data.begin(), data.end(), other.begin(), other.end(), std::inserter(result.data, result.data.end()));
return result;
}
template<typename ValueType>
VectorSet<ValueType> VectorSet<ValueType>::join(VectorSet<ValueType> const& other) {
ensureSet();
other.ensureSet();
VectorSet result;
std::set_union(data.begin(), data.end(), other.begin(), other.end(), std::inserter(result.data, result.data.end()));
return result;
}
template<typename ValueType>
typename VectorSet<ValueType>::iterator VectorSet<ValueType>::begin() {
ensureSet();
return data.begin();
}
template<typename ValueType>
typename VectorSet<ValueType>::iterator VectorSet<ValueType>::end() {
ensureSet();
return data.end();
}
template<typename ValueType>
typename VectorSet<ValueType>::const_iterator VectorSet<ValueType>::begin() const {
ensureSet();
return data.begin();
}
template<typename ValueType>
typename VectorSet<ValueType>::const_iterator VectorSet<ValueType>::end() const {
ensureSet();
return data.end();
}
template<typename ValueType>
ValueType const& VectorSet<ValueType>::min() const {
if (this->size() == 0) {
throw storm::exceptions::InvalidStateException() << "Cannot retrieve minimum of empty set.";
}
ensureSet();
return data.front();
}
template<typename ValueType>
ValueType const& VectorSet<ValueType>::max() const {
if (this->size() == 0) {
throw storm::exceptions::InvalidStateException() << "Cannot retrieve minimum of empty set.";
}
ensureSet();
return data.back();
}
template<typename ValueType>
void VectorSet<ValueType>::insert(ValueType const& element) {
data.push_back(element);
dirty = true;
}
template<typename ValueType>
typename VectorSet<ValueType>::iterator VectorSet<ValueType>::insert(typename VectorSet<ValueType>::const_iterator pos, ValueType const& element) {
dirty = true;
return data.insert(pos, element);
}
template<typename ValueType>
void VectorSet<ValueType>::insert(VectorSet<ValueType> const& other) {
data.insert(data.end(), other.data.begin(), other.data.end());
}
template<typename ValueType>
bool VectorSet<ValueType>::empty() const {
ensureSet();
return data.empty();
}
template<typename ValueType>
size_t VectorSet<ValueType>::size() const {
ensureSet();
return data.size();
}
template<typename ValueType>
void VectorSet<ValueType>::clear() {
data.clear();
dirty = false;
}
template<typename ValueType>
bool VectorSet<ValueType>::erase(ValueType const& element) {
ensureSet();
uint_fast64_t lowerBound = 0;
uint_fast64_t upperBound = data.size();
while (lowerBound != upperBound) {
uint_fast64_t currentPosition = lowerBound + (upperBound - lowerBound) / 2;
bool searchInLowerHalf = element < data[currentPosition];
if (searchInLowerHalf) {
upperBound = currentPosition;
} else {
bool searchInRightHalf = element > data[currentPosition];
if (searchInRightHalf) {
lowerBound = currentPosition + 1;
} else {
// At this point we have found the element.
data.erase(data.begin() + currentPosition);
return true;
}
}
}
return false;
}
template<typename ValueType>
void VectorSet<ValueType>::erase(VectorSet<ValueType> const& eraseSet) {
if (eraseSet.size() > 0) {
ensureSet();
eraseSet.ensureSet();
for (typename std::vector<ValueType>::reverse_iterator delIt = eraseSet.data.rbegin(), setIt = data.rbegin(); delIt != eraseSet.data.rend() && setIt != eraseSet.data.rend(); ++delIt) {
while (setIt != eraseSet.data.rend() && *setIt > *delIt) {
++setIt;
}
if (setIt != data.rend()) break;
if (*setIt == *delIt) {
data.erase((setIt + 1).base());
++setIt;
}
}
}
}
template<typename ValueType>
std::ostream& operator<<(std::ostream& stream, VectorSet<ValueType> const& set) {
set.ensureSet();
stream << "VectorSet(" << set.size() << ") { ";
if (set.size() > 0) {
for (uint_fast64_t index = 0; index < set.size() - 1; ++index) {
stream << set.data[index] << ", ";
}
stream << set.data[set.size() - 1] << " }";
} else {
stream << "}";
}
return stream;
}
template class VectorSet<uint_fast64_t>;
template class VectorSet<VectorSet<uint_fast64_t>>;
template std::ostream& operator<<(std::ostream& stream, VectorSet<uint_fast64_t> const& set);
template std::ostream& operator<<(std::ostream& stream, VectorSet<VectorSet<uint_fast64_t>> const& set);
}
}

253
src/storage/VectorSet.h

@ -19,254 +19,85 @@
namespace storm { namespace storm {
namespace storage { namespace storage {
template<typename T>
template<typename ValueType>
class VectorSet { class VectorSet {
public: public:
typedef T* difference_type;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator;
VectorSet() : data(), dirty(false) {
// Intentionally left empty.
}
VectorSet(uint_fast64_t size) : data(), dirty(false) {
data.reserve(size);
}
typedef ValueType* difference_type;
typedef ValueType value_type;
typedef ValueType* pointer;
typedef ValueType& reference;
typedef typename std::vector<ValueType>::iterator iterator;
typedef typename std::vector<ValueType>::const_iterator const_iterator;
VectorSet(std::vector<T> const& data) : data(data), dirty(true) {
ensureSet();
}
VectorSet(std::set<T> const& data) : dirty(false) {
this->data.reserve(data.size());
for (auto const& element : data) {
this->data.push_back(element);
}
}
VectorSet();
VectorSet(uint_fast64_t from, uint_fast64_t to) : dirty(false) {
data.reserve(to - from);
VectorSet(uint_fast64_t size);
for (uint_fast64_t element = from; element < to; ++element) {
data.push_back(element);
}
}
template<typename InputIterator>
VectorSet(InputIterator first, InputIterator last) : data(first, last), dirty(true) {
ensureSet();
}
VectorSet(VectorSet const& other) : dirty(false) {
other.ensureSet();
data = other.data;
}
VectorSet(std::vector<ValueType> const& data);
VectorSet& operator=(VectorSet const& other) {
data = other.data;
dirty = other.dirty;
return *this;
}
VectorSet(std::set<ValueType> const& data);
VectorSet(VectorSet&& other) : data(std::move(other.data)), dirty(std::move(other.dirty)) {
// Intentionally left empty.
}
VectorSet(uint_fast64_t from, uint_fast64_t to);
VectorSet& operator=(VectorSet&& other) {
data = std::move(other.data);
dirty = std::move(other.dirty);
return *this;
}
VectorSet(VectorSet const& other);
bool operator==(VectorSet const& other) const {
ensureSet();
if (this->size() != other.size()) return false;
return std::equal(data.begin(), data.end(), other.begin());
}
VectorSet& operator=(VectorSet const& other);
bool operator<(VectorSet const& other) const {
ensureSet();
if (this->size() < other.size()) return true;
if (this->size() > other.size()) return false;
for (auto it1 = this->begin(), it2 = other.begin(); it1 != this->end(); ++it1, ++it2) {
if (*it1 < *it2) return true;
if (*it1 > *it2) return false;
}
return false;
}
VectorSet(VectorSet&& other);
void ensureSet() const {
if (dirty) {
std::sort(data.begin(), data.end());
data.erase(std::unique(data.begin(), data.end()), data.end());
dirty = false;
}
}
VectorSet& operator=(VectorSet&& other);
bool contains(T const& element) const {
ensureSet();
return std::binary_search(data.begin(), data.end(), element);
}
bool operator==(VectorSet const& other) const;
bool subsetOf(VectorSet const& other) const {
ensureSet();
other.ensureSet();
return std::includes(other.begin(), other.end(), data.begin(), data.end());
}
bool operator<(VectorSet const& other) const;
bool supersetOf(VectorSet const& other) const {
ensureSet();
return other.subsetOf(*this);
}
bool operator>(VectorSet const& other) const;
VectorSet intersect(VectorSet const& other) {
ensureSet();
other.ensureSet();
VectorSet result;
std::set_intersection(data.begin(), data.end(), other.begin(), other.end(), std::inserter(result.data, result.data.end()));
return result;
}
void ensureSet() const;
VectorSet join(VectorSet const& other) {
ensureSet();
other.ensureSet();
VectorSet result;
std::set_union(data.begin(), data.end(), other.begin(), other.end(), std::inserter(result.data, result.data.end()));
return result;
}
bool contains(ValueType const& element) const;
iterator begin() {
ensureSet();
return data.begin();
}
bool subsetOf(VectorSet const& other) const;
iterator end() {
ensureSet();
return data.end();
}
bool supersetOf(VectorSet const& other) const;
const_iterator begin() const {
ensureSet();
return data.begin();
}
VectorSet intersect(VectorSet const& other);
const_iterator end() const {
ensureSet();
return data.end();
}
VectorSet join(VectorSet const& other);
T const& min() const {
if (this->size() == 0) {
throw storm::exceptions::InvalidStateException() << "Cannot retrieve minimum of empty set.";
}
iterator begin();
ensureSet();
return data.first;
}
iterator end();
T const& max() const {
if (this->size() == 0) {
throw storm::exceptions::InvalidStateException() << "Cannot retrieve minimum of empty set.";
}
const_iterator begin() const;
ensureSet();
return data.back;
}
const_iterator end() const;
void insert(T const& element) {
data.push_back(element);
dirty = true;
}
ValueType const& min() const;
template<typename InputIterator>
iterator insert(InputIterator first, InputIterator last) {
dirty = true;
return data.insert(data.end(), first, last);
}
ValueType const& max() const;
template<typename InputIterator>
iterator insert(InputIterator pos, T element) {
dirty = true;
return data.insert(pos, element);
}
void insert(ValueType const& element);
bool empty() const {
ensureSet();
return data.empty();
}
iterator insert(const_iterator pos, ValueType const& element);
size_t size() const {
ensureSet();
return data.size();
}
void insert(VectorSet<ValueType> const& other);
void clear() {
data.clear();
dirty = false;
}
bool empty() const;
bool erase(T const& element) {
ensureSet();
uint_fast64_t lowerBound = 0;
uint_fast64_t upperBound = data.size();
while (lowerBound != upperBound) {
uint_fast64_t currentPosition = lowerBound + (upperBound - lowerBound) / 2;
bool searchInLowerHalf = element < data[currentPosition];
if (searchInLowerHalf) {
upperBound = currentPosition;
} else {
bool searchInRightHalf = element > data[currentPosition];
if (searchInRightHalf) {
lowerBound = currentPosition + 1;
} else {
// At this point we have found the element.
data.erase(data.begin() + currentPosition);
return true;
}
}
}
return false;
}
size_t size() const;
void erase(VectorSet const& eraseSet) {
if (eraseSet.size() > 0) {
ensureSet();
eraseSet.ensureSet();
void clear();
for (typename std::vector<T>::reverse_iterator delIt = eraseSet.data.rbegin(), setIt = data.rbegin(); delIt != eraseSet.data.rend() && setIt != eraseSet.data.rend(); ++delIt) {
while (setIt != eraseSet.data.rend() && *setIt > *delIt) {
++setIt;
}
if (setIt != data.rend()) break;
bool erase(ValueType const& element);
if (*setIt == *delIt) {
data.erase((setIt + 1).base());
++setIt;
}
}
}
}
void erase(VectorSet const& eraseSet);
friend std::ostream& operator<< (std::ostream& stream, VectorSet const& set) {
set.ensureSet();
stream << "VectorSet(" << set.size() << ") { ";
if (set.size() > 0) {
for (uint_fast64_t index = 0; index < set.size() - 1; ++index) {
stream << set.data[index] << ", ";
}
stream << set.data[set.size() - 1] << " }";
} else {
stream << "}";
}
return stream;
}
template<typename ValueTypePrime>
friend std::ostream& operator<< (std::ostream& stream, VectorSet<ValueTypePrime> const& set);
private: private:
mutable std::vector<T> data;
mutable std::vector<ValueType> data;
mutable bool dirty; mutable bool dirty;
}; };
} }

Loading…
Cancel
Save