This page is a series of content that I have on the applicability of maths to the systems engineering space. Read here for how Set Theory applies to Systems or here for Fuzzy Logic.
Antecedents and Consequents
An example of a Requirement Statement, particularly a functional requirement statement, may be:
When the Engine_Temperature is greater than 100 degrees Celsius [212 degress Fahrenheit], then the Driver_Display shall indicate High_Engine_Temperature_Alarm.
Borrowing terms from Logic the portion “When the Engine_Temperature is greater than 100 degrees Celsius [212 degress Fahrenheit]” is the Antecedent of the statement and “the Driver_Display shall indicate High_Engine_Temperature_Alarm” is the Consequent. The Antecedent portion must be true in order for the Consequent to be true. Therefore the general form of a (functional) requirement statement is
[Antecedent], then [Consequent].
Mathematically this can be presented as a Condition such that
Antecedent → Consequent.
Antecedents are synonymous to the Pre-Condition, Trigger or Guard of the requirement statement whilst Consequent is synonymous to the collection of Effect, Qualifying or Post-Condition of the requirement statement.
Boolean Operators commonly used in Requirements
Boolean Operators are common functions that take one or multiple Boolean Operands to produce an output.
- AND (also represented as ∩, ˄ or ∙). If X and Y are logical operands then this function is used as “X AND Y”.
- OR (also represented as U, ˅ or +). Used as “X OR Y”.
- NOT (also represented as ¬, or a line over the operand). Used as “NOT X”
- THEN (also represented as ⟹). Used as “X THEN Y”
Not strictly an Operator but parentheses are used to nest Boolean Operators.
There are of course other Boolean Operators derived from those above, such as NAND, NOR, XOR, XNOR, etc. but these operators, used in a textual requirements, often cause more confusion than intended.
Take the below requirement as an example:
When [Device_A is Activated] NAND [Device_B is Activated], then Device C is Activated.
You probably read that and process it as follows:
When [Device_A is De-Activated] OR [Device_B is De-Activated], then Device C is Activated.
So instead of using derived Boolean Operators it is recommend to stick to the basics and avoid additional cognitive effort to understand textual requirements.
Boolean Operator AND
Boolean Operator AND is a conjunction of antecedent (or commonly consequents) operands. This is represented in a Venn diagram as follows:

Useful for drawing a logical graph the following symbol is used to represent the Boolean Operator AND.

Using a truth table the following table shows the output of the Boolean Operator AND.
| X | Y | X AND Y |
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
In terms of a Requirement Statement this Operator can be used as follows:
When the Power_Supply is ON AND the Light_Switch is ON then the Light shall illuminate.
Another example illustrating when there are more than one functions expected to be active at the same time given a set of antecedents:
When the Light_Switch is ON then the Primary_Light shall illuminate AND the Power_Status_Indicator shall illuminate green.
Strictly speaking the above requirement should be split into two, one having the consequent of an illuminated primary light and the other having the consequent of an illuminated power_status_indicator but in my experience they remain merged to minimize the number of requirements to manage.
Boolean Operator OR
Boolean Operator OR performs a disjunction of antecedent operands. This is represented in a Venn diagram as follows:

Useful for drawing a logical graph the following symbol is used to represent the Boolean Operator OR.

Using a truth table the following table shows the output of the Boolean Operator OR.
| X | Y | X OR Y |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
Whereas the AND operator may be used in either the antecedent or consequent the OR operator must only be used in the antecedent – when applied to requirements. For example if I wrote “When the Light_Switch is ON then the Primary_Light shall illuminate OR the Power_Status_Indicator shall illuminate green” the reader will be confused.
Boolean Operator NOT
Boolean Operator NOT performs a negation of antecedent operands. This is represented in a Venn diagram as follows:

Useful for drawing a logical graph the following symbol is used to represent the Boolean Operator NOT.

