[rules-users] Drools as Lexer / Parser (sequential data processing)

2009-09-02 Thread André Thieme
Hello group, I recently had the idea:
A rule system (like Drools) is ideal for making programs with complex
  rules simpler. Writing a lexer or parser can be non-trivial. So, is it
  possible and also meaningful to express such a task with rules?

Anyone here who maybe tried that already?
The two big questions for me are:
1) how easy is it to express a lexer with rules?
2) how bad (good?) will it perform?

If you happen to have a good idea of how to do it, could you please give
me an example for a simple lexer?
Let's say it will get natural language (a string, such as this email) as
input and should return a sequence (say, ArrayList) of Tokens, which may
look like this:

public class Token {
   public String value;
   public String category;

   Token(String value, String category) {
 this.value = value;
 this.category = category;
   }
}

We could have three categories:
word,  numeric  and  whitespace.

An input String could be:
We can   see 500 cars
And it should produce an ArrayList with the contents:
[
  Token(We, word),
  Token( , whitespace),
  Token(can, word),
  Token(   , whitespace),
  Token(see, word),
  Token( , whitespace),
  Token(500, numeric),
  Token( , whitespace),
  Token(cars, word)
]

At the moment I have difficulties to see if/how this could be achieved.
If you find this easy, please post a solution.
I am aware that JavaCC is really good for such tasks and will also
perform extremly well.


Greetings,
André
___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


Re: [rules-users] Maps in Drools

2009-08-21 Thread André Thieme
Edson Tirelli schrieb:
 
Andre,
 
The misunderstanding here is that the LHS, except for code blocks 
 like eval, return value expressions and accumulate code blocks, 
 are all Drools Language. When you use the dialect attribute in a 
 rule or package you are telling the compiler what dialect (MVEL or Java) 
 you will use inside these code blocks mentioned previously + the 
 language for the RHS.

Good that you clear that up, thanks.


 In other words:
 
 Map( this[type] == Point, $x : this[x], size == 5 )

I thought this is only possible when one declares the dialect MVEL.
Now I understand that what you just wrote also results in a valid rule,
even when MVEL is not set.

In your code above you:
1. check if this.get(type).equals(Point)
2. you set $x to the value of this.get(x)
3. check if this.size == 5
where I interpret 3. as calling the size() method of java.util.Map.
Was that right so far?


 Everything you see in the previous expression is Drools language, 
 does not matter if you set the dialect to java or mvel in the rule. It 
 happens that Drools uses the same map syntax as MVEL (and a lot of other 
 scripting languages). Also, we know, that drools implementation will 
 resolve the first 2 above expressions in MVEL behind the scenes, and the 
 3rd will be resolved nativelly, but that is not something users should 
 have to worry about, since they are writing it in Drools Language.

Yes, I understand.
Only with the middle part I still have some problems.
As you used it,   $x : this[x]   it works for me.
A minor issue I have with this, but we can ignore that for now, is, that
this will be interpreted.
The real problem for me is: it only works when between the brackets
there is a literal string.
I however can't do that, because my lib should support the general case,
where between the brackets there could be any type of object (which I
would pass in via a global var).


 If they write an eval, THEN they need to differentiate between MVEL 
 and Java according to the chosen dialect.
 
 rule xyz
dialect mvel
 when
eval( ...here you write MVEL code... )
 then
// here you write MVEL code
 end
 
 rule xyz2
dialect java
 when
eval( ...here you write JAVA code... )
 then
// here you write JAVA code
 end

Very good, thanks again for clearing this up.


André
-- 
___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


Re: [rules-users] Maps in Drools

2009-08-21 Thread André Thieme
Edson Tirelli schrieb:
 
 
 2009/8/20 André Thieme address.good.until.2009.dec...@justmail.de 
 mailto:address.good.until.2009.dec...@justmail.de
 
 Would there not be an addition to the syntax needed, for the default
 rule language? For mvel it would not require a change I guess.
 
 
 No, as I mentioned to you, the idea is for the DRL to remain the same, 
 so that the rules author does not have to worry about what the IT guys 
 are doing with the domain model. So, the rules author would write:
 
 Customer( name == bob )
 
 The IT guy would simply use a configuration to tell the engine: this 
 object type uses a map format, that one is a POJO, that other is an XML 
 entity, etc.
 For instance, if he wants to do that in DRL (he could also use API, or 
 conf files), he could do:
 
 declare Customer
 @format( map )
 end
 
 declare Order
 @format( pojo )
 end
 
 So, we have a clear distinction between the technical aspects and the 
 business aspects of the application.

Ah okay, that makes sense and sounds very good!
So, when Maps become first class not the rules will introduce a new
syntax, but intead we would add some declarations.
The only two challenges I see with that is:
1. to allow the keys to be any object and not just only strings.
2. differentiate between fields of the Maps and keys

