what is the differenc between these two "statments" in desciption logic - logic

I don't know if you call this statement or not, but I have this question
what is the difference between these two statments :
A ⊑ B ⊓ C
and
A ASSERTA_SYMBOL = B ⊓ C
sorry I don't know how to write the ASSERTA_SYMBOL, but it is in this image
a real example is this:

Both expressions describe or define a concept (or class or set).
The difference is subclass vs equivalent class.
An elephant is one kind of grey, large animals. There might be other kinds.
A happy father is a man who has at least one daughter and any man with at least one daughter is a happy father. There are no others.

⊑ represents a subconcept relationship, ≐ means agreement (sometimes called the same as constructor).

Related

In OWL, is it possible to assert that a class is not "empty"?

Given the different types of axioms available in OWL, is it possible to assert that a class is not "empty"? Or in other words, can we assert that there exists at least one individual that is part of the specified class?
So, basically I am looking for an equivalence of:
ObjectAssertNotEmpty(a:SomeClass)
In an RDF serialization, all it takes is to identify such an individual:
[] a a:SomeClass .
I presume the OWL syntax should be able to specify it this way:
ClassAssertion( a:SomeClass a:SomeIndividual )
It doesn't matter that you call the individual a:SomeIndividual here, it could very well be owl:sameAs any other individual. Once you state that something is in the class, it follows that the class is not empty.
That is exactly what the model theoretic underpinning of Description Logics aim to do is to assume that all concepts (or OWL classes) are not empty. When a reasoner is run over an ontology, it will give an error if a class is found to be empty. Such a class is deemed to be unsatisfiable. That is the basis of satisfiability checking (and consistency checking, since satisfiability checking can be translated to consistency checking).
See An introduction to Description Logics text for details.
Here is a simple example ontology to illustrate this:
Class: A
Class: NotA
EquivalentTo: not (A)
Class: B
EquivalentTo: A and NotA
Individual: b
Types: B
Note that class B will be equivalent to owl:Nothing which is the empty set. Now setting individual b to be an instance of B will lead to an inconsistency with explanation as shown below.
The answer as given by #IS4 will only work if SomeClass is found to be satisfiable (that is not empty), otherwise the reasoner will give an inconsistency.

Ontologies, OWL, Sparql: Modelling that "something is not there" and performance considerations

