Infinite Streams and Negations

Finite streams are rare. Here is an example:

Consider we have the goal (we will write it later) not_eq...

Then: not_eq(x, 3){dict()}: x can be EVERYTHING except any object that reduces to 3

This is an example of a goal that produces an infinite stream. We therefore we have revise our definition of a stream:

A stream:

  1. is the empty list

  2. a pair whose last element is a stream

  3. a suspension: an anonymous function that returns a stream

So, the stream representation of not_eq(x, 3)(dict()) is:

[{x:4},<streamgeneratorfn>][\{x: 4\}, <stream -generator-fn>]

Given this new definition of streams, we need to modify some functions. Specifically,

def take_inf(n, subst_stream, res): # res must be empty
    if n == 0: # unchanged
        return res
    elif len(subst_stream) == 0: # unchanged
        return res
        
        
    elif callable(subst_stream[0]): # checks if the currrent element is a generator
        print(f"when called, the generator gives {subst_stream[0]()}")
        return take_inf(n, subst_stream[0](), res) # change the list being looked at
        
        
    elif isinstance(subst_stream[0],dict): # unchanged
        res.append(subst_stream[0])
        return take_inf(n-1, subst_stream[1:], res)

OK, admittedly, this causes certain hard-to-avoid problems:

Let's say I want to specifically extract substitution for u from a random stream. Since

order of values in streams doesn't matter, we may end up in:

Drawing

Other, more nuanced implementations perform interleaving...

other changes:

append_inf sees no changes

Interestingly, we do not change eq_eq and unify. Why?

TO DEAL WITH ANOTHER LIMITATION:

So, it is not possible to prove logical equivalence with basic tools like these.

So, we don't need to change eq_eq and unify.

ONTO NEGATION:

This too is very difficult to implement purely, because of the problems posed by infinite streams. We have a very crude, hacky, unintellectual implementation.

We will not explain this, it is dumb and stupid code...

When we meet the base case of not_eq(u, 3)({}), we essentially try to "disunify" u with respect to 3. u can "technically" be mapped to any value, but we will stick to ints through the following not-equaliser.

Feel free to run the tool on reasonable examples of your choice!

Last updated