def get_violations(spec: Union[str, Iterable[str]]): """Get the list of violations for a given specification. Returns None if the problem is not satisfiable. Internally, Draco checks against the definitions, constraints, helpers, and hard constraints. :param spec: The specification top check """ if not isinstance(spec, str): spec = "\n".join(spec) c = "".join( blocks_to_program( constraints.blocks, set(constraints.blocks.keys()) - set(["violation"]) ) ) program = definitions.program + c + helpers.program + hard.program + spec try: model = next(run_clingo(program, 1)) return [ symbol.arguments[0].name for symbol in model.answer_set if symbol.name == "violation" ] except StopIteration: # Since the problem is not satisfiable, we return None to distinguish it from # satisfiable programs where you would expect violations to be [] return None
def is_valid(draco_query: List[str], debug=False) -> bool: """ Check a task. Args: draco_query: a list of facts Returns: whether the task is valid """ _, stdout = run_clingo(draco_query, files=["define.lp", "hard.lp"], silence_warnings=True, debug=debug) return json.loads(stdout)["Result"] != "UNSATISFIABLE"
def test_dict_to_fact_and_answer_set_to_dict(): expected = { "view": [ { "mark": [ {"type": "bar", "encoding": [{"channel": "x", "field": "foo"}]} ], "scale": [{"channel": "x", "type": "linear"}], } ], } program = dict_to_facts(expected) result = run_clingo(program) assert answer_set_to_dict(next(result).answer_set) == expected
def test_answer_set_to_dict(): program = [ # root "attribute(numberRows,root,42).", # first field "entity(field,root,0).", "attribute((field,unique),0,12).", "attribute((field,type),0,number).", # second fields "entity(field,root,1).", "attribute((field,unique),1,32).", "attribute((field,type),1,string).", ] result = run_clingo(program) assert answer_set_to_dict(next(result).answer_set) == { "numberRows": 42, "field": [ {"unique": 12, "type": "number"}, {"unique": 32, "type": "string"}, ], }