Using a truth table the following table shows the output of the Boolean Operator NOT.
| X | NOT X |
| 0 | 1 |
| 1 | 0 |
Similarly to the OR Operator, the NOT Operator, if needed at all, should only be used in the antecedent in the context of requirements. Typically for a property with a small number of possible enumerations (e.g. on / flashing / off) then it’s best to avoid the NOT Operator all together and just refer to the desired enumeration.
Universal Quantifier
The universal quantifier, written ∀ (“for all”), asserts that a property holds for every member of a given domain. A universal statement has the form:
∀x (P(x))
Read as: “For every x, P(x) is true.”
When paired with a conditional, it usually looks like:
∀x (Condition(x) ⟹ Outcome(x))
Example: “For every user, if the user is logged in, then the dashboard is visible.” (∀x (LoggedIn(x) ⟹ DashboardVisible(x)))
How It Relates to Functional Requirements
Functional requirements in engineering and software design are almost always universal statements in disguise. A requirement like: “The System shall reject any password shorter than 8 characters.”
This matters practically because universal requirements inherit the same verification burden as any ∀ statement:
- If the domain (all possible passwords, all possible users, all possible inputs) is unbounded or effectively infinite, you can never fully verify the requirement holds, you can only test a finite sample and gain confidence.
- You can conclusively disprove it with a single counterexample (one 7-character password that gets accepted).
This is why software testing practice leans on things like boundary testing and formal verification for critical systems as they’re all strategies for hunting counterexamples efficiently, since exhaustive verification of an unbounded requirement isn’t achievable through testing alone.
Existential Quantifier
The existential quantifier, written ∃ (“there exists”), asserts that a property holds for at least one member of a given domain. An existential statement has the form:
∃x (P(x))
Read as: “There exists an x such that P(x) is true.”
When paired with a conditional, it usually looks like:
∃x (Condition(x) ∧ Outcome(x))
Note the connective is usually ∧ (AND), not ⟹, when quantifying existentially — “there exists an x such that Condition(x) and Outcome(x) both hold.” (Pairing ∃ with ⟹ is logically valid but tends to produce weak, often trivially-true statements, since the conditional is satisfied by any x where the antecedent is simply false.)
Example: “There exists a user who is both an admin and currently logged in.” (∃x (Admin(x) ∧ LoggedIn(x)))
How It Relates to Functional Requirements
Functional requirements sometimes take an existential form usually when specifying that some capability, path, or fallback must exist, rather than that a property holds universally. For example:
“The system shall provide at least one recovery method if the primary authentication fails.”
This matters practically because existential requirements have the opposite verification profile from universal ones:
- You can verify the requirement by producing just one valid instance such as finding a working recovery method, and the requirement is satisfied.
- You generally cannot conclusively disprove it without checking the entire domain and confirming no instance qualifies, which is impractical when the domain is large or unbounded.
This is why existential requirements are comparatively easy to test-to-pass (find one example and you’re done) but hard to test-to-fail (proving “no such case exists anywhere” is difficult).
Boolean Algebra Identities
Applying the Boolean Operator OR to operands is performing Boolean addition to the Operand values. Boolean addition is similar to arithmetic addition except that the sum doesn’t go past the value of 1.
E.g. if X is TRUE (1), Y is FALSE (0) and Z is TRUE (1) then X OR Y OR Z has value TRUE (1) as (1 + 0 + 1 = 1).
Applying the Boolean Operator AND operands is performing Boolean multiplication to the Operand values. Boolean multiplication is the same as arithmetic multiplication.
E.g. if X is TRUE (1), Y is FALSE (0) and Z is TRUE (1) then X AND Y AND Z has value FALSE (0) as (1 x 0 x 1 = 0).
Below is a table of important Boolean Identities.
| Additative | Multiplicative |
| X ˅ 1 = 1 | X ˄ 1 = X |
| X ˅ 0 = X | X ˄ 0 = 0 |
| X ˅ X = X | X ˄ X = X |
| X ˅ ¬X = 1 | X ˄ ¬X = 0 |
Boolean Algebra Laws
Commutative Law
Boolean Algebra is commutative which means
- X ˄ Y = Y ˄ X
- X ˅ Y = Y ˅ X
Associative Law
Boolean Algebra is associative which means
- X ˄ (Y ˄ Z) = (X ˄ Y) ˄ Z
- X ˅ (Y ˅ Z) = (X ˅ Y) ˅ Z
Distributive Law
Boolean Algebra is distributive which means
- X ˄ (Y ˅ Z) = (X ˄ Y) ˅ (X ˄ Z)
- X ˅ (Y ˄ Z) = (X ˅ Y) ˄ (X ˅ Z)
The last one isn’t intuitive at first so needs some explanation:
- X ˅ (Y ˄ Z)
- let (X ˄ 1) ˅ (Y ˄ Z)
- let 1 = 1 ˅ Y therefore X ˄ (1 ˅ Y) ˅ (Y ˄ Z)
- use distributive law to multiple out therefore (X ˄ 1) ˅ (X ˄ Y) ˅ (Y ˄ Z)
- let 1 = 1 ˅ Z therefore X ˄ (1 ˅ Z) ˅ (X ˄ Y) ˅ (Y ˄ Z)
- (X ˄ X) ˅ (X ˄ Z) ˅ (X ˄ Y) ˅ (Y ˄ Z)
- (X ˅ Y) ˄ (X ˅ Z)
De Morgan’s Law
De Morgan’s Law has two parts.
- ¬(X ˄ Y) = ¬X ˅ ¬Y or negation of multiplication of operands is equivalent to sum of negated operands.
- ¬(X ˅ Y) = (¬X) ˄ (¬Y) or negation of sum of operands is equivalent to multiplication of negated operands
