def preprocess_problem(p: GenericProblem) -> List[str]: alphabet = p.get_alphabet() constraints = [move_root_label_to_center(x) for x in p.active_constraints] for i, label in enumerate(alphabet): constraints = [x.replace(label, str(i + 1)) for x in constraints] return constraints
def validate(p: GenericProblem) -> None: if p.flags.is_cycle: raise Exception("tlp", "Cannot classify if the graph is a cycle") if p.flags.is_directed_or_rooted: raise Exception("tlp", "Cannot classify if the tree/path is rooted/directed") if not p.flags.is_regular: raise Exception("tlp", "Cannot classify if the graph is not regular") if not p.root_allow_all or not p.leaf_allow_all: raise Exception("tlp", "Leaves and roots must allow all configurations") if len(p.get_alphabet()) > 3: raise Exception("tlp", "Cannot classify problems with more than 3 labels") active_degree = len(p.active_constraints[0]) if len( p.active_constraints) else 3 passive_degree = len(p.passive_constraints[0]) if len( p.passive_constraints) else 2 if not ((active_degree == 2 and passive_degree == 2) or (active_degree == 2 and passive_degree == 3) or (active_degree == 3 and passive_degree == 2)): raise Exception("rooted-tree", "Allowed degrees pairs are (2, 2), (2, 3), (3, 2)")
def to_problem(self) -> GenericProblem: p = GenericProblem(["A A"], ["A A"]) p.id = self.id p.active_constraints = self.active_constraints p.passive_constraints = self.passive_constraints p.leaf_constraints = self.leaf_constraints p.root_constraints = self.root_constraints alphabet = p.get_alphabet() p.leaf_allow_all = (set(flatten(p.leaf_constraints)) - {" "}) == set(alphabet) p.root_allow_all = (set(flatten(p.root_constraints)) - {" "}) == set(alphabet) p.flags = ProblemFlags( is_tree=self.is_tree, is_cycle=self.is_cycle, is_path=self.is_path, is_directed_or_rooted=self.is_directed_or_rooted, is_regular=self.is_regular, ) return p
def classify(p: GenericProblem, context: ClassifyContext) -> GenericResponse: if context.brt_preclassified: return GenericResponse(p) validate(p) alphabet = p.get_alphabet() constraints = [move_root_label_to_center(x) for x in p.active_constraints] for i, label in enumerate(alphabet): constraints = [x.replace(label, str(i + 1)) for x in constraints] result = getProblem(constraints) return GenericResponse( p, complexity_mapping[result["upper-bound"]], complexity_mapping[result["lower-bound"]], UNSOLVABLE, complexity_mapping[result[ "lower-bound"]], # because randomised LB is also a deterministic LB result["solvable-count"], result["unsolvable-count"], )
def store_problem_and_get_with_id(p: GenericProblem) -> GenericProblem: with get_db_cursor(commit=True) as cur: problem_data = ( p.get_active_degree(), p.get_passive_degree(), len(p.get_alphabet()), each_constr_is_homogeneous(p.active_constraints), each_constr_is_homogeneous(p.passive_constraints), list(p.active_constraints), list(p.passive_constraints), list(p.leaf_constraints), list(p.root_constraints), p.flags.is_tree, p.flags.is_cycle, p.flags.is_path, p.flags.is_directed_or_rooted, p.flags.is_regular, ) cur.execute( """ INSERT INTO problems ( active_degree, passive_degree, label_count, actives_all_same, passives_all_same, active_constraints, passive_constraints, root_constraints, leaf_constraints, is_tree, is_cycle, is_path, is_directed_or_rooted, is_regular ) VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s ) ON CONFLICT DO NOTHING RETURNING id;""", problem_data, ) res = cur.fetchone() if res is None: cur.execute( """ SELECT id FROM problems WHERE active_degree = %s AND passive_degree = %s AND label_count = %s AND actives_all_same = %s AND passives_all_same = %s AND active_constraints = %s AND passive_constraints = %s AND root_constraints = %s AND leaf_constraints = %s AND is_tree = %s AND is_cycle = %s AND is_path = %s AND is_directed_or_rooted = %s AND is_regular = %s; """, problem_data, ) res = cur.fetchone() p.id = res["id"] return p