Skip to content

PythonKnowledgeContainers

James Edmondson edited this page Jul 23, 2018 · 3 revisions

Python Guide Series
Architecture | Knowledge Base | Networking | Containers


MADARA Containers

The MADARA KaRL scripting environment is fast and efficient, but it can also be difficult to debug and work with for programmers more familiar with object-oriented programming in their host languages. To address the needs of object-oriented developers, MADARA also provides a set of containers which present facades into the Knowledge Base and mimic the look and feel of STL containers. These object-oriented containers are meant to be user-friendly and intuitive, but some guidance may be useful for users who do not know where they are and how they may be initialized.


Table of Contents


1. Types of Containers

In this section, we breakdown the types of containers. For a complete list of containers, see the files located inside of the include/madara/knowledge_engine/containers directory of your source distribution, or see the Library documentation for the Containers namespace.


1.1 Instance Variables

Instance variables are facades into single variable locations within the Knowledge Base and are the most efficient of the MADARA containers. Values are set with a set function, available through the container, and retrieved using the asterisk operator (*) or with a to_integer (), to_double (), or to_string () function. MADARA currently supports the following instance variables:


1.1.1 Integer

Location: madara.knowledge.containers.Integer
Documentation: help ('madara.knowledge.containers.Integer)

Integer is a container that provides interfaces for setting and getting an integer value from the Knowledge Base.

import madara.knowledge.containers.Integer
import madara.knowledge.KnowledgeBase

kb = madara.knowledge.KnowledgeBase ()
my_id = madara.knowledge.containers.Integer ()
my_id.set_name (".id", kb)
my_id.set (1)
...

// read the value later
my_int = my_id.to_integer ()

1.1.2 Double

Location: madara.knowledge.containers.Double
Documentation: help ('madara.knowledge.containers.Double)

Double is a container that provides interfaces for setting and getting a double value from the Knowledge Base.

import madara.knowledge.containers.Double
import madara.knowledge.KnowledgeBase

kb = madara.knowledge.KnowledgeBase ()
pay_rate = madara.knowledge.containers.Double ()
pay_rate.set_name (".id", kb)
pay_rate.set (20.00)
...

// read the value later
my_double = pay_rate.to_double ()

1.1.3 String

Location: madara.knowledge.containers.String
Documentation: help ('madara.knowledge.containers.String)

String is a container that provides interfaces for setting and getting a string value from the Knowledge Base.

import madara.knowledge.containers.String
import madara.knowledge.KnowledgeBase

kb = madara.knowledge.KnowledgeBase ()
name = madara.knowledge.containers.String ()
name.set_name (".name", kb)
name.set ("John Smith")
...

// read the value later
my_string = name.to_string ()

1.2 Vectors/Arrays

Array containers are facades into arrays of variable locations within the Knowledge Base, and provide O(1) access times to these elements. Unlike with instance variables, the name that is set for an array container is the prefix for variable locations instead of an actual variable name. MADARA currently supports the following vector/array containers:


1.2.1 Native Integer Vector

Location: madara.knowledge.containers.NativeIntegerVector
Documentation: help ('madara.knowledge.containers.NativeIntegerVector)

NativeIntegerVector is a container that points into a vector of integers inside of the KnowledgeBase. This is a highly optimized vector that is not entirely thread safe in multi-writer paradigms. The real intent of use is that you have a single producer that updates every entry in the Vector, and then you have many readers who might access this knowledge.

import madara.knowledge.containers.NativeIntegerVector
import madara.knowledge.KnowledgeBase

kb = madara.knowledge.KnowledgeBase ()
years_employed = madara.knowledge.containers.NativeIntegerVector ()
years_employed.set_name (".years_employed", kb)
years_employed.set (0, 2018)
years_employed.set (1, 2017)
years_employed.set (2, 2016)
...

// read the value later
years_employed_vector = years_employed.to_integers ()

1.2.2 Native Double Vector/Array

Location: madara.knowledge.containers.NativeDoubleVector
Documentation: help ('madara.knowledge.containers.NativeDoubleVector)

NativeDoubleVector is a container that points into a vector of doubles inside of the KnowledgeBase. This is a highly optimized vector that is not entirely thread safe in multi-writer paradigms. The real intent of use is that you have a single producer that updates every entry in the Vector, and then you have many readers who might access this knowledge.

import madara.knowledge.containers.NativeDoubleVector
import madara.knowledge.KnowledgeBase

kb = madara.knowledge.KnowledgeBase ()
test_scores = madara.knowledge.containers.NativeDoubleVector ()
test_scores.set_name (".test_scores", kb)
test_scores.set (0, 95.0)
test_scores.set (1, 86.0)
test_scores.set (2, 88.5)
...

// read the value later
test_scores_vector = test_scores.to_doubles ()

1.2.3 Dynamically-typed Vector/Array

Location: madara.knowledge.containers.Vector
Documentation: help ('madara.knowledge.containers.Vector)

Vector is a container that points into a vector of doubles inside of the KnowledgeBase. This is a highly optimized vector that is not entirely thread safe in multi-writer paradigms. The real intent of use is that you have a single producer that updates every entry in the Vector, and then you have many readers who might access this knowledge.

import madara.knowledge.containers.Vector
import madara.knowledge.KnowledgeBase

kb = madara.knowledge.KnowledgeBase ()
mishmash = madara.knowledge.containers.Vector ()
mishmash.set_name (".mishmash", kb)
mishmash.set (0, 95.0)
mishmash.set (1, 50)
mishmash.set (2, "Jeff Calhoun")
...

// read the value later
mishmash_vector = mishmash.to_records ()

1.3 CircularBuffer

Location: madara.knowledge.containers.CircularBuffer
Documentation: help ('madara.knowledge.containers.CircularBuffer)

The CircularBuffer container abstracts a fixed size buffer within the knowledge base with an index that moves along the buffer to indicate where the latest record has been inserted. This container readily supports a producer/consumer model for high-performance delivery of items between one thread and another.

import madara.knowledge.containers.CircularBuffer
import madara.knowledge.KnowledgeBase
import madara.knowledge.KnowledgeRecord

kb = madara.knowledge.KnowledgeBase ()
my_buffer = madara.knowledge.containers.CircularBuffer ()
my_buffer.set_name (".queue", kb)
my_buffer.add (KnowledgeRecord (95.5))
my_buffer.add (KnowledgeRecord (50))
my_buffer.add (KnowledgeRecord ("Jeff Calhoun"))
...

// read the value later
my_record = my_buffer.get ()

1.4 CircularBufferConsumer

Location: madara.knowledge.containers.CircularBufferConsumer
Documentation: help ('madara.knowledge.containers.CircularBufferConsumer)

The CircularBufferConsumer container consumes items from a CircularBuffer producer. This consumption process is entirely virtual and many consumers can iterate over the same CircularBuffer. The class contains an internal, local iterator and does not interfere with other instances of CircularBufferConsumer.

import madara.knowledge.containers.CircularBufferConsumer
import madara.knowledge.containers.CircularBuffer
import madara.knowledge.KnowledgeBase
import madara.knowledge.KnowledgeRecord

kb = madara.knowledge.KnowledgeBase ()
my_buffer = madara.knowledge.containers.CircularBuffer ()
my_buffer.set_name (".queue", kb)
my_buffer.add (KnowledgeRecord (95.5))
my_buffer.add (KnowledgeRecord (50))
my_buffer.add (KnowledgeRecord ("Jeff Calhoun"))
...

// read the value later
my_name = my_buffer.consume ()
my_age = my_buffer.consume ()
my_score = my_buffer.consume ()

2. Interaction with the Transport Layer

When creating containers, each constructor supports a madara.knowledge.KnowledgeUpdateSettings instance that provides control over the updating and retrieving of variables from the context. However, no function in the container classes directly interacts with the transport layer.

Container classes are intended to provide fast, efficient, and convenient facades into the Knowledge Base to support object-oriented programming. In order to send these updates to other reasoning agents in the network, functions will need to be called on the KnowledgeBase. In this section of the Wiki, we'll discuss how the containers are intended to be used and when interactions over the network occur.


2.1 The send_modifieds function

If the developer does not intend to use the evaluate or wait function on the Knowledge Base and intends to explicitly use MADARA containers, then the main option for communicating changes over the network is with the send_modifieds function. After all relevant changes have been made through the container classes, simply call send_modifieds.

To showcase this concept, we'll use a complete program that sends a profile over multicast.

import madara.knowledge.containers.Vector
import madara.knowledge.KnowledgeBase

kb = madara.knowledge.KnowledgeBase ()
mishmash = madara.knowledge.containers.Vector ()
mishmash.set_name ("mishmash", kb)
mishmash.set (0, 95.0)
mishmash.set (1, 50)
mishmash.set (2, "Jeff Calhoun")

kb.send_modifieds ();

Python Guide Series
Architecture | Knowledge Base | Networking | Containers