Print

Print


Hey ECJ-Users,

I'm using ECJ in a GP way to create rules. But the complexity of a possible rule is still low. So I want to use ADF to define a condition of the rule and change these conditions between my individuals. 

My old tree was:

gp.fs.0 = ec.gp.GPFunctionSet
gp.fs.0.name = f0
gp.fs.0.size = 13
gp.fs.0.func.0 = rulevolution.nodes.When
gp.fs.0.func.0.nc = nc0
gp.fs.0.func.1 = rulevolution.nodes.Not
gp.fs.0.func.1.nc = nc1
gp.fs.0.func.2 = rulevolution.nodes.And
gp.fs.0.func.2.nc = nc2
gp.fs.0.func.3 = rulevolution.nodes.Faktum
gp.fs.0.func.3.nc = nc6
gp.fs.0.func.4 = rulevolution.nodes.Contains
gp.fs.0.func.4.nc = nc5
gp.fs.0.func.5 = rulevolution.nodes.Exists
gp.fs.0.func.5.nc = nc3
gp.fs.0.func.6 = rulevolution.nodes.Eval
gp.fs.0.func.6.nc = nc4
gp.fs.0.func.7 = rulevolution.nodes.SubAnd
gp.fs.0.func.7.nc = nc7
gp.fs.0.func.8 = rulevolution.nodes.SubOr
gp.fs.0.func.8.nc = nc7
gp.fs.0.func.9 = rulevolution.nodes.SubAnd
gp.fs.0.func.9.nc = nc8
gp.fs.0.func.10 = rulevolution.nodes.SubOr
gp.fs.0.func.10.nc = nc8
gp.fs.0.func.11 = rulevolution.nodes.Eval
gp.fs.0.func.11.nc = nc11
gp.fs.0.func.12 = rulevolution.nodes.When
gp.fs.0.func.12.nc = nc10

which worked, but created too simple rules. Means maximum 2 or 3 conditions in a tree. If I increase the depth, the tree will just increase the subconditions with SubOr and SubAnd, so I thought that the conditions should have a fixed depth of 3 or 4 Nodes and the Tree can also have a depth of 3 or 4 nodes, which could at maximum define 2 ^ 4 = 16 conditions, that would be more than enough. Don't bother with the nc's, they're well defined. 

Now I wanted to add the ADF, which returns a condition:

gp.fs.0 = ec.gp.GPFunctionSet
gp.fs.0.name = f0
gp.fs.0.size = 11
gp.fs.0.func.0 = rulevolution.nodes.When
gp.fs.0.func.0.nc = nc0
gp.fs.0.func.1 = rulevolution.nodes.And
gp.fs.0.func.1.nc = nc2
gp.fs.0.func.2 = rulevolution.nodes.Faktum
gp.fs.0.func.2.nc = nc6
gp.fs.0.func.3 = rulevolution.nodes.Eval
gp.fs.0.func.3.nc = nc4
gp.fs.0.func.4 = rulevolution.nodes.When
gp.fs.0.func.4.nc = nc10
gp.fs.0.func.5 = rulevolution.nodes.SubAnd
gp.fs.0.func.5.nc = nc7
gp.fs.0.func.6 = rulevolution.nodes.SubOr
gp.fs.0.func.6.nc = nc7
gp.fs.0.func.7 = rulevolution.nodes.SubAnd
gp.fs.0.func.7.nc = nc8
gp.fs.0.func.8 = rulevolution.nodes.SubOr
gp.fs.0.func.8.nc = nc8
gp.fs.0.func.9 = ec.gp.ADF
gp.fs.0.func.9.nc = nc1
gp.fs.0.func.9.tree = 1
gp.fs.0.func.9.name = ADF1
gp.fs.0.func.10 = rulevolution.nodes.When
gp.fs.0.func.10.nc = nc10

gp.fs.1 = ec.gp.GPFunctionSet
gp.fs.1.name = f1
gp.fs.1.size = 9
gp.fs.1.func.0 = rulevolution.nodes.Not
gp.fs.1.func.0.nc = nc11
gp.fs.1.func.1 = rulevolution.nodes.Faktum
gp.fs.1.func.1.nc = nc6
gp.fs.1.func.2 = rulevolution.nodes.Contains
gp.fs.1.func.2.nc = nc5
gp.fs.1.func.3 = rulevolution.nodes.Exists
gp.fs.1.func.3.nc = nc3
gp.fs.1.func.4 = rulevolution.nodes.SubAnd
gp.fs.1.func.4.nc = nc7
gp.fs.1.func.5 = rulevolution.nodes.SubOr
gp.fs.1.func.5.nc = nc7
gp.fs.1.func.6 = rulevolution.nodes.SubOr
gp.fs.1.func.6.nc = nc8
gp.fs.1.func.7 = rulevolution.nodes.SubAnd
gp.fs.1.func.7.nc = nc8
gp.fs.1.func.8 = rulevolution.nodes.Exists
gp.fs.1.func.8.nc = nc1