Point 1.:
Your example  Customer( name == bob )  currently is expressed as:
$m : Map(eval($m.get(type == Customer)) 
  eval($m.get(name) == bob))
right?
In the declaration for Customer above one would probably have to specify
that for a Map being a Customer depends on the key type.
But what would  Customer( name == bob ) look like if name was not a
String but some other Object?
This info should go into the declare part, yes?


Point 2.:
in your other reply you gave the example:
Map( this[type] == Point, $x : this[x], size == 5 )

Projected on the  Customer( name == bob )  example we would need to
differentiate, in Java terms, between:
map.get(size) == 5and   map.size() == 5
So   Customer(name==Bob  size==5)   needs to be clear.



 Your clojure macro would generate always the same DRL code Customer( 
 name == bob ), but you said yourself that clojure is 100% java 
 compatible, so imagine the enterprise had a domain model implemented as 
 pojos already and as part of the new application some new entities are 
 modeled in clojure. The macro would generate always the same code, but 
 you would configure some entities in the domain as POJOs and other 
 entities as Maps.

Yes, it would be similar like that.
What I first do is to write a general macro named rule which should
be able to express everything that currently is possible in Drools.
On top of that macro I will define some more, for exmaple there could be
a macro map-rule which is specialized on maps.
This can get even more specialized, but in the end all those macros will
expand into the general one, and the general one will generate a
string S which contains all rules and then do a
ResourceFactory.newByteArrayResource(S.getBytes(utf-8)) to get the
rules into Drools, which will from then on continue.

And the way as you suggest it, to let the Drools syntax always be the
same, it may even be easier for me to write my lib. Good :)


 Hmm, but the MVEL syntax can not magically eliminate the eval. Under the
 hood the map accesses will still be inside an eval. Marc confirmed that
 a few days ago.
 MVEL only hides this from the user. This is what I will also do.
 But under the hood it will become
 
   $a:Map()
   $b:Map()
   eval( $a.get(type) == Customer )
   eval( $b.get(type) == DailyOrders )
 
 
 Here I think we have other misunderstanding.  I will try to explain, but
 ideally you need to learn a bit about the Rete algorithm to see the 
 whole picture.

Yes, I will read soon (I hope) Chapter 12 of my Drools book,
by Michal Bali.



 There are 2 types of eval(). Inline eval() and top level eval().

Ah, I see, I didn't know that.


 What you wrote above is a top level eval, meaning it will become 
 a node in the rete network. So your example above generates an 
 execution plan (making an analogy with SQL) that will get all Maps in 
 the working memory, join them in tuples size 2, and then test each tuple 
 for the 2 evals. So, you see why this will generate C(n,2) partial 
 matches, while C(n,2) as we know is n!/(n-2)!, what is really bad for 
 growing n.

Very good, now I understand what you mean. Thanks for the sql analogy.


 Now, the same thing could be written using inline evals as:
 
 $a:Map( eval( $a.get(type) == Customer ) )
 $b:Map( eval( $b.get(type) == DailyOrders ) )

Excellent, this is very helpful. I just tried this out and was also
successful with it. Now I can have my code generating alpha constraints
without having to use MVEL.


   In this case, the inline eval() will generate an alpha constraint in 
 the network, i.e., it will be applied BEFORE the joins. So, instead of 
 doing all

Re: [rules-users] Maps in Drools

2009-08-20 Thread André Thieme
Edson Tirelli schrieb:
 
ooops... correct version:
 
 when
Map( this[type] == Point, $x : this[x] )
Map( this[type] == Circle, this[x] == $x )
 then
 end

Okay, so in the mvel syntax this is possible.
Can this also be achieved in the default rule syntax, without mvel?

The mvel syntax needs to be interpreted at runtime, so my Clojure lib
will have to output rules in Drools' native rule language.

What interests me most is that first part:
Map( this[type] == Point, $x : this[x] )


André
-- 
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org/
___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


Re: [rules-users] Maps in Drools

2009-08-20 Thread André Thieme
Edson Tirelli schrieb:
 
   So, in principle having Maps support in the LHS is not a big challenge?
 
 No. Just requires developing a set of classes to work with maps. Being 
 brief:
 
 * Implement: MapObjectType extends ObjectType
 * Implement: MapReadAccessor and MapWriteAccessor
 * Add support to them into the builders (i.e., the actual wiring of the 
 new classes)
 * Test everything... I probably forgot something, since there's been 
 quite some time since I worked on this.

Would there not be an addition to the syntax needed, for the default
rule language? For mvel it would not require a change I guess.


   Could you please explain this in a bit more detail?
 Lets call |A| the number of A facts in the working memory and |B| the 
 number of B facts (i.e. cardinality). Lets call p(|A|,|B|) the number of 
 partial matches a rule will create given the cardinality of A and B. 
 Imagine your rule is:
 
 when
A()
B()
 then
 
 This rule creates a join between A() and B() and the number of join 
 attempts will be: p(|A|,|B|) = |A| * |B|
 
 Now, if instead of representing A and B as different classes you use 
 Maps with the type attribute as you was suggesting:
 
 $a : Map()
 $b : Map()
 eval( ... )
 
 The number of partial matches will be: p(|A|,|B|) = (|A|+|B|)! / 
 (|A|+|B|-2)!

Ah yes okay, I see what you mean.
Well, the current situation for me is that I have to do exactly that.
As it is typical for Clojure apps to store data in Maps I need support
for that. So, I want to allow rules like:

(map-rule Rule name, type
   (when
 Customer ( $cust-id id )
 DailyOrders (= 1 (get count $cust-id)))
   (then
 (println match)))

This is semantically exactly the same as in your example, where Customer
and DailyOrders were POJOs, while they are for me Maps.


 Draw the graph for these two functions and you will get the picture. If 
 you have more than 2 patterns, situation gets worst and worst.
 
 If instead of eval() you use some alpha constraints, things go down to 
 the same level as using different classes:
 
 $a : Map( this[type] == A )
 $b : Map( this[type] == B )
 
 The above will result in the same p(|A|,|B|) = |A| * |B| partial matches.

Hmm, but the MVEL syntax can not magically eliminate the eval. Under the
hood the map accesses will still be inside an eval. Marc confirmed that
a few days ago.
MVEL only hides this from the user. This is what I will also do.
But under the hood it will become

   $a:Map()
   $b:Map()
   eval( $a.get(type) == Customer )
   eval( $b.get(type) == DailyOrders )


And the only reason why I need to do it this way is because in its
current version Drools does not support Maps as 1st class objects.
If it would, then the eval would not be needed anymore.
So, for Clojure users (and basically everyone else who stores data
inside Maps, for whatever the reasons may be) it would be so good to
have that support.

You gave a perfect explanation of why this would be a great addition.

The actual rule syntax is not important for me. My lib will hide it,
as MVEL already does now.
But my lib will compile the rules into the fast native rule language.
It won't be interpreted or any slower than hand written rules.
But currently I am forced to produce this cross product, as there is
no direct support for Maps yet.



 2009/8/19 André Thieme address.good.until.2009.dec...@justmail.de 
 mailto:address.good.until.2009.dec...@justmail.de
 
 Edson Tirelli schrieb:
  
   I will skip the first half of your e-mail as I am not sure
 what were
   the reasons for your nit-picking. If my explanation was not
 helpful for
   the public it was intended to, you are welcome to explain yourself.
 
 Oh, I did not intend it to sound like nit-picking. I only meant that
 with a specialized syntax one can make rules operating on Maps looking
 basically identical to the ones operating on POJOs.
 
 
   Regarding the part that matters, i.e., adding the support to
 other
   fact types, Drools is prepared to support them in the LHS. Let me
   explain by example:
  
   when
   $c : Customer( name == bob )
   then
  
  For the reasoning algorithm, does not matter if Customer is a
 POJO,
   an XML document, a Map with the type attribute set to Customer as
   you mentioned, or whatever you can think. We use a set of interfaces
   that allows us to completely abstract that and we even supported 2
   different fact types as a proof of concept in the past.
 
 That sounds good!
 So, in principle having Maps support in the LHS is not a big challenge?
 As I understand it, code inside an eval can not be cached and needs to
 get executed every time and results in less performant code.
 
 
  The only reason we did not support multiple fact types yet for
 Drools
   is the RHS. Our reasoning is that does not make sense to abstract the
   LHS if you don't do the same

Re: [rules-users] Drools and Clojure

2009-08-20 Thread André Thieme
Mark Proctor schrieb:
 
 André Thieme wrote:
 Mark Proctor schrieb:
   
 Map( this['c'] == 206 )

 That should work, we do support MVEL syntax for maps and arrays - we 
 just don't suppor method calls, yet.
 
 Hello Mark. I just tested it and it indeed works for me.
 Although as I understand it, this will be compiled into an expression
 using eval (or it will even be only interpreted).
 So, if that is true it can't bring any performance advantage.
   
 yes, no performance benefit. As this form of use is a return value 
 really, it should be possible to index (if we assume that nest objects 
 do not change). Although it's a fair bit of work to do this, but 
 interesting work - if anyone wants to help out :)

It would be fantastic if there was the same optimization support for
Maps available as it exists for POJOs. Edson gave a great explanation
on how things slow down for cross products.

