>
> I oversimplified the explanation of "swapping" substituion/disequalities. 
> You right, additional efforts are required to handle `fresh` variables that 
> apper under negation. 
>
> First of all, I will admit, that when I execute `g` we consider its 
> `fresh` variables as usual, but when I negate its answers I change my point 
> of view on this variables and start to treat them like `universally` 
> quantified. I do not consider these variables as `universal` on the fly 
> because 
> of cases like `forall (x) (x =/= 1) || (x == 1))` (which, taken my 
> approach, executed as (not (fresh (x) (x == 1) && (x =/= 1) )).
>
> Substituion `x_1 = t_1 & ... & x_n = t_n` (if it contains bindings for 
> `universal` variables) becomes not a regular disequality, but 
> `anti-subsumption` constraint, or in other words constraint of the form 
> `forall (x) (t =/= u)`. I've already meantioned that constraints in 
> previous posts.
>
> In your example, after we get answer-substituion `x = 1`, it becomes 
> constraint `forall (x) (x =/= 1)` which fails trivially (because there is 
> such x = 1). 
>
> When I "swap" disequality `x_1 =/= t_1 || ... || x_n =/= t_n` I first 
> translate it to substutuion `x_1 = t_1 & ... & x_n = t_n`, but I also have 
> to recheck and detect if `universal` variables escape their scope. It is 
> not very smart, and I am not yet know how to perform this step more 
> efficiently without rechecking of each binding.
>

I think you can automatically achieve the factoring I describe in the 
rewrite examples, which might be more direct than what you have in mind.

States will track scope and maintain an order on variables based on the 
order they're introduced.  When variables introduced in newer scopes are 
unified with variables in older scopes, the newer variable points to and 
hands over ownership of its constraints to the older variable.  By tracking 
the 'fresh' scopes that a state has seen inside of a negation, the negation 
will know to clean out (that is, fail) constraints involving these 
variables, while complementing the others as usual, building a disjunction 
out of whatever remains, as you do.

Example:

(fresh (v)  ;; v is older than x.
  ...
  (not (fresh (x)  ;; state (x in scope)
           (=/= 5 x)  ;; state (x in scope): (=/= x 5)
           (== x v)))  ;; state (x in scope): (x points to v), (=/= v 5)  
;; v has inherited x's =/= constraint.
  ...)

The negation sees this state bubble up to it:

state (x in scope): (x points to v), (=/= v 5)

Since x is in scope, the (x points to v) equality is thrown away as a 
failure.

Since v is not in scope, (=/= v 5) is complemented to (v points to 5).

So you end up with a disjunction of (== v 5) and F.


This corresponds to the behavior of the factoring:

(fresh (v)  ;; v is older than x.
  ...
  (not (fresh (x) (=/= 5 x) (== x v)))
  ...)
==>
(fresh (v)
  ...
  (not (fresh (x) (=/= 5 v) (== x v)))
  ...)
==>
(fresh (v)
  ...
  (not (=/= 5 v) (fresh (x) (== x v)))
  ...)
==>
(fresh (v)
  ...
  (conde ((== 5 v)) (F))
  ...)


In some cases, such as pair unifications, some juggling is necessary to 
maintain the invariant that new variables always point to old.  "Old" may 
be the wrong description, since juggling may require generating new 
variables in old scopes.

I'll show this in an example:

(fresh (v)
  ...
  (not (fresh (x)
           (== `(2 . ,x) v)))
  ...)

We don't want v to point to x.  We can accomplish this with a complex 
maneuver that then leads to simplicity.  We can introduce a new tautology 
relating v to pairs, using fresh variables to provide a layer of 
indirection later on.  (I think this is a general maneuver that should work 
anytime we see such a pair unification.)

(fresh (v va vd)  ;; va and vd are added here.
  ...
  ;; This conde is the tautology.
  ;; Since va and vd are newly added, they are guaranteed not to be 
referenced anywhere except our tautology.
  ;; Therefore this goal implements the proposition: v is either a pair, or 
not a pair.
  (conde
    ((not-pairo v))
    ((== `(,va . ,vd) v)))

  ;; This goal will be absorbed into each conde clause.
  (not (fresh (x)
           (== `(2 . ,x) v)))
  ...)
==>
(fresh (v va vd)
  ...
  (conde
    ((not-pairo v)
     (not (fresh (x)
              (== `(2 . ,x) v))))  ;; Since (not-pairo v), this will fail.
    ((== `(,va . ,vd) v)
     (not (fresh (x)
              (== `(2 . ,x) v)))  ;; This can now be decomposed using va 
and vd.
  ...)
==>
(fresh (v va vd)
  ...
  (conde
    ((not-pairo v)
     (not (fresh (x) F)))
    ((== `(,va . ,vd) v)
     ;; Now this fresh can produce a state where nothing points to x.
     ;; We saw how to handle negating such a fresh in an earlier example.
     (not (fresh (x)
              (== 2 va)
              (== x vd)))
  ...)
==>
(fresh (v va vd)
  ...
  ;; This is the desired result, equivalent in meaning to (forall (x) (=/= 
`(2 . ,x) v)).  v isn't any pair with a car that is 2.
  (conde
    ((not-pairo v))
    ((== `(,va . ,vd) v)
     (=/= 2 va))
  ...)

I'm demonstrating using rewrites for clarity, but we should be able to 
perform this maneuver with a running computation.  One way is to allow v to 
temporarily point to `(2 . ,x), then have the negation recognize this 
situation, performing the tautology split itself.


Do you have a reason in mind that would make you want to wait until you 
>> have all of g's answers first?
>>
>
> Well you right, In some cases it is possible to fail earlier and do not 
> consume all stream. It is the case when `s_tmp = F` (F for the bottom of 
> lattice), i.e. when none of conjuncts from answer `s_(i-1)` compatible with 
> conjuncts from `s_i`.
>
> Note hovewer, that you should propogate each conjunct through the whole 
> stream of answers, because it may be compatible with some other conjunct.
>

What do you mean by compatibility in this case?  Are you looking for 
unsatisfiability?  Do you have an efficiency concern in mind (with an 
example)?

-- 
You received this message because you are subscribed to the Google Groups 
"minikanren" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/minikanren.
For more options, visit https://groups.google.com/d/optout.

Reply via email to