142 lines
7.8 KiB
142 lines
7.8 KiB
#pragma once
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <unordered_map>
|
|
#include <set>
|
|
|
|
|
|
#include "storm-pars/storage/ParameterRegion.h"
|
|
#include "storm-pars/utility/parametric.h"
|
|
#include "storm/storage/BitVector.h"
|
|
#include "storm/storage/SparseMatrix.h"
|
|
#include "storm/solver/OptimizationDirection.h"
|
|
|
|
namespace storm {
|
|
namespace transformer {
|
|
|
|
/*!
|
|
* This class lifts parameter choices to nondeterminism:
|
|
* For each row in the given matrix that considerd #par parameters, the resulting matrix will have one row group consisting of 2^#par rows.
|
|
* When specifying a region, each row within the row group is evaluated w.r.t. one vertex of the region.
|
|
* The given vector is handled similarly.
|
|
* However, if a vector entry considers a parameter that does not occur in the corresponding matrix row,
|
|
* the parameter is directly set such that the vector entry is maximized (or minimized, depending on the specified optimization direction).
|
|
*
|
|
* @note The row grouping of the original matrix is ignored.
|
|
*/
|
|
template<typename ParametricType, typename ConstantType>
|
|
class ParameterLifter {
|
|
public:
|
|
|
|
typedef typename storm::utility::parametric::VariableType<ParametricType>::type VariableType;
|
|
typedef typename storm::utility::parametric::CoefficientType<ParametricType>::type CoefficientType;
|
|
|
|
/*!
|
|
* Lifts the parameter choices to nondeterminisim. The computation is performed on the submatrix specified by the selected rows and columns
|
|
* @param pMatrix the parametric matrix
|
|
* @param pVector the parametric vector (the vector size should equal the row count of the matrix)
|
|
* @param selectedRows a Bitvector that specifies which rows of the matrix and the vector are considered.
|
|
* @param selectedColumns a Bitvector that specifies which columns of the matrix are considered.
|
|
*/
|
|
ParameterLifter(storm::storage::SparseMatrix<ParametricType> const& pMatrix, std::vector<ParametricType> const& pVector, storm::storage::BitVector const& selectedRows, storm::storage::BitVector const& selectedColumns, bool generateRowLabels = false);
|
|
|
|
void specifyRegion(storm::storage::ParameterRegion<ParametricType> const& region, storm::solver::OptimizationDirection const& dirForParameters);
|
|
|
|
// Returns the resulting matrix. Should only be called AFTER specifying a region
|
|
storm::storage::SparseMatrix<ConstantType> const& getMatrix() const;
|
|
|
|
// Returns the resulting vector. Should only be called AFTER specifying a region
|
|
std::vector<ConstantType> const& getVector() const;
|
|
|
|
/*
|
|
* During initialization, the actual regions are not known. Hence, we consider abstract valuations,
|
|
* where it is only known whether a parameter will be set to either the lower/upper bound of the region or whether this is unspecified
|
|
*/
|
|
class AbstractValuation {
|
|
public:
|
|
AbstractValuation() = default;
|
|
AbstractValuation(AbstractValuation const& other) = default;
|
|
bool operator==(AbstractValuation const& other) const;
|
|
|
|
void addParameterLower(VariableType const& var);
|
|
void addParameterUpper(VariableType const& var);
|
|
void addParameterUnspecified(VariableType const& var);
|
|
|
|
std::size_t getHashValue() const;
|
|
AbstractValuation getSubValuation(std::set<VariableType> const& pars) const;
|
|
std::set<VariableType> const& getLowerParameters() const;
|
|
std::set<VariableType> const& getUpperParameters() const;
|
|
std::set<VariableType> const& getUnspecifiedParameters() const;
|
|
|
|
/*!
|
|
* Returns the concrete valuation(s) (w.r.t. the provided region) represented by this abstract valuation.
|
|
* Note that an abstract valuation represents 2^(#unspecified parameters) many concrete valuations.
|
|
*/
|
|
std::vector<storm::utility::parametric::Valuation<ParametricType>> getConcreteValuations(storm::storage::ParameterRegion<ParametricType> const& region) const;
|
|
|
|
private:
|
|
std::set<VariableType> lowerPars, upperPars, unspecifiedPars;
|
|
};
|
|
|
|
// Returns for each row the abstract valuation for this row
|
|
// Note: the returned vector might be empty if row label generaion was disabled initially
|
|
std::vector<AbstractValuation> const& getRowLabels() const;
|
|
|
|
|
|
private:
|
|
/*
|
|
* We minimize the number of function evaluations by only calling evaluate() once for each unique pair of function and valuation.
|
|
* The result of each evaluation is then written to all positions in the matrix (and the vector) where the corresponding (function,valuation) occurred.
|
|
*/
|
|
|
|
/*!
|
|
* Collects all occurring pairs of functions and (abstract) valuations.
|
|
* We also store a placeholder for the result of each pair. The result is computed and written into the placeholder whenever a region and optimization direction is specified.
|
|
*/
|
|
class FunctionValuationCollector {
|
|
public:
|
|
FunctionValuationCollector() = default;
|
|
|
|
/*!
|
|
* Adds the provided function and valuation.
|
|
* Returns a reference to a placeholder in which the evaluation result will be written upon calling evaluateCollectedFunctions)
|
|
*/
|
|
ConstantType& add(ParametricType const& function, AbstractValuation const& valuation);
|
|
|
|
void evaluateCollectedFunctions(storm::storage::ParameterRegion<ParametricType> const& region, storm::solver::OptimizationDirection const& dirForUnspecifiedParameters);
|
|
|
|
private:
|
|
// Stores a function and a valuation. The valuation is stored as an index of the collectedValuations-vector.
|
|
typedef std::pair<ParametricType, AbstractValuation> FunctionValuation;
|
|
class FuncValHash{
|
|
public:
|
|
std::size_t operator()(FunctionValuation const& fv) const {
|
|
std::size_t seed = 0;
|
|
carl::hash_add(seed, fv.first);
|
|
carl::hash_add(seed, fv.second.getHashValue());
|
|
return seed;
|
|
}
|
|
};
|
|
|
|
// Stores the collected functions with the valuations together with a placeholder for the result.
|
|
std::unordered_map<FunctionValuation, ConstantType, FuncValHash> collectedFunctions;
|
|
};
|
|
|
|
FunctionValuationCollector functionValuationCollector;
|
|
|
|
// Returns the 2^(variables.size()) vertices of the region
|
|
std::vector<AbstractValuation> getVerticesOfAbstractRegion(std::set<VariableType> const& variables) const;
|
|
|
|
std::vector<AbstractValuation> rowLabels;
|
|
|
|
storm::storage::SparseMatrix<ConstantType> matrix; //The resulting matrix;
|
|
std::vector<std::pair<typename storm::storage::SparseMatrix<ConstantType>::iterator, ConstantType&>> matrixAssignment; // Connection of matrix entries with placeholders
|
|
|
|
std::vector<ConstantType> vector; //The resulting vector
|
|
std::vector<std::pair<typename std::vector<ConstantType>::iterator, ConstantType&>> vectorAssignment; // Connection of vector entries with placeholders
|
|
|
|
};
|
|
|
|
}
|
|
}
|