diff --git a/examples/prosumers/df.asl b/examples/prosumers/df.asl new file mode 100644 index 0000000..3cd4340 --- /dev/null +++ b/examples/prosumers/df.asl @@ -0,0 +1,16 @@ +/* Beliefs */ +registered([]). + +/* Register a new list of prosumers */ ++!register(Prosumers) : true +<- registered(Current); + New = .concat(Current, Prosumers); /* Concatenate the new prosumers */ + -registered(Current); + +registered(New); + .print("DF: Registered prosumers: ", New, "."). + +/* Provide the list of registered prosumers */ ++!get_prosumers : true +<- registered(Prosumers); /* Retrieve the list of registered prosumers */ + .print("DF: Sending list of registered prosumers: ", Prosumers, "."); + .send(prosumer1, tell, prosumer_list(Prosumers)). \ No newline at end of file diff --git a/examples/prosumers/prosumer1.asl b/examples/prosumers/prosumer1.asl new file mode 100644 index 0000000..7045605 --- /dev/null +++ b/examples/prosumers/prosumer1.asl @@ -0,0 +1,60 @@ +/* Beliefs */ +available_power(100). +demand(50). +neighbors([]). + +/* Register itself with the DF */ ++!start_discovery : true +<- .print("Prosumer1: Registering with DF..."); + .send(df, achieve, register([prosumer1])); + !retrieve_neighbors. + +/* Retrieve neighbors from the DF */ ++!retrieve_neighbors : true +<- .print("Prosumer1: Retrieving neighbors from DF..."); + .send(df, achieve, get_prosumers). + ++prosumers_list(Prosumers) : true +<- .print("Prosumer1: Received prosumer list: ", Prosumers, "."); + -neighbors(_); + +neighbors(Prosumers); + !start_optimization. + ++!start_optimization : true +<- .print("Prosumer1: Starting optimization process..."); + !optimize_energy. + +/* Optimize energy (Surplus > 0 => propose a trade) */ ++!optimize_energy +: available_power(Avail) & demand(Dem) & Surplus = (Avail - Dem) & (Surplus > 0) +<- .print("Prosumer1: Surplus of ", Surplus, " => proposing a trade..."); + !propose_trade(prosumer2, Surplus, 10). + +/* Optimize energy (Surplus <= 0 => no surplus) */ ++!optimize_energy +: available_power(Avail) & demand(Dem) & Surplus = (Avail - Dem) & (Surplus <= 0) +<- .print("Prosumer1: Not enough surplus (Surplus=", Surplus, "). No trade possible."); + !no_surplus(Surplus). + +/* Propose a trade to another agent */ ++!propose_trade(Neighbor, Quantity, Price) : true +<- .print("Prosumer1: Proposing ", Quantity, " units at price ", Price, " to ", Neighbor, "."); + .send(Neighbor, achieve, propose(Quantity, Price)). + +/* If no surplus */ ++!no_surplus(Surplus) : true +<- .print("Prosumer1: Surplus=", Surplus, ". No trade possible."). + +/* Plans for receiving acceptance/rejection of a trade */ ++propose_accept(Quantity, Price) : true +<- .print("Prosumer1: Proposal ACCEPTED for ", Quantity, " units at price ", Price, "."); + !propose_second_trade. + ++propose_reject(Quantity, Price) : true +<- .print("Prosumer1: Proposal REJECTED for ", Quantity, " units at price ", Price, "."). + ++!propose_second_trade : true +<- .print("Prosumer1: Preparing a second trade proposal..."); + !propose_trade(prosumer2, 90, 15). /* A higher quantity likely to be rejected */ + +!start_optimization. \ No newline at end of file diff --git a/examples/prosumers/prosumer2.asl b/examples/prosumers/prosumer2.asl new file mode 100644 index 0000000..e9501ff --- /dev/null +++ b/examples/prosumers/prosumer2.asl @@ -0,0 +1,26 @@ +/* Beliefs */ +available_power(80). + +/* Register itself with the DF */ ++!start_discovery : true +<- .print("Prosumer2: Registering with DF..."); + .send(df, achieve, register([prosumer2])). + +/* If we have enough available_power => accept */ ++!propose(Quantity, Price) +: available_power(Avail) & (Quantity <= Avail) +<- .print("Prosumer2: Received proposal for ", Quantity, " units at price ", Price, "."); + .print("Prosumer2: Enough power => ACCEPTING trade!"); + .send(prosumer1, tell, propose_accept(Quantity, Price)); + OldAvail = Avail; + NewAvail = (OldAvail - Quantity); + -available_power(OldAvail); + +available_power(NewAvail); + .print("Prosumer2: Updated power from ", OldAvail, " to ", NewAvail, "."). + +/* Not enough power => reject */ ++!propose(Quantity, Price) +: available_power(Avail) & (Quantity > Avail) +<- .print("Prosumer2: Received proposal for ", Quantity, " units at price ", Price, "."); + .print("Prosumer2: Insufficient power => REJECTING trade..."); + .send(prosumer1, tell, propose_reject(Quantity, Price)). \ No newline at end of file diff --git a/examples/prosumers/prosumers.py b/examples/prosumers/prosumers.py new file mode 100644 index 0000000..83fda5b --- /dev/null +++ b/examples/prosumers/prosumers.py @@ -0,0 +1,28 @@ +import os +import agentspeak.runtime +import agentspeak.stdlib + +def main(): + # Create the environment + env = agentspeak.runtime.Environment() + actions = agentspeak.stdlib.actions + + # Build the Directory Facilitator (DF) agent + with open(os.path.join(os.path.dirname(__file__), "df.asl")) as source: + df_agent = env.build_agent(source, actions) + + # Build the first agent (Prosumer1) + with open(os.path.join(os.path.dirname(__file__), "prosumer1.asl")) as source: + prosumer1 = env.build_agent(source, actions) + prosumer1.call(agentspeak.Trigger.addition, agentspeak.GoalType.achievement, agentspeak.Literal("start_discovery"), agentspeak.runtime.Intention()) + + # Build the second agent (Prosumer2) + with open(os.path.join(os.path.dirname(__file__), "prosumer2.asl")) as source: + prosumer2 = env.build_agent(source, actions) + prosumer2.call(agentspeak.Trigger.addition, agentspeak.GoalType.achievement, agentspeak.Literal("start_discovery"), agentspeak.runtime.Intention()) + + # Run the environment (starts all agents) + env.run() + +if __name__ == "__main__": + main()