Skip to content
Snippets Groups Projects
Commit 881f4dde authored by Jon's avatar Jon
Browse files

Add material and solution for week 5 workshop

parent 291651da
No related branches found
No related tags found
No related merge requests found
from pyDatalog import pyDatalog
pyDatalog.create_terms('IsFemale,IsMale,AreParents,IsHungry,Want,X,Y,Z')
#+ IsFemale('Jane')
#+ IsMale('Joe')
+ IsMale('Bob')
+ AreParents('Jane','Joe','Bob')
+ IsHungry('Bob')
# adding last fact with .load method
pyDatalog.load("+ Want('Bob','Milk')")
# adding clauses (and commenting the two given facts above)
IsFemale(X) <= AreParents(X, Y, Z)
IsMale(Y) <= AreParents(X, Y, Z)
result = IsMale(X)
print(result)
# asking with .ask method
answer = pyDatalog.ask('IsMale(X) & IsHungry(X)')
print(answer)
\ No newline at end of file
Name,Gender,EyeColour,HairColour,HairLength,LipsSize,HasMoustache,HasBeard,WearHat,IsBald,WearGlasses,WearEarrings
Alex,Male,Brown,Black,Short,Big,Yes,No,No,No,No,No
Alfred,Male,Blue,Red,Short,Small,Yes,No,No,No,No,No
Anita,Female,Blue,White,Short,Small,No,No,No,No,No,No
Anne,Female,Brown,Black,Short,Small,No,No,No,No,No,Yes
Bernard,Male,Brown,Brown,Short,Small,No,No,Yes,No,No,No
Bill,Male,Brown,Red,Short,Small,No,Yes,No,Yes,No,No
Charles,Male,Brown,Blond,Short,Big,Yes,No,No,No,No,No
Claire,Female,Brown,Red,Long,Small,No,No,Yes,No,Yes,No
David,Male,Brown,Blond,Long,Small,No,Yes,No,No,No,No
Eric,Male,Brown,Blond,Short,Small,No,No,Yes,No,No,No
Frans,Male,Brown,Red,Short,Small,No,No,No,No,No,No
George,Male,Brown,White,Short,Small,No,No,Yes,No,No,No
Herman,Male,Brown,Red,Short,Small,No,No,No,Yes,No,No
Joe,Male,Brown,Blond,Short,Small,No,No,No,No,Yes,No
Maria,Female,Brown,Brown,Long,Small,No,No,Yes,No,No,Yes
Max,Male,Brown,Black,Short,Big,Yes,No,No,No,No,No
Paul,Male,Brown,White,Short,Small,No,No,No,No,Yes,No
Peter,Male,Blue,White,Short,Big,No,No,No,No,No,No
Philip,Male,Brown,Black,Short,Small,No,Yes,No,No,No,No
Richard,Male,Brown,Brown,Short,Small,Yes,Yes,No,Yes,No,No
Robert,Male,Blue,Brown,Short,Small,No,No,No,No,No,No
Sam,Male,Brown,White,Short,Small,No,No,No,Yes,Yes,No
Susan,Female,Brown,Blond,Long,Big,No,No,No,No,No,Yes
Tom,Male,Blue,Black,Short,Small,No,No,No,Yes,Yes,No
\ No newline at end of file
import csv
import random
from pyDatalog import pyDatalog
import guess_who_kb
def find_best_question(remaining_characters, remaining_predicates):
# TODO
pass
if __name__ == '__main__':
# MAIN APPLICATION
names_answer = pyDatalog.ask("Gender(X, Y)")
names = []
for item in names_answer.answers:
names.append(item[0])
with open('guess_who.csv', newline='', mode='r', encoding='utf-8-sig') as f:
reader = csv.reader(f)
properties = None
for i, row in enumerate(reader):
if i == 0:
# First row with the predicates
properties = row[1:]
break
# selecting a character randomly that the AI agent would need to guess
character_name = random.choice(names)
print("The AI agent will need to guess the character with name '{0}'".format(character_name))
# start with all the possible characters
available_characters = names.copy()
# start with all the predicates we can use for questions
available_predicates = {}
for prop in properties:
query_outputs = pyDatalog.ask("{0}(X, Y)".format(prop))
predicate_values = []
for output in query_outputs.answers:
if output[1] not in predicate_values:
predicate_values.append(output[1])
available_predicates[prop] = predicate_values
# main body
print("AI starts the game with the following names on the board:")
print(available_characters)
# The game stops when we have only one character available or we have no more questions to ask
while len(available_characters) > 1 and len(available_predicates.keys()) > 0:
# looking for the best next question
best_question = find_best_question(available_characters, available_predicates)
if best_question is None:
print("Function find_best_question not implemented. Asking a random question")
predicate = random.choice(list(available_predicates.keys()))
value = random.choice(available_predicates[predicate])
best_question = (predicate, value)
question = "{0}(X, '{1}')".format(best_question[0], best_question[1])
print("AI Asking query: {0}".format(question))
# retrieving the names with the considered feature
names_with_feature = [r[0] for r in pyDatalog.ask(question).answers if r[0] in available_characters]
# checking if answer to the question is YES or NO
yes_no_answer = pyDatalog.ask("{0}('{1}','{2}')".format(best_question[0], character_name, best_question[1]))
yes_no_answer = "YES" if yes_no_answer is not None else "NO"
print("Opponent answering: The answer is {0}".format(yes_no_answer))
# removing predicate
available_predicates[best_question[0]].remove(best_question[1])
# if there is less than 2 options or the answer was YES, we can remove the predicate completely
if yes_no_answer == "YES" or len(available_predicates[best_question[0]]) < 2:
del available_predicates[best_question[0]]
# updating the remaining characters on the board
if yes_no_answer == "YES":
available_characters = names_with_feature.copy()
else:
for name in names_with_feature:
available_characters.remove(name)
print("AI updates the remaining names on the board. Remaining names:")
print(available_characters)
# making a guess
if len(available_characters) == 1:
# we are sure of the guess
print("AI says: The hidden character is {0}".format(available_characters[0]))
else:
# we are not sure, random guess
print("AI says: I am not sure who the character is. I will make a guess.")
guess = random.choice(available_characters)
print("AI says: The hidden character is {0}".format(guess))
\ No newline at end of file
import csv
from pyDatalog import pyDatalog
# KNOWLEDGE BASE
# loading the features of the guess who characters from the csv
# TODO
\ No newline at end of file
# Exercise 1
QUERIES = {
'alpha1': (lambda p, q, z: not (p or q) and z, ['P', 'Q', 'Z']),
'alpha2': (lambda p, q, z: (not p and q) or z, ['P', 'Q', 'Z']), # using logic equivalence
'alpha3': (lambda p, q, z: (p or q) == q, ['P', 'Q']),
'alpha4': (lambda p, q, z: (p and q) or (p or q) and not(p and z), ['P', 'Q', 'Z']),
'alpha5': (lambda p, q, z: p and not p, ['P'])
}
for query, query_val in QUERIES.items():
query_lambda, propsym = query_val
print("")
print("Models of M({0}):".format(query))
models = []
# list all models
for p in [True, False]:
for q in [True, False]:
for z in [True, False]:
if query_lambda(p, q, z):
model = {}
for sym in propsym:
model[sym] = eval(sym.lower())
if model not in models:
models.append(model)
print(model)
"""
Exercise 2:
Check the output from the script for exercise 1 for the models in M(alpha<N>).
1. For all models of alpha2 we have that Q OR Z is True, so alpha2 |= Q OR Z
2. For P = False and Q = True in M(alpha3), P <=> Q is False, so alpha3 does not entail P <=> Q
3. The sentence P => (Q OR NOT Z) is logically equivalent to NOT P OR (Q OR NOT Z).
For P = False, the sentence is always True.
For P = True the sentence is True when Q is True or Z is False. All the remaining models in M(alpha4) satisfy that.
So, alpha4 |= P => (Q OR NOT Z)
"""
\ No newline at end of file
KB = {
'P->Q': lambda p, q, r, s: not p or q, # using the logic equivalence
'not R -> not P or Q': lambda p, q, r, s: r or (not p or q),
'S -> not Q or R': lambda p, q, r, s: not s or (not q or r)
}
QUERIES = {
'P and S': lambda p, q, r, s: p and s,
'not Q and not R': lambda p, q, r, s: not q and not r,
'not P or Q': lambda p, q, r, s: not p or q
}
if __name__ == '__main__':
# listing all models in M(KB)
KB_models = []
for p in [True, False]:
for q in [True, False]:
for r in [True, False]:
for s in [True, False]:
valid = True
for rule in KB.values():
# Testing if current model
# makes KB rules true
# If only one rules is not true
# then set not valid and break
if not rule(p, q, r, s):
valid = False
break
# if a valid model, save it
if valid:
KB_models.append({
'P': p,
'Q': q,
'R': r,
'S': s
})
# listing the models in M(KB)
print("Models in M(KB):")
for m in KB_models:
print(m)
# testing queries
for query, query_lambda in QUERIES.items():
valid = True
for m in KB_models:
if not query_lambda(m['P'], m['Q'], m['R'], m['S']):
valid = False
print("The query '{0}' is not entailed by the KB: for P={1}, Q={2}, R={3}, S={4} KB is True but query is not".format(query, m['P'], m['Q'], m['R'], m['S']))
break
if valid:
print("The query '{0}' is entailed by the KB".format(query))
from pyDatalog import pyDatalog
pyDatalog.create_terms('IsFemale,IsMale,AreParents,IsHungry,Want,X,Y,Z')
#+ IsFemale('Jane')
#+ IsMale('Joe')
+ IsMale('Bob')
+ AreParents('Jane','Joe','Bob')
+ IsHungry('Bob')
# adding last fact with .load method
pyDatalog.load("+ Want('Bob','Milk')")
# adding clauses (and commenting the two given facts above)
IsFemale(X) <= AreParents(X, Y, Z)
IsMale(Y) <= AreParents(X, Y, Z)
result = IsMale(X)
print(result)
# asking with .ask method
answer = pyDatalog.ask('IsMale(X) & IsHungry(X)')
print(answer)
\ No newline at end of file
Name,Gender,EyeColour,HairColour,HairLength,LipsSize,HasMoustache,HasBeard,WearHat,IsBald,WearGlasses,WearEarrings
Alex,Male,Brown,Black,Short,Big,Yes,No,No,No,No,No
Alfred,Male,Blue,Red,Short,Small,Yes,No,No,No,No,No
Anita,Female,Blue,White,Short,Small,No,No,No,No,No,No
Anne,Female,Brown,Black,Short,Small,No,No,No,No,No,Yes
Bernard,Male,Brown,Brown,Short,Small,No,No,Yes,No,No,No
Bill,Male,Brown,Red,Short,Small,No,Yes,No,Yes,No,No
Charles,Male,Brown,Blond,Short,Big,Yes,No,No,No,No,No
Claire,Female,Brown,Red,Long,Small,No,No,Yes,No,Yes,No
David,Male,Brown,Blond,Long,Small,No,Yes,No,No,No,No
Eric,Male,Brown,Blond,Short,Small,No,No,Yes,No,No,No
Frans,Male,Brown,Red,Short,Small,No,No,No,No,No,No
George,Male,Brown,White,Short,Small,No,No,Yes,No,No,No
Herman,Male,Brown,Red,Short,Small,No,No,No,Yes,No,No
Joe,Male,Brown,Blond,Short,Small,No,No,No,No,Yes,No
Maria,Female,Brown,Brown,Long,Small,No,No,Yes,No,No,Yes
Max,Male,Brown,Black,Short,Big,Yes,No,No,No,No,No
Paul,Male,Brown,White,Short,Small,No,No,No,No,Yes,No
Peter,Male,Blue,White,Short,Big,No,No,No,No,No,No
Philip,Male,Brown,Black,Short,Small,No,Yes,No,No,No,No
Richard,Male,Brown,Brown,Short,Small,Yes,Yes,No,Yes,No,No
Robert,Male,Blue,Brown,Short,Small,No,No,No,No,No,No
Sam,Male,Brown,White,Short,Small,No,No,No,Yes,Yes,No
Susan,Female,Brown,Blond,Long,Big,No,No,No,No,No,Yes
Tom,Male,Blue,Black,Short,Small,No,No,No,Yes,Yes,No
\ No newline at end of file
import csv
import random
from pyDatalog import pyDatalog
import guess_who_kb
def find_best_question(remaining_characters, remaining_predicates):
best_question = None
max_avg_eliminated = 0
for predicate in remaining_predicates.keys():
for value in remaining_predicates[predicate]:
answer = pyDatalog.ask("{0}(X, '{1}')".format(predicate, value))
# characters I will be able to eliminate if answer is NO
names = [r[0] for r in answer.answers if r[0] in remaining_characters]
n_eliminated_no = len(names)
# whereas if answer is YES
n_eliminated_yes = len(remaining_characters) - len(names)
# we need to make sure that the question is not a silly one
# silly questions are questions that we already know the answer
# because all the remaining characters share the same common feature
# These questions lead to eliminating all the characters if the answer is YES or NO
if n_eliminated_no == len(remaining_characters) or n_eliminated_yes == len(remaining_characters):
continue
n_avg_eliminated = (n_eliminated_no + n_eliminated_yes)/2
if best_question is None or n_avg_eliminated > max_avg_eliminated:
best_question = (predicate, value)
max_avg_eliminated = n_avg_eliminated
return best_question
if __name__ == '__main__':
# MAIN APPLICATION
names_answer = pyDatalog.ask("Gender(X, Y)")
names = []
for item in names_answer.answers:
names.append(item[0])
with open('guess_who.csv', newline='', mode='r', encoding='utf-8-sig') as f:
reader = csv.reader(f)
properties = None
for i, row in enumerate(reader):
if i == 0:
# First row with the predicates
properties = row[1:]
break
# selecting a character randomly that the AI agent would need to guess
character_name = random.choice(names)
print("The AI agent will need to guess the character with name '{0}'".format(character_name))
# start with all the possible characters
available_characters = names.copy()
# start with all the predicates we can use for questions
available_predicates = {}
for prop in properties:
query_outputs = pyDatalog.ask("{0}(X, Y)".format(prop))
predicate_values = []
for output in query_outputs.answers:
if output[1] not in predicate_values:
predicate_values.append(output[1])
available_predicates[prop] = predicate_values
# main body
print("AI starts the game with the following names on the board:")
print(available_characters)
# The game stops when we have only one character available or we have no more questions to ask
while len(available_characters) > 1 and len(available_predicates.keys()) > 0:
# looking for the best next question
best_question = find_best_question(available_characters, available_predicates)
if best_question is None:
print("Function find_best_question not implemented. Asking a random question")
predicate = random.choice(list(available_predicates.keys()))
value = random.choice(available_predicates[predicate])
best_question = (predicate, value)
question = "{0}(X, '{1}')".format(best_question[0], best_question[1])
print("AI Asking query: {0}".format(question))
# retrieving the names with the considered feature
names_with_feature = [r[0] for r in pyDatalog.ask(question).answers if r[0] in available_characters]
# checking if answer to the question is YES or NO
yes_no_answer = pyDatalog.ask("{0}('{1}','{2}')".format(best_question[0], character_name, best_question[1]))
yes_no_answer = "YES" if yes_no_answer is not None else "NO"
print("Opponent answering: The answer is {0}".format(yes_no_answer))
# removing predicate
available_predicates[best_question[0]].remove(best_question[1])
# if there is less than 2 options or the answer was YES, we can remove the predicate completely
if yes_no_answer == "YES" or len(available_predicates[best_question[0]]) < 2:
del available_predicates[best_question[0]]
# updating the remaining characters on the board
if yes_no_answer == "YES":
available_characters = names_with_feature.copy()
else:
for name in names_with_feature:
available_characters.remove(name)
print("AI updates the remaining names on the board. Remaining names:")
print(available_characters)
# making a guess
if len(available_characters) == 1:
# we are sure of the guess
print("AI says: The hidden character is {0}".format(available_characters[0]))
else:
# we are not sure, random guess
print("AI says: I am not sure who the character is. I will make a guess.")
guess = random.choice(available_characters)
print("AI says: The hidden character is {0}".format(guess))
\ No newline at end of file
import csv
from pyDatalog import pyDatalog
# KNOWLEDGE BASE
# loading the features of the guess who characters from the csv
names = []
with open('guess_who.csv', newline='', mode='r', encoding='utf-8-sig') as f:
reader = csv.reader(f)
properties = None
for i, row in enumerate(reader):
if i == 0:
# First row with the predicates
# create the terms to use (variables and predicates)
properties = row[1:]
predicates = ','.join(row[1:])
pyDatalog.create_terms('{0},X,Y,Z'.format(predicates))
continue
# rows with names and values for the predicates
name = row[0]
names.append(name)
for idx, propval in enumerate(row[1:]):
# add a fact for each predicate of the character
pyDatalog.load("+ {0}('{1}', '{2}')".format(properties[idx], name, propval))
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment