Skip to main content

Prolog Incarnation Reference

Everything provided by jakta-prolog-incarnation, where beliefs are 2P-Kt clauses and goals are 2P-Kt terms. For an introduction see Incarnations.

Types​

TypePackageMeaning
PrologBeliefit.​unibo.​jakta.​dsl.​beliefAlias of 2P-Kt Rule: a fact (Fact) or an inference rule.
PrologGoalit.​unibo.​jakta.​dsl.​goalAlias of 2P-Kt Struct.
JaktaLogicProgrammingScopeit.​unibo.​jakta.​logicThe 2P-Kt logic programming DSL (variables A..Z, operators, impliedBy, standard library, ...). All the builder blocks below run in it.
MutableSubstitutionPlanContextit.​unibo.​jakta.​logicThe context of Prolog plans: a substitution that guards and bodies can extend with +=.

Prolog plans​

hasPlanLibrary {
prologPlan {
adding.goal { matchingGoal { "greet"(X) } } triggers { agent.print("Hello ", X) }
}
}

prologPlan { } (import it.unibo.jakta.logic.JaktaLogicProgrammingScope.Companion.prologPlan) opens a JaktaLogicProgrammingScope inside a plan library, so that the triggers, guards and bodies of the plans it contains share the same logic variables. Each prologPlan has its own scope: X in two different prologPlan blocks are different variables. A single block can contain several plans.

Beliefs​

Package it.unibo.jakta.dsl.belief.

FunctionWhereMeaning
initialBelief { struct }anywhereA fact. Must be ground.
inferenceRule { head impliedBy body }anywhereAn inference rule.
belief { struct }plan bodiesA fact with the current substitution applied. Must be ground after substitution.
beliefQuery { struct }plan bodiesA query (may contain variables) with the current substitution applied.
newContextBeliefQuery { struct }anywhereA query built in a fresh scope.
noSubstitutionBeliefQuery { struct }inside a logic scopeA query built in the current scope, without applying substitutions.
PrologBelief.​matchingBelief { query }belief triggersUnifies the belief with query, annotations included (see Annotations); returns the context or null.
PrologBelief.​matchBelief(​query)anywhereAs matchingBelief, with an already-built query.
believes {
+initialBelief { "parent"("alice", "bob") }
+initialBelief { "parent"("alice", "carol") }
+inferenceRule { "sibling"(X, Y) impliedBy ("parent"(Z, X) and "parent"(Z, Y) and (X neq Y)) }
}

Goals​

Package it.unibo.jakta.dsl.goal.

FunctionWhereMeaning
initialGoal { struct }anywhereA goal. Must be ground.
goal { struct }plan bodiesA goal with the current substitution applied. Must be ground after substitution.
goalQuery { struct }inside a logic scopeA goal query (may contain variables).
PrologGoal.​matchingGoal { query }goal triggersUnifies the goal with query, annotations included (see Annotations); returns the context or null.
replyOne(​query,​ messageId = _)triggersThe goal added by an incoming askOne, see KQML.
replyAllTo(​query,​ messageId = _)triggersThe goal added by an incoming askAll, see KQML.

Goals and beliefs must be predicates: a Struct whose functor is not a Prolog control construct (,, ;, :-, ...). An atom such as Atom.of("start") or "start".toAtom() is a valid goal.

Guards and queries​

FunctionPackageWhereMeaning
satisfies { query }it.​unibo.​jakta.​dsl.​planguardsSolves query against the belief base (facts and rules) with the current substitution applied. On success merges the solution into the context and returns it, otherwise returns null.
testQuery { query }it.​unibo.​jakta.​dsl.​planplan bodiesAs satisfies, but throws (failing the plan) if the query has no solution.
Collection<​Rule>​.​unifiesWith(​query)it.​unibo.​jakta.​logicanywhereSolves query on a collection of clauses, e.g. agent.​beliefs; returns the first 2P-Kt Solution.
Collection<​Rule>​.​allSolutionsOf(​query)it.​unibo.​jakta.​logicanywhereReturns all the solutions of query.
Struct.​annotatedMguWith(​query)it.​unibo.​jakta.​logicanywhereMost general unifier taking annotations into account.

Queries are solved by a Prolog solver in which unknown predicates fail.

prologPlan {
adding.goal {
matchingGoal { "introduce"(X) }
} onlyWhen {
satisfies { "sibling"(X, Y) }
} triggers {
agent.print(X, " is the sibling of ", Y)
testQuery { "parent"(P, X) }
agent.print(X, " is the child of ", P)
}
}

Reading variables​

FunctionPackageMeaning
Var.​value<​T>​(​)it.​unibo.​jaktaThe Kotlin value bound to the variable in the current context. Throws if the variable is not bound or cannot be converted.
MutableAgentState.​print(​vararg parts)it.​unibo.​jaktaPrints the concatenation of parts, replacing each variable with its value.