we want to model that "something is not there" as opposed to missing information, e.g. an explicit statement that "a patient did not get chemotherapy" or that "a patient does not have dyspnea" is different from missing information about whether a patient has dyspnea.
We thought about several approaches, e.g.
Using a negation class: "No_Dyspnea". But that seems semantically problematic, since what type would that class be? It cannot be a descendant of the "Dyspnea" class.
Using "not there" object properties, e.g. "denies" or "does_not_have" and then an individual of the Dyspnea root class as the object of that triple.
Using blank nodes that describe that the individual belongs to the group of things that do not have dyspnea. E.g.:
dat:PatientW2 a [ rdf:type owl:Class;
owl:complementOf [
rdf:type owl:Restriction ;
owl:onProperty roo:has_finding;
owl:someValuesFrom nci:Dyspnea;
]
] .
We feel like the 3rd option is the most "ontologically correct" way of expressing this. However, when playing around with it we encountered severe performance problems in simple scenarios.
We are using Sesame with an OWLIM-Lite store and imported the NCI thesaurus (280MB, about 80,000 concepts) and another very small ontology into the store and added two individuals, one having that complementOf/restriction class.
The following query took forever to execute and I terminated it after 15 minutes:
select *
where {
?s a [ rdf:type owl:Class;
owl:complementOf [
rdf:type owl:Restriction ;
owl:onProperty roo:has_finding;
owl:someValuesFrom nci:Dyspnea;
]
] .
} Limit 100
Does anybody know why? I would assume that this approach creates a lot of blank nodes and the query engine has to go through the entire NCI thesaurus and compare all blank nodes with this one?
If I put this triple in a separate graph and only query that graph, the query returns the result instantaneously.
To sum things up. The two basic questions are:
Is the third approach really the best for modelling "something is not there"
Is this going to affect query performance?
EDIT 1
We discussed the proposed options. It actually helped us in clarifying what we are really trying to achieve:
We want to be able to state that "Patient has Dyspnea" or "Patient does not have Dyspnea" at a particular point in time.
In the future there may/will be more information about that patient, e.g. that he/she now has dyspnea.
We want to be able to write Sparql queries that ask for "all patients that have dyspnea" and "all patients that do not have dyspnea".
We want to keep the Sparql as simple and intuitive as possible. E.g. only use one property "has_finding" rather than having to know about two properties (one for "has_exclusion"). Or having to know about some complex blank node construct.
We played around with options:
Negative Property Assertions: This sounded like the best solution to this problem since we are stating that one individual is not related to another individual on that property. The issues are that we have to create an individual of Dyspnea for the sake of having something as owl:targetIndividual. And we cannot find a way of querying the negative assertion easily other then going through the whole owl:sourceIndividual and owl:targetIndividual chain. Which makes the Sparql quite lengthy and puts a burden on the person writing the query to know about it.
Blank node with complementOf: We would be stating something with this that we do not want to state. This would state that "Patient1 can never have a finding of dyspnea". Whereas we want to state the "Patient1 does not have a dyspnea finding now (or at date X)". So we should not use this approach.
Using an Exclusion/Inclusion Types (Option 1 and 2): After a closer look a Jeen's suggestion we believe that using general :Exclusion and :Inclusion classes along with only one property has_finding and giving the dyspnea individual the inclusion/exclusion type is the easiest to understand, query and provides enough reasoning abilities. Example:
:Patient1 a :Patient .
:Dyspnea1 a :Dyspnea .
:Dyspnea1 a :Exclusion.
:Patient1 ex:has_finding :Dyspnea1 .
That way, the person writing the Sparql query only has to know that:
There is one property has_finding, which represents the intentions properly. Since "No dyspnea" is technically a finding as well.
But just querying using has_finding will not give sufficient information about whether the person actually has it or not. The query also needs to contain a triple about whether the dyspnea individual is a :Exclusion (or inclusion depending on the goal of the query).
While this puts some additional burden on the query writer, it is less than negative property assertions and easier to understand.
We would really appreciate some feedback on these conclusions!
If your diseases are represented as individuals, then you can use negative object property assertions to literally say, e.g.,
¬hasFinding(john,Dyspnea)
NegativeObjectPropertyAssertion(hasFinding john Dyspnea)
Of course, if you have lots of things that aren't the case, then this might get a bit involved. It's probably the most semantically correct, though. It also means that your query could match directly against the data in the ontology, which might make for quicker results. (Of course, you'd still have the issues of trying to infer when the negative object property holds.)
This doesn't work if diseases are represented as classes, though. If diseases are represented by classes, then you can use class expressions, similar to what you propose. E.g.,
(∀ hasFinding.¬Dyspnea)(john)
ClassAssertion(ObjectAllValuesFrom(hasFinding ObjectComplementOf(Dyspnea)) john)
This is similar to your third option, but I wonder if it might perform better. It seems like a slightly more direct way of saying what you're trying to say (i.e., if someone has a disease, it's not one of these diseases).
I do agree with Jeen's answer, though; there's a lot of subjectivity here, and a great deal of getting it "right" is actually just a matter of finding something that's reasonable to work with, performs well enough for you, and that seems not entirely unnatural.
With respect to the modeling question, I'd like to offer a fourth alternative, which is, in fact, a mix of your options 1 and 2: introduce a separate class (hierarchy) for these 'excluded/missing' symptoms, diseases or treatments, and have the specific exclusions as instances:
:Exclusion a owl:Class .
:ExcludedSymptom rdfs:subClassOf :Exclusion .
:ExcludedTreatment rdfs:subClassOf :Exclusion .
:excludedDyspnea a :ExcludedSymptom .
:excludedChemo a :ExcludedTreatment .
:Patient a owl:Class ;
owl:equivalentClass [ a owl:Restriction ;
owl:onProperty :excluded ;
owl:allValuesFrom :Exclusion ] .
// john is a patient without Dyspnea
:john a :Patient ;
:excluded :excludedDyspnea .
Optionally, you can link the exclusion instances semantically with the treatment/symptom/diseases:
:excludedDyspnea :ofSymptom :Dyspnea .
In my view, this is just as "ontologically correct" (this kind of thing is quite subjective to be honest) as your other options, and possibly a lot easier to maintain, query, and indeed reason with.
As for your second question: while I can't speak for the behavior of the particular reasoner you're using, in general any construction involving complementOf is computationally very heavy, but perhaps more importantly, it probably does not capture what you intend.
OWL has an open world assumption, which (in broad terms) means that we cannot decide a certain fact is untrue simply because that fact is currently unknown. Your complementOf construction will logically be an empty class, because for any individual X, even if we currently do not know that X has been diagnosed with Dyspnea, there is a possibility that in the future that fact will become known, and therefore X will not be in the complement class.
EDIT
In response to your edit, with the proposal using a single :hasFinding property, I think that generally looks good, though I would perhaps modify it slightly:
:patient1 a :Patient;
:hasFinding :dyspneaFinding1 .
:dyspneaFinding1 a :Finding ;
:of :Dyspnea ;
:conclusion false .
You have now separated the 'finding' as a concept a bit more cleanly from the symptom/treatment that it is a finding of. Also, whether or not the finding is positive or negative is explicitly modeled (rather than implied by the presence/absense of an 'excluded' property or a 'Exclusion' type).
(As an aside: since we link an individual with a class here via a non-typing relation (... :of :Dyspnea) we must rely on OWL 2 punning to make this valid in OWL DL)
To query for a patient with a finding (whether positive or negative) about Dyspnea:
SELECT ?x
WHERE {
?x a :Patient;
:hasFinding [ :of :Dyspnea ] .
}
And to query for patients with confirmed absense of Dyspnea:
SELECT ?x
WHERE {
?x a :Patient;
:hasFinding [ :of :Dyspnea ;
:conclusion false ] .
}

