sarl / sarl

SARL Agent-Oriented Programming Language http://www.sarl.io
Apache License 2.0
137 stars 46 forks source link

New keyword: space #105

Open gallandarakhneorg opened 10 years ago

gallandarakhneorg commented 10 years ago

To enable the developers to code in SARL as much as possible, it could be interesting to add a new keyword related to the space concept (the only concept that has no keyword in SARL):

With this keyword, we will be able to write:

space PhysicEnvironment {
  def getBodyFactory : BodyFactory
  def putInEnvironment(body : AgentBody, agent : Agent)
  def influence(body : AgentBody, influences : Influence*)
  def destroyBody(body : AgentBody)
}

The corresponding grammar rule is:

Space returns InheritingElement:
  {Space}
  'space' name=ValidID ('extends' superTypes+=JvmParametizedTypeReference
  ( ',' superTypes+=JvmParametizedTypeReference )* )? 
  ('{' features+=ActionSignature* '}')? ;

The implementation of a space may be done in Java since the developer will certainly extend a platform-dependent class.

gallandarakhneorg commented 8 years ago

I have reserved the keyword "space" in the grammar in order to avoid any conflict with variable names when we really introduces the space definition. The SARL grammar contains only an empty space declaration that must be extended with the features we want to appear in a space definition.

ngaud commented 8 years ago

Following the discussions of Friday 16, September 2016 on how to define interactions at the environment border/interface, in other words between application agents and agents in charge of environmental missions.

The support to describe an environmental interface is the Space that describes the existing methods that could be directly called by application agents and really implemented by environmental agents.

The same approach will be used to implement Physical Environment or Graphical User Interface shared by a collection of distributed agents.

No Artifacts in SARL, everything is Agent, an Artifact is just an object managed by an environmental agent. And a environmental agent is just an agent assuming some environmental missions defines and exhibits by a space.

space SmartHome {

    def update() fires SmartHomeUpdate

    capacity    Camera{
        def capture (int h, int w)  fires Capture
    }
}

The previous code will automatically generate 2 capacities (SmartHome and Camera) and corresponding skills

Environmental Agents (an agent responding to space methods):

Agent ACamera {

    on Capture {
        //Do something
    }

}

Agent Home {

    on SmartHomeUpdate {
        //Do something
    }

}

Non environmental agent, the client calling something provided by the environment through the space:

Agent HomeUser {
    uses Camera, SmartHome

    on Initialze {
        register(new SmartHome) // the registration gives the skills associated to Camera and SmartHome  capacities
        List<UUID> envtAgents = SmartHome.findallAgentWithCapacities(Camera.class)
    }

    on MyEvent {
         SmartHome.update() // send SmartHomeUpdate event to Home agent
    }

    on MySecondEvent {
         Camera.capture(23,35) // send Capture event to ACamera agent
    }
}
gallandarakhneorg commented 7 years ago

I have a concern regarding the names of the generated elements. Consider:

package smarthome
space SmartHome {

    def update() fires SmartHomeUpdate

    capacity    Camera{
        def capture (int h, int w)  fires Capture
    }
}

space Camera {
}

It will generate two capacities with the same name in the package. The problem is coming from the fact that the Camera in the space is defined inside SmartHome. We should use a clear naming scope. The question is: should we use the nested naming convention coming from Java? In other words, the generated capacities will be named: SmartHome, SmartHome.Camera and Camera. I'm not fully convinced but I don't see any other solution, since I think we should not use the mechanisms that adds the "Capacity" and "Space" strings of characters at the end of the names automatically. The names should stay unchanged from the developer point of view.

ngaud commented 7 years ago

We may generate a dedicated sub-package per space. (In our example, we may also consider the user is breaking naming conventions)

Packages: smarthome.smarthome and smarthome.camera Each one containing its set of provided capacities.

gallandarakhneorg commented 7 years ago

I'm not convinced by the implicit generation of packages because the problem will be moved. Consider the case the developer has defined by hand the generated package, and he has put capacities inside. We developer will have compilation errors that be not "fun"

gallandarakhneorg commented 7 years ago

_EXAMPLE 1_

Space with a shared data structure among the network, but without event bus. The shared modifier marks a field that should be created with a distributed data structure. It is assumed that the injection and the type validation will be done.

space BlackboardSpace {

    shared var Map<Object, Object> content

    capacity Blackboard {
        def putData(key : Object, value : Object)
        def readData : Map<Object, Object>
    }

    skill BlackBoardSkill implements Blackboard {
        def putData(key : Object, value : Object) {
            content.put(object, value)
        }
        def readData : Map<Object, Object> {
            Collections.unmodifiableMap(content)
        }
    }

}

_EXAMPLE 2_

Externalization of the capacity/skill definitions outside the space definition in order to enable reuses.

space BlackboardSpace {
    capacity Blackboard
    skill BlackboardSkill
}

capacity Blackboard {
    def putData(key : Object, value : Object)
    def readData : Map<Object, Object>
}

skill BlackBoardSkill implements Blackboard {
    def putData(key : Object, value : Object) {
    }

    def readData : Map<Object, Object> {
    }
}

_EXAMPLE 3_

Definition of a space with a shared data-structure among the network, and with an event bus.

event BlackboardChange

space BlackboardSpace2 extends OpenEventSpace {

    shared var Map<Object, Object> content

    capacity Blackboard {
        def putData(key : Object, value : Object) fires BlackboardChange
    }

    skill BlackBoardSkill implements Blackboard {
        def putData(key : Object, value : Object) fires BlackboardChange {
            content.put(object, value)
            /** Caution: the agent emits the event, not the space */
            emit(new BlackboardChange)
        }
    }

}

_EXAMPLE 4_

Space definition only with an event bus.

space BlackboardSpace3 extends OpenEventSpace {

    capacity Blackboard {
        def putData(key : Object, value : Object) fires BlackboardChange
    }

    skill BlackBoardSkill implements Blackboard {
        def putData(key : Object, value : Object) fires BlackboardChange {
            /** Caution: the agent emits the event, not the space */
            emit(new BlackboardChange(key, value))
        }
    }

}

_EXAMPLE 5_

Tentative to define a space factory that should evolves to a space specification.

factory BlackboardFactory of Blackboard {
    override create() {
        super.create()
    }
    def create(Map<Object, Object> initialData) {
        var spaceInstance = create
        spaceInstance.content += initialData
        spaceInstance
    }
}

_EXAMPLE 6_

Definition of a space for interactions with a situated environment (for simulation).

Introduction of the default keyword for capacities. The default keyword enables the agent to have implicit skill for a capacity. The better location for creating the default skill instance in the agent is in getSkill in order to enable overriding of the default skill with a skill given by the developer with setSkill. The default skill mechanism could be generalized.

event Perception {
    var neightbors : List<Object>
}

event Influence {
    var action : Object
}

space SituatedEnvironmentSpace extends OpenEventSpace {

    capacity EnvironmentManager default EnvironmentManagerSkill {
        def notifyPerceptions(perceptions : Map<UUID, List<Object>>) fires Perception
    }

    skill EnvironmentManagerSkill implements EnvironmentManager {
        def install {
            register(owner)
        }
        def uninstall {
            unregister(owner)
        }
        def notifyPerceptions(perceptions : Map<UUID, List<Object>>) fires Perception {
            perceptions.forEach [ val p = it; emit(new Perception => [ it.neightbors = p])
        }
    }

    capacity Situable default SituableSkill {
        def doAction(action : Object) fires Influence
    }

    skill SituableSkill implements Situable {
        def install {
            register(owner)
        }
        def uninstall {
            unregister(owner)
        }
        def doAction(act : Object) fires Influence {
            emit(new Influence => [ it.action = act])
        }
    }

}
ngaud commented 7 years ago
space SmartHome {

    var content : Map<Object, Object> 

    on MyEvent [Guard1] fires SmartHomeUpdate
    on MySecondEvent [content.get(?) == ?] fires Capture

    on SmartHomeUpdate [it.source == new Address(X) ] fires EventFromEnvt [EmitGuard/Scoping]
    on SmartHomeUpdate [it.hasCapacity(TotoCapicity)] fires Event2FromEnvt  [EmitGuard2]
    on Capture [ReceiveGuard5] fires Event3FromEnvt  [EmitGuard3], Event4FromEnvt  [EmitGuard4]

    def update() fires SmartHomeUpdate

    capacity    Camera{
        def capture (int h, int w)  fires Capture
    }

    [optional, espcially for other space that are not event-based]
    skill CamSkill implement Camera {
        def capture (int h, int w)  fires Capture {
                 if content.get(?) == ? {....}
        }
    }

}

Agent ACamera {

    on Capture {
        //Do something
    }

}

Agent Home {

    on SmartHomeUpdate {
        //Do something
    }

}

Agent HomeUser {
    uses Camera, SmartHome

    on Initialize {
        register(new SmartHome) // the registration gives the skills associated to Camera and SmartHome  capacities
        List<UUID> envtAgents = SmartHome.findallAgentWithCapacities(Camera.class)
    }

    on MyEvent {
         SmartHome.update() // send SmartHomeUpdate event to Home agent
    }

    on MySecondEvent {
         Camera.capture(23,35) // send Capture event to ACamera agent
    }
}

HomeAgent will have a skill overloading the asEventListener methods of an agent to insert a filter validating the Guard1 before calling the on clause of the MyEvent event. This skill requires to rewrite the default Behaviors BIC or the overload of the internal Eventlistener to implement this filtering process.

The space must exhibit a description containing the protocol to enable search on behaviours, capacities validating this protocol.

myspace.getDescription() : InteractionDescription

NewBIC.getAgentWithCapacities(C1): List (System Capacity Yellow Page) NewBIC.getAgentWithBehaviors(B1): List (System Behavior Yellow Page)

NewBIC.getBehaviorsValidatingDescription(InteractionDescription): List<List<Class<? extends Behaviors>> a second when you need multiple behavior to implement the space description.

Agent, Behavior and Space will have InteractionDescription that are dynamically computed and could then be matched to inform an agent of the list of behaviors it should acquire to enter a space.

class InteractionDescription { /* kinds of norms that is statically specified by the space and could be refine dynamically (runtime) */ 
      var in: Class<Event>
      var out: Class<Event>
}

implies to update the semantic of fire to be propagated into the hierarchy of caller (until an on clause, like a throw statement for an exception)

ngaud commented 7 years ago

Feature to consider for the space: transversal rule associated to the space that can limit the scope of certain event types.

gallandarakhneorg commented 12 months ago

A part of this work is under progress with @stefanotedeschi. It is focussing on the implementation of protocol with SARL. No work is ongoing on the SALR syntax yet.

srodriguez commented 12 months ago

Great. Please include me in the discussions. Happy to organize a call.

gallandarakhneorg commented 11 months ago

The specific works on protocols are in a separate project until we decide to include it in the main project: https://github.com/sarl/sarl-protocols

This project focuses on protocols only. We don't try to define the concept of space in all its possible dimensions.