It's not obvious to non-developers just how different computer expressed logic is from human expressed logic. It's one of the reasons why developers have a difficult time translating user requirements into conditional statements (rules) when designing software.
Knowing a language means being able to produce an infinite number of sentences never spoken before and to understand sentences never heard before. For us humans, it’s natural to say things like Tom likes football and pancakes. For non-developers, the mental effort required to translate such statements into computer language might not be that obvious. If we were to literally write the same statement into a computer program, it would mean (for the machine) that Tom is happy only when watching football while eating pancakes.
So when writing software, what you are basically doing is translating user requirements (human stories described using human language) into rules (conditional constructions written using computer language). And while doing that, you need to be aware of the differences between human-spoken logic and computer-spoken logic so that you don’t accidentally condemn Tom to only finding happiness when watching football while eating pancakes.
As computer language consists of both Propositional Logic (assumes that the world contains facts) and First Order Logic (assumes that the world contains objects, relations and functions), one may argue that developers are well-equipped and computer language is all that is needed to enable them to write any algorithm and conditional statement (rule) needed to translate a human requirement into code.
We argue that it isn’t, primarily because of three major difficulties that stand in the way of developers - the first difficulty is brought about by the complexity of the logic, as we will see below. The second and third difficulties (brought about by time and uncertainty) will be covered in the follow-up posts.
So now let’s look more closely into the process of building software applications using computer logic made up of conditional constructions.
Boolean Algebra - the language of mathematics and machines (the equivalent of Propositional Logic), has precise and well defined constructions or “machine words” that make up its vocabulary: the conjunction AND denoted as ∧, the disjunction OR denoted as ∨, and the negation NOT denoted as ¬.
So how should we then read this table:
For instance, De Morgan’s Law says the following: the negation of "a and b” is equivalent to "not a or not b", while the negation of "a or b" is equivalent to "not a and not b".
Now imagine a software program in which multiple statements using Boolean Algebra are joined together. The longer the conditional statements are, the harder it is to test their validity by reading the code alone. For instance, these statements are equivalent: (a < b || (a >= b && c == d)) , (a < b || c == d). Chaining a couple of these statements together makes it very hard to verify the intended logic.
The difficulty of verifying intended logic can also be measured by a metric called cyclomatic complexity, that Thomas McCabe came up with in 1976. Cyclomatic complexity is a quantitative measure of the number of linearly independent paths through a program's source code. Even though its usefulness as a measure of software quality has been questioned, in general, in order to fully test a module, all execution paths through the module must be exercised. This also implies that a module with higher complexity is more difficult to understand, since the programmer must understand the different pathways and the results of those pathways.
As circuit designers may point out, there are methods such as Boolean simplification and Karnaugh mappings for simplifying digital logic. K-maps can help, but someone reading the code must also understand its intent, something that isn’t at all easy with K-Maps.
So what we have seen already is that the complexity of logic already brings about two major hurdles for developers trying to translate user requirements into correct conditional statements (rules) when designing software:
- First, humans often use logical statements “incorrectly” when expressing rules using spoken language
- Second, even when these constructions are coded properly, it is still hard for humans to check their intended logic, if conditional statements are too long.
We argue in this white paper that this is one of the challenges that using a rules engine can solve. There are two other big ones - one is brought about by the time dimension and the other by the concept of uncertainty.
Building complex logic for IoT applications with a rules engine
So real-life application logic is complex and it will inevitably involve more variables than any textbook example. Complex logic is made up of high order logic (HOL) constructions, which is why it’s important for the rules engine to support them. To manage that, the rules engine should support the following:
- Combining multiple non-binary outcomes of functions (observations) in the rule, beyond Boolean true/false states.
Combining multiple non-binary states is what we do for example when we account for a multitude of factors before we decide whether to go on a city trip over the weekend. We look at the weather (and its range of non-binary states: light rain, heavy storms, snow, cloudy skies, sunny skies) in combination with day of week (seven states), cost of flights and accommodation, etc.
- Dealing with majority voting conditions in the rule
Majority voting refers to taking action based on most of the conditions for that action being met, but not necessarily all. This capability is important for example in healthcare diagnostic systems where some but not all indications may point to a medical issue. Another example where it’s used is in “fly by wire” control systems, such as the Boeing 777 fly-by-wire triple redundant computer that replicates the computations in three processors and then performs majority voting to determine the final result.
- Handling conditional executions of functions based on the outcomes of previous observations.
An execution based on previous observation is: “If the machine malfunctions, only then check the asset database, otherwise do nothing.”
We argue in this white paper that complex logic and the time dimension are two of the biggest challenges within IoT application development that using a rules engine can solve. A third one is brought about by the concept of uncertainty.