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 <<a = href=3D"javascript:;" onclick=3D"_e(event, 'cvml', 'sdementen@g= mail.com')">[email protected]</a>> wrote:<br> > @abstract<br> > def foo(a,b):<br> > =A0 pass<br> > foo.when =3D lambda condition: when(foo, condition) =A0 #<=3D=3D th= is could be<br> > 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 "s" function. =A0Still, it's definit= ely a way<br> around the IDE issues, and doesn'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> > For my second question, explaining the real domain space would need pa= ges so<br> > I must find a 'to-the-point" analogy that captures the gist o= f the problem.<br> > So here is one that does not use domain-specific terms but maps 100% w= ith<br> > the problem.<br> > I have different kind of cars (pickup, sedans, convertible, etc) which= have<br> > different transmissions (4x4, traction, propulsion) and different tire= s (all<br> > season, snow, high performance, etc) and all combinations of Car x<br> > Transmission x Tires are possible.<br> > Now the generic functions I want to write are like :<br> > =A0- "optimal_acceleration(car, weather)"<br> > =A0- "maintenance_planning(car)"<br> > =A0- "customer_match(car, customer_profile)"<br> > These functions may depend on the Car(Transmission, Tire) combination = and<br> > while all may not be supported, I want to be able to add support for a= ny of<br> > them. Moreover, if a user adds a new kind of transmission, or car, or = tire,<br> > I want to be able to add the functions for these new combinations (if = they<br> > 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't affect rule *precedence* (as far as what= 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'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'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. "param1>1 and param2>2" 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'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't even bother to mention this, except that from your<br> description I don'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. "Registry" 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. "Pattern matching" or "compiler" 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're<br> freely-orderable (i.e., can be tested independently), you can'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't tell if your use case is more<br> like #1 or #2, or some sort of hybrid. =A0If it'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's unlikely to do it in the kinds of uses I'm familiar= <br> with, but since I'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'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==--