210 likes | 344 Views
The MADARA Knowledge and Reasoning Language ( KaRL ) Engine. James Edmondson. What is the KaRL Engine?. The KaRL engine provides programmers with a language for rapidly developing distributed real-time applications
E N D
The MADARA Knowledge and Reasoning Language (KaRL) Engine James Edmondson
What is the KaRL Engine? • The KaRL engine provides programmers with a language for rapidly developing distributed real-time applications • The idea is that even novice programmers can code distributed applications, as long as they understand what each agent in the network is interested in • KaRL was originally developed as a knowledge and reasoning language but now supports general purpose programming with multi-modal logics • Can interface to the KaRL library from both C++ and Java
KaRL Engine Overview • The KaRL engine is an interpreter of expressions that interacts with a context, a transport layer, and a user. • Supports 64-bit integers, strings, and doubles • Supports images, text, XML, and binary files as first class entities • Supports IP multicast, broadcast, and DDS transports • Supports conditional waits • Nanosecond operation execution Knowledge Base Context Variables => values Interpreter Evaluates expressions Transport Disseminates knowledge
Using the KaRL Engine • Users provide an expression to the interpreter, which evaluates that expression against the context. • At the end of the expression, all knowledge mutations are aggregated and handed to the transport • Other agents in the network receive the knowledge and incorporate them into their own contexts 1. Interpreter .i [0->5) (++var{.i}) For loop on .i, from 0 to 5, increment var{.i} var0=1;var1=1;var2=1; var3=1;var4=1 2. 3. network Transport var0=1;var1=1;var2=1; var3=1;var4=1
Programming Mindset • To program effectively in most languages, it is often best to approach problems in a specific manner that the language is best suited for • In C, programmers concentrate on structured programming • In C++ and Java, the focus is on object-oriented programming • In Perl, programmers try to write obfuscated one-line programs that no one else can read • When writing KaRL applications, focus should be on what knowledge is important to a particular agent and how that can effect emergent behavior • You might say that the focus in KaRL is self-interest • What knowledge am I interested in? • Who else is interested in my knowledge?
Examples: Dijkstra K-State • Dijkstras n-state stabilization • Bottom: if L == S then S := (S + 1) % K fi • Non-bottom: if L != S then S := L fi • KaRL equivalent • Bottom: S{.left} == S{.self} => S{.self} = (S{.self} + 1) % .stop • Non-bottom: S{.left} != S{.self} => S{.self} = S{.left} • Expressions are evaluated with a wait statement, to minimize CPU and bandwidth usage and to allow the read thread to update the context while the main thread sleeps on a single processor system Bottom = S0 S1 S2 Non-Bottom = .self=1 .left=0 .self=0 .left=2 .self=2 .left=1
Examples: Dijkstra 3-state • Dijkstras n-state stabilization • Bottom: if (S+1) % 3 == R then S := (S-1) % 3 fi • Middle: if (S+1) % 3 == L then S:= L fi; • if (S+1) % 3 == R then S:= R fi; • Top: if L == R and (L+1) % 3 != S then S := (L+1)% 3 fi • KaRL equivalent • Bottom: (S{.self}+1) % 3 == S{.right} => S{.self} = (S{.self}+3-1) % 3 • Middle: (S{.self}+1) % 3 == S{.left} => S{.self} = S{.left}; • (S{.self}+1) % 3 == S{.right} => S{.self} = S{.right} • Top: S{.left} == S{.right} && (S{.left}+1) % 3 != S{.self} • => S{.self} = (S{.left}+1) % 3 Bottom = S0 S1 S2 Middle = Top = .self=0 .right=1 .self=1 .left=0 .right=2 .self=2 .left=1 .right=0
Both Operators • These operators always evaluate both a left and right-hand side expression, regardless of their individual returns • Max (;) • Returns the greater of the two • .var1 = (3 ; 5), yields 5 • Min (,) • Returns the lesser of the two • .var1 = (3, 5), yields 3 • Choose-Right (;>) • Always returns the value of the right-hand side • Useful targeting the interesting expression in a wait statement • knowledge.wait (“state=0 ;> left.state”), will always wait for there to be a left.state. Max would also return left.state every time, and Min would always return 0, resulting in infinite wait
Both Operators • These operators always evaluate both a left and right-hand side expression, regardless of their individual returns • Comparisons (<, <=, ==, >= >) • Comparisons always evaluate both the left and right expressions • (var2 = 0) <= var3, yields 1 if var3 is >= 0 • (var3 = 0) <= var3, yields 1 (0 is always less-than-or-equal to 0) • Comparisons between strings and integers/doubles result in the string being converted to a double • E.g., ‘1000’ > 15 is true • Assignments (=, +=, *=, /=) • Assignments a right hand size to the left hand, potentially after some operation (addition, multiplication, division) • var1 += 5, yields 10 if var1 was 5.
Conditional Both Operators • These operators conditionally evaluate a left and right-hand side expression, depending on their values • Or (||) • If left-hand side is false, evaluate right-hand side. Return first non-zero, if either. • .var1 = 1 || 2, yields 1. • And (&&) and Implies (=>) • If left-hand side is zero, right-hand side is not evaluated. If right-hand side is non-zero, right-hand side is evaluated. • (var1 = 0) && (var2 = 1), yields var1 = var2 = 0 • (var1 = 0) => var2 = 1, yields identical semantics
Unary operators • Not (!) • If zero, then 1. If non-zero, then 0. • state = 10; state = !!state yields state == 1 • Negate (-) • If positive, then negative. If negative, then positive. If zero, zero. • State = 10; state = -state yields state == -10 • Increment (++) • Add one to the integer or double • ++var1 yields var1 == 1, assuming var1 was uninitialized • Decrement (--) • Subtract one to the integer or double • --var1 yields var1 == -1, assuming var1 was uninitialized
Primitive Types • Strings • Agent1.Name = “James Edmondson” • Agent1.Drink = ‘Martini, shaken not stirred.’ • Doubles • Agent1.Height = 5.10, to signify 5ft 10inches • Integers • Agent1.Age = 31, to signify 31 years • Each type may be expanded into other variables through the variable expansion operators ({}) • .self = 1 ;> Agent{.self}.Name returns “James Edmondson”, assuming the Agent1.Name above
Advanced Types • Images • Agent1.image = #read_file (‘/path/to/img’, ‘jpeg’) • Agent1.image = #read_file (‘/path/to/img.jpg’) • XML • Agent1.dossier = #read_file (‘/path/to/dossier’, ‘xml’) • Agent1.dossier = #read_file (‘/path/to/dossier.xml’) • Text • Agent1.report = #read_file (‘/path/to/report’, ‘text’) • Agent1.report = #read_file (‘/path/to/report.txt’) • Binary • Agent1.encrypted_report = #read_file (‘/path/to/file’)
Iteration • KaRL currently supports one type of iteration—the for loop • Syntax: variable [start-increment>finish(inclusion) (expression) • Example: count = 0; .i [0->10) (count += agent{.i}.available) • for loop iterates over the variable .i from 0 to 10, exclusive • Executes count += agent{.i}.available from 0 to 9 • If only agent2.available and agent7.available had been set to 1, count would be set to 2 • Example: count = 0; .i [0 -2> 10] (count += agent{.i}.available) • For loop iterates over the variable .i from 0 to 10, inclusive, in increments of 2 • Executes count += agent{.i}.available for .i = 0, 2, 4, 6, 8, 10 • Given agent2.available and agent7.available had been set to 1, count would be set to 1 • Anonymous for loops are allowed (i.e., no variable) • The above can be simplified to .i[10) and .i[10], respectively • For loops return the number of times that expression was executed
External functions • Users may specify their own C functions to call from within the KaRL expression • Image and XML filters may be implemented like this • Through variable expansion, functions can be polymorphic Madara::Knowledge_Record return_var1(Madara::Knowledge_Engine::Function_Arguments & args, Madara::Knowledge_Engine::Variables & variables) { return variable.get(".var1"); } int main (void) { Madara::Knowledge_Engine::Knowledge_Base knowledge; knowledge.define_function (“my_function”, return_var1); return (int) knowledge.evaluate (“.var1 = 50 ;> .var2 = 35 ;> my_function ()”) } Args will contain the arguments passed in the Madara function call
System calls • System calls are a special type of function built-in to the MADARA KaRL engine • Generally are used to interface with the engine or a specific knowledge record to provide special information or access • #type (‘a string’) will return 1, which is a string • #log_level (10) sets the log level to 10, the highest granularity • #evaluate (‘var3 += 2’) will evaluate the expression ‘var3 += 2’. This can be useful for dynamic programs which read from a file. • #print (‘Hello world’) will print ‘Hello world’ • #print_system_calls () will print all of the supported system calls, along with corresponding descriptions of the call, for the version of MADARA you are using
Variable names • A prefix of “.” means the variable is local • Mutations to local variables are never disseminated • .var1 = 30; .var2 = 12; var3 = “nuts!”, will only disseminate var3=“nuts!” because var3 is the only mutated global variable • Local variables can be thought of as hidden variables or simply as state that is uninteresting to other agents in the network • Can be useful in Mechanism Design and as intermediate formats for disseminated knowledge • The user has control over dissemination • Versions of evaluate () and wait () have a boolean that controls whether or not mutations will be disseminated after this particular evaluate/wait call • Mutations will then be aggregated into later disseminations
Quality • Each variable has a quality attribute • Quality can be thought of as confidence in the knowledge value • Better sensors may have higher quality on relevant variables • Similarly, data from a commander is likely higher quality than that of a private • A higher quality update will overwrite a lower quality update • Quality is zero by default and does not come into play if the user never tweaks the value
Knowledge Engine Mechanisms • evaluate (expression) • Evaluates an expression once and returns the result to the user • wait (expression) • Waits for an expression to be true (non-zero) and returns the result to the user • Can be configured with a timeout to support real-time application scheduling and timing constraints • compile (expression) • Compiles a string expression into an expression tree that may be re-used in evaluate and wait calls • expand_statement (expression) • Expands all variables in a KaRL expression in order to make a more optimized expression (or print something)
Performance • Operators in KaRL are executed in nanoseconds on GHz machines (results from profile_architecture.exe on my laptop) • Windows timer precision and context switching skew max and compile time upward (my laptop is Core Duo on Windows 7)
Conclusion • KaRL provides programmers with an expressive language for distributed application development • The KaRL engine manages information dissemination and provides simple mechanisms for users to make information local or global • Variable expansion, iteration, and functions provide powerful features for users to make polymorphic programs • The operators and features discussed here are current as of MADARA v 0.9.29 (5/2/2013)