Browse Source
jltl2ba.LTLFragments: Determine syntactic LTL fragment (safety, guarantee, persistence, obligation) for a given SimpleLTL formula
jltl2ba.LTLFragments: Determine syntactic LTL fragment (safety, guarantee, persistence, obligation) for a given SimpleLTL formula
git-svn-id: https://www.prismmodelchecker.org/svn/prism/prism/trunk@12061 bbc10eb1-c90d-0410-af57-cb519fbb1720master
1 changed files with 330 additions and 0 deletions
@ -0,0 +1,330 @@ |
|||||
|
//============================================================================== |
||||
|
// |
||||
|
// Copyright (c) 2016- |
||||
|
// Authors: |
||||
|
// * Joachim Klein <klein@tcs.inf.tu-dresden.de> (TU Dresden) |
||||
|
// |
||||
|
//------------------------------------------------------------------------------ |
||||
|
// |
||||
|
// This file is part of PRISM. |
||||
|
// |
||||
|
// PRISM is free software; you can redistribute it and/or modify |
||||
|
// it under the terms of the GNU General Public License as published by |
||||
|
// the Free Software Foundation; either version 2 of the License, or |
||||
|
// (at your option) any later version. |
||||
|
// |
||||
|
// PRISM 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 PRISM; if not, write to the Free Software Foundation, |
||||
|
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
|
// |
||||
|
//============================================================================== |
||||
|
|
||||
|
package jltl2ba; |
||||
|
|
||||
|
/** |
||||
|
* Helper to determine syntactic fragments of LTL formulas. |
||||
|
* <br> |
||||
|
* Each object stores information about membership in the |
||||
|
* "safety", "guarantee/co-safety", "obligation", "recurrence" and "persistence" |
||||
|
* fragments of LTL. |
||||
|
*/ |
||||
|
public class LTLFragments |
||||
|
{ |
||||
|
private boolean syntacticSafety; |
||||
|
private boolean syntacticGuarantee; |
||||
|
private boolean syntacticObligation; |
||||
|
private boolean syntacticRecurrence; |
||||
|
private boolean syntacticPersistence; |
||||
|
|
||||
|
/** |
||||
|
* Constructor for basic formula (true, false, atomic proposition), |
||||
|
* contained in all fragments. |
||||
|
*/ |
||||
|
private LTLFragments() |
||||
|
{ |
||||
|
syntacticSafety = true; |
||||
|
syntacticGuarantee = true; |
||||
|
syntacticObligation = true; |
||||
|
syntacticRecurrence = true; |
||||
|
syntacticPersistence = true; |
||||
|
} |
||||
|
|
||||
|
/** Copy constructor */ |
||||
|
private LTLFragments(LTLFragments other) |
||||
|
{ |
||||
|
syntacticSafety = other.syntacticSafety; |
||||
|
syntacticGuarantee = other.syntacticGuarantee; |
||||
|
syntacticObligation = other.syntacticObligation; |
||||
|
syntacticRecurrence = other.syntacticRecurrence; |
||||
|
syntacticPersistence = other.syntacticPersistence; |
||||
|
} |
||||
|
|
||||
|
/** Do we belong to the syntactic safety fragment? */ |
||||
|
public boolean isSyntacticSafety() |
||||
|
{ |
||||
|
return syntacticSafety; |
||||
|
} |
||||
|
|
||||
|
/** Do we belong to the syntactic guarantee (co-safety) fragment? */ |
||||
|
public boolean isSyntacticGuarantee() |
||||
|
{ |
||||
|
return syntacticGuarantee; |
||||
|
} |
||||
|
|
||||
|
/** Do we belong to the syntactic obligation fragment? */ |
||||
|
public boolean isSyntacticObligation() |
||||
|
{ |
||||
|
return syntacticObligation; |
||||
|
} |
||||
|
|
||||
|
/** Do we belong to the syntactic recurrence fragment? */ |
||||
|
public boolean isSyntacticRecurrence() |
||||
|
{ |
||||
|
return syntacticRecurrence; |
||||
|
} |
||||
|
|
||||
|
/** Do we belong to the syntactic persistence fragment? */ |
||||
|
public boolean isSyntacticPersistence() |
||||
|
{ |
||||
|
return syntacticPersistence; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() |
||||
|
{ |
||||
|
String s = "["; |
||||
|
boolean first = true; |
||||
|
|
||||
|
if (isSyntacticSafety()) { |
||||
|
if (!first) s+=","; |
||||
|
first = false; |
||||
|
s+="syntactic safety"; |
||||
|
} |
||||
|
|
||||
|
if (isSyntacticGuarantee()) { |
||||
|
if (!first) s+=","; |
||||
|
first = false; |
||||
|
s+="syntactic guarantee"; |
||||
|
} |
||||
|
|
||||
|
if (isSyntacticObligation()) { |
||||
|
if (!first) s+=","; |
||||
|
first = false; |
||||
|
s+="syntactic obligation"; |
||||
|
} |
||||
|
|
||||
|
if (isSyntacticRecurrence()) { |
||||
|
if (!first) s+=","; |
||||
|
first = false; |
||||
|
s+="syntactic recurrence"; |
||||
|
} |
||||
|
|
||||
|
if (isSyntacticPersistence()) { |
||||
|
if (!first) s+=","; |
||||
|
first = false; |
||||
|
s+="syntactic persistence"; |
||||
|
} |
||||
|
|
||||
|
return s+"]"; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Apply the Boolean AND operator (i.e., corresponding to this & other), |
||||
|
* returning the result. |
||||
|
*/ |
||||
|
private LTLFragments and(LTLFragments other) |
||||
|
{ |
||||
|
LTLFragments result = new LTLFragments(this); |
||||
|
|
||||
|
result.syntacticSafety &= other.syntacticSafety; |
||||
|
result.syntacticGuarantee &= other.syntacticGuarantee; |
||||
|
result.syntacticObligation &= other.syntacticObligation; |
||||
|
result.syntacticRecurrence &= other.syntacticRecurrence; |
||||
|
result.syntacticPersistence &= other.syntacticPersistence; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Apply the Boolean OR operator (i.e., corresponding to this | other), |
||||
|
* returning the result. |
||||
|
*/ |
||||
|
private LTLFragments or(LTLFragments other) |
||||
|
{ |
||||
|
LTLFragments result = new LTLFragments(this); |
||||
|
|
||||
|
result.syntacticSafety &= other.syntacticSafety; |
||||
|
result.syntacticGuarantee &= other.syntacticGuarantee; |
||||
|
result.syntacticObligation &= other.syntacticObligation; |
||||
|
result.syntacticRecurrence &= other.syntacticRecurrence; |
||||
|
result.syntacticPersistence &= other.syntacticPersistence; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Apply the Boolean NOT operator (i.e., corresponding to !this), |
||||
|
* returning the result. |
||||
|
*/ |
||||
|
private LTLFragments not() |
||||
|
{ |
||||
|
LTLFragments result = new LTLFragments(); |
||||
|
|
||||
|
// take opposites |
||||
|
result.syntacticSafety = this.syntacticGuarantee; |
||||
|
result.syntacticGuarantee = this.syntacticSafety; |
||||
|
|
||||
|
// obligation stays the same |
||||
|
result.syntacticObligation = this.syntacticObligation; |
||||
|
|
||||
|
// take opposites |
||||
|
result.syntacticRecurrence = this.syntacticPersistence; |
||||
|
result.syntacticPersistence = this.syntacticRecurrence; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Apply the temporal "nextstep" operator (i.e., corresponding to X this), |
||||
|
* returning the result. |
||||
|
*/ |
||||
|
private LTLFragments nextstep() |
||||
|
{ |
||||
|
return new LTLFragments(this); // just a copy |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Apply the temporal "eventually" operator (i.e., corresponding to F this), |
||||
|
* returning the result. |
||||
|
*/ |
||||
|
private LTLFragments eventually() |
||||
|
{ |
||||
|
LTLFragments result = new LTLFragments(this); // copy |
||||
|
|
||||
|
result.syntacticSafety = false; |
||||
|
// syntacticGuarantee inherited |
||||
|
result.syntacticObligation = syntacticGuarantee; |
||||
|
result.syntacticRecurrence = syntacticGuarantee; |
||||
|
// syntacticPersistence inherited |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Apply the temporal "always" operator (i.e., corresponding to G this), |
||||
|
* returning the result. |
||||
|
*/ |
||||
|
private LTLFragments always() |
||||
|
{ |
||||
|
LTLFragments result = new LTLFragments(this); // copy |
||||
|
|
||||
|
// syntacticSafety inherited |
||||
|
result.syntacticGuarantee = false; |
||||
|
result.syntacticObligation = syntacticSafety; |
||||
|
// syntacticRecurrence inherited |
||||
|
result.syntacticPersistence = syntacticSafety; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Apply the temporal "until" operator (i.e., corresponding to this U other), |
||||
|
* returning the result. |
||||
|
*/ |
||||
|
private LTLFragments until(LTLFragments other) |
||||
|
{ |
||||
|
LTLFragments result = new LTLFragments(); |
||||
|
|
||||
|
result.syntacticSafety = false; |
||||
|
result.syntacticGuarantee = this.syntacticGuarantee & other.syntacticGuarantee; |
||||
|
result.syntacticObligation = this.syntacticObligation & other.syntacticGuarantee; |
||||
|
result.syntacticRecurrence = this.syntacticRecurrence & other.syntacticGuarantee; |
||||
|
result.syntacticPersistence = this.syntacticPersistence & other.syntacticPersistence; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Apply the temporal "release" operator (i.e., corresponding to this R other), |
||||
|
* returning the result. |
||||
|
*/ |
||||
|
private LTLFragments release(LTLFragments other) |
||||
|
{ |
||||
|
LTLFragments result = new LTLFragments(); |
||||
|
|
||||
|
result.syntacticSafety = this.syntacticSafety & other.syntacticSafety; |
||||
|
result.syntacticGuarantee = false; |
||||
|
result.syntacticObligation = this.syntacticObligation & other.syntacticSafety; |
||||
|
result.syntacticRecurrence = this.syntacticRecurrence & other.syntacticRecurrence; |
||||
|
result.syntacticPersistence = this.syntacticPersistence & other.syntacticSafety; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Apply the Boolean EQUIV operator (i.e., corresponding to this <-> other), |
||||
|
* returning the result. |
||||
|
*/ |
||||
|
private LTLFragments equiv(LTLFragments other) |
||||
|
{ |
||||
|
LTLFragments left = and(other); |
||||
|
LTLFragments right = not().and(other.not()); |
||||
|
|
||||
|
return left.or(right); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Apply the Boolean IMPLIES operator (i.e., corresponding to this -> other), |
||||
|
* returning the result. |
||||
|
*/ |
||||
|
private LTLFragments implies(LTLFragments other) |
||||
|
{ |
||||
|
LTLFragments result = not().or(other); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Analyse a given LTL formula and return the syntactic LTL fragments it belongs to. |
||||
|
* @param root the root of the LTL formula |
||||
|
* @return the LTLFragments it belongs to |
||||
|
*/ |
||||
|
public static LTLFragments analyse(SimpleLTL root) |
||||
|
{ |
||||
|
switch (root.kind) { |
||||
|
case TRUE: |
||||
|
case FALSE: |
||||
|
return new LTLFragments(); // all true |
||||
|
case AP: |
||||
|
return new LTLFragments(); // all true |
||||
|
case NOT: |
||||
|
return analyse(root.left).not(); |
||||
|
|
||||
|
case AND: |
||||
|
return analyse(root.left).and(analyse(root.right)); |
||||
|
case OR: |
||||
|
return analyse(root.left).or(analyse(root.right)); |
||||
|
|
||||
|
case FINALLY: |
||||
|
return analyse(root.left).eventually(); |
||||
|
case GLOBALLY: |
||||
|
return analyse(root.left).always(); |
||||
|
case NEXT: |
||||
|
return analyse(root.left).nextstep(); |
||||
|
case UNTIL: |
||||
|
return analyse(root.left).until(analyse(root.right)); |
||||
|
case RELEASE: |
||||
|
return analyse(root.left).release(analyse(root.right)); |
||||
|
|
||||
|
case EQUIV: |
||||
|
return analyse(root.left).equiv(analyse(root.right)); |
||||
|
case IMPLIES: |
||||
|
return analyse(root.left).implies(analyse(root.right)); |
||||
|
} |
||||
|
throw new UnsupportedOperationException(); |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue