[PEAK] Re: PEAK-rules question
Sébastien de Menten
sdementen at gmail.com
Thu Sep 5 16:08:36 EDT 2013
On Tuesday, 3 September 2013, PJ Eby wrote:
> On Sun, Sep 1, 2013 at 4:07 PM, Sébastien de Menten <sdementen at gmail.com<javascript:;>>
> wrote:
> > @abstract
> > def foo(a,b):
> > pass
> > foo.when = lambda condition: when(foo, condition) #<== this could be
> > better implemented in the abstract decorator
>
> Better still might be to implement @when() and other such APIs as
> macros that transform just the second argument; that way your code
> would not need the extra "s" function. Still, it's definitely a way
> around the IDE issues, and doesn't suffer from the usual issues of
> access to source code (I assume, anyway).
>
> Indeed, good idea !
>
> > For my second question, explaining the real domain space would need
> pages so
> > I must find a 'to-the-point" analogy that captures the gist of the
> problem.
> > So here is one that does not use domain-specific terms but maps 100% with
> > the problem.
> > I have different kind of cars (pickup, sedans, convertible, etc) which
> have
> > different transmissions (4x4, traction, propulsion) and different tires
> (all
> > season, snow, high performance, etc) and all combinations of Car x
> > Transmission x Tires are possible.
> > Now the generic functions I want to write are like :
> > - "optimal_acceleration(car, weather)"
> > - "maintenance_planning(car)"
> > - "customer_match(car, customer_profile)"
> > These functions may depend on the Car(Transmission, Tire) combination and
> > while all may not be supported, I want to be able to add support for any
> of
> > them. Moreover, if a user adds a new kind of transmission, or car, or
> tire,
> > I want to be able to add the functions for these new combinations (if
> they
> > make sense ... otherwise, an exception NoApplicableMethods is perfect !
>
> Sounds just like what PEAK-Rules is intended for.
>
> One thing you might want to watch out for in de-structuring rules like
> this (ones that depend on attributes of a parameter), is to remember
> that PEAK-Rules generally applies tests to parameters before testing
> attributes. This doesn't affect rule *precedence* (as far as what's
> most specific), but it does affect *evaluation order*.
>
> For example, if all your rules for a given function read in this order:
>
> isinstance(car.tires, Foo) and isinstance(car.transmission, Bar)
>
> That is, if they all check the tires before checking the transmission,
> then PEAK-Rules will conservatively assume that it's not safe to
> access the transmission attribute until after the tires are checked.
> This limits the shapes that the dispatch tree will be built in, even
> though it doesn't affect the answers given. Under some circumstances,
> this might create larger or slower dispatch trees.
>
> In contrast, tests based directly on parameters are assumed to be
> independent of each other (e.g. "param1>1 and param2>2" is assumed to
> allow checking either condition first) and so can be used at any level
> of the dispatch tree, and so the builder is free to use whatever shape
> works best for that subtree (at a cost of a little more setup time to
> decide which shape is best.)
>
> I guess what I'm trying to say is that if you have a relatively flat
> rule structure, based mainly on car, car.tires, and car.transmission,
> you may find it useful to make the tires and transmissions direct
> parameters, or else to deliberately vary the order they appear in your
> rules, so that the rule system will have maximum freedom to construct
> dispatch trees.
>
> I wouldn't even bother to mention this, except that from your
> description I don't have any way to know just how complex your
> dispatch trees will be. In general, I find that generic functions
> tend to follow one of two patterns:
>
> 1. "Registry" functions -- not heavily dependent on predicates, more
> dependent on types of a few key parameters, relatively simple rules
> with occasional extra criteria
> 2. "Pattern matching" or "compiler" functions -- while one or two
> parameter types may be involved, the bulk of the rules are predicates,
> often deeply nested predicates on component objects; often found in
> compilers or compiler-like systems (such as PEAK-Rules itself) to
> pattern-match subtrees with complex conditions.
>
> In pattern #2, evaluation order may be rather important, but the tree
> size is fairly limited by the fact that most of the actual predicates
> exist for only a few rules. In pattern #1, the bulk of the indexing
> is for that handful of parameters, so as long as they're
> freely-orderable (i.e., can be tested independently), you can't get a
> blowup of tree size. (And in pattern #1, the tests are usually done
> directly on the parameters, not on attributes or methods or formulas
> using the parameters.)
>
> From your vague description, I can't tell if your use case is more
> like #1 or #2, or some sort of hybrid. If it's basically #1 but using
> lots of independent attribute-level checks, and you have very large
> rulesets, then you may want to promote the attributes to parameters
> (or access those attributes in different order some of the time), in
> order to allow PEAK-Rules full tree reordering freedom. It will not
> affect the answers you get, only memory usage (and possibly speed).
> Even then, it's unlikely to do it in the kinds of uses I'm familiar
> with, but since I'm not familiar with your case, I am being
> extra-thorough and cautious. ;-)
>
It is definitely more the #2 (pattern matching). Is there some
introspection ability on the decision tree PEAK-rules build ? Otherwise,
i'll check first the overhead to see if it is penalising or not before
optimising.
Thank you for you detailed description of these mechanisms !
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.eby-sarna.com/pipermail/peak/attachments/20130905/07015cd8/attachment.html
More information about the PEAK
mailing list