Re: [rules-users] Maps in Drools

2009-08-21 Thread Edson Tirelli
   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.

In other words:

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

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.

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

[]s
Edson

2009/8/20 André Thieme address.good.until.2009.dec...@justmail.de

 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




-- 
 Edson Tirelli
 JBoss Drools Core Development
 JBoss by Red Hat @ www.jboss.com
___
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 Edson Tirelli
2009/8/20 André Thieme 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.

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.


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. There are 2 types of eval(). Inline eval() and top level eval().
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.

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 ) )

  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
combinaions possible between all maps as above, it will first find all
Customer maps and all DailyOrders maps and only after that will make a join
between them. So you get Customers * DailyOrders partial matches. The above
evals are semantically equivalent as:

$a:Map( this[ type ] == Customer )
$b:Map( this[ type ] == DailyOrders )


 But currently I am forced to produce this cross product, as there is no
direct support for Maps yet.

I hope that by the above you see that the problem of the cross products is
not a problem with Maps support, but rather a question of how to write
better rules. The same way you can write 2 completely different SQL queries
that return the same result but one is fast and the other is completely
heavy and slow, you can also write good rules and really bad rules.

   []s
   Edson
___
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 for 

Re: [rules-users] Maps in Drools

2009-08-20 Thread Mark Proctor

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.


Mark

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é
  


___
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 KDR

Thanks again Edson. I'd just used a String object to try a simple test but of
course your example makes a lot more sense. And thanks also for clarifying
that there's full syntax support in the latest mvel jar version.

I know this is a Drools rather Java list but as I'm new to both, may I ask
further how to install that new jar version you mentioned into my current
Eclipse Drools project, or indeed how to get new Drools projects in Eclipse
to use it please, instead of the old version? I've tried copying the jar
into the Drools runtime folder but it doesn't work?

Cheers


Edson Tirelli-3 wrote:
 
 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. Using maps as domain
 entities is possible, but usually makes your rules unreadable. 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.
 
 Regarding the bug, it was a regression that was fixed. All the syntax
 support we intended to have for them is in Drools. Not sure what you mean
 by
 support is fully there.
 
 Hope it helps.
 
 []s
 Edson
 
-- 
View this message in context: 
http://www.nabble.com/Maps-in-Drools-tp25031348p25045607.html
Sent from the drools - user mailing list archive at Nabble.com.

___
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 Edson Tirelli
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.

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.

   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.

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

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.

[]s
Edson


2009/8/19 André Thieme address.good.until.2009.dec...@justmail.de

 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 

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] Maps in Drools

2009-08-19 Thread Edson Tirelli
   ooops... correct version:

when
   Map( this[type] == Point, $x : this[x] )
   Map( this[type] == Circle, this[x] == $x )
then
end


2009/8/19 Edson Tirelli tire...@post.com


 when
Map( this[type] == Point, $x : this[x] )
Map( this[type] == Circle, x == $x )
 then
 end


 2009/8/19 André Thieme address.good.until.2009.dec...@justmail.de

 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




 --
  Edson Tirelli
  JBoss Drools Core Development
  JBoss by Red Hat @ www.jboss.com




-- 
 Edson Tirelli
 JBoss Drools Core Development
 JBoss by Red Hat @ www.jboss.com
___
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-18 Thread Edson Tirelli
   Yes, that was a bug that was fixed in newer versions of MVEL. Just update
your MVEL jar to 2.0.12.

   []s
   Edson

2009/8/18 André Thieme address.good.until.2009.dec...@justmail.de

 KDR schrieb:
  Hi, I'm relatively new to both Java and Drools. I'm trying to figure out
 how
  to use maps in Drools. I've looked at the thread
  http://www.mail-archive.com/rules-users@lists.jboss.org/msg09802.html
 
 From what I've read generally it seems best to insert objects directly
  rather than use nested accessors. So I've been experimenting with trying
 to
  insert a map and then checking stuff in it.
 
  I set up a simple test map of String to Integer, with just a as key and
 1
  as value, and b with 2.
  MapString, Integer map = new HashMapString, Integer();
  map.put(a, 1);
  map.put(b, 2);
  String a = a;
 
  I then inserted the map and also inserted the String a of value a.
 
  Here's the test rule, with various things I tried commented out:
 
  rule testing maps
dialect mvel
when
$str: String()
// $m: Map( this[$str] == 1 ) # error
// $m: Map( this.$str == 1 )   # error
// $m: Map( this[$str] == 1 ) # compiles but rule won't
 fire
$m: Map( this[a] == 1 ) # this works however!
then
System.out.println($m[$str]); #also works with String and
 Map objects  no
  conditions
  end
 
  It obviously doesn't like it when I try to use the String object as the
 key
  for the map. But it works when I use a String literal as the key. What am
 I
  doing wrong?
 
  Does anyone have any suggestions please, or shall I give up and either
 use
  eval as mentioned in
  http://www.mail-archive.com/rules-users@lists.jboss.org/msg09716.html or
 use
  the map as a field of another object which I insert instead of the map
 (in
  fact that was my original plan!)?

 In exactly this thread Marc answered to that problem.
 http://www.mail-archive.com/rules-users@lists.jboss.org/msg09837.html

 His first idea is that this is a bug in the mvel dialect.
 I tried exactly that. I had a global var and put the string a into it.
 Then I wanted to check if Map( this[myVar] == 1 ) but this didn't work.


  I'd also need to test for null i.e. whether a key/value pair exists for a
  given String as the key.

 This seems to be only true when you go the route that I go, namely using
 the default rule syntax, i.e., eval.


 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




-- 
 Edson Tirelli
 JBoss Drools Core Development
 JBoss by Red Hat @ www.jboss.com
___
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-18 Thread KDR

Apologies, I should have given the error message I get with $m: Map(
this[$str] == 1 ) and also with $m: Map( this.$str == 1 ) -
org.drools.RuntimeDroolsException: Exception executing predicate this[$str]
== 1
and lots more lines followed by -
Caused by: [Error: unable to resolve method: java.util.HashMap.$str()
[arglength=0]]


KDR wrote:
 
 Hi, I'm relatively new to both Java and Drools. I'm trying to figure out
 how to use maps in Drools. I've looked at the thread
 http://www.mail-archive.com/rules-users@lists.jboss.org/msg09802.html
 
 From what I've read generally it seems best to insert objects directly
 rather than use nested accessors. So I've been experimenting with trying
 to insert a map and then checking stuff in it.
 
 I set up a simple test map of String to Integer, with just a as key and
 1 as value, and b with 2.
 MapString, Integer map = new HashMapString, Integer();
 map.put(a, 1);
 map.put(b, 2);
 String a = a;
   
 I then inserted the map and also inserted the String a of value a.
 
 Here's the test rule, with various things I tried commented out:
 
 rule testing maps
   dialect mvel
   when
   $str: String()
   // $m: Map( this[$str] == 1 ) # error
   // $m: Map( this.$str == 1 )   # error
   // $m: Map( this[$str] == 1 ) # compiles but rule won't fire
   $m: Map( this[a] == 1 ) # this works however!
   then
   System.out.println($m[$str]); #also works with String and Map 
 objects 
 no conditions
 end
 
 It obviously doesn't like it when I try to use the String object as the
 key for the map. But it works when I use a String literal as the key. What
 am I doing wrong?
 
 Does anyone have any suggestions please, or shall I give up and either use
 eval as mentioned in
 http://www.mail-archive.com/rules-users@lists.jboss.org/msg09716.html or
 use the map as a field of another object which I insert instead of the map
 (in fact that was my original plan!)?
 
 I'd also need to test for null i.e. whether a key/value pair exists for a
 given String as the key.
 
 Any thoughts would be very much appreciated.
 
 Many thanks in advance.
 

-- 
View this message in context: 
http://www.nabble.com/Maps-in-Drools-tp25031348p25031731.html
Sent from the drools - user mailing list archive at Nabble.com.

___
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-18 Thread KDR

Many thanks for your replies André and Edson. For some reason they hadn't
shown up on my computer before I posted my follow up info.

I'll download the updated jar and cross my fingers! 

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?

André on your point below:

André Thieme-4 wrote:
 
 KDR schrieb:
 I'd also need to test for null i.e. whether a key/value pair exists for a
 given String as the key.
 
 This seems to be only true when you go the route that I go, namely using
 the default rule syntax, i.e., eval.
 

- I don't think I quite follow? If I need to check whether the key/value
pair exists for a particular String key i.e. whether the get(key) returns
null, is the only way to do that currently by using the eval?

Cheers and thanks again for the help.
-- 
View this message in context: 
http://www.nabble.com/Maps-in-Drools-tp25031348p25034293.html
Sent from the drools - user mailing list archive at Nabble.com.


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