Jess considers only the last mapped instance - protege

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.

Related

Where is scripted the Dalaran Well teleport (game object)?

When you try to reach the Dalaran Well in Dalaran, you are teleported to the sewers.
It is using this Game object: Doodad_Dalaran_Well_01 (id = 193904 )
Where is it scripted? How?
I've found nothing in the table smart_scripts, and found nothing in the core about this specific id so I'm curious because this type of teleport is really better than clicking on a game object
This gameobject is a unique case because it works like instance teleports do. If you check the gameobject_template table, you will see that it has several Data columns that have diferent values based on the type of the gameobject.
The gameobject you are refering too is the Well It self but the portal gameobject inside the well gives the player a dummy spell to tell the core that the player has been teleported (spell ID 61652).
For the specific case of the dalaran well, it's type is 30 which means, as the documentation says, GAMEOBJECT_TYPE_AURAGENERATOR. As soon as the player is in range, a dummy aura is cast on him to notify the core that this areatrigger has been activated (You could do stuff when player gets hit by the dummy spell).
The trick here is a bunny, but not the bunny itself since it is there mostly to determine an areatrigger. If you use command .go gobject 61148 you can check him out, he's inside the well.
Areatriggers are a DBC object that are actually present on our database on world.areatrigger. You can check the columns here. When the player enters the Radius box specified on the areatrigger, another thing happens in the core which is world.areatrigger_teleport.
If you run the following query you will be able to check the position where the trigger will teleport the player to.
SELECT * FROM areatrigger_teleport WHERE `Name` LIKE '%Dalaran Well teleporter%';

Clear session or session variables on Bixby

Is there a way to specify that a session should be ended, or to clear out the memory of previous actions? In my testing (simulator only) I'm seeing a couple cases where Bixby is remembering a previous entry that isn't relevant anymore.
Example utterances
remove wet diaper
wet diaper
In this case there's 2 possible enums that can be said. "actionType" that is optional, in this case "remove" and "statType", in this case "wet diaper".
What is happening is on the second phrase it's caching the actionType. So, the second phrase my JavaScript still receives the "remove" even though it's not included.
I haven't tried this on an actual device (only the simulator) so it's possible this is just a simulation quirk.
This is kind of related to this question. There was a follow-up comment that the OP asked related to session management.
How does Bixby retain data from a previous NL input?
So, if you read that link. Is there a way I can signal to bixby that the conversation is over, or at least to not remember previous entries for the action?
One way would be to use the transient feature. Here is more information
For example, alter your input type so it doesn't carry over across executions.
name (ActionType) {
features {
transient
}
}
make sure all input types are NL friendly. name/enum concepts are meant for NL and you can attach vocabulary to them.
I used to have a similar issue like yours, in my case, my problem was related to the type of the 'requires' property inside the input-group declared in my action.model.bxb.
You need to handle by separate this two input cases in diferent action.model.bxb files:
In one of them you might have something like (model 1):
input-group(removeWeaper){
requires (OneOrMoreOf)
collect{
input (ActionType) {
type (Type)
min (Optional)
}
input (StatType) {
type (Type)
min (Optional)
}
}
Here, Bixby Will know that at least one of these properties will be apear in your input and will be waiting for an input with that structure.
In the other file you might have (model 2):
input-group(Weaper){
requires (OneOf)
collect{
input (StatType) {
type (Type)
min (Optional)
}
}
Here, Bixby will be waiting to catch an input that contains only one of the indicated values in you input.
(model 1) This could be ok only if you run 'wet diaper' by first time, also when you try again and run 'remove wet diaper' it might work, the problem is when you run again 'wet diaper' because Bixby Stores you previous approach including "remove". i'm not sure if there is something to clear the stored values, but, here is when (model 2) will help you to catch only the input 'wet diaper' as a different statement.
I share you this work around as my own experience, and i hope this could help you solving or getting another perspective of how you could handle or solve your problem.

Maximo automatisation script to change statut of workorder

I have created a non-persistent attribute in my WoActivity table named VDS_COMPLETE. it is a bool that get changed by a checkbox in one of my application.
I am trying to make a automatisation script in Python to change the status of every task a work order that have been check when I save the WorkOrder.
I don't know why it isn't working but I'm pretty sure I'm close to the answer...
Do you have an idea why it isn't working? I know that I have code in comments, I have done a few experimentations...
from psdi.mbo import MboConstants
from psdi.server import MXServer
mxServer = MXServer.getMXServer()
userInfo = mxServer.getUserInfo(user)
mboSet = mxServer.getMboSet("WORKORDER")
#where1 = "wonum = :wonum"
#mboSet .setWhere(where1)
#mboSet.reset()
workorderSet = mboSet.getMbo(0).getMboSet("WOACTIVITY", "STATUS NOT IN ('FERME' , 'ANNULE' , 'COMPLETE' , 'ATTDOC')")
#where2 = "STATUS NOT IN ('FERME' , 'ANNULE' , 'COMPLETE' , 'ATTDOC')"
#workorderSet.setWhere(where2)
if workorderSet.count() > 0:
for x in range(0,workorderSet.count()):
if workorderSet.getString("VDS_COMPLETE") == 1:
workorder = workorderSet.getMbo(x)
workorder.changeStatus("COMPLETE",MXServer.getMXServer().getDate(), u"Script d'automatisation", MboConstants.NOACCESSCHECK)
workorderSet.save()
workorderSet.close()
It looks like your two biggest mistakes here are 1. trying to get your boolean field (VDS_COMPLETE) off the set (meaning off of the collection of records, like the whole table) instead of off of the MBO (meaning an actual record, one entry in the table) and 2. getting your set of data fresh from the database (via that MXServer call) which means using the previously saved data instead of getting your data set from the screen where the pending changes have actually been made (and remember that non-persistent fields do not get saved to the database).
There are some other problems with this script too, like your use of "count()" in your for loop (or even more than once at all) which is an expensive operation, and the way you are currently (though this may be a result of your debugging) not filtering the work order set before grabbing the first work order (meaning you get a random work order from the table) and then doing a dynamic relationship off of that record (instead of using a normal relationship or skipping the relationship altogether and using just a "where" clause), even though that relationship likely already exists.
Here is a Stack Overflow describing in more detail about relationships and "where" clauses in Maximo: Describe relationship in maximo 7.5
This question also has some more information about getting data from the screen versus new from the database: Adding a new row to another table using java in Maximo

else branch of a swrl rule

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.

Combo Core Data Fetch

I have two types of entities: Subjects and Correspondents. They're both related to each other via a to-many relationship. I want to have a single fetchRequest that I can pass to a NSFetchedResultsController which will have it return:
All of the subjects which have more than one correspondent.
All of the correspondents which have subjects that only they are apart of.
After trying a variety of things, I decided that it's not possible to make a single fetch that returns both Subjects and Correspondents, so I turned to StackOverflow and found someone else suggesting that you have a single entity which does nothing more than have relationships with the two entities you'd like to return.
So I created a third type of entity, which I called Folders, which each have an optional to-one relationship with a Subject and a Correspondent. It also has two attributes, hasCorrespondent and hasSubject, which are booleans keeping track of whether Subject or Correspondent are set.
So I wrote this predicate which returns the Folder entities:
(hasCorrespondent == 1 AND ANY correspondent.subjects.correspondents.#count == 1)
OR
(hasSubject == 1 AND subject.correspondents.#count >= 1)
The issue with this is I'm getting an error:
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: 'Unsupported function expression count:(correspondent.subjects.correspondents)
So, any suggestions as to what I'm doing incorrectly? How can I accomplish what I'd like? Are there any additional details I should share?
UPDATE
With Martin's suggestion, I changed the offending portion to this:
SUBQUERY(correspondent.subjects, $s, $s.correspondents.#count == 1).#count > 0
But that generated a new error:
Keypath containing KVC aggregate where there shouldn't be one;
failed to handle $s.correspondents.#count
After googling around, I found suggestions to add a check that the collection being enumerated over had at least one object, but modifying the offending line to this didn't change my error messages (so as far as I can tell it did nothing):
correspondent.subjects.#count > 0 AND
SUBQUERY(correspondent.subjects, $s, $s.correspondents.#count == 1).#count > 0
I had a similar problem. I created an additional field countSubentity. And when add/remove subentity change this field. And predicate looks:
[NSPredicate predicateWithFormat:#"SUBQUERY(subcategories, $s,
$s.countSubentity > 0).#count > 0"];
This work around has been less than ideal, but it seems to get the job done:
1 - I added an attribute to subject called count.
2 - I set (part of) my expression to
ANY correspondent.subjects.count == 1
Note that no SUBQUERY() was necessary for this workaround.
3 - Everytime I modify a subject's correspondents set, I run
subject.count = #(subject.correspondents.count);
I'm still hoping for a better solution and will be happy to mark any (working) better solution as correct.

Resources