예제 #1
0
def mcf_or(modal_context, fml, clausal_form_dict, id_mc):
    """ Takes OR fml, and applies transformation rules.
    """
    global max_mc_id
    mcf_dict_key = len(modal_context)
    modal_context_clauses = False

    # modal context does not distribute over the 'or' operator
    left_fml = fml[1]
    right_fml = fml[2]

    # if both formulas are simple, add to context
    if not u.is_complex(left_fml) or not u.is_complex(right_fml):
        if not u.is_complex(left_fml) and not u.is_complex(right_fml):
            to_mcf(modal_context, left_fml, clausal_form_dict, id_mc)
            to_mcf(modal_context, right_fml, clausal_form_dict, id_mc)
        else:  # one of the formulas must be complex - &, | or modality
            if u.is_complex(right_fml):
                complex_fml = right_fml
                simple_fml = left_fml
            else:
                complex_fml = left_fml
                simple_fml = right_fml

            # check simple_fml is only other conjunct in context
            if mcf_dict_key in clausal_form_dict:
                modal_context_clauses = eq_modal_context(
                    modal_context, id_mc, clausal_form_dict[mcf_dict_key])
            complex_fml_connective = complex_fml[0]

            if repr(complex_fml_connective) == '|' or modal_context_clauses:
                to_mcf(modal_context, simple_fml, clausal_form_dict, id_mc)
                to_mcf(modal_context, complex_fml, clausal_form_dict, id_mc)
            elif repr(complex_fml_connective) == '&':
                # simple_fml is only other conjunct in context therefore apply de morgans
                com_left_fml = complex_fml[1]
                com_right_fml = complex_fml[2]
                to_mcf(modal_context, [
                    u.op('&'), [u.op('|'), simple_fml, com_left_fml],
                    [u.op('|'), simple_fml, com_right_fml]
                ], clausal_form_dict, id_mc)
            elif isinstance(complex_fml_connective, parser.Modality):
                # simple_fml is only other conjunct in context
                to_mcf(modal_context, simple_fml, clausal_form_dict, id_mc)
                to_mcf(modal_context, complex_fml, clausal_form_dict, id_mc,
                       False)

            else:
                mcf_error(modal_context, fml, clausal_form_dict, id_mc)

    else:  # both arguments are complex sub formulas
        to_mcf(modal_context, left_fml, clausal_form_dict, id_mc, True)
        to_mcf(modal_context, right_fml, clausal_form_dict, id_mc, True)
예제 #2
0
def get_bool(atom):
    """
    :param atom: parsed classical atom, can be negated

    :return z3 appropriate boolean value
    """
    assert not is_complex(atom), "Error adding atom to sat solver: %s" % atom

    # need to account for 'False' and 'True'
    if is_atomic(atom):
        if atom == TOP:
            return True
        elif atom == BOTTOM:
            return False
        else:
            return Bool(str(atom))
    elif str(atom[0]) == '~':
        if atom[1] == TOP:
            return False
        elif atom[1] == BOTTOM:
            return True
        else:
            return Not(Bool(str(atom[1])))
    else:  # error
        sys.stderr.write('Error adding atom to sat solver: ' + str(atom) +
                         '\n')
        raise SystemExit(1)
예제 #3
0
def check_activation(modal_implication, valuation):
    """
    :param modal_implication: see active_modalities above
    :param valuation: see active_modalities above

    :return tuple representing modal implications (modal atom, classical atom) if modality is active.
    otherwise, return False.
    """
    assert len(
        modal_implication.disjuncts
    ) <= 2, "The modal disjunction is not formed correctly: %s" % modal_implication
    prop_atom, modal_atom = None, None
    true_literals = valuation[0]
    false_literals = valuation[1]

    # given assertion there should be one prop atom and one modal atom
    for disjunct in modal_implication.disjuncts:
        if not is_complex(disjunct):
            prop_atom = disjunct
        elif my_isinstance(disjunct[0], Modality):
            modal_atom = disjunct

    # check valuation of prop_atom, to determine num_modal_atoms activity
    # check if prop_atom is negated
    if is_atomic(prop_atom) and str(prop_atom) not in true_literals:
        # not negated
        return modal_atom, prop_atom

    if not is_atomic(prop_atom) and str(prop_atom[1]) not in false_literals:
        return modal_atom, prop_atom

    return False
예제 #4
0
def to_mcf(modal_context,
           nnf_fml,
           clausal_form_dict,
           id_mc,
           distributive=False):
    """ Given an expression in nnf (nnf_fml), return an equivalent expression in modal clausal form.
    """
    if nnf_fml and u.is_complex(nnf_fml):
        connective = repr(nnf_fml[0])
        switch = {
            '&': mcf_and,
            '|': mcf_or,
            'box': mcf_modality,
            'dia': mcf_modality,
        }
        operation = switch.get(connective, mcf_error)
        if operation == mcf_and or operation == mcf_modality:
            operation(modal_context, nnf_fml, clausal_form_dict, id_mc,
                      distributive)
        else:
            operation(modal_context, nnf_fml, clausal_form_dict, id_mc)

    else:
        # expr is a classical literal, add to relevant disjunct
        mcf_classical_atom(modal_context, nnf_fml, clausal_form_dict, id_mc)

    return clausal_form_dict
예제 #5
0
 def get_modal_lit(self):
     """ Returns first modal atom in a given disjunction.
     """
     for disjunct in self.disjuncts:
         if u.is_complex(disjunct):
             if isinstance(disjunct[0], parser.Modality):
                 self.disjuncts.remove(disjunct)
                 return disjunct
     return None
