i just stumbeled across this behaviour in haxall. Is there any proper definition or documentation of the haystack filters "not" behaviour? (https://project-haystack.org/doc/docHaystack/Filters is not detailed enough)
pseudo code grid rows example: p = point, sensor, equipRef: someEquip, systemRef: [a,b] a = equip, system, air b = equip, system, water
Given a list of refs (here, systemRef) in a row, the following filter would apply as "any":
"point and systemRef->air"
For above example, this will return "p" as one of its system refs contains the air tag. So far, so good, and rather intuitive.
However, for the following query:
"point and not systemRef->air"
This still returns "p", while I expected the "not" to produce the negation of the part that comes after it, therefore returning nothing.
Is this a bug or is this intended behaviour, if so, is there any documentation on "not" behaviour when applied to trap paths?
On a side note, how can i distinguish ref and list of ref in the trio definitions, where one is allowed, and where not? https://project-haystack.org/doc/docHaystack/Filters#refLists refers to refs can be list of refs, but this is never to be used for "fundamental containment refs" e.g. siteRef, equipRef,...
systemRef are defined in trio as [^ref] def: ^systemRef is: [^ref]
while airRef as ^ref def: ^airRef is: ^ref
however, both are supposedly fine to use as list of refs aswell. The square brackets in "is" as i understood them signify something akin to multi inheritance, so that something is all of the listed. e.g. site: def: ^site is: [^entity, ^geoPlace]
so in either case, what does [^ref] in the systemRef definitions exactly mean?
thank you, cheers thomas
Brian FrankMon 13 Jan
We can beef up the documentation. But the Haxall implemention is as your describe. You must have a complete path to the final tag or the filter evaluates to false. Then the only the leaf record is checked if it is missing the tag.
So given the filter: not systemRef->air, then any record missing the systemRef tag will evaluate to false. Only records that have a systemRef that points to a record missing the air tag will match.
On a side note, how can i distinguish ref and list of ref in the trio definitions
You cannot do this in the Trio defs today. But basically anything that uses the containedBy relationship cannot use a list, but anything that uses the inputs relationship can.
In the Xeto definitions the difference is formally defined by sys::Ref vs a sys::MultiChoice. Note the current tags compiled from defs have not been updated to use MultiChoice yet (will fix soon)
Thomas HirschYesterday
Hi! Thank you for the quick reply.
So given the filter: not systemRef->air, then any record missing the systemRef tag will evaluate to false.
This is perfectly clear.
My original question was: If my point has two refs in systemRef, and only one has an air tag:
The filter systemRef->air will return true for this point.
The filter not systemRef->air will also return true for this point in haxall.
Which is not what I expected, as my intuition tells me that the not applies to the boolean return value of whatever comes after it. This would also be my preferred behaviour, and loosely what https://project-haystack.org/doc/docHaystack/Filters suggests with "You can combine filters using and, or, or not" which reads to me that these operations apply to the filters, not inside the filters.
However, it could be argued that not systemRef->air is equivalent to systemRef->(not air) by returning true if any of the systemRef point to something that it not air. (Although I dislike this definition)
Anyways, playing around I now found that: I have a point with two refs in systemRef. Both systems have an air tag. not systemRef->air returns this point. It should not, in none of the above described applications of not.
I think this is a bug. Heres a test grid to reproduce:
with the query point and not systemRef->air I expect only to get some_other_sensor back, however, haxall reports both.
I can create an issue in the haxall github if that is desired, i just wanted to clarify the beaviour as defined in haystack first.
thank you! cheers thomas
Brian FrankToday 8:45am
Just a note the not operation really means missing tag rather than logical negation in Haystack Filters.
But you are definitely right, that was a bug in my Haxall implementation. I pushed a fix you can look at it.
I also updated the Xeto tag definitions to be MultiRef where appropriate in this changeset
Thomas HirschToday 10:24am
hi!
wow, awesome! thank you. i checked out the main branch and that works now.
Just a note the not operation really means missing tag rather than logical negation in Haystack Filters.
ok, but that alone would not specify the behavior on multirefs.
For example: point and air and point and not air must result in disjoint sets. point and systemRef->air and point and not systemRef->air in my opinion should also result in disjoint sets. (but in haxall they dont).
For the behaviour that haxall currently implements i would expect a query in the form not systemRef or systemRef->(not air) (despite this not being a valid filter).
I also dont see any use case for the current logic, as all use cases i currently have and i can think of require me to have not someRef->someMarker to be the logical opposite of someRef->someMarker.
E.g. Air refs: i want to find an equipment that does not directly connect to outside air. E.g. System refs: i want to find a temp sensor point that is not used in an ahu system.
These questions are currently not answerable in haxall.
If this is really the intended behaviour for haystack filters, this should documented that systemRef->air and not systemRef->air can produce overlapping sets as the not part does not apply the following statement as a whole but in case of trap operator(s) at any level of the trapped path and branches.
thank you, cheers, thomas
Brian FrankToday 11:07am
That isn't a valid hayson file so I can't really test with. Maybe post a zinc file.
But the way lists of refs are defined, its an OR operation against any of the refs in the list. So as long as one item in the list matches, then its overall match.
For example:
// given this record
systemRef: [@hasFoo, @missingFoo]
// this this filter....
not systemRef->foo
// ..essentially maps to this
(not @hasFoo->foo) or (not @missingFoo->foo)
Although honestly using not should be strongly discouraged and we've been trying to remove its use in the ontology design. Its also very difficult to optimize because it requires a full database scan.
If this is really the intended behaviour for haystack filters, this should documented that systemRef->air and not systemRef->air can produce overlapping sets
Thomas Hirsch Mon 13 Jan
Hi all,
i just stumbeled across this behaviour in haxall. Is there any proper definition or documentation of the haystack filters "not" behaviour? (https://project-haystack.org/doc/docHaystack/Filters is not detailed enough)
pseudo code grid rows example: p = point, sensor, equipRef: someEquip, systemRef: [a,b] a = equip, system, air b = equip, system, water
Given a list of refs (here, systemRef) in a row, the following filter would apply as "any":
"point and systemRef->air"
For above example, this will return "p" as one of its system refs contains the air tag. So far, so good, and rather intuitive.
However, for the following query:
"point and not systemRef->air"
This still returns "p", while I expected the "not" to produce the negation of the part that comes after it, therefore returning nothing.
Is this a bug or is this intended behaviour, if so, is there any documentation on "not" behaviour when applied to trap paths?
On a side note, how can i distinguish ref and list of ref in the trio definitions, where one is allowed, and where not? https://project-haystack.org/doc/docHaystack/Filters#refLists refers to refs can be list of refs, but this is never to be used for "fundamental containment refs" e.g. siteRef, equipRef,...
systemRef are defined in trio as [^ref] def: ^systemRef is: [^ref]
while airRef as ^ref def: ^airRef is: ^ref
however, both are supposedly fine to use as list of refs aswell. The square brackets in "is" as i understood them signify something akin to multi inheritance, so that something is all of the listed. e.g. site: def: ^site is: [^entity, ^geoPlace]
so in either case, what does [^ref] in the systemRef definitions exactly mean?
thank you, cheers thomas
Brian Frank Mon 13 Jan
We can beef up the documentation. But the Haxall implemention is as your describe. You must have a complete path to the final tag or the filter evaluates to false. Then the only the leaf record is checked if it is missing the tag.
So given the filter:
not systemRef->air
, then any record missing the systemRef tag will evaluate to false. Only records that have a systemRef that points to a record missing theair
tag will match.The logic for the Filter behavior is here
You cannot do this in the Trio defs today. But basically anything that uses the
containedBy
relationship cannot use a list, but anything that uses theinputs
relationship can.In the Xeto definitions the difference is formally defined by
sys::Ref
vs asys::MultiChoice
. Note the current tags compiled from defs have not been updated to use MultiChoice yet (will fix soon)Thomas Hirsch Yesterday
Hi! Thank you for the quick reply.
This is perfectly clear.
My original question was: If my
point
has two refs insystemRef
, and only one has anair
tag:The filter
systemRef->air
will return true for this point.The filter
not systemRef->air
will also return true for this point in haxall.Which is not what I expected, as my intuition tells me that the
not
applies to the boolean return value of whatever comes after it. This would also be my preferred behaviour, and loosely what https://project-haystack.org/doc/docHaystack/Filters suggests with "You can combine filters using and, or, or not" which reads to me that these operations apply to the filters, not inside the filters.However, it could be argued that
not systemRef->air
is equivalent tosystemRef->(not air)
by returning true if any of thesystemRef
point to something that it notair
. (Although I dislike this definition)Anyways, playing around I now found that: I have a point with two refs in
systemRef
. Both systems have anair
tag.not systemRef->air
returns this point. It should not, in none of the above described applications of not.I think this is a bug. Heres a test grid to reproduce:
{
}
with the query
point and not systemRef->air
I expect only to getsome_other_sensor
back, however, haxall reports both.I can create an issue in the haxall github if that is desired, i just wanted to clarify the beaviour as defined in haystack first.
thank you! cheers thomas
Brian Frank Today 8:45am
Just a note the
not
operation really means missing tag rather than logical negation in Haystack Filters.But you are definitely right, that was a bug in my Haxall implementation. I pushed a fix you can look at it.
I also updated the Xeto tag definitions to be MultiRef where appropriate in this changeset
Thomas Hirsch Today 10:24am
hi!
wow, awesome! thank you. i checked out the main branch and that works now.
ok, but that alone would not specify the behavior on multirefs.
For example:
point and air
andpoint and not air
must result in disjoint sets.point and systemRef->air
andpoint and not systemRef->air
in my opinion should also result in disjoint sets. (but in haxall they dont).For the behaviour that haxall currently implements i would expect a query in the form
not systemRef or systemRef->(not air)
(despite this not being a valid filter).given this example grid: {
}
I also dont see any use case for the current logic, as all use cases i currently have and i can think of require me to have
not someRef->someMarker
to be the logical opposite ofsomeRef->someMarker
.E.g. Air refs: i want to find an equipment that does not directly connect to outside air. E.g. System refs: i want to find a temp sensor point that is not used in an ahu system.
These questions are currently not answerable in haxall.
If this is really the intended behaviour for haystack filters, this should documented that
systemRef->air
andnot systemRef->air
can produce overlapping sets as thenot
part does not apply the following statement as a whole but in case of trap operator(s) at any level of the trapped path and branches.thank you, cheers, thomas
Brian Frank Today 11:07am
That isn't a valid hayson file so I can't really test with. Maybe post a zinc file.
But the way lists of refs are defined, its an OR operation against any of the refs in the list. So as long as one item in the list matches, then its overall match.
For example:
Although honestly using
not
should be strongly discouraged and we've been trying to remove its use in the ontology design. Its also very difficult to optimize because it requires a full database scan.This is correct