-
Notifications
You must be signed in to change notification settings - Fork 10
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
Substitution lazy cloning #270
Conversation
- Add Substitution.unify that clones the partial input substitution on demand (i.e., when an additional variable assignment is required). - Modify NaiveGrounder and AbstractLiteralInstantiationStrategy to not clone Substitutions upfront.
Codecov Report
@@ Coverage Diff @@
## master #270 +/- ##
=========================================
Coverage ? 77.44%
Complexity ? 2311
=========================================
Files ? 178
Lines ? 7782
Branches ? 1352
=========================================
Hits ? 6027
Misses ? 1335
Partials ? 420
Continue to review full report at Codecov.
|
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.
I think everything is ok from a functional point of view, i.e. the code does what it's supposed to do, however, I find it hard to read and confusing in places, see more detailed comments. I'm aware not all of those are easy to address (or even necessarily need to be addressed), but I think some discussion makes sense.
} | ||
return substitution; | ||
|
||
boolean unifyTerms(Term termNonGround, Term termGround, Substitution partialSubstitution) { |
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.
It seems wrong (or at least really confusing) to me that we now have UnificationHelper::unifyTerms(Term, Term, Substitution)
as well as Substitution::unifyTerms(Term, Term)
. The only difference seems to be that the one in Substitution
always operates on this
and modifying the substitution it's called on, while the other one operates on the given partialSubstitution
. I think the version in UnificationHelper
should be adapted so that the other one isn't needed.
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.
Agreed, the Substitution::unifyTerms(Term, Term)
is only ever needed in unit tests, while the new one is not tested. Will adapt the tests to run on the real thing and get rid of the other.
* already is a unifier, it is returned. If the unifying substitution is an extension of the input | ||
* substitution, a new substitution will be returned. | ||
*/ | ||
public static Substitution unify(Atom atom, Instance instance, Substitution substitution) { |
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.
More of a general question, and maybe out of the scope of this review... We also have classes Unifier
and Unification
, with Unification
implementing utility functions looking very similar to some of the methods in Substitution
. In order to avoid duplicating code, or writing several very similar versions, would it make sense to use the (accordingly adapted) methods from Unification
here?
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.
There is a slight difference between the two (and maybe we should adapt our naming): the one in Substitution
is assuming that variables only ever occur on the left-hand side (i.e., the second parameter is always ground). The version in Unification
really computes the unifier between two non-ground Atom
s. Maybe we should rename the methods in Substitution
to instantiate()
instead of unify()
.
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.
I decided to rename Substitution::unify
to Substitution::specializeSubstitution
as it specializes the given partial substitution to also unify the given atom and the instance.
private static class UnificationHelper { | ||
Substitution returnSubstitution; | ||
|
||
Substitution unify(List<Term> termList, Instance instance, Substitution partialSubstitution) { |
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.
Note that this is a matter of personal taste, but I'm not sure I agree with the return types here..
I think it might make sense if unifyTerms
returned something other than boolean, thereby getting rid of the side-effects of potentially modifying the given partialSubstitution. Instead, unifyTerms
could return a Substitution
that may be either a new (cloned) one, or the one passed in in case nothing changed. Alternatively, we could also use an Optional<Substitution>
here, where the presence of a value would indicate that a new variable got bound. The version with Optional
could also be used for Substitution::unify
as an alternative to returning null
.
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.
Letting unifyTerms
return a Substitution
is a good idea. I would not want to return an Optional
however, since substitutions are used at the core of grounding and Optional
is likely slower and creates more objects.
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.
Actually, I decided to remove unifyTerms
as it was only ever used in unit tests. These unit tests have been adapted to now test the new/renamed specializeSubstitution
.
That is exactly the reason why I like our four-eyes policy on pull requests. It forces one to deliver better code. Thank you for the comments! |
- Remove superfluous Substitution.unifyTerms. - Adapt SubstitutionTest to Substitution specialization. - Remove duplicate tests from UnifierTest.
Comments have been addressed, please check if this is better now. |
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.
Thanks for all the improvements, this looks really good now!
Removes the need for upfront cloning of Substitutions when checking unification.