Like you see the node "Not" and "Exists" are only defined in the ADF-Tree, because they're the root of each condition. You can also see that my ADF-Tree has no Eval nodes, because it is not needed in a condition. nc1, nc5 , nc6 and nc10 are the terminals and everything else are non-terminals. 

I don't know why, but the algorithm is resetting the Faktum non-stop. Faktum is simply taking a random method from a parameterized class and putting the conditions into the arguments of the method. Here's the flow of the node:

Do
  check (Method == null or reset == true) -> method = getRandomMethod(m); reset = false //m is a random number
  check (Parameter of Method > Conditions) -> resetNode -> reset = true; m = new random number in range of declaredmethods; increase resets
  Else put conditions into arguments and break;
while resets < 100

check (arguments does not exist) -> remove method and use "true" //true always works in rules, it will be removed from the interpreter
  

I don't know where the infinite loop should come from. But here's a snippet of the threaddump I've created:

"ECJ Evaluation Thread 10" daemon prio=10 tid=0x00002ae1904a3000 nid=0x282 runnable [0x00002ae196c17000]
   java.lang.Thread.State: RUNNABLE
	at sun.reflect.Reflection.getCallerClass(Native Method)
	at java.lang.ClassLoader.getCallerClassLoader(ClassLoader.java:1383)
	at java.lang.Class.getDeclaredMethods(Class.java:1792)
	at rulevolution.nodes.Faktum.getMethod(Faktum.java:63)
	at rulevolution.nodes.Faktum.eval(Faktum.java:81)
	at rulevolution.nodes.SubOr.eval(SubOr.java:36)
	at rulevolution.nodes.SubAnd.eval(SubAnd.java:38)
	at rulevolution.nodes.Eval.eval(Eval.java:35)
	at rulevolution.nodes.When.eval(When.java:36)
	at rulevolution.RuleProblem.evaluate(RuleProblem.java:178)
	at ec.simple.SimpleEvaluator.evalPopChunk(SimpleEvaluator.java:259)
	at ec.simple.SimpleEvaluator$SimpleEvaluatorThreadCG.run(SimpleEvaluator.java:341)
	at ec.util.ThreadPool$PoolThread.run(ThreadPool.java:57)

   Locked ownable synchronizers:
	- None

"ECJ Evaluation Thread 9" daemon prio=10 tid=0x00002ae190a66000 nid=0x281 in Object.wait() [0x00002ae196b16000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000000975097b8> (a [Ljava.lang.Object;)
	at java.lang.Object.wait(Object.java:485)
	at ec.util.ThreadPool$PoolThread.run(ThreadPool.java:51)
	- locked <0x00000000975097b8> (a [Ljava.lang.Object;)

   Locked ownable synchronizers:
	- None

"ECJ Evaluation Thread 8" daemon prio=10 tid=0x00002ae19037c800 nid=0x280 runnable [0x00002ae196a15000]
   java.lang.Thread.State: RUNNABLE
	at sun.reflect.Reflection.getCallerClass(Native Method)
	at java.lang.ClassLoader.getCallerClassLoader(ClassLoader.java:1383)
	at java.lang.Class.getDeclaredMethods(Class.java:1792)
	at rulevolution.nodes.Faktum.resetNode(Faktum.java:233)
	at rulevolution.nodes.Faktum.eval(Faktum.java:88)
	at rulevolution.nodes.Eval.eval(Eval.java:35)
	at rulevolution.nodes.When.eval(When.java:36)
	at rulevolution.RuleProblem.evaluate(RuleProblem.java:178)
	at ec.simple.SimpleEvaluator.evalPopChunk(SimpleEvaluator.java:259)
	at ec.simple.SimpleEvaluator$SimpleEvaluatorThreadCG.run(SimpleEvaluator.java:341)
	at ec.util.ThreadPool$PoolThread.run(ThreadPool.java:57)

   Locked ownable synchronizers:
	- None

Does someone got an idea where the infinite loop comes from?

Thanks and greetings

Bojan