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.
 
 
 
 

342 lines
8.1 KiB

/*
* This file is part of the program ltl2dstar (http://www.ltl2dstar.de/).
* Copyright (C) 2005-2007 Joachim Klein <j.klein@ltl2dstar.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef APMONOM_H
#define APMONOM_H
/** @file
* Provides class APMonom.
*/
#include "common/Exceptions.hpp"
#include "common/SimpleBitSet.hpp"
#include <cassert>
#include <iostream>
// As TRUE and FALSE are defined to equal true and false on Windows, they need to be undefined.
#undef TRUE
#undef FALSE
/**
* Class representing a subset of 2^AP where AP is the set of
* atomic propositions (APSet). It stores two bits per AP:
* One bit to determine if the value of this AP is set,
* the second bit to store the value.<br>
* Additionally, the APMonom can have the special values
* TRUE or FALSE.<br>
* Currently, the APSet can only have 31 members.
*/
class APMonom {
public:
/**
* Constructor.
*/
APMonom() {*this=TRUE;}
/**
* Constructor.
* @param set_bits integer representation of the bits which are set
* @param value_bits integer representation of the value bits
*/
APMonom(unsigned int set_bits, unsigned int value_bits) {
bits_set.set(set_bits);
bits_value.set(value_bits);
}
/**
* Is the AP set?
* @param index index of AP
* @return <b>true</b> if AP is set
*/
bool isSet(unsigned int index) const {
if (!isNormal()) {
THROW_EXCEPTION(IllegalArgumentException, "Can't get AP, is either TRUE/FALSE!");
}
return bits_set.get(index);
}
/**
* Gets the value for this AP. You can't get the value if the AP is not set.
* @param index index of AP
* @return <b>true</b> if AP is true
*/
bool getValue(unsigned int index) const {
if (!isNormal()) {
THROW_EXCEPTION(IllegalArgumentException, "Can't get AP, is either TRUE/FALSE!");
}
if (!bits_set.get(index)) {
THROW_EXCEPTION(IllegalArgumentException, "Can't get value: AP not set!");
}
return bits_value.get(index);
}
/**
* Sets the value for this AP. Implicitly, it also sets the AP to 'set'.
* @param index index of AP
* @param value value of AP
*/
void setValue(unsigned int index, bool value) {
bits_set.set(index, true);
bits_value.set(index, value);
#ifdef APMONOM_DEBUG
assert(isNormalized());
#endif
}
/**
* Perform a logical AND operation of this APMonom with a single AP.
* @param index index index of AP
* @param value value of AP
*/
void andAP(unsigned int index, bool value) {
if (isFalse()) {return;}
if (!isTrue()) {
if (isSet(index) && getValue(index)!=value) {
// contradiction
*this=FALSE;
return;
}
}
setValue(index, value);
}
/**
* Unsets this AP.
* @param index index of AP
*/
void unset(unsigned int index) {
bits_value.set(index,false);
bits_set.set(index, false);
#ifdef APMONOM_DEBUG
assert(isNormalized());
#endif
}
/**
* Checks if this APMonom is equivalent to TRUE.
* @return <b>true</b> if this APMonom is TRUE
*/
bool isTrue() const {
return *this==TRUE;
}
/**
* Checks if this APMonom is equivalent to FALSE.
* @return <b>true</b> if this APMonom is FALSE
*/
bool isFalse() const {
return *this==FALSE;
}
/**
* Checks if this APMonom is a normal APMonon (not equivalent to TRUE or FALSE).
* @return <b>true</b> if this APMonom is normal (not TRUE/FALSE).
*/
bool isNormal() const {
return bits_set!=0;
}
/**
* Provides access to the underlying bitset representing the
* value (AP occurs in positive or negative form).
* @return the SimpleBitSet of the values
*/
SimpleBitSet getValueBits() const {
#ifdef APMONOM_DEBUG
assert(isNormalized());
#endif
return bits_value;
}
/**
* Provides access to the underlying bitset representing the
* bits that are set (AP occurs).
* @return the SimpleBitSet of the occuring APs
*/
SimpleBitSet getSetBits() const {
#ifdef APMONOM_DEBUG
assert(isNormalized());
#endif
return bits_set;
};
/**
* Performs an intersection check.
* @param m1 the first APMonom
* @param m2 the second APMonom
* @return <b>true</b> if the intersection of <i>m1</i> and <i>m2</i> is empty.
*/
static bool isIntersectionEmpty(const APMonom& m1,
const APMonom& m2) {
// check if there are contradicting values
unsigned int set_in_both=
m1.getSetBits() & m2.getSetBits();
if ((m1.getValueBits() & set_in_both) !=
(m2.getValueBits() & set_in_both)) {
// contradiction
return true;
} else {
return false;
}
}
/**
* Perform logical conjunction with other APMonom.
* @param other the other APMonom
*/
APMonom operator&(const APMonom& other) const {
if (this->isFalse() || other.isFalse()) {
return FALSE;
}
if (this->isTrue()) {return other;}
if (other.isTrue()) {return *this;}
// both are not TRUE/FALSE:
if (isIntersectionEmpty(*this, other)) {
// return APMonom equivalent to false
return FALSE;
}
// both Monoms are not contradicting...
unsigned int result_set=
this->getSetBits() | other.getSetBits();
unsigned int result_value=
this->getValueBits() | other.getValueBits();
return APMonom(result_set, result_value);
}
/**
* Perform 'minus' operation (equal to *this & !other).
* @param other the other APMonom
*/
APMonom operator-(const APMonom& other) const {
if (this->isFalse()) {
// false & anything == false
return FALSE;
}
if (other.isFalse()) {
// *this & !(false) == *this & true == *this
return *this;
}
if (other.isTrue()) {
// *this & !(true) == *this & false == false
return FALSE;
}
// the result will be false, if there are two set bits
// with equal value
unsigned int set_in_both=
this->getSetBits() & other.getSetBits();
if ((this->getValueBits() & set_in_both) !=
((~other.getValueBits()) & set_in_both)) {
// return false;
return FALSE;
}
unsigned int result_set=
this->getSetBits() | other.getSetBits();
unsigned int result_value=
this->getValueBits() & (~(other.getValueBits()));
return APMonom(result_set, result_value);
}
/**
* Checks for equality.
* @param other the other APMonom
* @return <b>true</b> if this and the other APMonom are equal
*/
bool operator==(const APMonom& other) const {
return (this->getValueBits()==other.getValueBits()) &&
(this->getSetBits()==other.getSetBits());
}
/**
* Output APMonom on an ostream.
* @param out the output stream
* @param m the APMonom
*/
friend std::ostream& operator<<(std::ostream& out,
const APMonom& m) {
if (m.isTrue()) {
out << "true";
} else if (m.isFalse()) {
out << "false";
} else {
for (unsigned int i=0;i<32;i++) {
if (m.isSet(i)) {
if (m.getValue(i)) {
out << "+" << i;
} else {
out << "-" << i;
}
}
}
}
return out;
}
/** An APMonom representing TRUE */
static const APMonom TRUE;
/** An APMonom representing FALSE */
static const APMonom FALSE;
private:
/** The bitset for the values */
SimpleBitSet bits_value;
/** The bitset for the occurence */
SimpleBitSet bits_set;
/** Checks to see if the bitset representation is normalized. */
bool isNormalized() {
if (isTrue() || isFalse()) {
return true;
}
return (bits_value.getBitSet() & ~(bits_set.getBitSet())) == 0;
}
};
#endif