Skip to main content

Prolog Incarnation Caveats

Things that commonly trip people up, and how to deal with them.

Writing terms​

Capitalized strings are variables. "likes"("Bob", "alice") is likes(Bob, alice) with Bob a variable. Use lowercase atoms, or Atom.of("Bob"). See the DSL in a nutshell.

Beliefs and goals must be ground. initialBelief, initialGoal, belief { } and goal { } throw IllegalArgumentException (Belief must be ground, ...) if the term contains unbound variables. In a body, make sure every variable was bound by the trigger or the guard (see term builders).

Guards and queries​

Unknown predicates fail silently. The solver is configured to make unknown predicates fail rather than raise an error. A typo in a guard, like satisfies { "ancestr"(A, P) }, just makes the plan never applicable. If a plan never fires, check predicate names and arities first.

Guards use the first solution. satisfies { } and testQuery { } only look at the first solution. To use all of them, collect them explicitly, e.g. with agent.beliefs.allSolutionsOf(query) or a findall/3 query: see use every solution.

No test goals. AgentSpeak's ?g test goals are not available, since plan bodies can query the beliefs directly (see why there are no test goals). Use satisfies { } in guards, or testQuery { } in bodies: see Write guards and inference rules.

Beliefs​

A belief has a single source. Beliefs that differ only in their annotations are the same belief: if Alice and Carol both tell ping(1), the agent keeps a single ping(1) with the first source. Include the information in the belief itself, e.g. ping(1, alice), when several sources matter. See annotations and sources.

Perceptions do not replace beliefs by themselves. A perception handler returns additions and removals. If it only adds on(a, b), the stale on(a, table) stays. Remove the old facts explicitly, selecting them with newContextBeliefQuery { } filters: see Turn perceptions into Prolog facts.

Messaging​

KQML questions need an explicit answer. Without test goals, nothing answers a question automatically (see why). askOneTo puts a replyOne(Q, M)[source(S)] goal in the receiver, and someone must write the plan that answers it (see answer a question). askOneTo returns null only on timeout; check isSuccess on the returned substitution before reading the variables. askAllTo likewise needs a plan for replyAllTo(Q, M)[source(S)] goals.

Performance and platforms​

Every guard queries the whole belief base. Each satisfies call builds a solver whose theory is the current belief base. That is cheap for small belief bases, but it grows with their size: keep bulky data in Kotlin objects (for example in a skill), and keep in beliefs what the agent reasons about.

JVM and JavaScript only. 2P-Kt targets the JVM and JavaScript, so the Prolog incarnation is not available for native targets.