Skip to content

Instantly share code, notes, and snippets.

@dacr
Last active October 6, 2024 10:54
Show Gist options
  • Save dacr/55b8f8d90570ac6546413734d552a418 to your computer and use it in GitHub Desktop.
Save dacr/55b8f8d90570ac6546413734d552a418 to your computer and use it in GitHub Desktop.
Simple drools backward chaining example. / published by https://github.com/dacr/code-examples-manager #5b2fc2f1-e0f3-4960-b729-7d15200e2688/263a0b165c3f48c5180913f49746a2cf55ff9bf2
// summary : Simple drools backward chaining example.
// keywords : scala, drools, mvel, scalatest, ai, @testable
// publish : gist
// authors : David Crosson
// license : Apache NON-AI License Version 2.0 (https://raw.githubusercontent.com/non-ai-licenses/non-ai-licenses/main/NON-AI-APACHE2)
// id : 5b2fc2f1-e0f3-4960-b729-7d15200e2688
// execution : scala ammonite script (http://ammonite.io/) - run as follow 'amm scriptname.sc'
// created-on : 2018-09-12T21:11:39+02:00
// managed-by : https://github.com/dacr/code-examples-manager
// run-with : scala-cli $file
// ---------------------
//> using scala "3.5.1"
//> using dep "fr.janalyse::drools-scripting:1.2.0"
//> using dep "org.scalatest::scalatest:3.2.19"
// ---------------------
import fr.janalyse.droolscripting.*, org.scalatest.*, flatspec.*, matchers.*, OptionValues.*
import scala.jdk.CollectionConverters.*
import org.kie.api.runtime.rule.Variable
import DroolsEngineConfig.*
object SimpleDroolsBackwardChainingTest extends AnyFlatSpec with should.Matchers {
override val suiteName = "SimpleDroolsBackwardChainingTest"
"drools" should "be able to achieve backward chaining" in {
val drl =
"""package testdrools
|
|
|declare Someone
| name: String
| age: int
|end
|
|declare ParentOf
| child: Someone
| parent: Someone
|end
|
|rule "init"
|when
|then
| Someone a = new Someone("john", 12);
| Someone b = new Someone("sarah", 50);
| Someone c = new Someone("mickael", 60);
| ParentOf rab = new ParentOf(a, b);
| ParentOf rbc = new ParentOf(b, c);
| insert(a);
| insert(b);
| insert(c);
| insert(rab);
| insert(rbc);
|end
|
|query "adult"
| person:Someone(age>=18)
|end
|
|query inParented(Someone x, Someone y)
| ParentOf(x,y;) // ; is mandatory here
| or
| ( ParentOf(z,y;) and ?inParented(x, z;) )
|end
|
|""".stripMargin
val engine = DroolsEngine(drl, configWithIdentity)
engine.fireAllRules()
val r = engine.session.getQueryResults("adult")
r.size() shouldBe 2
val people = engine.getModelInstances("testdrools.Someone")
people.size shouldBe 3
val peopleByName =
people
.groupBy(p => engine.getModelInstanceAttribute(p, "name").value)
.view
.mapValues(_.head)
.collect{case (name:String, someone:Object) => name -> someone}
.toMap
val john = peopleByName.get("john").value
val sarah = peopleByName.get("sarah").value
val mickael = peopleByName.get("mickael").value
// First check if we can find undirect parent relationship
val r2 = engine.session.getQueryResults("inParented", john, mickael)
r2.size shouldBe 1
info(r2.getIdentifiers.mkString(","))
info(r2.asScala.head.get("x").toString)
// it has returned both x and y
// now let's try again to see who has families using unification
val r3 = engine.session.getQueryResults("inParented", Variable.v, mickael)
r3.size shouldBe 2
r3.asScala.map(_.get("x")) should contain allOf(john, sarah)
// So john AND sarah are in parented of mickael
}
}
SimpleDroolsBackwardChainingTest.execute()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment