else branch of a swrl rule - protege

I want to ask if it is possible to express the else branch of a rule in SWRL?
I know it can express p->q but i want to be able to assert r if non(p)
example
HeavyPrecipitation(?x) -> hasObservationTag(?x,FalsePositiveOutlier)
and now i want to say else hasObservationTag(?x,TruePositiveOutlier)
How can this be done?
thanks

In a rule like (p->q) there is no way to say (not(p) -> ...); in OWL-DL+SWRL it will never be possible.
BUT, you can do things that may a be a workaround for your specific usage:
OWL : ComplementOf(ClassExpression) : work like a negation of
the ClassExpression
SWRL : DifferentIndividualsAtom(Arg1,Arg2) : useful to exclude
a Value or a Range
They are is the only way to express something that look like negation.
On your example :
then-rule ClassAtom(HeavyPrecipitation,?x) -> propertyAtom(hasObservationTag,?x,FalsePositiveOutlier)
else-rule ClassAtom(ComplementOf(HeavyPrecipitation),?x) -> propertyAtom(hasObservationTag,?x,TruePositiveOutlier)
Note : the negation is tricky with Open World Assumption and DL; sometime both rules (the 'then' and 'else') can be true at the same time (mainly depend on how your class are defined). Sometime none of your rules will apply : it totaly depend on how you declare classes on your individuals.

Related

validate.js returning error "unknown validator pattern"

I'm trying to use validate.js to validate input from the front end before entering it in the database with node but I'm getting an error that I can't figure out. I've gone over the docs and believe I setup the constraints correctly. The exact error is:
message:"Unknown validator pattern"
my validator is setup like this:
let alphanumeric = /^[a-zA-Z0-9]*$/;
let constraints = {
clientUsername:{
presence: true,
length: {min:8, max:15},
pattern:alphanumeric,
message: 'make sure client username is between 8-15 characters, is only numbers and letters'
},
tileCategory:{
presence:true,
length:{min:1, max:1},
numericality:{
onlyInteger:true,
lessThanOrEqualTo:tileCategoryNumber,
},
message:'enter a number, 1 char in length, less than or equal to 3' //the current number of tiles
}
};
validate({clientUsername: input.clientUsername},constraints);
At first I thought it was the regex pattern but tried commenting that out and then it said
message:"Unknown validator messsage"
so I'm guessing there is something wrong with my validator in general.
at the very top I of course included const validate = require('validate.js');
Something similar to this just burned me, have a look at the documentation again.
pattern is sort of a sub-validator of format and should look like:
{
format: {
pattern: "[A-Za-z0-9]+"
}
}
You're trying to use pattern at the "top level". I don't see anything in the documentation that implies helper patterns like alphanumeric exist. (I think the language the tool would use is to say "pattern is an option of the format validator" but I'm not sure.)
Your stated error message also implies a misspelling: it tells you it doesn't recognize messsage, which has 3 of the letter 's' but should have 2.
There's (2) things I could see being the issue. Firstly, you're using JS based regexes with the preceding and following /. Try removing these.
Beyond that, I'd recommend trying to remove the alphanumeric parameter & input the regex directly... it may be a type issue as well.
pattern:"^[a-zA-Z0-9]*$",
Hope this helps! :)

Jess considers only the last mapped instance

