def satisfiable(expr, algorithm="dpll2"): """ Check satisfiability of a propositional sentence. Returns a model when it succeeds Examples: >>> from sympy.abc import A, B >>> from sympy.logic.inference import satisfiable >>> satisfiable(A & ~B) {A: True, B: False} >>> satisfiable(A & ~A) False """ expr = to_cnf(expr) if algorithm == "dpll": from sympy.logic.algorithms.dpll import dpll_satisfiable return dpll_satisfiable(expr) elif algorithm == "dpll2": from sympy.logic.algorithms.dpll2 import dpll_satisfiable return dpll_satisfiable(expr) raise NotImplementedError
def satisfiable(expr, algorithm="dpll2"): """ Check satisfiability of a propositional sentence. Returns a model when it succeeds. Returns {true: true} for trivially true expressions. Examples ======== >>> from sympy.abc import A, B >>> from sympy.logic.inference import satisfiable >>> satisfiable(A & ~B) {A: True, B: False} >>> satisfiable(A & ~A) False >>> satisfiable(True) {True: True} """ expr = to_cnf(expr) if algorithm == "dpll": from sympy.logic.algorithms.dpll import dpll_satisfiable return dpll_satisfiable(expr) elif algorithm == "dpll2": from sympy.logic.algorithms.dpll2 import dpll_satisfiable return dpll_satisfiable(expr) raise NotImplementedError
def satisfiable(expr, algorithm="dpll2"): """ Check satisfiability of a propositional sentence. Returns a model when it succeeds Examples: >>> from sympy.abc import A, B >>> from sympy.logic.inference import satisfiable >>> satisfiable(A & ~B) {A: True, B: False} >>> satisfiable(A & ~A) False """ if expr is True: return {} if expr is False: return False expr = to_cnf(expr) if algorithm == "dpll": from sympy.logic.algorithms.dpll import dpll_satisfiable return dpll_satisfiable(expr) elif algorithm == "dpll2": from sympy.logic.algorithms.dpll2 import dpll_satisfiable return dpll_satisfiable(expr) raise NotImplementedError
def test_dpll_satisfiable(): A, B, C = symbols('A,B,C') assert dpll_satisfiable(A & ~A) is False assert dpll_satisfiable(A & ~B) == {A: True, B: False} assert dpll_satisfiable(A | B) in ({ A: True }, { B: True }, { A: True, B: True }) assert dpll_satisfiable((~A | B) & (~B | A)) in ({ A: True, B: True }, { A: False, B: False }) assert dpll_satisfiable((A | B) & (~B | C)) in ({ A: True, B: False }, { A: True, C: True }, { B: True, C: True }) assert dpll_satisfiable(A & B & C) == {A: True, B: True, C: True} assert dpll_satisfiable((A | B) & (A >> B)) == {B: True} assert dpll_satisfiable(Equivalent(A, B) & A) == {A: True, B: True} assert dpll_satisfiable(Equivalent(A, B) & ~A) == {A: False, B: False}
def satisfiable(expr, algorithm="dpll2", all_models=False): """ Check satisfiability of a propositional sentence. Returns a model when it succeeds. Returns {true: true} for trivially true expressions. On setting all_models to True, if given expr is satisfiable then returns a generator of models. However, if expr is unsatisfiable then returns a generator containing the single element False. Examples ======== >>> from sympy.abc import A, B >>> from sympy.logic.inference import satisfiable >>> satisfiable(A & ~B) {A: True, B: False} >>> satisfiable(A & ~A) False >>> satisfiable(True) {True: True} >>> next(satisfiable(A & ~A, all_models=True)) False >>> models = satisfiable((A >> B) & B, all_models=True) >>> next(models) {A: False, B: True} >>> next(models) {A: True, B: True} >>> def use_models(models): ... for model in models: ... if model: ... # Do something with the model. ... print(model) ... else: ... # Given expr is unsatisfiable. ... print("UNSAT") >>> use_models(satisfiable(A >> ~A, all_models=True)) {A: False} >>> use_models(satisfiable(A ^ A, all_models=True)) UNSAT """ expr = to_cnf(expr) if algorithm == "dpll": from sympy.logic.algorithms.dpll import dpll_satisfiable return dpll_satisfiable(expr) elif algorithm == "dpll2": from sympy.logic.algorithms.dpll2 import dpll_satisfiable return dpll_satisfiable(expr, all_models) raise NotImplementedError
def test_dpll_satisfiable(): A, B, C = symbols('A,B,C') assert dpll_satisfiable( A & ~A ) == False assert dpll_satisfiable( A & ~B ) == {A: True, B: False} assert dpll_satisfiable( A | B ) in ({A: True}, {B: True}, {A: True, B: True}) assert dpll_satisfiable( (~A | B) & (~B | A) ) in ({A: True, B: True}, {A: False, B:False}) assert dpll_satisfiable( (A | B) & (~B | C) ) in ({A: True, B: False}, {A: True, C:True}) assert dpll_satisfiable( A & B & C ) == {A: True, B: True, C: True} assert dpll_satisfiable( (A | B) & (A >> B) ) == {B: True} assert dpll_satisfiable( Equivalent(A, B) & A ) == {A: True, B: True} assert dpll_satisfiable( Equivalent(A, B) & ~A ) == {A: False, B: False}
def satisfiable(expr, algorithm="dpll"): """Check satisfiability of a propositional sentence. Returns a model when it succeeds Examples >>> from sympy import symbols >>> A, B = symbols('AB') >>> satisfiable(A & ~B) {A: True, B: False} >>> satisfiable(A & ~A) False """ expr = to_cnf(expr) if algorithm == "dpll": from sympy.logic.algorithms.dpll import dpll_satisfiable return dpll_satisfiable(expr) raise NotImplementedError
def satisfiable(expr, algorithm=None, all_models=False): """ Check satisfiability of a propositional sentence. Returns a model when it succeeds. Returns {true: true} for trivially true expressions. On setting all_models to True, if given expr is satisfiable then returns a generator of models. However, if expr is unsatisfiable then returns a generator containing the single element False. Examples ======== >>> from sympy.abc import A, B >>> from sympy.logic.inference import satisfiable >>> satisfiable(A & ~B) {A: True, B: False} >>> satisfiable(A & ~A) False >>> satisfiable(True) {True: True} >>> next(satisfiable(A & ~A, all_models=True)) False >>> models = satisfiable((A >> B) & B, all_models=True) >>> next(models) {A: False, B: True} >>> next(models) {A: True, B: True} >>> def use_models(models): ... for model in models: ... if model: ... # Do something with the model. ... print(model) ... else: ... # Given expr is unsatisfiable. ... print("UNSAT") >>> use_models(satisfiable(A >> ~A, all_models=True)) {A: False} >>> use_models(satisfiable(A ^ A, all_models=True)) UNSAT """ if algorithm is None or algorithm == "pycosat": pycosat = import_module('pycosat') if pycosat is not None: algorithm = "pycosat" else: if algorithm == "pycosat": raise ImportError("pycosat module is not present") # Silently fall back to dpll2 if pycosat # is not installed algorithm = "dpll2" if algorithm == "dpll": from sympy.logic.algorithms.dpll import dpll_satisfiable return dpll_satisfiable(expr) elif algorithm == "dpll2": from sympy.logic.algorithms.dpll2 import dpll_satisfiable return dpll_satisfiable(expr, all_models) elif algorithm == "pycosat": from sympy.logic.algorithms.pycosat_wrapper import pycosat_satisfiable return pycosat_satisfiable(expr, all_models) raise NotImplementedError
def test_f5(): assert bool(dpll_satisfiable(load(f5)))
def solve_problem(input): """ the MAIN function. calls all the other functions :param input: 4 keys dict - police(int), medics(int), observations(list), queries(list) :type input: dict :return: : dict where the keys are the queries and the values are 'T', 'F' or '?' :type return: dict """ # put your solution here, remember the format needed # tile options: # [H, U, I, Q0, Q1, S0, S1, S2] police = input["police"] medics = input["medics"] queries = input["queries"] ######################### Step 0.0 - set the given observation into a 'state map' ####################### state_map = [] observation_counter = 0 #### Step 0.1 define the dict that we will return at the end. the dict answer order is as the queries order ### queries_answer_dict = {} for query in queries: queries_answer_dict[query] = '?' question_mark_options = [] question_mark_locations = [] ### Step 0.2 find the 'U' locations in the future states and implement it in the previous states ### unpopulated_location_list = [] for observation in input["observations"]: temp_observation = [] for row in observation: temp_row = [] for tile in row: temp_row.append( find_initial_list_tile_letter(tile, observation_counter)) temp_observation.append(temp_row) state_map.append(temp_observation) unpopulated_location_list.extend( find_unpopulated_location(temp_observation)) observation_counter += 1 unpopulated_location_list = list(set(unpopulated_location_list)) for observation in state_map: for loc in unpopulated_location_list: observation[loc[0]][loc[1]] = number_to_tile_state(1) # U # start going through the solution steps: for turn_counter in range(len(state_map) - 1): if turn_counter == 0: ########## step 1 - find all '?' locations and next level combinations taken from all '?' ########## state_options = [0, 1, 5] question_mark_locations = find_question_mark_locations( state_map[turn_counter]) question_mark_options = list( itertools.combinations_with_replacement( state_options, len(question_mark_locations))) ################## step 2.0 - find all possible next level observations ################### actual_observation_list = [] possible_next_observation_list = [] # Step 3.0 find locations in the next turn that are Q and in this turn are S q_location_next_turn = find_quarantine_location( state_map[turn_counter + 1]) s_location = find_sick_location(state_map[turn_counter]) # in this locations the police must act police_action_location = [ loc for loc in q_location_next_turn if loc in s_location ] # Step 3.0 find locations in the next turn that are I and in this turn are H i_location_next_turn = find_immune_location(state_map[turn_counter + 1]) h_location = find_healthy_location(state_map[turn_counter]) # in this locations the medics must act medics_action_location = [ loc for loc in i_location_next_turn if loc in h_location ] for qm_option in question_mark_options: actual_observation = copy.deepcopy( state_map[turn_counter] ) # copy the curent state to 'actual_observation' for i in range(len(question_mark_locations)): actual_observation[(question_mark_locations[i])[0]][(question_mark_locations[i])[1]] = \ number_to_tile_state(qm_option[i]) ######## step 3.1 - medics, police and system dynamics ####### # using the data in step 3.0 - earlier we searched for given Q and I locations in next turn and now # we want to use this data and append the police and medics actions that are making it happen. must_be_actions = [] for loc in police_action_location: must_be_actions.append(("quarantine", loc)) for loc in medics_action_location: must_be_actions.append(("vaccinate", loc)) # find '?' in the current and the next turn. two_turns_question_mark_locations = copy.deepcopy( question_mark_locations) two_turns_question_mark_locations.extend( find_question_mark_locations(state_map[turn_counter + 1])) two_turns_question_mark_locations = list( set(two_turns_question_mark_locations)) # if there are free police and medics, we will use the 'actions' function to find al the 'possible_actions'. if not (len(police_action_location) == police and len(medics_action_location) == medics): possible_actions = actions( actual_observation, must_be_actions, two_turns_question_mark_locations, police - len(police_action_location), medics - len(medics_action_location)) else: possible_actions = [tuple(must_be_actions)] if not must_be_actions: possible_actions = [()] # go through all the actions and check if they are possible with next known state for action in possible_actions: # check with DPLL if generate_new_state(actual_observation, action) similar to state(next turn) possible_next_observation = generate_new_state( actual_observation, action) ### step 4 - DPLL compare next level observations to the known \ given next level observation ### break_flag = False for row in range(len(possible_next_observation)): for col in range(len(possible_next_observation[row])): possible_next_observation_tile_clause = \ convert_tile_to_symbolic_clause(possible_next_observation[row][col]) next_observation_tile_clause = \ convert_tile_to_symbolic_clause(state_map[turn_counter+1][row][col]) if not dpll_alg.dpll_satisfiable( possible_next_observation_tile_clause & next_observation_tile_clause): break_flag = True break if break_flag: break if not break_flag: actual_observation_list.append(actual_observation) possible_next_observation_list.append( possible_next_observation) ##### step 5 - conclusions #### # step5.1 - compare current turn\step if len(actual_observation_list) == 1: # if the len of the current possible observation list is 1, then it is the only possible option. state_map[turn_counter] = actual_observation_list[0] elif len(actual_observation_list) > 1: # if the len of the current possible observation list is greater than 1, # then there are several options, and we have to check them using dpll for qm_loc in question_mark_locations: comparison_break_flag = False comparable_observation_tile_clause = \ convert_tile_to_symbolic_clause(actual_observation_list[0][qm_loc[0]][qm_loc[1]]) for act_observation in actual_observation_list: comparison_ans = dpll_alg.dpll_satisfiable( comparable_observation_tile_clause & convert_tile_to_symbolic_clause(act_observation[ qm_loc[0]][qm_loc[1]])) if not comparison_ans: comparison_break_flag = True break if not comparison_break_flag: state_map[turn_counter][qm_loc[0]][qm_loc[ 1]] = actual_observation_list[0][qm_loc[0]][qm_loc[1]] question_mark_locations_next_turn = find_question_mark_locations( state_map[turn_counter + 1]) # step5.2 - compare next turn\step qm_next_dict = {} if len(possible_next_observation_list) == 1: state_map[turn_counter + 1] = possible_next_observation_list[0] elif len(possible_next_observation_list) > 1: for qm_loc in question_mark_locations_next_turn: comparison_break_flag = False comparable_observation_tile_clause = \ convert_tile_to_symbolic_clause(possible_next_observation_list[0][qm_loc[0]][qm_loc[1]]) for pos_next_observation in possible_next_observation_list: comparison_ans = dpll_alg.dpll_satisfiable( comparable_observation_tile_clause & convert_tile_to_symbolic_clause(pos_next_observation[ qm_loc[0]][qm_loc[1]])) if not comparison_ans: comparison_break_flag = True break if not comparison_break_flag: state_map[turn_counter+1][qm_loc[0]][qm_loc[1]] = \ possible_next_observation_list[0][qm_loc[0]][qm_loc[1]] else: qm_next_dict[(qm_loc[0], qm_loc[1])] = calc_qm_option_list( possible_next_observation_list, qm_loc) question_mark_locations = list(qm_next_dict.keys()) if question_mark_locations: question_mark_options = qm_options_generator( [qm_next_dict[key] for key in question_mark_locations]) # step5.3 - go through the queries and answer them query_to_del = copy.deepcopy(queries) for query in query_to_del: query_answer_list = [] if query[1] == turn_counter: for act_observation in actual_observation_list: query_loc = query[0] query_letter = find_initial_list_tile_letter( query[2], turn_counter) query_letter_clause = convert_tile_to_symbolic_clause( query_letter) act_observation_tile_clause = \ convert_tile_to_symbolic_clause(act_observation[query_loc[0]][query_loc[1]]) query_answer_list.append( dpll_alg.dpll_satisfiable( query_letter_clause & act_observation_tile_clause)) if len(list(filter((lambda x: x), query_answer_list))) == len(actual_observation_list) \ and len(actual_observation_list) > 0: queries_answer_dict[query] = 'T' queries.remove(query) elif len(list(filter( (lambda x: x), query_answer_list))) == 0 or len( actual_observation_list) == 0: queries_answer_dict[query] = 'F' queries.remove(query) else: queries_answer_dict[query] = '?' elif query[1] == turn_counter + 1: for pos_observation in possible_next_observation_list: query_loc = query[0] query_letter = find_initial_list_tile_letter( query[2], turn_counter + 1) query_letter_clause = convert_tile_to_symbolic_clause( query_letter) pos_observation_tile_clause = \ convert_tile_to_symbolic_clause(pos_observation[query_loc[0]][query_loc[1]]) query_answer_list.append( dpll_alg.dpll_satisfiable( query_letter_clause & pos_observation_tile_clause)) if len(list(filter((lambda x: x), query_answer_list))) == len(possible_next_observation_list) \ and len(possible_next_observation_list) > 0: queries_answer_dict[query] = 'T' queries.remove(query) elif len(list(filter((lambda x: x), query_answer_list))) == 0 \ or len(possible_next_observation_list) == 0: queries_answer_dict[query] = 'F' queries.remove(query) else: queries_answer_dict[query] = '?' if not queries: return queries_answer_dict return queries_answer_dict
def main(): with open(sys.argv[1]) as cnf_file: cnf = load(cnf_file.read()) result = dpll_satisfiable(cnf) print(result) return 0
def test_f4(): assert not bool(dpll_satisfiable(load(f4)))
def test_f2(): assert bool(dpll_satisfiable(load(f2)))
def test_f3(): assert bool(dpll_satisfiable(load(f3)))
def test_f1(): assert bool(dpll_satisfiable(load(f1)))
def test_f4(): # re-enable this when dpll is efficient skip('Takes too much time') assert not bool(dpll_satisfiable(load(f4)))