Can anyone correct my prolog answer for the given statement if it is wrong?

1.Whale has a backbone.
whale(X):-backbone(X).
2.Whale grows with their mother's milk.
whale(X):-grows(X,Y),milk(Y,mother).
OR
grows(X):-whale(X),drinks(X,mother's_milk).
It really depends how you want to organize your database. You could, for example, also say:
A vertebrate (has a backbone) is a whale, or a dog, or a snake.
vertebrate(whale).
vertebrate(god).
vertebrate(snake).
Is whale a vertebrate?
?- vertebrate(whale).
true.
Similarly,
A mammal (feeds on their mother's milk) is a whale, or a dog.
mammal(whale).
mammal(dog).
The message here is that since you need to actully provide the database in some form, and since "has spine" and "is vertebrate" are the same thing, you might as well explicitly list all mammals.
Or are you thinking of some use case where the argument to whale/1 is an object created by the program, and backbone needs to look at it in some specific way (look at the value of an attribute, for example) to succeed or fail?
Edit
Think about it like this:
Whale has a backbone
has(whale, backbone).
But then, you could write,
vertebrate(X) :-
has_backbone(X).
has_backbone(X) :-
has(X, backbone).
And at that point you should see why this is indeed not necessary. Just write:
vertebrate(whale). % :- has_backbone(whalte) :- has(whale, backbone).
And, in the same way:
Whale grows on their mother's milk
grows_on(whale, 'mother\'s milk').
has(X, 'mammary glands') :-
grows_on(X, 'mother\'s milk').
mammal(X) :-
has(X, 'mammary glands').
Identical to above, you end up with:
mammal(whale).
As Boris indicates, it depends upon how you want to organize your data. Specifically, upon what detailed level you want to define your facts. If you get down to lower level facts, you'd look at the definition for mammal, for instance (OED):
Mammal: a warm-blooded vertebrate animal of a class that is
distinguished by the possession of hair or fur, the secretion of milk
by females for the nourishment of the young, and (typically) the birth
of live young.
So here, assuming the conditions given in the above definition are not only necessary but sufficient, you could define mammal in detail as:
mammal(X) :-
vertebrate(X),
warm_blooded(X),
(has_fur(X) ; has_hair(X)),
feeds_by_milk(X),
gives_live_birth(X).
Which would then require that you define all of these kinds facts for whatever beasts/things you are wanting to query about. (And, yes, a whale has hair, although very little of it.) The statement:
Whale grows with their mother's milk.
Would be a fact, not based upon a rule, because there's no fundamental fact that such a rule would be derived from. The fact, using the terms I introduced above, would be:
feeds_by_milk(whale).
If you don't want to have all those detailed data, then you'd do as Boris showed which is establish your lowest level facts as mammal:
mammal(whale).
mammal(dog).
In Prolog, it's important to think carefully about how facts are defined and what they really mean, semantically. In your initial example, you have what appears to be a fact called milk that has two arguments. You have an example usage, milk(Y, mother), but it doesn't very directly express the fact that Y feeds on it's mother's milk. It introduces mother as an argument, but unnecessarily since it's not likely that you'd have also something like milk(Y, father). feeds_by_milk(Y) or even, feeds_on_mothers_milk(Y) is a better expression of the fact in this case. Likewise, whale(X) doesn't have clear semantics. What is X in this case? Do the whales have personal names, like whale(shamu)? Perhaps. The above discussion is dealing with whales categorically. That is, a whale, in this discussion, is an atomic entity, so would more likely be the argument in your facts, not one of the fact names. If you want to deal with them individually (e.g., answer the question, Is Shamu a whale?) then you would need a rule that identifies whale(X) using facts and rules which eventually lead to questions to the user such as, Is shamu warm blooded?, and then after answers to such questions are asserted, the query whale(shamu) run to see if it succeeds.

In Prolog (SWI), how to build a knowledge base of user supplied pairs and assert to be equal

I am very new to Prolog and trying to learn.
For my program, I would like to have the user provide pairs of strings which are "types of".
For example, user provides at command line the strings "john" and "man". These atoms would be made to be equal, i.e. john(man).
At next prompt, then user provides "man" and "tall", again program asserts these are valid, man(tall).
Then the user could query the program and ask "Is john tall?". Or in Prolog: john(tall) becomes true by transitive property.
I have been able to parse the strings from the user's input and assign them to variables Subject and Object.
I tried a clause (where Subject and Object are different strings):
attribute(Subject, Object) :-
assert(term_to_atom(_ , Subject),
term_to_atom(_ , Object)).
I want to assert the facts that Subject and Object are valid pair. If the user asserts it, then they belong to together. How do I force this equality of the pairs?
What's the best way to go about this?
Questions of this sort have been asked a lot recently (I guess your professors all share notes or something) so a browse through recent history might have been productive for you. This one comes to mind, for instance.
Your code is pretty wide of the mark. This is what you're trying to do:
attribute(Subject, Object) :-
Fact =.. [Object, Subject],
assertz(Fact).
Using it works like this:
?- attribute(man, tall).
true.
?- tall(X).
X = man.
So, here's what you should notice about this code:
We're using =../2, the "univ" operator, to build structures from lists. This is the only way to create a fact from some atoms.
I've swapped subject and object, because doing it the other way is almost certainly not what you want.
The predicate you want is assertz/1 or asserta/1, not assert/2. The a and z on the end just tells Prolog whether you want the fact at the beginning or end of the database.
Based on looking at your code, I think you have a lot of baggage you need to shed to become productive with Prolog.
Prolog predicates do not return values. So assert(term_to_atom(... wasn't even on the right track, because you seemed to think that term_to_atom would "return" a value and it would get substituted into the assert call like in a functional or imperative language. Prolog just plain works completely differently from that.
I'm not sure why you have an empty variable in your term_to_atom predicates. I think you did that to satisfy the predicate's arity, but this predicate is pretty useless unless you have one ground term and one variable.
There is an assert/2, but it doesn't do what you want. It should be clear why assert normally only takes one argument.
Prolog facts should look like property(subject...). It is not easy to construct facts and then query them, which is what you'd have to do using man(tall). What you want to say is that there is a property, being tall, and man satisfies it.
I would strongly recommend you back up and go through some basic Prolog tutorials at this point. If you try to press forward you're only going to get more lost.
Edit: In response to your comment, I'm not sure how general you want to go. In the basic case where you're dealing with a 4-item list with [is,a] in the middle, this is sufficient:
build_fact([Subject,is,a,Object], is_a(Subject, Object)).
If you want to isolate the first and last and create the fact, you have to use univ again:
build_fact([Subject|Rest], Fact) :-
append(PredicateAtoms, [Object], Rest),
atomic_list_concat(PredicateAtoms, '_', Predicate),
Fact =.. [Predicate, Subject, Object].
Not sure if you want to live with the articles ("a", "the") that will wind up on the end though:
?- build_fact([john,could,be,a,man], Fact).
Fact = could_be_a(john, man)
Don't do variable fact heads. Prolog works best when the set of term names is fixed. Instead, make a generic place for storing properties using predefined, static term name, e.g.:
is_a(john, man).
property(man, tall).
property(john, thin).
(think SQL tables in a normal form). Then you can use simple assertz/1 to update the database:
add_property(X, Y) :- assertz(property(X, Y)).

Representing a sentence in FOL

How to represent the following sentence in FOL ( First Order Logic ) "There is an animal which only eats meat" Is the following represantaion true ?
Ǝx Eats(x, meat) where x is animal
No, it's not entirely correct. As pointed out in the comments by Gabe, your expression does not exclude the possibility of x eating other things as well. You'll need to add a conjunct that excludes all foodstuffs that aren't meat. How you do this depends a bit on which kind of logic you're using.
Could he just say:
-Eats(x, y) ^ y != meat
implying meat is the only thing the animal doesn't not eat?
Pretty pessimistic view, but it gets the job done, haha.
One minor correction would make it corrrect. It would look a little silly though.
Make Eats into OnlyEats.
I think that a simple way to represent the sentence is:
Ǝx∀y (Animal(x) ∧ Eats(x,y)) --> Meat(y)

Resources