I have a question in Jess Tab in Protege,I am building an ontology of 1 class Message and 3 instances :message 1 message2 message 3 , each each 3 datatype properties : category , interests , class .For each message I want to classify it as ham if the category and interests are equal , spam otherwise.The classification should be done using Jess Rules by which the class slot / property should change to ham or spam so I use modify-instance for that , as the interests of a message instance could change by time so it's not a static classification (or I would need to reclassify it)
Here is an example for message1 in protege :
So I mapped the instances as shown to Jess Engine using Jess Tab :
Here are screenshots with my rules the :
When I type (run) the Jess engine will classify only 1 instance correctly which is message3 the last instance , I mean I thus have to send only 1 instance at a time to the engine else it won't classify all messages correctly.
I tried to otherwise print the classification value and it works correctly( in my example the 3 messages should be classified as ham )
and when I added both rules the result was that the "ham/spam" printing enters a for loop . I've asked a question before and I got an answer that infinite loop happens because the rule keeps firing as the "if " in the action (RHS) is always correct :
Is this a feature of Jess that it considers the last received instance. And is there a way to force Jess engine to consider more than 1 message at a time ? and why is the infinite loop happening ?
I am really stuck in this part and in desperate need for speed to finalize it for my thesis . So you help is appreciated .
(I have implemented these rules in swrl busing SWRL+Jess Tab in Protege and the rules worked fine the problem was the facts were asserted in the ontology and I want them to be modified not asserted so that's why I used Jess Rules , do you think I am on the write track or I should use Sweet Rules for example better ?)
I updated the rule as follows by making constraint on the fact's slot value but no change :
(defrule MAIN::test2
(object (is-a http://www.owl-ontologies.com/Ontology1496039955.owl#Message) (OBJECT ?o))
(object (OBJECT ?o) (http://www.owl-ontologies.com/Ontology1496039955.owl#interests $?i))
(object (OBJECT ?o) (http://www.owl-ontologies.com/Ontology1496039955.owl#category $?c&:(eq (intersection$ $?i $?c) )))
(object (OBJECT ?o) (http://www.owl-ontologies.com/Ontology1496039955.owl#class $?cl&:(neq $?cl "spam")))
=>
(modify-instance ?o (http://www.owl-ontologies.com/Ontology1496039955.owl#class spam)))
This may not really be an answer, but you should consider changing your code accordingly, and if your problem continues, edit your question.
Don't use (if) on the right hand side. If there are two different situations due to values in the facts, distinguish them by rules.
Don't use (if) with just a single operand. This will always return true.
To avoid looping, either use the rule attribute no-loop or add a condition that is true unless something has been changed by the right hand side.
I would test rules in plain Jess first, before wrestling with the Protege layer.

AQL: (why) are document functions like HAS, UNSET not working?

I try to use document functions like HAS, UNSET etc. (hopefyully) like they are described in the documentation. Unofortunately the lead to Syntax error 1501. I also see that they do NOT get highlighted in the AQL editor like the other signal words do.
Here is one example (which I also tested on the tutorial server):
FOR u IN users
LIMIT 1
UNSET(u, "birthday")
RETURN u
Does anybody sees what's wrong?
An AQL function cannot appear on the top-level of an AQL. The only things allowed on the top-level are statements such as FOR, FILTER, RETURN, LET, COLLECT, SORT, INSERT etc.
If a function should be executed, it's return value should be captured inside a LET statement for further processing, or, if no further processing is required, the function can be called in a RETURNs expression, e.g.
FOR u IN users
LIMIT 1
RETURN UNSET(u, "birthday")
OK, OK ... after writing this I got it: One has to assign this to something. e.g.
FOR u IN users
LIMIT 1
LET tmp = UNSET(u, "birthday")
RETURN tmp
Sorry for posting it ... but I keep it in, maybe other beginners do the same mistake :-)
This may be helpful for other users: The UNSET function does not actually replace the document in the collection. To do this, you need to run
FOR u IN users
LIMIT 1
LET u_new = UNSET(u, "birthday")
REPLACE u WITH u_new IN users

Share data among rules using a Map

This should be simple, but I am still lost.
There is a very similar post here: How to share data between Drools rules in a map?
but it doesn't fix my problem:
I have a set of rules and, before launching them, I insert a Map<String, Object> as a fact.
In these rules I use the map to write some conclusions like:
when
$map : Map();
something ocurrs;
then
$map.put("conclusion1", 100);
Now I would like to use these intermediate conclusions in other rules, something like:
when
$map : Map(this["conclusion1"] > 50)
then
do something cool;
The problem is that when I execute the rules it is like the second rule doesn't see the conclusions of the first one, and it does not fire.
I have tried putting a break point and analysing the working memory, and, in fact, the Map would contain the conclusion1, 100 after the first rule is fired.
I have also tried by making an update($map) in the conclusion, but that would trigger an infinite loop.
Any idea of why this wouldn't work, or any alternative solution to my problem?
Thanks !
When you modify a fact you need to notify the engine you are doing so. One of the ways of doing that is by using modify(). E.g.:
when
$map : Map();
something ocurrs;
then
modify( $map ) {
put("conclusion1", 100)
}
end

Using Groovy find String from Exclusion List

In groovy, I want to search text (which is typically an xml structure) and find an occurrence of the ignore list.
For example:
My different search data requests are (reduced for clarity, but most are large):
<CustomerRQ field='a'></CustomerRQ>
<AddressRQ field='a'></AddressRQ>
My ignore list is:
CustomerRQ
CustomerRS
Based on the above two incoming requests of "customer" and "address", I want to ignore "Customer" since it's in my ignore list, but I want to identify "address" as a hit.
The overall intent is to use this for logging. I want to not log some incoming requests based on my "ignore" list, but all others will be logged.
Here's some pseudo code that may be on the right track but not really.
def list = ["CustomerRQ", "CustomerRS"]
println(list.contains("<CustomerRQ field='a'>"))
I'm not sure, but I think a closure will work in this case, but learning the groovy ropes here. Maybe a regexp will work as well. But the importance is to search in the incoming string (indexOf, exists...) across all of my exclusions list.
A quick solution:
shouldIgnore = list.inject(false) { bool, val -> bool || line.contains(val) }
Whether or not this is the best idea depends on information we don't have; it may be better to do something more-XMLy rather than checking against a string.

Resources