Re: PEAK-rules question

Sébastien de Menten <[email protected]> Thu, 5 Sep 2013 22:08:36 +0200
Newsgroups gmane.comp.python.peak
Message-ID <CAB2pxDsAFTz6NqNccpVSOkO+yWyLGt3y2A_aYbpT_Xvd8Yk6qQ@mail.gmail.com>
--===============0421216988==
Content-Type: multipart/alternative; boundary=001a11c2047abc3b7104e5a87cd6

--001a11c2047abc3b7104e5a87cd6
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

On Tuesday, 3 September 2013, PJ Eby wrote:

> On Sun, Sep 1, 2013 at 4:07 PM, S=E9bastien de Menten <[email protected]=
m<javascript:;>>
> wrote:
> > @abstract
> > def foo(a,b):
> >   pass
> > foo.when =3D lambda condition: when(foo, condition)   #<=3D=3D this cou=
ld 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% wi=
th
> > 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 a=
nd
> > while all may not be supported, I want to be able to add support for an=
y
> 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 !

--001a11c2047abc3b7104e5a87cd6
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<br><br>On Tuesday, 3 September 2013, PJ Eby  wrote:<br><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex">On Sun, Sep 1, 2013 at 4:07 PM, S=E9bastien de Menten &lt;<a =
href=3D"javascript:;" onclick=3D"_e(event, &#39;cvml&#39;, &#39;sdementen@g=
mail.com&#39;)">[email protected]</a>&gt; wrote:<br>

&gt; @abstract<br>
&gt; def foo(a,b):<br>
&gt; =A0 pass<br>
&gt; foo.when =3D lambda condition: when(foo, condition) =A0 #&lt;=3D=3D th=
is could be<br>
&gt; better implemented in the abstract decorator<br>
<br>
Better still might be to implement @when() and other such APIs as<br>
macros that transform just the second argument; that way your code<br>
would not need the extra &quot;s&quot; function. =A0Still, it&#39;s definit=
ely a way<br>
around the IDE issues, and doesn&#39;t suffer from the usual issues of<br>
access to source code (I assume, anyway).<br>
<br></blockquote><div>Indeed, good idea !=A0</div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left=
:1ex">
<br>
&gt; For my second question, explaining the real domain space would need pa=
ges so<br>
&gt; I must find a &#39;to-the-point&quot; analogy that captures the gist o=
f the problem.<br>
&gt; So here is one that does not use domain-specific terms but maps 100% w=
ith<br>
&gt; the problem.<br>
&gt; I have different kind of cars (pickup, sedans, convertible, etc) which=
 have<br>