I thought about one thing:
Could there could maybe be a new attribute, immutable true or
something like that, which would signal that the rule writer promises
the engine that only immutable objects are used?
That way my lib could implicitly always set that attribute.


 The syntax is nothing I worry about. In Clojure, which is a Lisp, I have
 macros and can remove any obstacles in the syntax I like. It is trivial
 to develop new domain specific languages for rules. So, my rule syntax
 for Clojure will look very lispy, and each user is free to change and
 extend it. I will also allow the RHS to be written in Clojure code, no
 Java needed.
   
 Btw if you are doing lispy stuff:
 http://blog.athico.com/2008/02/drools-clips.html
 http://blog.athico.com/2008/06/drools-clips-progress.html

Ah yes, very interesting.
In principle it is very similar what I do.
With Clojure there is a full featured Lisp on the JVM.
What I do is adding some functions and macros, easy to use, which will
do all the Drools managing and hide it from the user.
It will be simple to add all kinds of syntaxes as soon I am done.
You can have the Jess syntax. Just write a macro and expand it into
mine. It will result in compiled rules code.
So, in some days (when I have time) the project above will be
finished ;-)


 see Null-Safe Bean Navigation
 http://mvel.codehaus.org/MVEL+2.0+Property+Navigation

Ah of course, I forgot the null. And MVEL already has the check built
in.
I think I will also implicitly add it.


 And another interesting thing I noticed:
 to both rules I added the line
 global String s;
 and in the LHS's of both rules I removed the c and put s at its place.
 Then the first thing I did after creating a session was to
 (.setGlobal session s c)

 The rule 1 accepted this change. I can use s instead of c. But there
 is still the limitation that I can only insert Maps into the session
 which do have the String c as key. Otherwise: NPE.
 The rule 2 (mvel) however does not accept s as a placeholder. I get:
 Exception executing predicate this[s] == 206
 [Thrown class org.drools.RuntimeDroolsException]

 Any ideas how to get rid of the NPE?
   
 We'll have to look into this, probably a bug.

Edson confirmed that this is an MVEL problem.
In a different thread KDR may have discovered another one.


André
-- 
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org/
___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


Re: [rules-users] Maps in Drools

2009-08-20 Thread André Thieme
Mark Proctor schrieb:
   André Thieme wrote:
 Edson Tirelli schrieb:
   
ooops... correct version:

 when
Map( this[type] == Point, $x : this[x] )
Map( this[type] == Circle, this[x] == $x )
 then
 end
 
   
 We default to MVEL, because it's simple and already contains everything 
 we need for expression evaluation. However it would definitely be 
 possible to implement this natively, effectively emulating MVEL - 
 although you need to think what this actual buys? It doesn't buy 
 indexing, as it's not MVEL that is the problem here.

Ah okay, I didn't know that you are now defaulting to MVEL. Pretty much
all the examples I found online and in the books don't use MVEL.

You asked about what it buys: maybe nothing.
I am very new to Drools and still need more experience. But now at least
I *think* that MVEL rules run slower. I read on the official website
that MVEL gets interpreted at runtime.
Some days ago Greg did a little test:
http://www.mail-archive.com/rules-users@lists.jboss.org/msg09839.html

Right now it seems that Drools used from within Clojure would perform
not too well in real world examples, because complex rules will have to
look at 3-5 Maps. That would mean, as Edson explained, a cross product
of all maps, which will reduce performance.
If I don't use mvel I will manually say:

$m1:Map()
$m2:Map()
$m3:Map()
$m4:Map()
eval ( $m1.get ...)
eval ( $m2.get ...)

and so on.
In MVEL syntax it *looks* nicer, because I can make constraints directly
by using the this keyword. But as MVEL is nothing but syntactic sugar
over the real thing it will need to do the same when the program is running.
On top of that, MVEL will be interpreted, thus resulting in even slower
execution, although the rules will look more nicely.


Now while I write this I just got a new thought:
when the Drools engine is fed with the rules, it will also have to
compile them, or interpret them at at runtime.
I take a string s and do a s.getBytes(utf-8) and have this as an
argument to ResourceFactory.newByteArrayResource.
This is how I get rules into the Drools engine. It works.
But now my new thought: shouldn't I be able to create new rules by
purely writing Java code?

If that were possible, then I would not compile my Clojure code into
a string of either MVEL dialect or non-MVEL, but instead compile it to
code which will do everything that would have happened if I had used
a user readable string.
Yeah, now that I think about it, then *this* is the right way how I
should do it.
That way I can do anything that Drools allows and not depend on any
dialect. And my code would be compiled into byte code at runtime. No
interpretation at all. Cool :)

Now that I think about it: you could even trivially get a new dialect
then with my library. dialect Lisp could be the attribute. That one
would be as easy as mvel, but lispish (= more parens), but it would run
at max speed, because it could be compiled directly into byte code.
And it would be trivial to have a domain specific language with that.

Could you please give me a start for a trivial example?

rule points
  when
   Point( x == 0 )
  then
   System.out.println(foobar);