예제 #6
0
def get_modality(disjunctions):
    """
    :param disjunctions: list of disjunctions

    :return first stripped modal literal
    """
    for disjunct in disjunctions:
        if is_complex(disjunct):
            connective = disjunct[0]
            if my_isinstance(connective, Modality): return repr(connective)
    return False
예제 #7
0
def mcf_modality(modal_context, fml, clausal_form_dict, id_mc, distributive):
    """ Takes MODAL fml, and applies transformation rules.
    """
    global max_mc_id

    # print("MODAL " + str(fml) + ", id: " + str(id_mc))

    nested_fml = fml[1]
    max_mc_id = max(id_mc, max_mc_id)

    if not distributive:
        if not u.is_complex(nested_fml):
            create_mc(modal_context, id_mc, clausal_form_dict, fml)
        else:  # nested_fml is complex
            disjunctive_atoms = get_num_atoms(modal_context, id_mc,
                                              clausal_form_dict)
            p_atom = create_atom()

            # no classical literal in disjunction, therefore add false
            if disjunctive_atoms == 0:
                false_literal = parser.Atomic(parser.BOTTOM)
                create_mc(modal_context, id_mc, clausal_form_dict,
                          false_literal)

            # complex modal formula with one classical literal in disjunction
            if disjunctive_atoms <= 1:
                max_mc_id += 2
                create_mc(modal_context, id_mc, clausal_form_dict,
                          [fml[0], p_atom])

                updated_modal_context = copy.deepcopy(modal_context)
                updated_modal_context.append(parser.Modality('box', fml[0].id))
                upd_fml = [u.op('|'), [u.op('~'), p_atom], nested_fml]

                to_mcf(updated_modal_context,
                       upd_fml,
                       clausal_form_dict,
                       max_mc_id,
                       distributive=False)

            else:
                to_mcf(modal_context, fml, clausal_form_dict, id_mc, True)

    else:  # complex modal fml nested within OR connective
        p_atom = create_atom()
        to_mcf(modal_context, p_atom, clausal_form_dict, id_mc)
        upd_fml = [u.op('|'), [u.op('~'), p_atom], fml]
        max_mc_id += 2
        to_mcf(modal_context,
               upd_fml,
               clausal_form_dict,
               max_mc_id,
               distributive=False)
예제 #8
0
def get_num_atoms(modal_context, id_modal_context, clausal_form_dict):
    """ Returns number of classical literals in given modal context (returns max 2).
    """
    classic_atoms = 0
    mcf_dict_key = len(modal_context)

    if not mcf_dict_key in clausal_form_dict:
        return 0  # disjunction has not been created

    modal_context_clauses = eq_modal_context(modal_context, id_modal_context,
                                             clausal_form_dict[mcf_dict_key])
    if modal_context_clauses:
        for disjunct in modal_context_clauses.disjuncts:
            if not u.is_complex(disjunct):
                classic_atoms += 1
                if classic_atoms > 1: return 2
            elif isinstance(disjunct[0], parser.Modality):
                return 2
        return 1
    else:
        return 0  # disjunction (mc and id) has not been created
예제 #9
0
def get_constraints(modal_clause_dict, w):
    """
    :return parses modal clauses for input w and returns dictionary of following clauses:
        A disjunction of classical literals
        IB disjunction of one box literal and one classical literal
        ID disjunction of one diamond literal and one classical literal
        D single diamond literal
    """
    A = set()
    IB = set()
    ID = set()
    D = set()

    if w in modal_clause_dict.keys():
        w_modal_clauses = modal_clause_dict[w]
        # modal_clause is a ModalExpr - modal context and list of disjunctions
        for modal_clause in w_modal_clauses:
            disjunction = modal_clause.disjuncts

            if len(disjunction) > 2:
                A.add(modal_clause)
            elif len(disjunction) == 1:
                if not is_complex(disjunction[0]):
                    A.add(modal_clause)
                else:
                    assert get_modality(disjunction) == 'dia', \
                        "Error in getting constraint sets - incorrectly formed modal clause: %s" % modal_clause
                    D.add(modal_clause
                          )  # if complex, has to be single dia literal
            else:  # by deduction, only two disjuncts in modal_clause
                mod = get_modality(disjunction)
                if mod == 'box':
                    IB.add(modal_clause)
                elif mod == 'dia':
                    ID.add(modal_clause)
                else:
                    A.add(modal_clause)

    return {'A': A, 'IB': IB, 'ID': ID, 'D': D}
예제 #10
0
    def add_disjunct(self, arg):
        """ Add modal and classical literals to disjunction. Checks to ensure modal clauses are well formed.
        """
        if not u.is_complex(arg):  # not complex, as in classical literal
            self.disjuncts.append(get_tuple(arg))
            self.num_prop_atoms += 1

            if self.num_modal_atoms >= 1 and self.num_prop_atoms > 1:
                offending_atom = self.get_modal_lit()
                return self.adjust_modal_literal(offending_atom)
            else:
                return None
        elif isinstance(arg[0], parser.Modality):
            if self.num_modal_atoms == 0 and self.num_prop_atoms <= 1:
                self.disjuncts.append(get_tuple(arg))
                self.num_modal_atoms += 1
                return None
            else:
                return self.adjust_modal_literal(arg)

        else:
            mcf_error(self.mc, arg, self.disjuncts, self.mcid)
예제 #11
0
def mcf_classical_atom(modal_context, fml, clausal_form_dict, id_mc):
    """ Takes classical literal (fml), and adds to relevant disjunction.
    """
    assert not u.is_complex(fml)
    create_mc(modal_context, id_mc, clausal_form_dict, fml)