/** Constructor for a node containing an atomic proposition (index into APSet) */ public LTLNode(int ap) { _type = type_t.T_AP; _left = null; _right = null; _ap = ap; }
public static LTLFormula parse(ltl2ba.Node LTLHeadNode, APSet predefined_apset) { // boost::char_separator<char> sep(" "); //ltl_seperator sep; tokenizer tokens(formula, sep); APSet apset = new APSet(); //tokenizer::iterator it = tokens.begin(); //LTLNode ltl = parse(apset, predefined_apset); //if (it != tokens.end()) //{ // THROW_EXCEPTION(Exception, "Unexpected character(s) at end of LTL formula: '" + *it + "'"); //} LTLNode ltl = TranslateLTL(LTLHeadNode, apset, predefined_apset); APSet apset_ = predefined_apset ?? apset; return(new LTLFormula(ltl, apset_)); }
/** * Constructor * @param root the root node * @param apset the underlying APSet */ public LTLFormula(LTLNode root, APSet apset) { _root = root; _apset = apset; }
public LTLNode(type_t type, LTLNode left) : this(type, left, null) { }
/** * Generate formula in DNF. Formula has to have only * AND, OR, TRUE, FALSE, ! as operators, and has to * be in PNF */ public LTLNode toDNF() { switch (_type) { case type_t.T_TRUE: return(new LTLNode(type_t.T_TRUE, null)); case type_t.T_FALSE: return(new LTLNode(type_t.T_FALSE, null)); case type_t.T_NOT: return(new LTLNode(type_t.T_NOT, getLeft().toDNF())); case type_t.T_AP: return(new LTLNode(getAP())); case type_t.T_OR: return(new LTLNode(type_t.T_OR, getLeft().toDNF(), getRight().toDNF())); case type_t.T_AND: { LTLNode left = getLeft().toDNF(); LTLNode right = getRight().toDNF(); if (left.getType() == type_t.T_OR) { LTLNode a = left.getLeft(); LTLNode b = left.getRight(); if (right.getType() == type_t.T_OR) { LTLNode c = right.getLeft(); LTLNode d = right.getRight(); LTLNode a_c = new LTLNode(type_t.T_AND, a, c), b_c = new LTLNode(type_t.T_AND, b, c), a_d = new LTLNode(type_t.T_AND, a, d), b_d = new LTLNode(type_t.T_AND, b, d); return(new LTLNode(type_t.T_OR, new LTLNode(type_t.T_OR, a_c, b_c).toDNF(), new LTLNode(type_t.T_OR, a_d, b_d).toDNF())); } else { LTLNode a_c = new LTLNode(type_t.T_AND, a, right), b_c = new LTLNode(type_t.T_AND, b, right); return(new LTLNode(type_t.T_OR, a_c.toDNF(), b_c.toDNF())); } } else if (right.getType() == type_t.T_OR) { LTLNode a, b; a = right.getLeft(); b = right.getRight(); LTLNode a_c = new LTLNode(type_t.T_AND, left, a), b_c = new LTLNode(type_t.T_AND, left, b); return(new LTLNode(type_t.T_OR, a_c.toDNF(), b_c.toDNF())); } else { return(new LTLNode(type_t.T_AND, left, right)); } } default: throw new Exception("Illegal operator for DNF!"); } }
/** * Get a LTLFormula_ptr for the subformula rooted at subroot */ public LTLFormula getSubFormula(LTLNode subroot) { LTLFormula sub = new LTLFormula(subroot, _apset); return sub; }
public LTLNode toPNF(bool negate) { switch (_type) { case type_t.T_XOR: throw new Exception("XOR not yet supported!"); case type_t.T_IMPLICATE: { if (negate) { // ! (a->b) = !(!a | b) = (a & ! b) return new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF(true)); } else { // (a->b) = (!a | b) return new LTLNode(type_t.T_OR, getLeft().toPNF(true), getRight().toPNF()); } break; } case type_t.T_EQUIV: { if (negate) { // ! (a<->b) == (a & !b) || (!a & b) return new LTLNode(type_t.T_OR, new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF(true)), new LTLNode(type_t.T_AND, getLeft().toPNF(true), getRight().toPNF())); } else { // (a<->b) = (!a && !b) || (a && b) return new LTLNode(type_t.T_OR, new LTLNode(type_t.T_AND, getLeft().toPNF(true), getRight().toPNF(true)), new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF())); } } case type_t.T_NOT: if (negate) { // double negation return getLeft().toPNF();////////////////////?? shouldn't be getRight().toPNF()? !(!a) = a } else { if (getLeft().getType() == type_t.T_AP) { // we are in front of an AP, negation is ok return new LTLNode(type_t.T_NOT, getLeft()); } else { return getLeft().toPNF(true); } } case type_t.T_AP: if (negate) { return new LTLNode(type_t.T_NOT, new LTLNode(_ap)); } else { return new LTLNode(_ap); } case type_t.T_TRUE: if (negate) { return new LTLNode(type_t.T_FALSE, null); } else { return new LTLNode(type_t.T_TRUE, null); } case type_t.T_FALSE: if (negate) { return new LTLNode(type_t.T_TRUE, null); } else { return new LTLNode(type_t.T_FALSE, null); } case type_t.T_AND: // ! (a & b) = (!a | !b) if (negate) { return new LTLNode(type_t.T_OR, getLeft().toPNF(true), getRight().toPNF(true)); } else { return new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF()); } case type_t.T_OR: if (negate) { // ! (a | b) = (!a & !b) return new LTLNode(type_t.T_AND, getLeft().toPNF(true), getRight().toPNF(true)); } else { return new LTLNode(type_t.T_OR, getLeft().toPNF(), getRight().toPNF()); } case type_t.T_NEXTSTEP: // ! (X a) = X (!a) if (negate) { return new LTLNode(type_t.T_NEXTSTEP, getLeft().toPNF(true)); } else { return new LTLNode(type_t.T_NEXTSTEP, getLeft().toPNF()); } case type_t.T_FINALLY: // ! (F a) = G (!a) = f V !a if (negate) { return new LTLNode(type_t.T_RELEASE, new LTLNode(type_t.T_FALSE, null), getLeft().toPNF(true)); } else { // F a = t U a return new LTLNode(type_t.T_UNTIL, new LTLNode(type_t.T_TRUE, null), getLeft().toPNF()); } case type_t.T_GLOBALLY: // ! (G a) = F (!a) = t U ! a if (negate) { return new LTLNode(type_t.T_UNTIL, new LTLNode(type_t.T_TRUE, null), getLeft().toPNF(true)); } else { // f V a return new LTLNode(type_t.T_RELEASE, new LTLNode(type_t.T_FALSE, null), getLeft().toPNF()); } case type_t.T_UNTIL: // ! (a U b) = (!a V !b) if (negate) { return new LTLNode(type_t.T_RELEASE, getLeft().toPNF(true), getRight().toPNF(true)); } else { return new LTLNode(type_t.T_UNTIL, getLeft().toPNF(), getRight().toPNF()); } case type_t.T_RELEASE: // ! (a R b) = (!a U !b) if (negate) { return new LTLNode(type_t.T_UNTIL, getLeft().toPNF(true), getRight().toPNF(true)); } else { return new LTLNode(type_t.T_RELEASE, getLeft().toPNF(), getRight().toPNF()); } case type_t.T_WEAKUNTIL: { LTLNode weak_until = new LTLNode(type_t.T_UNTIL, getLeft(), new LTLNode(type_t.T_OR, getRight(), new LTLNode(type_t.T_GLOBALLY, getLeft(), null))); return weak_until.toPNF(negate); } case type_t.T_WEAKRELEASE: throw new Exception("Operator WEAKRELEASE not yet supported"); case type_t.T_BEFORE: throw new Exception("Operator BEFORE not yet supported"); } throw new Exception("Implementation error"); }
/** * Get a LTLFormula_ptr for the subformula rooted at subroot */ public LTLFormula getSubFormula(LTLNode subroot) { LTLFormula sub = new LTLFormula(subroot, _apset); return(sub); }
/** Constructor for an operator of type */ public LTLNode(type_t type, LTLNode left, LTLNode right) { _type = type; _left = left; _right = right; }
/** * Generate formula in DNF. Formula has to have only * AND, OR, TRUE, FALSE, ! as operators, and has to * be in PNF */ public LTLNode toDNF() { switch (_type) { case type_t.T_TRUE: return new LTLNode(type_t.T_TRUE, null); case type_t.T_FALSE: return new LTLNode(type_t.T_FALSE, null); case type_t.T_NOT: return new LTLNode(type_t.T_NOT, getLeft().toDNF()); case type_t.T_AP: return new LTLNode(getAP()); case type_t.T_OR: return new LTLNode(type_t.T_OR, getLeft().toDNF(), getRight().toDNF()); case type_t.T_AND: { LTLNode left = getLeft().toDNF(); LTLNode right = getRight().toDNF(); if (left.getType() == type_t.T_OR) { LTLNode a = left.getLeft(); LTLNode b = left.getRight(); if (right.getType() == type_t.T_OR) { LTLNode c = right.getLeft(); LTLNode d = right.getRight(); LTLNode a_c = new LTLNode(type_t.T_AND, a, c), b_c = new LTLNode(type_t.T_AND, b, c), a_d = new LTLNode(type_t.T_AND, a, d), b_d = new LTLNode(type_t.T_AND, b, d); return new LTLNode(type_t.T_OR, new LTLNode(type_t.T_OR, a_c, b_c).toDNF(), new LTLNode(type_t.T_OR, a_d, b_d).toDNF()); } else { LTLNode a_c = new LTLNode(type_t.T_AND, a, right), b_c = new LTLNode(type_t.T_AND, b, right); return new LTLNode(type_t.T_OR, a_c.toDNF(), b_c.toDNF()); } } else if (right.getType() == type_t.T_OR) { LTLNode a, b; a = right.getLeft(); b = right.getRight(); LTLNode a_c = new LTLNode(type_t.T_AND, left, a), b_c = new LTLNode(type_t.T_AND, left, b); return new LTLNode(type_t.T_OR, a_c.toDNF(), b_c.toDNF()); } else { return new LTLNode(type_t.T_AND, left, right); } } default: throw new Exception("Illegal operator for DNF!"); } }
/** Return an LTLFormula_ptr of the negation of this formula */ public LTLFormula negate() { LTLNode new_root = new LTLNode(type_t.T_NOT, getRootNode()); return new LTLFormula(new_root, _apset); }
/** Copy constructor (not deep) */ public LTLFormula(LTLFormula other) { _root = other._root; _apset = other._apset; }
/** Return an LTLFormula_ptr of the negation of this formula */ public LTLFormula negate() { LTLNode new_root = new LTLNode(type_t.T_NOT, getRootNode()); return(new LTLFormula(new_root, _apset)); }
public LTLNode toPNF(bool negate) { switch (_type) { case type_t.T_XOR: throw new Exception("XOR not yet supported!"); case type_t.T_IMPLICATE: { if (negate) { // ! (a->b) = !(!a | b) = (a & ! b) return(new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF(true))); } else { // (a->b) = (!a | b) return(new LTLNode(type_t.T_OR, getLeft().toPNF(true), getRight().toPNF())); } break; } case type_t.T_EQUIV: { if (negate) { // ! (a<->b) == (a & !b) || (!a & b) return(new LTLNode(type_t.T_OR, new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF(true)), new LTLNode(type_t.T_AND, getLeft().toPNF(true), getRight().toPNF()))); } else { // (a<->b) = (!a && !b) || (a && b) return(new LTLNode(type_t.T_OR, new LTLNode(type_t.T_AND, getLeft().toPNF(true), getRight().toPNF(true)), new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF()))); } } case type_t.T_NOT: if (negate) { // double negation return(getLeft().toPNF()); ////////////////////?? shouldn't be getRight().toPNF()? !(!a) = a } else { if (getLeft().getType() == type_t.T_AP) { // we are in front of an AP, negation is ok return(new LTLNode(type_t.T_NOT, getLeft())); } else { return(getLeft().toPNF(true)); } } case type_t.T_AP: if (negate) { return(new LTLNode(type_t.T_NOT, new LTLNode(_ap))); } else { return(new LTLNode(_ap)); } case type_t.T_TRUE: if (negate) { return(new LTLNode(type_t.T_FALSE, null)); } else { return(new LTLNode(type_t.T_TRUE, null)); } case type_t.T_FALSE: if (negate) { return(new LTLNode(type_t.T_TRUE, null)); } else { return(new LTLNode(type_t.T_FALSE, null)); } case type_t.T_AND: // ! (a & b) = (!a | !b) if (negate) { return(new LTLNode(type_t.T_OR, getLeft().toPNF(true), getRight().toPNF(true))); } else { return(new LTLNode(type_t.T_AND, getLeft().toPNF(), getRight().toPNF())); } case type_t.T_OR: if (negate) { // ! (a | b) = (!a & !b) return(new LTLNode(type_t.T_AND, getLeft().toPNF(true), getRight().toPNF(true))); } else { return(new LTLNode(type_t.T_OR, getLeft().toPNF(), getRight().toPNF())); } case type_t.T_NEXTSTEP: // ! (X a) = X (!a) if (negate) { return(new LTLNode(type_t.T_NEXTSTEP, getLeft().toPNF(true))); } else { return(new LTLNode(type_t.T_NEXTSTEP, getLeft().toPNF())); } case type_t.T_FINALLY: // ! (F a) = G (!a) = f V !a if (negate) { return(new LTLNode(type_t.T_RELEASE, new LTLNode(type_t.T_FALSE, null), getLeft().toPNF(true))); } else { // F a = t U a return(new LTLNode(type_t.T_UNTIL, new LTLNode(type_t.T_TRUE, null), getLeft().toPNF())); } case type_t.T_GLOBALLY: // ! (G a) = F (!a) = t U ! a if (negate) { return(new LTLNode(type_t.T_UNTIL, new LTLNode(type_t.T_TRUE, null), getLeft().toPNF(true))); } else { // f V a return(new LTLNode(type_t.T_RELEASE, new LTLNode(type_t.T_FALSE, null), getLeft().toPNF())); } case type_t.T_UNTIL: // ! (a U b) = (!a V !b) if (negate) { return(new LTLNode(type_t.T_RELEASE, getLeft().toPNF(true), getRight().toPNF(true))); } else { return(new LTLNode(type_t.T_UNTIL, getLeft().toPNF(), getRight().toPNF())); } case type_t.T_RELEASE: // ! (a R b) = (!a U !b) if (negate) { return(new LTLNode(type_t.T_UNTIL, getLeft().toPNF(true), getRight().toPNF(true))); } else { return(new LTLNode(type_t.T_RELEASE, getLeft().toPNF(), getRight().toPNF())); } case type_t.T_WEAKUNTIL: { LTLNode weak_until = new LTLNode(type_t.T_UNTIL, getLeft(), new LTLNode(type_t.T_OR, getRight(), new LTLNode(type_t.T_GLOBALLY, getLeft(), null))); return(weak_until.toPNF(negate)); } case type_t.T_WEAKRELEASE: throw new Exception("Operator WEAKRELEASE not yet supported"); case type_t.T_BEFORE: throw new Exception("Operator BEFORE not yet supported"); } throw new Exception("Implementation error"); }
private static LTLNode TranslateLTL(ltl2ba.Node CurrentNode, APSet apset, APSet predefined_apset) { if (CurrentNode == null) { return(null); } type_t nodeType = type_t.T_TRUE; switch ((Operator)CurrentNode.ntyp) { case Operator.ALWAYS: nodeType = type_t.T_GLOBALLY; break; case Operator.AND: nodeType = type_t.T_AND; break; case Operator.EQUIV: nodeType = type_t.T_EQUIV; break; case Operator.EVENTUALLY: nodeType = type_t.T_FINALLY; break; case Operator.FALSE: nodeType = type_t.T_FALSE; break; case Operator.IMPLIES: nodeType = type_t.T_IMPLICATE; break; case Operator.NOT: nodeType = type_t.T_NOT; break; case Operator.OR: nodeType = type_t.T_OR; break; case Operator.TRUE: nodeType = type_t.T_TRUE; break; case Operator.U_OPER: nodeType = type_t.T_UNTIL; break; case Operator.V_OPER: nodeType = type_t.T_RELEASE; break; case Operator.NEXT: nodeType = type_t.T_NEXTSTEP; break; case Operator.PREDICATE: nodeType = type_t.T_AP; string ap = CurrentNode.sym.name; char ch = ap[0]; if (ch == '"') { // std::cerr << ap << std::endl; Debug.Assert(ap[ap.Length - 1] == '"'); // last char is " if (ap.Length <= 2) { // empty ap! throw new Exception("LTL-Parse-Error: empty quoted string"); } ap = ap.Substring(1, ap.Length - 2); // cut quotes } else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { // nop } else { throw new Exception("LTL-Parse-Error"); } int ap_i; // the AP index if (predefined_apset != null) { if ((ap_i = predefined_apset.find(ap)) != -1) { return(new LTLNode(ap_i)); } else { // not found in predefined APSet! //std::cerr << "[" << (int)s[2] << "]" << std::endl; throw new Exception("Can't parse formula with this APSet!"); } } else { if ((ap_i = apset.find(ap)) != -1) { // AP exists already return(new LTLNode(ap_i)); } else { // create new AP ap_i = apset.addAP(ap); return(new LTLNode(ap_i)); } } break; default: break; } LTLNode newNode = new LTLNode(nodeType, TranslateLTL(CurrentNode.lft, apset, predefined_apset), TranslateLTL(CurrentNode.rgt, apset, predefined_apset)); return(newNode); }
private static LTLNode TranslateLTL(ltl2ba.Node CurrentNode, APSet apset, APSet predefined_apset) { if (CurrentNode == null) { return null; } type_t nodeType = type_t.T_TRUE; switch ((Operator) CurrentNode.ntyp) { case Operator.ALWAYS: nodeType = type_t.T_GLOBALLY; break; case Operator.AND: nodeType = type_t.T_AND; break; case Operator.EQUIV: nodeType = type_t.T_EQUIV; break; case Operator.EVENTUALLY: nodeType = type_t.T_FINALLY; break; case Operator.FALSE: nodeType = type_t.T_FALSE; break; case Operator.IMPLIES: nodeType = type_t.T_IMPLICATE; break; case Operator.NOT: nodeType = type_t.T_NOT; break; case Operator.OR: nodeType = type_t.T_OR; break; case Operator.TRUE: nodeType = type_t.T_TRUE; break; case Operator.U_OPER: nodeType = type_t.T_UNTIL; break; case Operator.V_OPER: nodeType = type_t.T_RELEASE; break; case Operator.NEXT: nodeType = type_t.T_NEXTSTEP; break; case Operator.PREDICATE: nodeType = type_t.T_AP; string ap = CurrentNode.sym.name; char ch = ap[0]; if (ch == '"') { // std::cerr << ap << std::endl; Debug.Assert(ap[ap.Length - 1] == '"'); // last char is " if (ap.Length <= 2) { // empty ap! throw new Exception("LTL-Parse-Error: empty quoted string"); } ap = ap.Substring(1, ap.Length - 2); // cut quotes } else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { // nop } else { throw new Exception("LTL-Parse-Error"); } int ap_i; // the AP index if (predefined_apset != null) { if ((ap_i = predefined_apset.find(ap)) != -1) { return new LTLNode(ap_i); } else { // not found in predefined APSet! //std::cerr << "[" << (int)s[2] << "]" << std::endl; throw new Exception("Can't parse formula with this APSet!"); } } else { if ((ap_i = apset.find(ap)) != -1) { // AP exists already return new LTLNode(ap_i); } else { // create new AP ap_i = apset.addAP(ap); return new LTLNode(ap_i); } } break; default: break; } LTLNode newNode = new LTLNode(nodeType, TranslateLTL(CurrentNode.lft, apset, predefined_apset), TranslateLTL(CurrentNode.rgt, apset, predefined_apset)); return newNode; }