&gt; different transmissions (4x4, traction, propulsion) and different tire=
s (all<br>
&gt; season, snow, high performance, etc) and all combinations of Car x<br>
&gt; Transmission x Tires are possible.<br>
&gt; Now the generic functions I want to write are like :<br>
&gt; =A0- &quot;optimal_acceleration(car, weather)&quot;<br>
&gt; =A0- &quot;maintenance_planning(car)&quot;<br>
&gt; =A0- &quot;customer_match(car, customer_profile)&quot;<br>
&gt; These functions may depend on the Car(Transmission, Tire) combination =
and<br>
&gt; while all may not be supported, I want to be able to add support for a=
ny of<br>
&gt; them. Moreover, if a user adds a new kind of transmission, or car, or =
tire,<br>
&gt; I want to be able to add the functions for these new combinations (if =
they<br>
&gt; make sense ... otherwise, an exception NoApplicableMethods is perfect =
!<br>
<br>
Sounds just like what PEAK-Rules is intended for.<br>
<br>
One thing you might want to watch out for in de-structuring rules like<br>
this (ones that depend on attributes of a parameter), is to remember<br>
that PEAK-Rules generally applies tests to parameters before testing<br>
attributes. =A0This doesn&#39;t affect rule *precedence* (as far as what&#3=
9;s<br>
most specific), but it does affect *evaluation order*.<br>
<br>
For example, if all your rules for a given function read in this order:<br>
<br>
=A0 =A0 isinstance(car.tires, Foo) and isinstance(car.transmission, Bar)<br=
>
<br>
That is, if they all check the tires before checking the transmission,<br>
then PEAK-Rules will conservatively assume that it&#39;s not safe to<br>
access the transmission attribute until after the tires are checked.<br>
This limits the shapes that the dispatch tree will be built in, even<br>
though it doesn&#39;t affect the answers given. =A0Under some circumstances=
,<br>
this might create larger or slower dispatch trees.<br>
<br>
In contrast, tests based directly on parameters are assumed to be<br>
independent of each other (e.g. &quot;param1&gt;1 and param2&gt;2&quot; is =
assumed to<br>
allow checking either condition first) and so can be used at any level<br>
of the dispatch tree, and so the builder is free to use whatever shape<br>
works best for that subtree (at a cost of a little more setup time to<br>
decide which shape is best.)<br>
<br>
I guess what I&#39;m trying to say is that if you have a relatively flat<br=
>
rule structure, based mainly on car, car.tires, and car.transmission,<br>
you may find it useful to make the tires and transmissions direct<br>
parameters, or else to deliberately vary the order they appear in your<br>
rules, so that the rule system will have maximum freedom to construct<br>
dispatch trees.<br>
<br>
I wouldn&#39;t even bother to mention this, except that from your<br>
description I don&#39;t have any way to know just how complex your<br>
dispatch trees will be. =A0In general, I find that generic functions<br>
tend to follow one of two patterns:<br>
<br>
1. &quot;Registry&quot; functions -- not heavily dependent on predicates, m=
ore<br>
dependent on types of a few key parameters, relatively simple rules<br>
with occasional extra criteria<br>
2. &quot;Pattern matching&quot; or &quot;compiler&quot; functions -- while =
one or two<br>
parameter types may be involved, the bulk of the rules are predicates,<br>
often deeply nested predicates on component objects; often found in<br>
compilers or compiler-like systems (such as PEAK-Rules itself) to<br>
pattern-match subtrees with complex conditions.<br>
<br>
In pattern #2, evaluation order may be rather important, but the tree<br>
size is fairly limited by the fact that most of the actual predicates<br>
exist for only a few rules. =A0In pattern #1, the bulk of the indexing<br>
is for that handful of parameters, so as long as they&#39;re<br>
freely-orderable (i.e., can be tested independently), you can&#39;t get a<b=
r>
blowup of tree size. =A0(And in pattern #1, the tests are usually done<br>
directly on the parameters, not on attributes or methods or formulas<br>
using the parameters.)<br>
<br>
>From your vague description, I can&#39;t tell if your use case is more<br>
like #1 or #2, or some sort of hybrid. =A0If it&#39;s basically #1 but usin=
g<br>
lots of independent attribute-level checks, and you have very large<br>
rulesets, then you may want to promote the attributes to parameters<br>
(or access those attributes in different order some of the time), in<br>
order to allow PEAK-Rules full tree reordering freedom. =A0It will not<br>
affect the answers you get, only memory usage (and possibly speed).<br>
Even then, it&#39;s unlikely to do it in the kinds of uses I&#39;m familiar=
<br>
with, but since I&#39;m not familiar with your case, I am being<br>
extra-thorough and cautious. =A0;-)<br>
</blockquote><div>It is definitely more the #2 (pattern matching). Is there=
 some introspection ability on=A0the decision tree PEAK-rules build ? Other=
wise, i&#39;ll check first the overhead to see if it is penalising or not b=
efore optimising.=A0</div>
<div>Thank you for you detailed description of these=A0mechanisms !<span></=
span></div>

--001a11c2047abc3b7104e5a87cd6--

--===============0421216988==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
PEAK mailing list
[email protected]
http://www.eby-sarna.com/mailman/listinfo/peak
--===============0421216988==--