Relations and Concepts
using AlgebraicAgents
This example demonstrates how to define and manipulate relations between agents and concepts in the AlgebraicAgents framework, and how to visualize these relations. We also demonstrate the concept of wires. Consider wires.jl
for a more comprehensive example.
Define a simple hierarchy
Instantiate two agents
client = FreeAgent("client")
server = FreeAgent("server")
agent server with uuid 899416e2 of type FreeAgent
Create a system (the “universe” in which they interact)
system = ⊕(client, server, name="System")
agent System with uuid 1726a7f8 of type FreeAgent
inner agents:
agent client with uuid 1e7a81be of type FreeAgent
agent server with uuid 899416e2 of type FreeAgent
Communication wires
Client sends a request to Server
add_wire!(system;
from = client,
to = server,
from_var_name = "request_payload",
to_var_name = "incoming_request"
)
1-element Vector{NamedTuple{(:from, :from_var_name, :to, :to_var_name), <:Tuple{AbstractAlgebraicAgent, Any, AbstractAlgebraicAgent, Any}}}:
(from = FreeAgent{name=client, uuid=1e7a81be, parent=FreeAgent{name=System, uuid=1726a7f8, parent=nothing}}, from_var_name = "request_payload", to = FreeAgent{name=server, uuid=899416e2, parent=FreeAgent{name=System, uuid=1726a7f8, parent=nothing}}, to_var_name = "incoming_request")
Server sends a response back to Client
add_wire!(system;
from = server,
to = client,
from_var_name = "response_payload",
to_var_name = "incoming_response"
)
2-element Vector{NamedTuple{(:from, :from_var_name, :to, :to_var_name), <:Tuple{AbstractAlgebraicAgent, Any, AbstractAlgebraicAgent, Any}}}:
(from = FreeAgent{name=client, uuid=1e7a81be, parent=FreeAgent{name=System, uuid=1726a7f8, parent=nothing}}, from_var_name = "request_payload", to = FreeAgent{name=server, uuid=899416e2, parent=FreeAgent{name=System, uuid=1726a7f8, parent=nothing}}, to_var_name = "incoming_request")
(from = FreeAgent{name=server, uuid=899416e2, parent=FreeAgent{name=System, uuid=1726a7f8, parent=nothing}}, from_var_name = "response_payload", to = FreeAgent{name=client, uuid=1e7a81be, parent=FreeAgent{name=System, uuid=1726a7f8, parent=nothing}}, to_var_name = "incoming_response")
Define generic Concepts
c_data = Concept("Data", Dict(:format => "binary")) # abstract container
c_request = Concept("Request", Dict(:purpose => "query")) # a kind of Data
c_response = Concept("Response", Dict(:purpose => "reply")) # a kind of Data
concept Response with uuid 14d67ed6 of type Concept
Bind all Concepts into our system
add_concept!.(Ref(system), [c_data, c_request, c_response])
3-element Vector{Vector{AbstractConcept}}:
[Concept{name=Data, uuid=f2dd0e08, related_entities=}, Concept{name=Request, uuid=b41261b3, related_entities=}, Concept{name=Response, uuid=14d67ed6, related_entities=}]
[Concept{name=Data, uuid=f2dd0e08, related_entities=}, Concept{name=Request, uuid=b41261b3, related_entities=}, Concept{name=Response, uuid=14d67ed6, related_entities=}]
[Concept{name=Data, uuid=f2dd0e08, related_entities=}, Concept{name=Request, uuid=b41261b3, related_entities=}, Concept{name=Response, uuid=14d67ed6, related_entities=}]
Concept hierarchy
Request ⊂ Data
add_relation!(c_request, c_data, :is_a)
relation Request [concept] is_a Data [concept]
Response ⊂ Data
add_relation!(c_response, c_data, :is_a)
relation Response [concept] is_a Data [concept]
Set up Agent–Concept relations
Client produces requests and consumes responses
add_relation!(client, c_request, :produces)
add_relation!(client, c_response, :consumes)
relation client [agent] consumes Response [concept]
Server consumes requests and produces responses
add_relation!(server, c_request, :consumes)
add_relation!(server, c_response, :produces)
relation server [agent] produces Response [concept]
Print out the concepts.
for r in server.opera.concepts
println(r)
end
Concept{name=Data, uuid=f2dd0e08, related_entities=Request, Response}
Concept{name=Request, uuid=b41261b3, related_entities=Data, client, server}
Concept{name=Response, uuid=14d67ed6, related_entities=Data, client, server}
Print out the the relations.
for r in server.opera.relations
println(r)
end
AlgebraicAgents.ConceptRelation{from=Request, relation=is_a, to=Data}
AlgebraicAgents.ConceptRelation{from=Response, relation=is_a, to=Data}
AlgebraicAgents.ConceptRelation{from=client, relation=produces, to=Request}
AlgebraicAgents.ConceptRelation{from=client, relation=consumes, to=Response}
AlgebraicAgents.ConceptRelation{from=server, relation=consumes, to=Request}
AlgebraicAgents.ConceptRelation{from=server, relation=produces, to=Response}
Query related concepts/agents
println("Entities related to Data:")
for r in get_relations(c_data)
println(r)
end
println("Entites that Client produces:")
for r in get_relations(client, :produces)
println(r)
end
isrelated(client, c_request, :produces) == true
true
Visualize the wires and relations
Visualize the wiring diagram of the system (you can run run_graphviz
on the resulting DOT string, see that function's documentation for more details)
wiring_diagram(system)
"digraph \"algagents\" {\n compound=true;\n node[color=Teal, fontsize=7.0, width=0.5, height=0.5, shape=circle];\n 1 [label=\"client\"]\n2 [label=\"server\"]\n3 [label=\"System\"]\n \n3 -> 1 [len=1, penwidth=0.5, arrowsize=0.4, arrowtype=normal, style=dashed, fontsize=5.0, c" ⋯ 71 bytes ⋯ ", style=dashed, fontsize=5.0, color=grey]\n1 -> 2 [len=1, headlabel=request_payload, taillabel=incoming_request, arrowsize=0.3, arrow=normal, fontsize=7.0]\n2 -> 1 [len=1, headlabel=response_payload, taillabel=incoming_response, arrowsize=0.3, arrow=normal, fontsize=7.0]\n}"
Visualize the concept graph of the system
concept_graph(get_relation_closure(server))
"digraph \"algagents_relations\" {\n rankdir=LR;\n node [fontsize=10];\n \"14d67ed6\" [label=\"Response\", shape=circle, style=filled, fontsize=7.0, width=0.5, height=0.5, fillcolor=lightblue, color=\"transparent\"];\n \"f2dd0e08\" [label=\"Data\", shape=circle, style=filled, fon" ⋯ 656 bytes ⋯ "4];\n \"1e7a81be\" -> \"14d67ed6\" [label=\"consumes\", fontsize=5, penwidth=0.5, arrowsize=0.4];\n \"899416e2\" -> \"b41261b3\" [label=\"consumes\", fontsize=5, penwidth=0.5, arrowsize=0.4];\n \"899416e2\" -> \"14d67ed6\" [label=\"produces\", fontsize=5, penwidth=0.5, arrowsize=0.4];\n}\n"
Manipulate relations and concepts
Remove the concept-to-concept relation
remove_relation!(c_data, c_request, :is_a)
6-element Vector{AlgebraicAgents.ConceptRelation}:
relation Request [concept] is_a Data [concept]
relation Response [concept] is_a Data [concept]
relation client [agent] produces Request [concept]
relation client [agent] consumes Response [concept]
relation server [agent] consumes Request [concept]
relation server [agent] produces Response [concept]
Remove the Fruit concept entirely
remove_concept!(server, c_request)
concept Request with uuid b41261b3 of type Concept