Friday, January 24, 2014

It is possible to change the patterns of thought and shift into "flow" intentionally and without rituals, etc. The difficulty is the delay between the decision and the onset of the mental state. Patience and experience bridge the gap.


Monday, January 13, 2014

Should all of the constraints use sets?

I'm considering making all constraints use sets. This change would be contained to the connector class since every value that didn't use sets already could have all of its values implicitly wrapped into Singletons and then unwrapped on getValue calls. The problem there is, of course, that then the constraints which do make use of sets will have to form their own singletons whenever they request a value. Obviously, this is annoying. Part of the usage of sets that I'm thinking of is with inequalities. I want to be able to specify that a whole range of values could satisfy an inequality where previously, I had to settle for just not setting anything on that connector. In this context, singleton values don't make sense because they need to be dereferenced to the exact value anyway.

The main thing is that when we set a single value on top of a set, we have to test membership, but when we set another set on top of a set, we have to test the intersection is non-null (and possibly another value).
This gives something like:

(define (consistent? newval v)
(match (list newval v)
       [`(,(? Set? x) ,(? Set? y))
        (intersect x y)]
       [(or `(,(? Set? x) ,(? (negate Set?) y))
            `(,(? (negate Set?) y) ,(? Set? x)))
        (member? x y)]) ; member? returns y or (gensym)
to get the value to set. Note that this also changes the meaning of consistent? to what might be called makeConsistent. An operator that takes two values of some type and returns an value that is consistent with both of them. This can be achieved by way of generics. The various set functions can be used with any values that they need and Connector only needs to know about the generic function makeConsistent. This allows for us to make any number of types and give them a their own definition of makeConsistent, but also to not require any changes to Connector -- the two concerns are completely separated. Going back to the original point of this post, we still have to change the use of consistent? Connector to makeConsistent and change the semantics of the constraint solver such that any constraint can set values on the connector (this was the case before), but may not be the setter anymore since the value that is finally set doesn't belong to any of them. However, assuming the makeConsistent functions are correctly implemented, we have to notify neither the setter of the old value nor the setter of the new one since the result will be consistent with them both. This may make the logic slightly more complicated, but the advantage of allowing extension of types by users outweighs that concern.


Wednesday, January 1, 2014

Rule matching with the Observer pattern

A rule matching algorithm has an intuitive implementation with the use of the observer pattern. Model state data as observables and productions as observers of state objects. Updates to the state objects trigger notices to productions. Notices to productions can include the state object which sent the notice. Productions request to add themselves to a set of rules-to-execute. Conflict resolution between productions can be done on addition to the set or in a separate phase.

Running time estimations

Updates to N state objects with at most M productions depending on any rule takes O(N*M) time if the productions know which rule fired and productions get notified independently for each state object of all changes to their preconditions. Deleting a production takes O(B) time to unregister the production from each of B data objects. Deleting N data objects with at most M dependents depending on at most B data objects takes O(N*M*B) time if the objects must unregister themselves when they can't be satisfied (presumably they can't if all precondition variables must be present to fire), or O(N*M) otherwise.

This algorithm improves over a naive implementation of searching through the whole list of productions on each update, but doesn't perform as well as Rete matching on updates.