def categorize_bounds(formula: FNode, sender_symbol: FNode): """ categorize symbolic bounds for a given variable :param formula: FNode formula in CNF form :param sender_symbol: FNode of the bounded variable :return: upper_bounds, lower_bounds, parent_atoms """ clauses = set() formula = simplify(formula) if formula.is_or() or is_literal(formula): clauses.add(formula) else: # formula of CNF form for clause in formula.args(): assert is_literal(clause) or clause.is_or() clauses.add(clause) bounds = defaultdict(list) for clause in clauses: if clause.is_le() or clause.is_lt(): # single literal clause bound, bound_type = atom_to_bound(clause, sender_symbol) bounds[bound_type].append(bound) continue for atom in clause.get_atoms(): # atom: inequality a * x + b * y < c assert atom.is_le() or atom.is_lt() bound, bound_type = atom_to_bound(atom, sender_symbol) bounds[bound_type].append(bound) return list(set(bounds[UPPER])), list(set(bounds[LOWER])), \ list(set(bounds[NEITHER]))
def check_clause(formula: FNode): """ check if formula is either an atom or disjunctive of atoms :param formula: :return: """ flag = True formula = simplify(formula) if len(formula.get_atoms()) == 1: return True if not formula.is_or(): return False for atom in formula.get_atoms(): flag = flag and (atom in atom.get_atoms()) return flag
def formula_to_interval_set(formula: FNode, sender_symbol: FNode, test_point: float): clauses = set() if formula.is_or() or is_literal(formula): clauses.add(formula) else: # formula of CNF form for clause in formula.args(): assert is_literal(clause) or clause.is_or() clauses.add(clause) interval_list = [] for clause in clauses: intervals = clause_to_intervals(clause, sender_symbol, test_point) if intervals: interval_list.append(intervals) return interval_list