end

where Point would be a
public class Point {
   private int x;
   private int y;
}
plus two getters and a constructor.

The rule points. If you would not have this as a file on disk or as a
string in ram, but would want to add it with pure Java code, how would
you then do it?


André
-- 
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org/
___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


Re: [rules-users] Maps in Drools

2009-08-19 Thread André Thieme
Edson Tirelli schrieb:
 
 On the general issue, is it received wisdom that it's better not to insert
 map objects direct, at least for now until map support is fully there - or
 is it 6 of one / half a dozen?
 
Maps are data structures, not Domain entities.

When we speak about equivalence in the mathematical sense then this
statement is not true, as you say yourself:

 Using maps as domain entities is possible,

Exactly.
Instead of a class Point with the fields x and y we could have a Map
with the three slots x, y and type, where the makePoint method
would always return a Map whose type key always is set to Point.

In Clojure this is an idiom. (Clojure is a language which compiles to
Java Byte code and is fully compatible to the rest of Java.)


  but usually makes your rules unreadable.

You are so deeply trained to think in Java that you forget the
possibility of other syntaxes, in which it is perfectly readable.

  That is  why it is bad to use any data structures or simple numbers,
  strings, dates as isolated facts...
  they don't have a well known business  semantic in a given
  business model (not to mention how they get mixed
 with each other and cause cross products, etc). A rule like the 
 following has no explicit meaning:
 
when
$str: String()
$m: Map( this[$str] == 1 )
then
 
 But when you write something like:
 
 when
Customer( $custId : id )
DailyOrders( count[$custId] == 1 )
 then
 
 Things are clear just by looking at them, even if $custId is a 
 String and count is a Map as in the original example.

But now think about how this could be in Clojure.
We would have a macro map-rule which tells Drools that we are using
exclusively maps, and it may look like:
(map-rule Rule name, type
   (when
 Customer ( $cust-id id )
 DailyOrders (= 1 (get count $cust-id)))
   (then
 (println match)))

The first argument is here type and tells the macro, that all maps do
have a key type. It now dispatches to those. In the when part we first
look at all Maps of type Customer.
They may look like:
{id 4,  name Carlos,  type Customer}
{id 1,  name Tina,  type Customer}

Then we look at all Maps of type DailyOrders. Those Maps may look like:
{id 27,
  day java.util.Date Object,
  count {4 abc,  18 xyz},
  type DailyOrders}

get takes the key under which a DailyOrders instance has another Map as
value, and accesses is with the key which is the second value here,
the $cust-id.
The when part looks exactly the same, only that I did not use the
syntactic sugar for accessing maps.

As soon I have enough time in the coming days I will write a Clojure lib
which will make Drools easily usable from within Clojure.
The good thing about that is that rules are not longer strings - they
now become code. And because in Clojure  Code = Data  we will have the
full power of Lisp available, and can write programs that write programs,
such as rules. This easily opens rules to be automatically created via
Genetic Programming, or, if the search space is not too huge, then all
combinations of rules can be generated and tried out, to see which of
those 18000 can solve my domain specific problem best.


Currently the rule I showed above would become a Drools rule like:
rule Rule name
  when
   m1:clojure.lang.APersistentMap()
   m2:clojure.lang.APersistentMap()
   eval( m1.get(type) == Customer )
   eval( m2.get(type) == DailyOrders 
 (m2.get(count)).get(m1.get(id)) == 1 )
  then
   ((clojure.lang.IFn)globalVarWithClojureCode.get(17)).call())
end

This would happen under the hood, and it would not be exposed to the
users of my lib. I did not test this specific example code, and maybe
I got something wrong, but that is the basic idea. Drools can work with
this and does not have the readability problems of humans.
In Clojure we can easily eliminate all readability isseus. I will offer
some few macros for defining rules, and users can simply add others if
they want. They won't have to care about what the underlying real Drools
rules syntax looks like. They only expand their macros into my existing
ones and have automatically optimized code, adopted to their readability
needs in their specific domain.


Now if the Drools Devs find a way how it would be possible to add the
same optimization support for Maps as they currently already exist for
POJOs, then rules acting on Maps could be very fast.
I understand that the call to the method get() itself will be slower,
because a hash value needs to be computed before the lookup can be made,
but I think that lookup will not be the bottleneck.
It would be fantastic if the Drools Devs could make it the bottleneck.
In that case, that Maps would not need to be placed in eval anymore and
become 1st class objects, exactly as POJOs, then get() would be the
slowest part (which is now eval and full execution without caching).

And Clojure Maps are also immutable. Drools can be 

Re: [rules-users] Maps in Drools

2009-08-19 Thread André Thieme
Edson Tirelli schrieb:

 when
Customer( $custId : id )
DailyOrders( count[$custId] == 1 )
 then

