diff --git a/prism/src/acceptance/AcceptanceGenRabin.java b/prism/src/acceptance/AcceptanceGenRabin.java
index 5ce9c6c2..ca2a7063 100644
--- a/prism/src/acceptance/AcceptanceGenRabin.java
+++ b/prism/src/acceptance/AcceptanceGenRabin.java
@@ -30,6 +30,8 @@ package acceptance;
import java.util.ArrayList;
import java.util.BitSet;
+import prism.PrismException;
+import prism.PrismNotSupportedException;
import jdd.JDDVars;
/**
@@ -188,6 +190,22 @@ public class AcceptanceGenRabin
return false;
}
+ /** Complement this acceptance condition, return as AcceptanceGeneric. */
+ public AcceptanceGeneric complementToGeneric()
+ {
+ AcceptanceGeneric generic = toAcceptanceGeneric();
+ return generic.complementToGeneric();
+ }
+
+ @Override
+ public AcceptanceOmega complement(int numStates, AcceptanceType... allowedAcceptance) throws PrismException
+ {
+ if (AcceptanceType.contains(allowedAcceptance, AcceptanceType.GENERIC)) {
+ return complementToGeneric();
+ }
+ throw new PrismNotSupportedException("Can not complement " + getTypeName() + " acceptance to a supported acceptance type");
+ }
+
@Override
public void lift(LiftBitSet lifter) {
for (GenRabinPair pair : this) {
diff --git a/prism/src/acceptance/AcceptanceGeneric.java b/prism/src/acceptance/AcceptanceGeneric.java
index f6b662c3..5aa92458 100644
--- a/prism/src/acceptance/AcceptanceGeneric.java
+++ b/prism/src/acceptance/AcceptanceGeneric.java
@@ -29,6 +29,8 @@ package acceptance;
import java.util.BitSet;
+import prism.PrismException;
+import prism.PrismNotSupportedException;
import jdd.JDDVars;
/**
@@ -198,6 +200,43 @@ public class AcceptanceGeneric implements AcceptanceOmega {
throw new UnsupportedOperationException("Unsupported operator in generic acceptance condition");
}
+ /** Complement this acceptance condition, return as AcceptanceGeneric. */
+ public AcceptanceGeneric complementToGeneric()
+ {
+ switch (kind) {
+ case TRUE: return new AcceptanceGeneric(false);
+ case FALSE: return new AcceptanceGeneric(true);
+
+ case AND:
+ return new AcceptanceGeneric(ElementType.OR,
+ getLeft().complementToGeneric(),
+ getRight().complementToGeneric());
+ case OR:
+ return new AcceptanceGeneric(ElementType.AND,
+ getLeft().complementToGeneric(),
+ getRight().complementToGeneric());
+ case FIN:
+ return new AcceptanceGeneric(ElementType.INF, (BitSet) states.clone());
+ case FIN_NOT:
+ return new AcceptanceGeneric(ElementType.INF_NOT, (BitSet) states.clone());
+ case INF:
+ return new AcceptanceGeneric(ElementType.FIN, (BitSet) states.clone());
+ case INF_NOT:
+ return new AcceptanceGeneric(ElementType.FIN_NOT, (BitSet) states.clone());
+ default:
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ @Override
+ public AcceptanceOmega complement(int numStates, AcceptanceType... allowedAcceptance) throws PrismException
+ {
+ if (AcceptanceType.contains(allowedAcceptance, AcceptanceType.GENERIC)) {
+ return this.complementToGeneric();
+ }
+ throw new PrismNotSupportedException("Can not complement " + getTypeName() + " acceptance to required acceptance type");
+ }
+
@Override
public void lift(LiftBitSet lifter) {
switch(kind) {
@@ -272,4 +311,5 @@ public class AcceptanceGeneric implements AcceptanceOmega {
}
}
+
}
diff --git a/prism/src/acceptance/AcceptanceOmega.java b/prism/src/acceptance/AcceptanceOmega.java
index e55b1cbf..0e36d841 100644
--- a/prism/src/acceptance/AcceptanceOmega.java
+++ b/prism/src/acceptance/AcceptanceOmega.java
@@ -28,6 +28,7 @@ package acceptance;
import java.util.BitSet;
+import prism.PrismException;
import jdd.JDDVars;
/**
@@ -64,6 +65,13 @@ public interface AcceptanceOmega extends Cloneable
/** Make a copy of the acceptance condition. */
public AcceptanceOmega clone();
+ /**
+ * Complement the acceptance condition if possible.
+ * @param numStates the number of states in the underlying model / automaton (needed for complementing BitSets)
+ * @param allowedAcceptance the allowed acceptance types that may be used for complementing
+ */
+ public AcceptanceOmega complement(int numStates, AcceptanceType... allowedAcceptance) throws PrismException;
+
/** Abstract functor for use with the lift function. */
public static abstract class LiftBitSet {
public abstract BitSet lift(BitSet states);
diff --git a/prism/src/acceptance/AcceptanceRabin.java b/prism/src/acceptance/AcceptanceRabin.java
index 94f42b48..298ef3c6 100644
--- a/prism/src/acceptance/AcceptanceRabin.java
+++ b/prism/src/acceptance/AcceptanceRabin.java
@@ -29,6 +29,8 @@ package acceptance;
import java.util.ArrayList;
import java.util.BitSet;
+import prism.PrismException;
+import prism.PrismNotSupportedException;
import jdd.JDDVars;
/**
@@ -58,7 +60,10 @@ public class AcceptanceRabin
/** State set K (should be visited infinitely often) */
private BitSet K;
- /** Constructor with L and K state sets */
+ /**
+ * Constructor with L and K state sets.
+ * (F G !"L") & (G F "K")
+ */
public RabinPair(BitSet L, BitSet K) {
this.L = L;
this.K = K;
@@ -175,7 +180,7 @@ public class AcceptanceRabin
* any word that is accepted by this condition is rejected by the returned Streett condition.
* @return the complement Streett acceptance condition
*/
- public AcceptanceStreett complement()
+ public AcceptanceStreett complementToStreett()
{
AcceptanceStreett accRabin = new AcceptanceStreett();
@@ -189,6 +194,15 @@ public class AcceptanceRabin
return accRabin;
}
+ @Override
+ public AcceptanceOmega complement(int numStates, AcceptanceType... allowedAcceptance) throws PrismException
+ {
+ if (AcceptanceType.contains(allowedAcceptance, AcceptanceType.STREETT)) {
+ return complementToStreett();
+ }
+ throw new PrismNotSupportedException("Can not complement " + getTypeName() + " acceptance to a supported acceptance type");
+ }
+
/**
* Returns a new Rabin acceptance condition that corresponds to the disjunction
* of this and the other Rabin acceptance condition. The RabinPairs are cloned, i.e.,
diff --git a/prism/src/acceptance/AcceptanceReach.java b/prism/src/acceptance/AcceptanceReach.java
index 74af4192..99d0034e 100644
--- a/prism/src/acceptance/AcceptanceReach.java
+++ b/prism/src/acceptance/AcceptanceReach.java
@@ -28,6 +28,8 @@ package acceptance;
import java.util.BitSet;
+import prism.PrismException;
+import prism.PrismNotSupportedException;
import jdd.JDDVars;
/**
@@ -76,6 +78,54 @@ public class AcceptanceReach implements AcceptanceOmega
return bscc_states.intersects(goalStates);
}
+ /**
+ * Get a Rabin acceptance condition that is the complement of this condition, i.e.,
+ * any word that is accepted by this condition is rejected by the returned Rabin condition.
+ *
+ * Relies on the fact that once the goal states have been reached, all subsequent states
+ * are goal states.
+ *
+ * @param numStates the number of states in the underlying model / automaton (needed for complementing BitSets)
+ * @return the complement Rabin acceptance condition
+ */
+ public AcceptanceRabin complementToRabin(int numStates)
+ {
+ AcceptanceRabin rabin = new AcceptanceRabin();
+ BitSet allStates = new BitSet();
+ allStates.set(0, numStates-1);
+ rabin.add(new AcceptanceRabin.RabinPair((BitSet) goalStates.clone(), allStates));
+ return rabin;
+ }
+
+ /**
+ * Get a Streett acceptance condition that is the complement of this condition, i.e.,
+ * any word that is accepted by this condition is rejected by the returned Streett condition.
+ *
+ * Relies on the fact that once the goal states have been reached, all subsequent states
+ * are goal states.
+ *
+ * @param numStates the number of states in the underlying model / automaton (needed for complementing BitSets)
+ * @return the complement Streett acceptance condition
+ */
+ public AcceptanceStreett complementToStreett(int numStates)
+ {
+ AcceptanceStreett streett = new AcceptanceStreett();
+ streett.add(new AcceptanceStreett.StreettPair((BitSet) goalStates.clone(), new BitSet()));
+ return streett;
+ }
+
+ @Override
+ public AcceptanceOmega complement(int numStates, AcceptanceType... allowedAcceptance) throws PrismException
+ {
+ if (AcceptanceType.contains(allowedAcceptance, AcceptanceType.RABIN)) {
+ return complementToRabin(numStates);
+ } else if (AcceptanceType.contains(allowedAcceptance, AcceptanceType.STREETT)) {
+ return complementToStreett(numStates);
+ } else if (AcceptanceType.contains(allowedAcceptance, AcceptanceType.GENERIC)) {
+ return new AcceptanceGeneric(AcceptanceGeneric.ElementType.FIN, (BitSet) goalStates.clone());
+ }
+ throw new PrismNotSupportedException("Can not complement " + getTypeName() + " acceptance to a supported acceptance type");
+ }
@Override
public void lift(LiftBitSet lifter)
diff --git a/prism/src/acceptance/AcceptanceStreett.java b/prism/src/acceptance/AcceptanceStreett.java
index 852ea066..5577d018 100644
--- a/prism/src/acceptance/AcceptanceStreett.java
+++ b/prism/src/acceptance/AcceptanceStreett.java
@@ -29,6 +29,8 @@ package acceptance;
import java.util.ArrayList;
import java.util.BitSet;
+import prism.PrismException;
+import prism.PrismNotSupportedException;
import jdd.JDDVars;
/**
@@ -58,7 +60,10 @@ public class AcceptanceStreett
/** State set G */
private BitSet G;
- /** Constructor with R and G state sets */
+ /**
+ * Constructor with R and G state sets.
+ * (G F "R") -> (G F "G")
+ */
public StreettPair(BitSet R, BitSet G)
{
this.R = R;
@@ -179,7 +184,7 @@ public class AcceptanceStreett
* any word that is accepted by this condition is rejected by the returned Rabin condition.
* @return the complement Rabin acceptance condition
*/
- public AcceptanceRabin complement()
+ public AcceptanceRabin complementToRabin()
{
AcceptanceRabin accRabin = new AcceptanceRabin();
@@ -191,6 +196,16 @@ public class AcceptanceStreett
}
return accRabin;
}
+
+ @Override
+ public AcceptanceOmega complement(int numStates, AcceptanceType... allowedAcceptance) throws PrismException
+ {
+ if (AcceptanceType.contains(allowedAcceptance, AcceptanceType.RABIN)) {
+ return complementToRabin();
+ }
+ throw new PrismNotSupportedException("Can not complement " + getTypeName() + " acceptance to a supported acceptance type");
+ }
+
/**
* Returns a new Streett acceptance condition that corresponds to the conjunction