value<T>() converts Prolog terms to Kotlin values: integers to Int, Long, Double, ...; reals to Double, Float, ...; atoms to String; lists to List<T> or Set<T> (recursively); tuples and two-element lists to Pair<A, B>; true/false to Boolean. Asking for a 2P-Kt type (e.g. Term, Struct) returns the term itself.

prologPlan {
adding.goal {
matchingGoal { "sum"(L) }
} triggers {
val numbers: List<Int> = L.value()
agent.print("The sum of ", L, " is ", numbers.sum())
}
}

Annotations​

Package it.unibo.jakta.

ElementMeaning
term[annotation,​ .​.​.​]Annotates a term, e.g. "ping"(​1)[source(​X)]. Import it.​unibo.​jakta.​get.
term.​tag(​annotation,​ .​.​.​)Same as [.​.​.​], as a function.
source(​agentId), source(​"name"), source(​term)The source(​.​.​.​) annotation. source(​agentId) uses the id's toString(​), i.e. its UUID for a BaseAgentID.
selfThe atom self.

Matching semantics, the same for beliefs (matchingBelief, satisfies, testQuery) and goals (matchingGoal), as in Jason. A belief or goal without annotations is treated as annotated with [source(self)]. Then every annotation of the query must unify with a distinct annotation of the belief or goal, so a query without annotations matches whatever the source.

So matchingBelief { "ping"(N) } matches both the agent's own beliefs and those told by others, matchingBelief { "ping"(N)[source(self)] } only the agent's own, and matchingBelief { "ping"(N)[source(S)] } both, binding S to the sender or to self. Goals delegated with delegateAchieveTo work the same way.

Beliefs that differ only in their annotations are the same belief: an agent cannot hold ping(1)[source(alice)] and ping(1)[source(carol)] at once.

KQML​

Package it.unibo.jakta.kqml. Sending requires a MessagingSkill in scope; receiving requires delegating message handling to handleKQMLPayload:

handlesMessageEvents {
when (val payload = it.payload) {
is KQMLPayload -> handleKQMLPayload(payload, it.sender)
else -> null
}
}

Performatives​

SenderPayloadReceiver update
agent.​tellTo(​receiver,​ vararg beliefs)Tell(​beliefs)Adds each belief, annotated with [source(​sender)]. Beliefs must be ground facts.
agent.​broadcastTell(​vararg beliefs)TellAs above, for every other agent.
agent.​untellTo(​receiver,​ query)Untell(​query)Removes the beliefs matching query[source(​sender)], i.e. only those told by the sender.
agent.​broadcastUntell(​query)UntellAs above, for every other agent.
agent.​delegateAchieveTo(​receiver,​ goal)Achieve(​goal)Adds the goal goal[source(​sender)]. The goal must be ground.
agent.​broadcastAchieve(​goal)AchieveAs above, for every other agent.
agent.​sendUnachieveTo(​receiver,​ query)Unachieve(​query)Removes the goal query[source(​sender)], triggering removing.​goal plans. It does not stop intentions already pursuing it.
agent.​broadcastUnachieve(​query)UnachieveAs above, for every other agent.
agent.​askOneTo(​receiver,​ query,​ timeout = null)AskOne(​query)Adds the goal replyOne(​query,​ id)[source(​sender)].
agent.​askAllTo(​receiver,​ query,​ timeout = null)AskAll(​query)Adds the goal replyAllTo(​query,​ id)[source(​sender)].
agent.​tellTo(​receiver,​ replyingTo,​ vararg beliefs)Tell(​beliefs,​ replyingTo)A tell that answers the question with id replyingTo.

Every payload has a unique id.

Asking and replying​

askOneTo is a suspend function that must be called in a Prolog plan body:

  1. it sends AskOne(query) and suspends until a Tell replying to that question arrives from receiver, or until timeout expires;
  2. it returns null on timeout; otherwise it unifies the first told belief with query, merges the result into the plan context (so the query variables become bound) and returns the substitution — which is a failed substitution if the reply does not unify with the query.

Questions are not answered automatically: the receiver must have a plan for replyOne goals, which answers with the question id. BaseAgentID(id = S.value()) rebuilds the sender's identifier from the source annotation, since source(agentId) stores the id's UUID. See Ask and answer with KQML for the asking and answering plans.

askAllTo works the same way with a replyAllTo(Q, M)[source(S)] goal, which the receiver answers with a single tellTo(sender, questionId, ...) carrying every solution: it returns the list of successful substitutions of query against the told beliefs, or null on timeout. It does not bind the query variables in the plan context.