Use inheritance for my first program (python)

Who is the intruder ?

Find the intruder

Now that we know how to launch our program, it's time to add a touch of intelligence

getUp

Let us begin by making our program understand the meaning of each word. To do that, we will use the getUp function. This function applied to an individual returns us all the classes of which our individual inherits.

def getWordsInheritance(words):
inheritances = []
for word in words:
inheritance = _onto.individuals.getUp(word)
inheritances.insert(len(inheritances), inheritance)
return inheritances

This function, therefore, applies the getUp method to each word found in the "words" list and it returns a list for which each cell corresponds to the list returned by getUp.

inheritance = _onto.individuals.getUp(word)

We also notice that we are going to look for the getUp function among the individuals because we know that the input words will be only individuals.

In order to see the effect of this function, we will add the following lines in our main function, just after the call to the "say" function.

inheritances = getWordsInheritance(_names)
for i in range(len(inheritances)):
print (_names[i] + ' is a:')
for is_a in inheritances[i]:
print ('- ' + is_a)

We can now launch it!

roslaunch ontologenius_tutorial intruder.launch

In another terminal we will publish a few words to see the result:

rostopic pub -1 /intruder/input std_msgs/String "data: 'bob'"
rostopic pub -1 /intruder/input std_msgs/String "data: 'alice'"
rostopic pub -1 /intruder/input std_msgs/String "data: 'kevin'"
rostopic pub -1 /intruder/input std_msgs/String "data: 'start'"

At the end of our program, you should have this:

[SAY]on bob alice kevin
bob is a:
- human
- man
- agent
alice is a:
- woman
- human
- agent
kevin is a:
- human
- man
- agent
[SAY]Let's play!

Our program knows what each word means

We can represent this part of the ontology as follow:

tutorial 1 inheritance graph

Delete the same

We will now create a function that will simply remove classes from which all words inherit. If we look at the previous example, we can see that Alice, Bob, and Kevin all inherit active and human classes. That is to say that the agent and human classes can not allow us to determine the intruder and that we can therefore remove them from our reasoning. We will not analyze this code together because it is not the center of this tutorial.

def deleteTheSame(inheritances):
if(len(inheritances) > 1):
sames = []
for word in inheritances[0]:
is_same = True
for i in range(1, len(inheritances)):
if not word in inheritances[i]:
is_same = False

if is_same:
sames.insert(1, word)

for same in sames:
for inheritance in inheritances:
if same in inheritance:
inheritance.remove(same)

Add the call to this function in the main function just after the getWordsInheritance call.

inheritances = getWordsInheritance(_names)
deleteTheSame(inheritances)

Compile this and run the program, then in another terminal re-query the programs on the words: bob alice and kevin.

This time, you should have this:

[SAY]on bob alice kevin
bob is a :
- man
alice is a :
- woman
kevin is a :
- man
[SAY]Let's play!

Find the intruder

Now that we have removed the classes from which all individuals inherit, we are not going to look for the individual who is the only one to inherit from a class but rather the class of which all but one inherit.

That's exactly what the next function will do.

We will finally code algorithms to find intruders. Indeed, in function, it is sometimes possible to find several intruders for different reasons.

Once again, we will not analyze the following algorithm because it does not use Ontologenius directly.

To still be able to analyze it for yourself, here are some key elements:

  • We go through all the words of each heritage vector. For each of these words, we seek to know if it exists in all other vectors except one.
  • The intruder_index variable represents the index of the vector in which the search word does not exist. This variable is set to -1 as long as we have not found or found more than one vector that does not have the word.
  • In the case where we found an intruder, we add it to our intruder vector, only if it does not already exist for the same reason.
def find_intruder(names, inheritances):
intruders = []
for inheritance_i in range(len(inheritances)):
for class_i in inheritances[inheritance_i]:
intruder_index = -1

for inheritance_j in range(len(inheritances)):
if inheritance_i != inheritance_j:
if not class_i in inheritances[inheritance_j]:
if intruder_index == -1:
intruder_index = inheritance_j
else:
intruder_index = -1
break

if intruder_index != -1:
new_intruder = (names[intruder_index], class_i)
exist = False
for intruder in intruders:
if intruder[0] == new_intruder[0] and intruder[1] == new_intruder[1]:
exist = True

if not exist:
intruders.insert(1, new_intruder)

return intruders

We can therefore call this new function in our main function and replace our old display with the intruder display.

deleteTheSame(inheritances)
intruders = find_intruder(_names, inheritances)
for intruder in intruders:
say('the intruder is ' + intruder[0] + ' because it is the only one that is not: ' + intruder[1])

Run the program, then in another terminal re-query the programs on the words: bob alice and kevin.

This time, you should have this:

[SAY]on bob alice kevin
[SAY]the intruder is alice because it is the only one that is not: man
[SAY]Let's play!

IT WORKS!

Now is the time to have a little fun. Test for example with the words banana, lemon, apple, and carrot or only with the words banana, lemon, and carrot.

You should have this:

[SAY]on banana lemon apple carrot
[SAY]the intruder is carrot because it is the only one that is not: fruit
[SAY]Let's play!
[SAY]on banana lemon carrot
[SAY]the intruder is carrot because it is the only one that is not: yellow
[SAY]the intruder is carrot because it is the only one that is not: fruit
[SAY]Let's play!

Do not hesitate to look at all the available words and see how our algorithm reacts.