-
Notifications
You must be signed in to change notification settings - Fork 356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Element Equivalence Interfaces #2003
Add Element Equivalence Interfaces #2003
Conversation
- Separate out results into option results class argument. - Add isAttributeEquivalent() to avoid duplication
Hi @ld-kerley , @jstone-lucasfilm
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking pretty good to me - just left a couple of very minor code style things.
- Use const instead of non-const - Fix formatting - Get rid of uneeded bool. - Fix up naming of c1, c2
Review Updates - Revert operator== name changes - Change c2Element to rhsElement.
I added in Python bindings to avoid another PR. I have an equivalence script, but that's not necessary to add in unless you think it's worthwhile to ship with it import argparse
import sys, os
import MaterialX as mx
def main():
parser = argparse.ArgumentParser(description="Test if two documents are functionally equivalent.")
parser.add_argument(dest="inputFilename", help="Filename of the input document.")
parser.add_argument(dest="inputFilename2", help="Filename of the input document to compare against.")
parser.add_argument('-sa', '--skipAttributes', nargs='+', help="List of attributes to exclude from comparisons.")
parser.add_argument('-sv', '--skipValueComparisons', action='store_true', help="Skip value comparisons. Default is False.")
parser.add_argument('-p', '--precision', type=int, default=None, help="Specify the precision for floating-point comparisons.", )
opts = parser.parse_args()
# Check if both files exist
if not os.path.isfile(opts.inputFilename):
print(f"File {(opts.inputFilename)} does not exist.")
sys.exit(0)
if not os.path.isfile(opts.inputFilename2):
print(f"File {(opts.inputFilename2)} does not exist.")
sys.exit(0)
doc = mx.createDocument()
try:
mx.readFromXmlFile(doc, opts.inputFilename)
except mx.ExceptionFileMissing as err:
print(err)
sys.exit(0)
doc2 = mx.createDocument()
try:
mx.readFromXmlFile(doc2, opts.inputFilename2)
except mx.ExceptionFileMissing as err:
print(err)
sys.exit(0)
equivalence_opts = mx.ElementEquivalenceOptions()
if opts.skipAttributes:
for attr in opts.skipAttributes:
equivalence_opts.skipAttributes.add(attr)
if opts.skipValueComparisons:
equivalence_opts.skipValueComparisons = True
if opts.precision:
equivalence_opts.precision = opts.precision
results = mx.ElementEquivalenceResult()
equivalent = doc.isEquivalent(doc2, equivalence_opts)
equivalent = doc.isEquivalent(doc2, equivalence_opts, results)
if equivalent:
print(f"Documents are equivalent")
else:
print(f"Documents are not equivalent: {results.differenceCount()} differences found")
for i in range(0, results.differenceCount()):
difference = results.getDifference(i)
print(f"- Difference[{i}] : Path: {difference[0]} vs path: {difference[1]}. Difference Type: {difference[2]}"
+ (f" attribute: {difference[3]}" if difference[3] else ""))
if __name__ == '__main__':
main() |
- Cleanup single result class to be structures. Create a vector class for this. - Fix Python bindings to return [ status, result } pair. - Fixed a logic regression. Previous changed removed non-value compare in ValueElement::isAttributeEquivalent()
- Rename ElementEquivalenceResults to ElementEquivalenceResultVec
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me, thanks @kwokcb!
a5073ac
into
AcademySoftwareFoundation:main
Issue
Addresses issues: #1988 and #1981 dealing with comparison of element values by adding in a new "functionally" equivalent interface, such that functional equivalence means that the 2 elements perform the same computation. This differs from the existing
operator==
interface which checks for syntactical equivalence.The key points for functional equivalence include:
Element
does not matter.Document
or aCompound NodeGraph
.uimax
oruimin
).Name
andCategory
equivalence cannot be skipped.Changes
isEquivalent
method toElement
.isAttributeEquivalent
method forElement
and override forValueElement
to allow for value vs string comparisons on the latter.ElementEquivalanceOptions
which can be passed in as an argument toisEquivalent
ElementEquivalenceResult
which can be passed in as an argument toisEquivalent
andisAttributeEquivalent
.The following equivalence options are available:
ValueElement
. This is the same precision mechanism used for all value<->string conversions including values for code generation and file I/O.{ xpos, ypos }
.operator==
) currently does instead of value comparisons for aValueElement
.Implementation Notes
extraneous string formatting such as leading and trailing spaces,
0
and leading+
sign.Value
's string representation is used to perform the actual comparison allow for support of precision options.Tests
A new unit test has been added with various numeric variations to test values, ordering, and precision.
The document pair used for testing looks like this:
and
This command script was used to test the Python API: