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.
195 lines
5.9 KiB
195 lines
5.9 KiB
/*
|
|
* CuddUtility.cpp
|
|
*
|
|
* Created on: 26.01.2013
|
|
* Author: Christian Dehnert
|
|
*/
|
|
|
|
#include "CuddUtility.h"
|
|
#include "src/exceptions/InvalidArgumentException.h"
|
|
|
|
#include "log4cplus/logger.h"
|
|
#include "log4cplus/loggingmacros.h"
|
|
|
|
extern log4cplus::Logger logger;
|
|
|
|
#include <stdio.h>
|
|
#include <iostream>
|
|
|
|
namespace storm {
|
|
|
|
namespace utility {
|
|
|
|
storm::utility::CuddUtility* storm::utility::CuddUtility::instance = nullptr;
|
|
|
|
ADD* CuddUtility::getNewAddVariable() {
|
|
ADD* result = new ADD(manager.addVar());
|
|
allDecisionDiagramVariables.push_back(result);
|
|
return result;
|
|
}
|
|
|
|
ADD* CuddUtility::getAddVariable(int index) const {
|
|
return new ADD(manager.addVar(index));
|
|
}
|
|
|
|
ADD* CuddUtility::getOne() const {
|
|
return new ADD(manager.addOne());
|
|
}
|
|
|
|
ADD* CuddUtility::getZero() const {
|
|
return new ADD(manager.addZero());
|
|
}
|
|
|
|
ADD* CuddUtility::getConstantEncoding(uint_fast64_t constant, std::vector<ADD*> const& variables) const {
|
|
if ((constant >> variables.size()) != 0) {
|
|
LOG4CPLUS_ERROR(logger, "Cannot create encoding for constant " << constant << " with "
|
|
<< variables.size() << " variables.");
|
|
throw storm::exceptions::InvalidArgumentException() << "Cannot create encoding"
|
|
<< " for constant " << constant << " with " << variables.size()
|
|
<< " variables.";
|
|
}
|
|
|
|
// Determine whether the new ADD will be rooted by the first variable or its complement.
|
|
ADD initialNode;
|
|
if ((constant & (1 << (variables.size() - 1))) != 0) {
|
|
initialNode = *variables[0];
|
|
} else {
|
|
initialNode = ~(*variables[0]);
|
|
}
|
|
ADD* result = new ADD(initialNode);
|
|
|
|
// Add (i.e. multiply) the other variables as well according to whether their bit is set or not.
|
|
for (uint_fast64_t i = 1; i < variables.size(); ++i) {
|
|
if ((constant & (1 << (variables.size() - i - 1))) != 0) {
|
|
*result *= *variables[i];
|
|
} else {
|
|
*result *= ~(*variables[i]);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void CuddUtility::setValueAtIndex(ADD* add, uint_fast64_t index, std::vector<ADD*> const& variables, double value) const {
|
|
if ((index >> variables.size()) != 0) {
|
|
LOG4CPLUS_ERROR(logger, "Cannot create encoding for index " << index << " with "
|
|
<< variables.size() << " variables.");
|
|
throw storm::exceptions::InvalidArgumentException() << "Cannot create encoding"
|
|
<< " for index " << index << " with " << variables.size()
|
|
<< " variables.";
|
|
}
|
|
|
|
// Determine whether the new ADD will be rooted by the first variable or its complement.
|
|
ADD initialNode;
|
|
if ((index & (1 << (variables.size() - 1))) != 0) {
|
|
initialNode = *variables[0];
|
|
} else {
|
|
initialNode = ~(*variables[0]);
|
|
}
|
|
ADD* encoding = new ADD(initialNode);
|
|
|
|
// Add (i.e. multiply) the other variables as well according to whether their bit is set or not.
|
|
for (uint_fast64_t i = 1; i < variables.size(); ++i) {
|
|
if ((index & (1 << (variables.size() - i - 1))) != 0) {
|
|
*encoding *= *variables[i];
|
|
} else {
|
|
*encoding *= ~(*variables[i]);
|
|
}
|
|
}
|
|
|
|
*add = encoding->Ite(manager.constant(value), *add);
|
|
}
|
|
|
|
void CuddUtility::setValueAtIndices(ADD* add, uint_fast64_t rowIndex, uint_fast64_t columnIndex, std::vector<ADD*> const& rowVariables, std::vector<ADD*> const& columnVariables, double value) const {
|
|
if ((rowIndex >> rowVariables.size()) != 0) {
|
|
LOG4CPLUS_ERROR(logger, "Cannot create encoding for index " << rowIndex << " with "
|
|
<< rowVariables.size() << " variables.");
|
|
throw storm::exceptions::InvalidArgumentException() << "Cannot create encoding"
|
|
<< " for index " << rowIndex << " with " << rowVariables.size()
|
|
<< " variables.";
|
|
}
|
|
if ((columnIndex >> columnVariables.size()) != 0) {
|
|
LOG4CPLUS_ERROR(logger, "Cannot create encoding for index " << columnIndex << " with "
|
|
<< columnVariables.size() << " variables.");
|
|
throw storm::exceptions::InvalidArgumentException() << "Cannot create encoding"
|
|
<< " for index " << columnIndex << " with " << columnVariables.size()
|
|
<< " variables.";
|
|
}
|
|
if (rowVariables.size() != columnVariables.size()) {
|
|
LOG4CPLUS_ERROR(logger, "Number of variables for indices encodings does not match.");
|
|
throw storm::exceptions::InvalidArgumentException()
|
|
<< "Number of variables for indices encodings does not match.";
|
|
}
|
|
|
|
ADD initialNode;
|
|
if ((rowIndex & (1 << (rowVariables.size() - 1))) != 0) {
|
|
initialNode = *rowVariables[0];
|
|
} else {
|
|
initialNode = ~(*rowVariables[0]);
|
|
}
|
|
ADD* encoding = new ADD(initialNode);
|
|
if ((columnIndex & (1 << (rowVariables.size() - 1))) != 0) {
|
|
*encoding *= *columnVariables[0];
|
|
} else {
|
|
*encoding *= ~(*columnVariables[0]);
|
|
}
|
|
|
|
for (uint_fast64_t i = 1; i < rowVariables.size(); ++i) {
|
|
if ((rowIndex & (1 << (rowVariables.size() - i - 1))) != 0) {
|
|
*encoding *= *rowVariables[i];
|
|
} else {
|
|
*encoding *= ~(*rowVariables[i]);
|
|
}
|
|
if ((columnIndex & (1 << (columnVariables.size() - i - 1))) != 0) {
|
|
*encoding *= *columnVariables[i];
|
|
} else {
|
|
*encoding *= ~(*columnVariables[i]);
|
|
}
|
|
}
|
|
|
|
*add = encoding->Ite(manager.constant(value), *add);
|
|
}
|
|
|
|
|
|
ADD* CuddUtility::getConstant(double value) const {
|
|
return new ADD(manager.constant(value));
|
|
}
|
|
|
|
ADD* CuddUtility::permuteVariables(ADD* add, std::vector<ADD*> fromVariables, std::vector<ADD*> toVariables, uint_fast64_t totalNumberOfVariables) const {
|
|
std::vector<int> permutation;
|
|
permutation.resize(totalNumberOfVariables);
|
|
for (uint_fast64_t i = 0; i < totalNumberOfVariables; ++i) {
|
|
permutation[i] = i;
|
|
}
|
|
for (uint_fast64_t i = 0; i < fromVariables.size(); ++i) {
|
|
permutation[fromVariables[i]->NodeReadIndex()] = toVariables[i]->NodeReadIndex();
|
|
}
|
|
return new ADD(add->Permute(&permutation[0]));
|
|
}
|
|
|
|
void CuddUtility::dumpDotToFile(ADD* add, std::string filename) const {
|
|
std::vector<ADD> nodes;
|
|
nodes.push_back(*add);
|
|
|
|
FILE* filePtr;
|
|
filePtr = fopen(filename.c_str(), "w");
|
|
manager.DumpDot(nodes, 0, 0, filePtr);
|
|
fclose(filePtr);
|
|
}
|
|
|
|
Cudd const& CuddUtility::getManager() const {
|
|
return manager;
|
|
}
|
|
|
|
CuddUtility* cuddUtilityInstance() {
|
|
if (CuddUtility::instance == nullptr) {
|
|
CuddUtility::instance = new CuddUtility();
|
|
}
|
|
return CuddUtility::instance;
|
|
}
|
|
|
|
} // namespace utility
|
|
|
|
} // namespace storm
|
|
|
|
|