diff --git a/README.md b/README.md index 425f587..802c40d 100644 --- a/README.md +++ b/README.md @@ -482,6 +482,51 @@ Finally, we run 50 iterations of the scenario: environment.run(50) ``` +## Belief Revision +By default, JS-son agents get their belief update from the environment and revise their existing +beliefs as follows: + +```JavaScript +beliefs = { + ...oldBeliefs, + ...newBeliefs +} +``` +Here, ``oldBeliefs`` are the agent's existing beliefs, whereas ``newBeliefs`` are the belief updates the agent receives; *i.e.*, the agent always accepts the belief update. +However, JS-son supports the implementation of a custom belief revision function that allows agents to (partially or fully) reject belief updates received from their environment, to post-process beliefs in any other manner, or to acquire additional beliefs on their own. +For example, let us implement the following simple agent: + +```JavaScript +let agent = new Agent('myAgent', { ...Belief('a', true) }, {}, []) +``` + +Now, let us run the agent so that the environment changes the agent's belief about ``a``. + +```JavaScript +agent.next({ ...Belief('a', false) }) +``` + +``agent.beliefs.a`` is ``false``. + +We can implement a custom belief revision function that guarantees that the belief about ``a`` must not be overwritten: + +```JavaScript +const (oldBeliefs, newBeliefs) => ({ + ...oldBeliefs, + ...newBeliefs, + a: true +}) +let agent = new Agent('myAgent', { ...Belief('a', true) }, {}, [], undefined, false, reviseBeliefs) +``` + +To test the change, proceed as follows: + +```JavaScript +agent.next({ ...Belief('a', false) }) +``` + +``agent.beliefs.a`` is ``true``. + ## Messaging JS-son agents can send "private" messages to any other JS-son agent, which the environment will then relay to this agent only. Agents can send these messages in the same way they register the execution of an action as the result of a plan. diff --git a/spec/src/agent/Agent.spec.js b/spec/src/agent/Agent.spec.js index ecbbf74..d5269cb 100644 --- a/spec/src/agent/Agent.spec.js +++ b/spec/src/agent/Agent.spec.js @@ -72,4 +72,11 @@ describe('Agent / next()', () => { const newAgent = new Agent('myAgent', beliefs, desires, newPlans, preferenceFunctionGen, false) expect(() => newAgent.next()).toThrow(new TypeError("Cannot set property 'test' of undefined")) }) + + it('should allow for a custom belief revision function that rejects belief updates from the environment', () => { + const reviseBeliefs = (oldBeliefs, newBeliefs) => !newBeliefs.dogNice ? oldBeliefs : newBeliefs + const newAgent = new Agent('myAgent', beliefs, desires, plans, undefined, false, reviseBeliefs) + newAgent.next({ ...Belief('dogNice', false) }) + expect(newAgent.beliefs.dogNice).toBe(true) + }) }) diff --git a/src/agent/Agent.js b/src/agent/Agent.js index 4317f59..6b5f6ee 100644 --- a/src/agent/Agent.js +++ b/src/agent/Agent.js @@ -11,6 +11,11 @@ const Intentions = require('./Intentions') turns all desires into intentions * @param {boolean} selfUpdatesPossible If true, agents can update their own belief, plans et cetera via a body of their plans. Defaults to ``true``. + * @param {function} reviseBeliefs belief revision function that takes the agent's currently held + beliefs as well as the "new" beliefs obtained from the + environment and revises the agent's beliefs based on this. + Defaults to: ``(oldBeliefs, newBeliefs) =>`` + ``({ ...oldBeliefs, ...newBeliefs })`` * @returns {object} JS-son agent object */ @@ -20,7 +25,8 @@ function Agent ( desires, plans, determinePreferences = (beliefs, desires) => desireKey => desires[desireKey](beliefs), - selfUpdatesPossible = true + selfUpdatesPossible = true, + reviseBeliefs = (oldBeliefs, newBeliefs) => ({ ...oldBeliefs, ...newBeliefs }) ) { this.id = id this.beliefs = beliefs @@ -28,12 +34,10 @@ function Agent ( this.plans = plans this.preferenceFunction = determinePreferences this.selfUpdatesPossible = selfUpdatesPossible + this.reviseBeliefs = reviseBeliefs this.isActive = true this.next = function (beliefs) { - this.beliefs = { - ...this.beliefs, - ...beliefs - } + this.beliefs = this.reviseBeliefs(this.beliefs, beliefs) if (this.isActive) { if (Object.keys(desires).length === 0) { this.intentions = this.beliefs