You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

182 lines
8.7 KiB

#include <string>
#include <unordered_map>
#include "src/storage/ppg/ProgramGraph.h"
#include "src/storage/jani/Model.h"
#include "src/storage/jani/Location.h"
#include "src/storage/jani/EdgeDestination.h"
#include "src/storage/IntegerInterval.h"
#include "src/exceptions/NotSupportedException.h"
#include "src/utility/macros.h"
namespace storm {
namespace builder {
enum class JaniProgramGraphVariableDomainMethod {
Unrestricted, IntervalPropagation
};
struct JaniProgramGraphBuilderSetting {
JaniProgramGraphVariableDomainMethod variableDomainMethod = JaniProgramGraphVariableDomainMethod::Unrestricted;
};
class JaniProgramGraphBuilder {
public:
static unsigned janiVersion;
JaniProgramGraphBuilder(storm::ppg::ProgramGraph const& pg) : programGraph(pg) {
rewards = programGraph.rewardVariables();
constants = programGraph.constants();
auto boundedVars = programGraph.constantAssigned();
for(auto const& v : boundedVars) {
variableRestrictions.emplace(v, programGraph.supportForConstAssignedVariable(v));
}
}
virtual ~JaniProgramGraphBuilder() {
for (auto& var : variables ) {
delete var.second;
}
}
//void addVariableRestriction(storm::expressions::Variable const& var, storm::IntegerInterval const& interval ) {
//}
void restrictAllVariables(int64_t from, int64_t to) {
restrictAllVariables(storm::storage::IntegerInterval(from, to));
}
void restrictAllVariables(storm::storage::IntegerInterval const& restr) {
for (auto const& v : programGraph.getVariables()) {
if(isConstant(v.first)) {
continue;
}
if(variableRestrictions.count(v.first) > 0) {
continue; // Currently we ignore user bounds if we have bounded integers;
}
if(v.second.hasIntegerType() ) {
userVariableRestrictions.emplace(v.first, restr);
}
}
}
storm::jani::Model* build(std::string const& name = "program_graph") {
expManager = programGraph.getExpressionManager();
storm::jani::Model* model = new storm::jani::Model(name, storm::jani::ModelType::MDP, janiVersion, expManager);
storm::jani::Automaton mainAutomaton("main");
addProcedureVariables(*model, mainAutomaton);
janiLocId = addProcedureLocations(*model, mainAutomaton);
addVariableOoBLocations(mainAutomaton);
addEdges(mainAutomaton);
model->addAutomaton(mainAutomaton);
model->setStandardSystemComposition();
return model;
}
private:
std::string janiLocationName(storm::ppg::ProgramLocationIdentifier i) {
return "l" + std::to_string(i);
}
std::string janiVariableOutOfBoundsLocationName(storm::ppg::ProgramVariableIdentifier i) {
return "oob-" + programGraph.getVariableName(i);
}
storm::jani::OrderedAssignments buildOrderedAssignments(storm::jani::Automaton& automaton, storm::ppg::DeterministicProgramAction const& act) ;
void addEdges(storm::jani::Automaton& automaton);
std::vector<storm::jani::EdgeDestination> buildDestinations(storm::jani::Automaton& automaton, storm::ppg::ProgramEdge const& edge );
/**
* Helper for probabilistic assignments
*/
std::vector<storm::jani::EdgeDestination> buildProbabilisticDestinations(storm::jani::Automaton& automaton, storm::ppg::ProgramEdge const& edge );
std::pair<std::vector<storm::jani::Edge>, storm::expressions::Expression> addVariableChecks(storm::ppg::ProgramEdge const& edge);
bool isUserRestrictedVariable(storm::ppg::ProgramVariableIdentifier i) const {
return userVariableRestrictions.count(i) == 1 && !isRewardVariable(i);
}
bool isRestrictedVariable(storm::ppg::ProgramVariableIdentifier i) const {
// Might be different from user restricted in near future.
return (variableRestrictions.count(i) == 1 && !isRewardVariable(i)) || isUserRestrictedVariable(i);
}
storm::storage::IntegerInterval const& variableBounds(storm::ppg::ProgramVariableIdentifier i) const {
assert(isRestrictedVariable(i));
if (userVariableRestrictions.count(i) == 1) {
return userVariableRestrictions.at(i);
} else {
return variableRestrictions.at(i);
}
}
bool isRewardVariable(storm::ppg::ProgramVariableIdentifier i) const {
return std::find(rewards.begin(), rewards.end(), i) != rewards.end();
}
bool isConstant(storm::ppg::ProgramVariableIdentifier i) const {
return std::find(constants.begin(), constants.end(), i) != constants.end();
}
void addProcedureVariables(storm::jani::Model& model, storm::jani::Automaton& automaton);
std::map<storm::ppg::ProgramLocationIdentifier, uint64_t> addProcedureLocations(storm::jani::Model& model, storm::jani::Automaton& automaton) {
std::map<storm::ppg::ProgramLocationIdentifier, uint64_t> result;
std::map<std::string, storm::jani::BooleanVariable const*> labelVars;
std::set<std::string> labels = programGraph.getLabels();
for(auto const& label : labels) {
storm::jani::BooleanVariable janiVar(label, expManager->declareBooleanVariable(label), expManager->boolean(false), true);
labelVars.emplace(label, &model.addVariable(janiVar));
}
for (auto it = programGraph.locationBegin(); it != programGraph.locationEnd(); ++it) {
storm::jani::Location janiLoc(janiLocationName(it->second.id()));
for(auto const& label : programGraph.getLabels(it->second.id())) {
assert(labelVars.count(label) > 0);
janiLoc.addTransientAssignment(storm::jani::Assignment(*(labelVars.at(label)), expManager->boolean(true)));
}
result[it->second.id()] = automaton.addLocation(janiLoc);
if (it->second.isInitial()) {
automaton.addInitialLocation(result[it->second.id()]);
}
}
return result;
}
void addVariableOoBLocations(storm::jani::Automaton& automaton) {
for(auto const& restr : userVariableRestrictions) {
if(!isRewardVariable(restr.first)) {
storm::jani::Location janiLoc(janiVariableOutOfBoundsLocationName(restr.first));
uint64_t locId = automaton.addLocation(janiLoc);
varOutOfBoundsLocations[restr.first] = locId;
}
}
}
/// Transient variables
std::vector<storm::ppg::ProgramVariableIdentifier> rewards;
/// Variables that are constants
std::vector<storm::ppg::ProgramVariableIdentifier> constants;
/// Restrictions on variables (automatic)
std::map<uint64_t, storm::storage::IntegerInterval> variableRestrictions;
/// Restrictions on variables (provided by users)
std::map<uint64_t, storm::storage::IntegerInterval> userVariableRestrictions;
/// Locations for variables that would have gone ot o
std::map<uint64_t, uint64_t> varOutOfBoundsLocations;
std::map<storm::ppg::ProgramLocationIdentifier, uint64_t> janiLocId;
std::map<storm::ppg::ProgramVariableIdentifier, storm::jani::Variable*> variables;
/// The expression manager
std::shared_ptr<storm::expressions::ExpressionManager> expManager;
/// The program graph to be translated
storm::ppg::ProgramGraph const& programGraph;
};
}
}