This example shows the basics about artifact creation and use, including observation. Two agents create, use and observe a shared artifact.
MAS example01_useobs { environment: c4jason.CartagoEnvironment agents: user user agentArchClass c4jason.CAgentArch #1; observer observer agentArchClass c4jason.CAgentArch #1; classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar"; }
The user
agent creates a c0
artifact of type c4jexamples.Counter
and then uses it twice, executing the inc
action (operation) two times:
!create_and_use. +!create_and_use : true <- !setupTool(Id); inc; inc [artifact_id(Id)]. +!setupTool(C): true <- makeArtifact("c0","c4jexamples.Counter",[],C).
Hightlights:
makeArtifact
action, provided by the workspace
artifact. An empty list of parameters is specified, and the artifact id is retrieved, bound to the C
variable.inc
: the artifact is automatically selected from the workspace. If there are no artifacts providing such action, the action fails. If more than one artifact is found, first artifacts created by the agent itself are considered. If more than one artifact is found, one is selected non deterministically. Then, the rest of the artifacts are considered, and one is selected non deterministically.inc
is executed, the target artifact is specified. This can be done by adding the annotation [artifact_id(Id)]
, where Id
must be bound to the artifact identifier. Alternatively, the annotation [artifact_name(Name)]
can be used, where Name
must be bound to the logic name of the artifact.wsp_id
annotation. Ex: inc [wsp_id(WspID)]
.The Counter
artifact is characterised by a single inc
operation and a count
observable property, updated by the operation. The operation also generates a tick
signal.
package c4jexamples; import cartago.*; public class Counter extends Artifact { void init(){ defineObsProperty("count",0); } @OPERATION void inc(){ ObsProperty prop = getObsProperty("count"); prop.updateValue(prop.intValue()+1); signal("tick"); } }
Highlights
Artifact
base class.init
method in artifact classes represents artifact constructor, useful to initialize the artifact as soon as it is created. The actual parameter of the init
method - in this case there are no parameters - can be specified when executing the makeArtifact
action.@OPERATION
and with void
return parameter. Methods parameter corresponds to operations parameters.defineObsProp
primitive. In their most general form, an observable properties is represented by a tuple, with a functor and one or multiple arguments, of any type. In this case the count
property has a single argument value, of integer type. To retrieve the reference to an observable property the getObsProperty
primitive is provided, specifying the property name. Then updateValue
methods can be used to change the value of the property.tick
signal generated by the operation has no argument. The primitive signal
is provided to generate signals. It comes in two flavours:
signal(String signalName, Object... params) :
generates a signal which is perceivable by all the agents that are observing the artifact (because they did a focus).signal(AgentId id, String signalName, Object... params):
generates a signal which is perceivable only by the specified agent. The agent must be observing the artifact, anyway.await
, described in next examples)Finally, an observer
agent observes the counter and prints on standard output a message each time it perceives
a change in count
observable property or a tick
signal:
!observe. +!observe : true <- ?myTool(C); // discover the tool focus(C). +count(V) <- println("observed new value: ",V). +tick [artifact_name(Id,"c0")] <- println("perceived a tick"). +?myTool(CounterId): true <- lookupArtifact("c0",CounterId). -?myTool(CounterId): true <- .wait(10); ?myTool(CounterId).
Highlights
lookupArtifact
action provided by the workspace
artifact, specifying either the logic name of the artifact to discover or its type (in this last case, if multiple artifacts are found, one is chosen non deterministically). In the example, if the observer agent executes a lookupArtifact
before the artifact has been created (by the other agent), then the lookupArtifact
fails and the repairing plan -?myTool(...)
is executed. Variants:focus
action, provided by the workspace
artifact, specifying the identifier of the artifact to focus.
focus(ArtifactId id, IEventFilter filter)
specifies a filter to select the percepts to receive.focusWhenAvailable(String artName)
focuses the specified artifact as soon as it is available in the workspace.+count(V)
triggering event. Beliefs related to observable properties are decorated with annotations that can be used to select the relevant/applicable plan, in particular:
source(percept)
, percept_type(obs_prop)
: define the percept typeartifact_id(Id)
, artifact_name(id,name)
, artifact_type(id,type)
,
workspace(id,wspname)
: provide information about the source artifact and workspace. It is important to remark that, being beliefs, the value of observable properties can be accessed by means of test goals (e.g. ?count(X)
, when specifying context conditions, and so on).+tick
- even if in this case the belief base is not changed. As in the case of observable properties, annotations that can be used to select the relevant/applicable plan, in particular:
source(ArtifactId)
, percept_type(obs_ev)
- define the percept typeartifact_id(Id)
), artifact_name(id,name)
, artifact_type(id,type)
, workspace(id,wspname)
- provide information about the source artifact and workspace.