Btw, this brings me to a new syntax question for the default Drools rule
syntax. Is this possible:

when
   m:Map()
   eval( m.get(type) == Point, $x : m.get(x) )
   ...
   Circle( x == $x )
then
   ...


or, an alternative which may be clearer:

when
   m:Map()
   eval( m.get(type) == Point )
   $x : m.get(x)
   ...
then
   ...

So, what I would like to have is:
1) looking at all Maps which have the value Point under the key type
2) of all those Maps: store in a var what value they have under key x
3) reuse the var, here $x instead of having an expensive lookup over and
over again.

Is that possible? Or would I have to write my example above as
...
c:Circle()
eval(c.getX() == m.get(x))


André
-- 
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org/
___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


Re: [rules-users] Maps in Drools

2009-08-19 Thread André Thieme
Edson Tirelli schrieb:
 
 I will skip the first half of your e-mail as I am not sure what were 
 the reasons for your nit-picking. If my explanation was not helpful for 
 the public it was intended to, you are welcome to explain yourself.

Oh, I did not intend it to sound like nit-picking. I only meant that
with a specialized syntax one can make rules operating on Maps looking
basically identical to the ones operating on POJOs.


 Regarding the part that matters, i.e., adding the support to other 
 fact types, Drools is prepared to support them in the LHS. Let me 
 explain by example:
 
 when
 $c : Customer( name == bob )
 then
 
For the reasoning algorithm, does not matter if Customer is a POJO, 
 an XML document, a Map with the type attribute set to Customer as 
 you mentioned, or whatever you can think. We use a set of interfaces 
 that allows us to completely abstract that and we even supported 2 
 different fact types as a proof of concept in the past.

That sounds good!
So, in principle having Maps support in the LHS is not a big challenge?
As I understand it, code inside an eval can not be cached and needs to
get executed every time and results in less performant code.


The only reason we did not support multiple fact types yet for Drools 
 is the RHS. Our reasoning is that does not make sense to abstract the 
 LHS if you don't do the same for the RHS. So, for instance, using java 
 dialect:
 
 when
 $c : Person( name == bob )
 then
 $c.setAge( 30 ) ;
 end
 
 If we will support that rule, written as is, for POJOs, and we want 
 to support Maps as facts, then our java parser needs to properly handle 
 the consequence code as $c.put(age, 30). Same thing if Person was an 
 XML document and so on.

 From my perspective the RHS is not important at all for my lib and for
Clojure users who like to work with Drools.
For me mostly one thing is interesting: getting Map lookups out of eval,
so they can profit from exactly the same caching and optimizations that
exist for POJOs.

The RHS will be fully written in Clojure, and all challenges that occur
in it would have to be solved by myself.
If you Drools Devs could make it possible to give support for Maps in
the LHS, then most issues for Clojure users could be solved.


 
 If you want to contribute to the project solving this problem, you 
 are most welcome.

Unfortunately I have not enough Java knowledege and not time.
But I would like to contribute indirectly, by writing a lib for Clojure
users which will make Drools easily accessible to them. It would also
provide other users of Drools with an alternative syntax, which gets
compiled into the default rule language. (Not into mvel, as that seems
to be interpreted and runs a bit slower.)


 Regarding your rule rewrite, the way you propose is not feasible. 
 Using multiple patterns of the same type without proper alpha 
 constraints will lead to combinatorial explosion.

Could you please explain this in a bit more detail?
If Maps as 1st class rule objects, shouldn't my example then be exactly
the same as the one that you gave?

Your example was:

when
   Customer( $custId : id )
   DailyOrders( count[$custId] == 1 )
then ...


My example was:

rule Rule name
   when
 m1:clojure.lang.APersistentMap()
 m2:clojure.lang.APersistentMap()
 eval( m1.get(type) == Customer )
 eval( m2.get(type) == DailyOrders 
  (m2.get(count)).get(m1.get(id)) == 1 )
   then
 ((clojure.lang.IFn)globalVarWithClojureCode.get(17)).call())
end


And with direct Map support it could become something like:

rule Rule name
   MapDefaultKey type
   Salience  2
   when
 Customer( $custId : id )
 DailyOrders( get(count, $custId) == 1 )
   then
 ((clojure.lang.IFn)globalVarWithClojureCode.get(17)).call())
end

Instead of the one could have syntactical sugar which may look
unfamiliar: count[$custId]

If the key is not a string but a float one would even have
88.5[$custId] instead get(88, $custId).
This is just a matter of taste, and users could have their DSLs anyway.


André
-- 
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org/
___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


Re: [rules-users] Drools and Clojure

2009-08-13 Thread André Thieme
Greg Barton schrieb:
 There's no reason why a rete based system couldn't use maps as first
 class objects, but Drools is heavily oriented towards POJOS.  Using
 eval in the way you have is pretty much the way to go.

