Correct and optimize setof/3 and bagof/3#3211
Conversation
|
There is also #1526, is this related to |
src/machine/variant_hashing.rs
Outdated
| // to h1 produces h2 (ISO Prolog standard section 7.1.6.1). | ||
| // return false on success and true on failure like eq_test. | ||
| #[inline(always)] | ||
| pub fn is_non_variant(&self, h1: HeapCellValue, h2: HeapCellValue) -> bool { |
There was a problem hiding this comment.
Per https://stackoverflow.com/questions/26900414/difference-between-two-variant-implementations, variant/2 is:
variant(X, Y) :- copy_term(Y, YC), subsumes_term(X, YC), subsumes_term(YC, X).
Maybe this can be used instead?
There was a problem hiding this comment.
variant_disjoint(X, Y) :-
term_variables(X, XVars), append(XVars, _, Dict),
term_variables(Y, YVars), append(YVars, _, Dict),
X == Y.
For bagof/3 and setof/3, the first goals are to be executed prior to any comparisons.
There was a problem hiding this comment.
This is the key idea: That is, first all solutions get the very same variables (but this only works if these constraints are not copied around), and then == is good enough. No need for any hashing and the like.
|
A general comment on variant and the like. In this context here, there is no need for full variant functionality. In fact, all of this is not necessary. |
no, it's because |
It's unclear to me how |
|
In an ideal implementation, |
|
Otherwise |
|
I can't find a way to replace |
Would it work to map each variable to a term representing the position in the term that variable first occurs at, so that we then have a ground term and can use the sort order of ground terms? Or what am I missing that wouldn't make this work? i.e. use a reserved functor (so that it can't occur in any of the terms e.g.
i.e. assuming the functor
|
This is overkill. It is only necessary that the terms contain the very same variables, then regular |
|
Hashing is also very challenging in the presence of rational trees (the default in Scryer). It means that even more cases of rational trees disclose their internal representation than those exposed by |
|
Or more explicitly, |
aa2d04c to
9221a6a
Compare
|
sort_without_dedup/2: commonly called keysort/2 |
|
And sort_without_dedup/2 is incorrect, which can be seen: |
|
Just one more remark on |
Cargo.toml
Outdated
| serde_json = "1.0.122" | ||
| serde = "1.0.204" | ||
| parking_lot = "0.12.4" | ||
| hashbrown = "0.16.1" |
UWN
left a comment
There was a problem hiding this comment.
Progress!
What I am still very suspicious about are these two sort/2 s and this set_difference. We have term_variables and append for this! Witnesses0 is already unique, so why sort it? You will just introduce some evil implementation dependence.
d74e0ad to
695c09e
Compare
UWN
left a comment
There was a problem hiding this comment.
(If might be a good idea to share more of the identical variable analysis in one common auxiliary predicate, but that is nit-picking)
695c09e to
c79fd74
Compare
Use variant hashing and equivalence checking in Rust to replace the special purpose constant variable keysort, which produced incorrect solutions for #3151 and #3187 as @jjtolton showed in #3176. Performance is now much faster, a factor of O(N) in the solution size (#3186).
A variable safety bug was exposed in the course of implementing these corrections, which this PR also corrects.