def test_issue_4(self): """ Patch for a dynamic method Ensures that the patch is working. https://code.google.com/p/pyswip/issues/detail?id=4 """ from pyswip import Prolog Prolog.dynamic('test_issue_4_d/1') Prolog.assertz('test_issue_4_d(test1)') Prolog.assertz('test_issue_4_d(test1)') Prolog.assertz('test_issue_4_d(test1)') Prolog.assertz('test_issue_4_d(test2)') results = list(Prolog.query('test_issue_4_d(X)')) self.assertEqual(len(results), 4) Prolog.retract('test_issue_4_d(test1)') results = list(Prolog.query('test_issue_4_d(X)')) self.assertEqual(len(results), 3) Prolog.retractall('test_issue_4_d(test1)') results = list(Prolog.query('test_issue_4_d(X)')) self.assertEqual(len(results), 1)
def test_issue_4(self): """ Patch for a dynamic method Ensures that the patch is working. https://code.google.com/p/pyswip/issues/detail?id=4 """ from pyswip import Prolog Prolog.dynamic('test_issue_4_d/1') Prolog.assertz('test_issue_4_d(test1)') Prolog.assertz('test_issue_4_d(test1)') Prolog.assertz('test_issue_4_d(test1)') Prolog.assertz('test_issue_4_d(test2)') results = list(Prolog.query('test_issue_4_d(X)')) self.assertEqual(len(results), 4) Prolog.retract('test_issue_4_d(test1)') results = list(Prolog.query('test_issue_4_d(X)')) self.assertEqual(len(results), 3) Prolog.retractall('test_issue_4_d(test1)') results = list(Prolog.query('test_issue_4_d(X)')) self.assertEqual(len(results), 1)
class AbalonePrologAIEngine(object): # loads the abalone.pl prolog file def __init__(self): self.swipl = Prolog() self.swipl.consult("./abalone.pl") result = list(self.swipl.query("start_game")) if not result: raise Exception('Error in initializing the game') # make_move # @color - the color of the current player # @from_cell - the beginning cell of the move # #end_cell - the end cell of the move # execute in prolog: # can_make_move query for validation the move is valid # make_move query for executing the move in prolog. # returns tuple of the MoveType and Move Direction def make_move(self, color, from_cell, to_cell='not_exist'): result = list(self.swipl.query( "can_make_move(MoveType, %s, Direction, %s, %s), " "make_move(MoveType, %s, Direction, %s, %s)" % ( color, from_cell, to_cell, color, from_cell, to_cell))) if not result: return None, None return PROLOG_MOVES_TO_PUSH_TYPE[str(result[0]['MoveType'])], result[0]['Direction'] # make_move # @color - the color of the current player # execute in prolog: # get_best_move query for getting the computer best move # make_move query for executing the move in prolog. # returns tuple of the MoveType, Move Direction, FromCell, EndCell def get_best_move(self, color): result = list(self.swipl.query( "get_best_move(%s, MoveType, Direction, From, To)" % color)) if not result: return None, None, None, None query = "make_move(%s, %s, %s, %s, %s)" % ( (result[0]['MoveType']), color, result[0]['Direction'], result[0]['From'], result[0]['To']) result2 = list(self.swipl.query(query)) if not result2: print('unexpected error') return PROLOG_MOVES_TO_PUSH_TYPE[str(result[0]['MoveType'])], result[0]['Direction'], \ result[0]['From'], result[0]['To'] def change_level(self, level): self.swipl.retract("level(OldLevel)" ) self.swipl.asserta('level(%s)' % level) # get_current_score # execute in prolog # game_score query for getting the current game score # returns tuple of the number of white cells, blackcells, and weather the game ended. def get_current_score(self): result = list(self.swipl.query("game_score(Black, White, Victory)")) return result[0]['White'], result[0]['Black'], result[0]['Victory']
class FamilyTree: def __init__(self): self.prolog = Prolog() self.predicates = list() self.table = list() self.apply([str(datetime.today().year), 'current_year']) def apply(self, args: list): args[0], args[1] = args[1], args[0] predicate = f"{args[0]}({','.join(args[1:])})" self.prolog.assertz(predicate) self.predicates.append(predicate) args[0], args[1] = args[1], args[0] self.table.append(args) def query(self, query: str): for item in self.prolog.query(query): for key in item.keys(): print(f'\t {key} = {item[key]} ; \t', end='') print() def consult(self, prolog_program_file: str): self.prolog.consult(prolog_program_file) def remove_last_predicate(self): last_predicate = self.predicates[-1] self.prolog.retract(last_predicate) del self.predicates[-1] del self.table[-1] def print_as_table(self): columns = max([len(row) for row in self.table]) headers = ['Subject', 'Predicate'] + [f'Object-{i}' for i in range(columns - 2)] t = PrettyTable(headers) for row in self.table: t.add_row(row + ['' for _ in range(len(headers) - len(row))]) print(t)
class PrologReplier(telepot.aio.helper.ChatHandler): def __init__(self, *args, **kwargs): super(PrologReplier, self).__init__(*args, **kwargs) self.prolog = Prolog() self.prolog.consult('Askid.pl') self.activities = {'eat': 'Did you eat anything at school today?', 'play': 'Did you play anything at school today?', 'learn': 'Did you learn anything at school today?', 'rest': 'Did you have a good rest at school today?', 'sports': 'Did you do any sports at your school today?'} self.unused_activities = list(self.activities.keys()) self.activity = '' self.question = '' async def on_chat_message(self, msg): _, _, id = telepot.glance(msg) if (msg['text'] == '/start'): self.prolog = Prolog() self.prolog.consult('Askid.pl') self.question = random.choice(list(self.activities.keys())) self.activity = self.question self.prolog.assertz('curr({})'.format(self.question)) self.prolog.query("assert(asked('{}'))".format( self.activities[self.question])) # await self.sender.sendMessage(self.activities[self.question]) kb = ReplyKeyboardMarkup(keyboard=[['YES', 'NO']]) await bot.sendMessage(id, self.activities[self.question], reply_markup=kb) elif (msg['text'] == 'YES'): if self.question in self.activities: self.question = list(self.prolog.query( 'random_question(X)'))[0]['X'] kb = ReplyKeyboardMarkup(keyboard=[['YES', 'NO']]) # await self.sender.sendMessage(self.question, reply_markup = kb) await bot.sendMessage(id, self.question, reply_markup=kb) else: # For some strange bugs, multiple print() functions must be inserted for the query to run successfully. print(list(self.prolog.query("play(X)"))) self.prolog.query("assert(yes('{}'))".format(self.question)) print(list(self.prolog.query( "assert(yes('{}'))".format(self.question)))) questions = list(self.prolog.query( "ask('{}', X)".format(self.question))) print(questions) self.question = random.choice(questions)['X'] self.prolog.query("assert(asked('{}'))".format(self.question)) kb = ReplyKeyboardMarkup(keyboard=[['YES', 'NO']]) # await self.sender.sendMessage(self.question, reply_markup = kb) await bot.sendMessage(id, self.question, reply_markup=kb) elif (msg['text'] == 'NO'): self.unused_activities.remove(self.activity) self.prolog.retract("curr({})".format(self.activity)) if (len(self.unused_activities) == 0): self.prolog = Prolog() self.prolog.consult('Askid.pl') self.unused_activities = list(self.activities.keys()) self.question = random.choice(list(self.activities.keys())) self.activity = self.question self.prolog.assertz('curr({})'.format(self.question)) else: self.question = random.choice(self.unused_activities) self.activity = self.question self.prolog.assertz('curr({})'.format(self.question)) self.prolog.query("assert(asked('{}'))".format( self.activities[self.question])) kb = ReplyKeyboardMarkup(keyboard=[['YES', 'NO']]) # await self.sender.sendMessage(self.activities[self.question], reply_markup = kb) await bot.sendMessage(id, self.activities[self.question], reply_markup=kb)
class AIEngine: instance: AIEngine = None COM_TYPE_ASSERTZ = 1 COM_TYPE_RETRACT = 0 def __init__(self): self.history = [] # [{"com": int, "data": str}] self.prolog = None if AIEngine.instance is not None: self.history = AIEngine.instance.history self.prolog = AIEngine.instance.prolog else: AIEngine.instance = self self.init({}) def _debug_save_in(self, file): if isinstance(file, str): file = open(file, "w", encoding="utf-8") dump(self.history, file) def _debug_load_from(self, file): if isinstance(file, str): file = open(file, "r", encoding="utf-8") history = load(file) self.init(history) def save(self): return { "history": AIEngine.cleaned_history(self.history), } @staticmethod def load(saved): obj = AIEngine() obj.init(saved["history"]) return obj @staticmethod def cleaned_history(history): r_history = history[:] i = 0 while i < len(r_history): fact = r_history[i] if fact["com"] == AIEngine.COM_TYPE_RETRACT: del r_history[i] r_history.remove({ "com": AIEngine.COM_TYPE_ASSERTZ, "data": fact["data"], }) i -= 1 else: i += 1 return r_history def init(self, history): self._init_prolog() for fact in history: self.ack_fact(fact["com"], fact["data"]) def _init_prolog(self): if self.prolog is not None: #raise RuntimeError("Resetting Prolog is impossible") return self.prolog = Prolog() def ack_fact(self, com, data): self.history.append({"com": com, "data": data}) if com == AIEngine.COM_TYPE_ASSERTZ: self.prolog.assertz(data) elif com == AIEngine.COM_TYPE_RETRACT: self.prolog.retract(data) def assertz(self, data): self.ack_fact(AIEngine.COM_TYPE_ASSERTZ, data) def retract(self, data): self.ack_fact(AIEngine.COM_TYPE_RETRACT, data)
class PrologPhoneChoiceAssistant(PhoneChoiceAssistant): _REQUIRE_TEMPLATE = "user_requirement({rule_key}, {value})" def __init__( self, rules_file: str, knowledge_base_file: str, ): super().__init__() self._prolog = Prolog() self._load_knowledge_base(knowledge_base_file) self._load_rules(rules_file) self._loaded_rules: Dict[RuleKey, Rule] = dict() def _load_rules( self, rules_file: str, ): self._prolog.consult(rules_file) def _load_knowledge_base( self, knowledge_base_file: str, ): self._prolog.consult(knowledge_base_file) def suggest(self) -> Set[Model]: models: Generator[Dict[str, bytes], None, None] = self._prolog.query("is_sufficient(Model)") models_list = [d["Model"].decode("utf-8") for d in models] return set(models_list) def battery_life(self, battery_life: BatteryLife): rule_key = "battery_life" self._require(rule_key, battery_life.name.lower()) def cpu_frequency(self, cpu_frequency: CPUFrequency): rule_key = "cpu_frequency" self._require(rule_key, cpu_frequency.name.lower()) def touch_screen(self): rule_key = "touch_screen" self._require(rule_key, RequiredFeature_String) def nfc(self): rule_key = "nfc" self._require(rule_key, RequiredFeature_String) def water_resistant(self): rule_key = "touch_screen" self._require(rule_key, RequiredFeature_String) def dual_sim(self): rule_key = "dual_sim" self._require(rule_key, RequiredFeature_String) def cpu_n_cores(self, cpu_n_cores: CpuNCores): rule_key = "cpu_n_cores" self._require(rule_key, cpu_n_cores.name.lower()) def back_camera_matrix(self, back_camera_matrix: BackCameraMatrix): rule_key = "back_camera_matrix" self._require(rule_key, back_camera_matrix.name.lower()) def front_camera_matrix(self, front_camera_matrix: FrontCameraMatrix): rule_key = "front_camera_matrix" self._require(rule_key, front_camera_matrix.name.lower()) def phone_for_business(self): rule_key = "phone_for_business" self._require(rule_key, RequiredFeature_String) def big_screen(self): rule_key = "big_screen" self._require(rule_key, RequiredFeature_String) def very_big_screen(self): rule_key = "very_big_screen" self._require(rule_key, RequiredFeature_String) def phone_for_teenager(self): rule_key = "phone_for_teenager" self._require(rule_key, RequiredFeature_String) def phone_to_listening_music(self): rule_key = "phone_to_listening_music" self._require(rule_key, RequiredFeature_String) def phone_for_social_media(self): rule_key = "phone_for_social_media" self._require(rule_key, RequiredFeature_String) def phone_to_play_games(self): rule_key = "phone_to_play_games" self._require(rule_key, RequiredFeature_String) def phone_to_make_photos(self): rule_key = "phone_to_make_photos" self._require(rule_key, RequiredFeature_String) def phone_for_trips(self): rule_key = "phone_for_trips" self._require(rule_key, RequiredFeature_String) def _require(self, rule_key: str, value: Any): previous_rule = self._loaded_rules.get(rule_key) if previous_rule: self._prolog.retract(previous_rule) new_rule = PrologPhoneChoiceAssistant._REQUIRE_TEMPLATE.format( rule_key=rule_key, value=value, ) print(new_rule) self._prolog.asserta(new_rule) self._loaded_rules[rule_key] = new_rule def clear_requirements(self): self._prolog.retractall("user_requirement(A,B)") self._loaded_rules = dict()
class PrologConnector: def __init__(self): self.prolog = Prolog() @staticmethod def create_temp_file(code) -> str: # create temp file for Prolog code if 'connect_files' not in os.listdir(): # custom dir try: os.mkdir('connect_files') except PermissionError: raise PermissionError("Don't have permission for create a dir") with tempfile.NamedTemporaryFile('w', delete=False, suffix='.pro', dir='connect_files') as file: file.write(code) return file.name[file.name.rfind('\\') + 1::] def consult_code(self, code: str, delete=True): # consult Prolog code via temp file self.consult_file('connect_files/' + self.create_temp_file(code), delete) def consult_file(self, file_name: str, delete=False): self.prolog.consult(file_name) if delete: os.remove(file_name) # warning! can be broken if maxresult = -1 def get_n_ans(self, instructions: str, maxresult=1, **kwargs) -> [dict]: # query for prolog return self.prolog.query(instructions, maxresult=maxresult, **kwargs) def get_n_ans_new(self, instructions: str, maxresults=-1, solves=True) -> list: ' functors and items of predicates, variables' terms, vars, statements = self.parse_ins(instructions) vars_ans = [] if solves else {i[0]: [] for i in vars } # list/dict of variable values statements_ans = {} # list of statements if terms: q = Query(*terms) # make query while q.nextSolution() and maxresults: # find solutions maxresults -= 1 if solves: # append values vars_ans.append({k: v.value for k, v in vars}) else: for k, v in vars: if v.value not in vars_ans[k]: vars_ans[k].append(v.value) q.closeQuery() if statements: for statement in statements: statements_ans.update({statement[1]: call(statement[0])}) return vars_ans, statements_ans @staticmethod def parse_ins(instruction) -> list and list and list: if instruction[-1] != ';': instruction += ';' terms = [] # if need var(s) vars = [] statements = [] # if need True or False pnames = re.compile( r'\[.+\]|[\w\d]+') # find names(vars|lists|strings|ints) in atoms plist = re.compile(r'\[.+\]') # find list # find predirects for pred, atoms in re.findall(r'([^\(\)\,\s]+|\S)(\([^\)]+\))\;', instruction): names = pnames.findall(atoms) items = [] there_is_var = False for atom in names: atom = atom.strip() if atom[0].isupper(): # check for var any_var = Variable() # link to Prologs var items.append(any_var) vars.append((atom, any_var)) there_is_var = True elif atom.isdigit(): # check for int items.append(int(atom)) elif plist.search(atom): # check for list items.append(literal_eval(atom)) else: try: # check for float items.append(float(atom)) except ValueError: items.append(atom) if there_is_var: terms.append(Functor(pred, len(names))(*items)) else: statements.append((Functor(pred, len(names))(*items), pred + atoms)) return terms, vars, statements def make_req(self, command: str, solves=False, **kwargs): # with custom parameters 'for all solves of only 1 request(may be unused)' a = self.get_n_ans_new(command, solves=solves, **kwargs) # getting only 1 result if a[0]: return a[0] elif a[1]: for i in a[1].values(): return i else: return None def assert_code(self, ins: str): """ for assertion facts(the same as consult_code) """ for i in ins.split(';'): self.prolog.assertz(i) def retract_code(self, ins: str, all=False): g = ins.split(';') if all: for i in g: self.prolog.retractall(i) else: for i in g: self.prolog.retract(i)
class CovidAIBrigde: """ Communicates directly with prolog scripts to return diagnosis """ def __init__(self, name, log=False): self.prolog = Prolog() self.patient_name = name.split(" ")[0].lower() self.log = log self.prolog.consult('covid.pl') def store_home_parish(self, parish): """ Store the patient current home parish Parameters: parish(list): What symptoms does the patients """ parish = parish.lower() if "st." in parish: parish = parish.split(" ") parish[0] = "saint" parish = "_".join(parish) query_string = f"from_parish({self.patient_name}, {parish})" self.prolog.asserta(query_string) if self.log: self.__log_function(query_string) def store_symptoms(self, symptoms): """ Store the patient symptoms Parameters: symptoms(list): What symptoms does the patients """ query_strings = [ f"has_symptom({self.patient_name}, '{symptom}')" for symptom in symptoms ] for query_string in query_strings: self.prolog.asserta(query_string) if self.log: for query_string in query_strings: self.__log_function(query_string) def store_temperature(self, temperature): """ Store the patient temperature Parameters: temperature(int): What is the patients temperature """ query_string = f"patient_temperature({self.patient_name}, {temperature})" self.prolog.asserta(query_string) if self.log: self.__log_function(query_string) def store_patient_activities(self, wm, t, s, p): """ Store the patient activities that could contribute to diagnosis Parameters: wm(str): Does the patient usually wear a mask t(str): Does the patient travel alot s(str): Does the patient sanitize regularly p(str): Does the patient go to parties """ query_string_mask = f"wears_mask({self.patient_name}, {wm.lower()})" query_string_travel = f"travels({self.patient_name}, {t.lower()})" query_string_sanitize = f"sanitizes({self.patient_name}, {s.lower()})" query_string_party = f"goes_parties({self.patient_name}, {p.lower()})" self.prolog.asserta(query_string_mask) self.prolog.asserta(query_string_travel) self.prolog.asserta(query_string_sanitize) self.prolog.asserta(query_string_party) if (self.log): self.__log_function(query_string_mask) self.__log_function(query_string_travel) self.__log_function(query_string_sanitize) self.__log_function(query_string_party) def diagnose(self): """ Diagnosis and returns a value for how much the chances this patient has covid """ results = list(self.prolog.query(f"has_covid({self.patient_name}, X)")) return results[0] def __log_function(self, string): """ prints out any string passed in with specific format """ print(f"I KNOW: {string}.") def memory_wipe(self): """ wipe information about patient from the agents memory """ # define predicate strings query_string_symptom = f"has_symptom({self.patient_name},_)" query_string_parish = f"from_parish({self.patient_name},_)" query_string_temp = f"patient_temperature({self.patient_name},_)" query_string_mask = f"wears_mask({self.patient_name},_)" query_string_travel = f"travels({self.patient_name},_)" query_string_sanitize = f"sanitizes({self.patient_name},_)" query_string_party = f"goes_parties({self.patient_name},_)" self.prolog.retractall(query_string_symptom) self.prolog.retract(query_string_parish) self.prolog.retract(query_string_temp) self.prolog.retract(query_string_mask) self.prolog.retract(query_string_travel) self.prolog.retract(query_string_sanitize) self.prolog.retract(query_string_party) def __open_db_connection(self): """ Open connection to database """ try: self.con = sqlite3.connect("covidAi.db") print("[Connection established]") except Error: print(Error) def __get_parish_statistics(self): cursorObj = self.con.cursor() cursorObj.execute("SELECT * FROM parishes") rows = list(cursorObj.fetchall()) return rows def update_knowledgebase(self): self.__open_db_connection() statistics = self.__get_parish_statistics() for (id, parish, chance) in statistics: parish_assersion = f"covid_cases({parish}, {chance})" print(parish_assersion) self.prolog.asserta(parish_assersion)