Thanks for confirming that.
For now I know that I am doing it right by using eval and that this
means that rules for typical Clojure objects will not benefit from some
of the optimizations Drools usually can apply.
Maybe it will change in the future.


 As long as type information is accessible (both for first class types
 and their members) you should be able to have the left hand side of a
 rule (the conditions) be as it is now.

I think that if Maps become 1st class objects there could be a different
Syntax, without using eval.


 If you lobby the devs hard enough and get others on your side you may
 be able to convince them to go in that direction, but I doubt it
 would be possible before version 6 or so, if that early.  (And I'm
 not even sure it's possible.)

At this point it is mostly interesting for me to get Drools working with
Clojure together and concentrate on correctness. The goal is that users
of my lib can use do all typical things people do with Drools without
writing Java code. Everything, including the rules, would be written in
Clojure.
But of course it would be very interesting if the devs could indeed have
Clojure in mind. I don't know how reusable the existing code is, for
using Maps without the need for eval and with having the respective
performance advantages.
I understand that the looup of the value for a given key can not be
optimized away. On my hardware get() is limited to only 1000 calls
per msec and core. Reading a field from a POJO is faster.
If I understand it correctly then the problem with eval is that it
needs to be executed each time, and no clever caching can be done.
So, eliminating that by having Maps being 1st class is what sounds
interesting.
When I refer to Maps and Clojure, then I talk about Maps having only
very few key/value pairs, just like POJOs, and being immutable.
This immutability may even be very helpful for optimization. It is
guaranteed that a given object will never change.

I hope the devs will find it okay if I make some concrete suggestions
in the coming weeks.


Sunny greetings,
André
-- 
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org/
___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


Re: [rules-users] Drools and Clojure

2009-08-13 Thread André Thieme
Mark Proctor schrieb:
 Map( this['c'] == 206 )
 
 That should work, we do support MVEL syntax for maps and arrays - we 
 just don't suppor method calls, yet.

Hello Mark. I just tested it and it indeed works for me.
Although as I understand it, this will be compiled into an expression
using eval (or it will even be only interpreted).
So, if that is true it can't bring any performance advantage.

The syntax is nothing I worry about. In Clojure, which is a Lisp, I have
macros and can remove any obstacles in the syntax I like. It is trivial
to develop new domain specific languages for rules. So, my rule syntax
for Clojure will look very lispy, and each user is free to change and
extend it. I will also allow the RHS to be written in Clojure code, no
Java needed.


But back to your example: I noticed something very interesting:
when I use the MVEL dialect for the Map lookup, then I get no NPE
anymore when I check in a Map which does *not* have the key I test
for.
So, now I have two versions of my rule:

package droolsandclojure;
import java.util.Map;

rule Clojure test 1
   when
m:Map()
eval((Integer)m.get(c) == 206)
   then
System.out.println(Match:  + m);
end

and

package droolsandclojure;
import java.util.Map;

rule Clojure MVEL test 2
  dialect mvel
   when
m:Map( this[c] == 206 )
   then
System.out.println(Match:  + m);
end


Only one of these two rules is used, not both at the same time.
When I use rule 1 then I can not insert Maps into my session which do
not have a key c. If I try it and run my code I get a NPE.

When I use rule 2, the MVEL version, this is different. Now I can
insert any Maps and will not get an exception. The rule will simply
just not execute the RHS.

How can rule 1 be changed so that it will not put a constraint on the
objects which are allowed to go into the session without throwing a NPE?


And another interesting thing I noticed:
to both rules I added the line
global String s;
and in the LHS's of both rules I removed the c and put s at its place.
Then the first thing I did after creating a session was to
(.setGlobal session s c)

The rule 1 accepted this change. I can use s instead of c. But there
is still the limitation that I can only insert Maps into the session
which do have the String c as key. Otherwise: NPE.
The rule 2 (mvel) however does not accept s as a placeholder. I get:
Exception executing predicate this[s] == 206
[Thrown class org.drools.RuntimeDroolsException]

Any ideas how to get rid of the NPE?
-- 
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org/
___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


Re: [rules-users] Drools and Clojure

2009-08-13 Thread André Thieme
With what have you been wrong Greg?
I understood Marks reply in such a way that the mvel dialect allows to
use Maps without eval. But this is just syntactic sugar. When compiled
or interpreted (I don't know which of those Drools will do with mvel
rules), this will get replaced with an eval under the hood.
So, that means that still the optimizations can't be applied.
Maybe the mvel rule is only interpreted, which would make it even slower.

For me it does not matter much which syntax will be my target.
My Clojure lib will allow to write down rules in s-expression
syntax, and it will compile them (compilation is also available at
runtime) into any syntax Drools accepts.
Currently my target is the default syntax - that means I will
produce strings that access Maps with eval.

IF the mvel syntax will result in more performant code because it
makes Drools handle it better without using eval under the hood, then
sure, I can also compile into mvel syntax.
Although with that I still have the little problem to have globals in
place of literals for Map lookups (see my other mail).



Greg Barton schrieb:
 I was wrong. :). See Mark's later email.
 
 GreG
 
 On Aug 13, 2009, at 17:25, André Thieme 
 address.good.until.2009.dec...@justmail.de wrote:
 
 Greg Barton schrieb:
 There's no reason why a rete based system couldn't use maps as first
 class objects, but Drools is heavily oriented towards POJOS.  Using
 eval in the way you have is pretty much the way to go.
 
 Thanks for confirming that.
 For now I know that I am doing it right by using eval and that this
 means that rules for typical Clojure objects will not benefit from some
 of the optimizations Drools usually can apply.
 Maybe it will change in the future.
 
 
 As long as type information is accessible (both for first class types
 and their members) you should be able to have the left hand side of a
 rule (the conditions) be as it is now.
 
 I think that if Maps become 1st class objects there could be a different
 Syntax, without using eval.
 
 
 If you lobby the devs hard enough and get others on your side you may
 be able to convince them to go in that direction, but I doubt it
 would be possible before version 6 or so, if that early.  (And I'm
 not even sure it's possible.)
 
 At this point it is mostly interesting for me to get Drools working with
 Clojure together and concentrate on correctness. The goal is that users
 of my lib can use do all typical things people do with Drools without
 writing Java code. Everything, including the rules, would be written in
 Clojure.
 But of course it would be very interesting if the devs could indeed have
 Clojure in mind. I don't know how reusable the existing code is, for
 using Maps without the need for eval and with having the respective
 performance advantages.
 I understand that the looup of the value for a given key can not be
 optimized away. On my hardware get() is limited to only 1000 calls
 per msec and core. Reading a field from a POJO is faster.
 If I understand it correctly then the problem with eval is that it
 needs to be executed each time, and no clever caching can be done.
 So, eliminating that by having Maps being 1st class is what sounds
 interesting.
 When I refer to Maps and Clojure, then I talk about Maps having only
 very few key/value pairs, just like POJOs, and being immutable.
 This immutability may even be very helpful for optimization. It is
 guaranteed that a given object will never change.
 
 I hope the devs will find it okay if I make some concrete suggestions
 in the coming weeks.
 
 
 Sunny greetings,
 André


-- 
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org/
___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


[rules-users] Drools and Clojure (maps as facts)

2009-07-31 Thread André Thieme
Hello group!

I am a Clojure user and would like to look into using Drools with it.
 From Clojure I can use all Java classes and call all methods. So,
instantiating a KnowledgeBase, KnowledgePackages or a KBFactory is no
problem, and calling the respective methods, to get the system started,
or insert facts into a session, dispose it and fireAllRules is also
fine.

It is just that in Clojure one typically does not use POJOs.
The most typical data structures used are: hashmaps, vectors, structs,
lists, structuremaps and sets (in no particular order).
Those are persistent and concurrency ready Clojure DSs, and btw, also
usable from Java directly.

Now the basic Drools examples I saw all work with POJOs.
They were mostly comparisons of native typed fields in a class.
I however would be interested to compare different qualities of key/
value pairs in a hashmap, or compare structs with each other.
Comparing structuremaps is maybe what comes closest to the POJO examples.
For example, we may have a struct (defstruct person :name :age :type)
and store it's instances in a vector. And we would also insert it into
our Drools session object:
(doseq [p all-persons] (.insert session p))
which would correspond roughly to
for (Person p : allPersons) { session.insert(p); }
Only that person is a map, not a class.
Well, of course it is also an object and under the hood a class, a
java.util.Map even - but I mean that unlike POJOs the key/value pairs
are stored differently (fields in classes are also just key/value pairs).

So, is there a way to insert maps (let it be java.util.HashMaps for
example) and also to reason about them? I won't care if the syntax
for that is complicated. As Clojure is a Lisp I would just write a
little macro and have a very nice and readable syntax (probably a bit
similar to the one of Jess or Lisa).
Instead of looking at all instances of the type Person AND then have
their age compared, I would look at all maps/structs which have a key
:type with the value :person AND then compare the value of their :age
key with a number, such as:
(rule example person rule, matching non-adults
   :when (= :type :person)
 ( :age 18)
   :then
 (println No service for minors.))

In Java terms it would mean that we insert several instances of
java.util.HashMap, all having the k/v pairs for name, age and type.
HashMapString, Object hm = new HashMapString, Object();
hm.put(name, someName);
hm.put(age, someAge);
hm.put(type, person);
session.insert(hm);

Is that in principle possible with Drools 5?


Sunny greetings,
André
-- 
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org/
___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users