Does IEC-61131 Structured Text allow comparison of boolean operands? - plc

I'm building a parser and type checker for Structured Text. ST is a derivative of Pascal.
It is clear that ST allows equality comparison of two declared real variables X and Y as
X = Y
It is also clear you can write
X <> Y
and
X > Y
If I have two declared boolean variables A and B, is
A = B
legal? Pascal would certainly say so. The reference documents I have for ST (including an Australian version of the 2004 standard, and several vendors implementations) are unclear.
Can I write:
A > B
and what does it mean?
[In the abstract, I'm interested in the same questions for comparing strings. Brownie points for addressing that issue too].
[No, I can't just try it on a real controller; I don't actually have one and the nearest one is effectively two days away from me.]
What's the answer, and what's the reference document you consulted that shows the answer?

The answer to this question really depends on IDE. Although there is a standard for ST, every vendor implement it little bit differently.
In general this is valid statement.
VAR
a, b: BOOL;
END_VAR
IF a = b THEN
// Do something
END_IF
Here is what is in IEC 61131-3 draft. Unfortunately it is not open document and costs money that is why I cannot post it here or provide a link.
https://webstore.iec.ch/publication/4552
GT > Decreasing sequence: OUT := (IN1>IN2) & (IN2>IN3) & ... & (INn-1 > INn)
GE >= Monotonic sequence: OUT := (IN1>=IN2)&(IN2>=IN3)& ... & (INn-1 >= INn)
EQ = Equality: OUT := (IN1=IN2) & (IN2=IN3) & ... & (INn-1 = INn)
LE <= Monotonic sequence: OUT := (IN1<=IN2)&(IN2<=IN3)& ... & (INn-1 <= INn)
LT < Increasing sequence: OUT := (IN1<IN2) & (IN2<IN3) & ... & (INn-1 < INn)
NE <> Inequality (non-extensible) OUT := (IN1 <> IN2)
This also means that in some IDEs you can use
IF EQ(a, b) THEN
// Do something
END_IF
And this should be valid as well.
Can I write:
A > B
and what does it mean?
If A greater than B this expression will return TRUE otherwise FALSE.

Related

How can I prevent Coq notations in closed scopes interfering with notations in open ones?

I'm fairly new to Coq, and I'm trying to use ListNotations in Coq so that I can write lists like [ 1 ; 2 ] rather than cons 1 (cons 2 nil). However, I'm using a library that defines its own notation for the ; character. I was thinking that I could simply close the right scopes so that the notation I want is visible, but it's not working as I expected.
As a simple example, if I create a file test.v:
Declare Scope example_scope.
Notation "a ; b" := (or a b) (at level 50) : example_scope.
Close Scope example_scope.
Require Import List.
Import ListNotations.
Locate ";".
Compute [ 1 ; 2 ].
...then the output of coqc test.v is:
Notation
"a ; b" := or a b : example_scope
"[ x ; y ; .. ; z ]" := cons x (cons y .. (cons z nil) ..) : list_scope
(default interpretation)
File "./test.v", line 8, characters 10-15:
Error: Unknown interpretation for notation "_ ; _".
If the top three lines are removed from test.v, then it works fine.
Two questions:
Why does this happen? It seems to recognize that the notation I want exists and marks it as the "default interpretation." So then why does it become an "unknown notation" when I try to use it?
What can I do in my code (without altering the top three lines of test.v, for example) to get the notation I want?
Why does this happen? It seems to recognize that the notation I want exists and marks it as the "default interpretation." So then why does it become an "unknown notation" when I try to use it?
There are three points to be aware in this case:
Even if the notations definitions (a.k.a. interpretations) are indeed attached to a scope (or to the default scope), their syntactic definition "goes beyond a given scope" (namely, there is a Reserved Notation vernacular that defines the precedence level and associativity for a notation, independently of the scope).
Here is a related remark in the "Reserving notations" section of Coq refman:
Coq expects all uses of the notation to be defined at the same precedence and with the same associativity. [emphasis mine] To avoid giving the precedence and associativity every time, this command declares a parsing rule (string) in advance without giving its interpretation.
So, your example does not satisfy this rule, as the two occurrences of the ; operands have a different precedence level:
Print Grammar constr. (* tested using Coq 8.11.1 *)
…
| "50" LEFTA
[ SELF; ";"; NEXT
| …
| "0" LEFTA
[ "["; "]"
| "["; constr:operconstr LEVEL "200"; ";"; constr:operconstr LEVEL "200";
";"; LIST1 (constr:operconstr LEVEL "200") SEP ";"; "]"
| "["; constr:operconstr LEVEL "200"; ";"; constr:operconstr LEVEL "200";
"]"
| "["; constr:operconstr LEVEL "200"; "]"
| …
(200 being the default precedence level for inner expressions)
Sometimes, it happens we want to define two notations which share some tokens, typically x < y and x < y < z, to borrow the example from the "Simple factorization rules" section of Coq refman:
Coq extensible parsing is performed by Camlp5 which is essentially a LL1 parser: it decides which notation to parse by looking at tokens from left to right. Hence, some care has to be taken not to hide already existing rules by new rules. Some simple left factorization work has to be done. Here is an example.
Notation "x < y" := (lt x y) (at level 70).
Fail Notation "x < y < z" := (x < y /\ y < z) (at level 70).
(*…*)
Notation "x < y < z" := (x < y /\ y < z) (at level 70, y at next level).
Even if this remark is loosely related to your example, it highlights the fact that defining several notations that share several tokens (a common prefix) can be feasible by tuning the precedence level of the inner sub-expressions.
Last but not least, it appears that combining the notations a ; b and [x ; y ; .. ; z] leads to an ambiguous syntax, because (assuming the precedence-level issue mentioned in point 1. were solved), if both scopes are opened, how do you distinguish between cons True (cons True nil) and cons (or True True) nil? both would be a possible interpretation of [True; True].
What can I do in my code (without altering the top three lines of test.v, for example) to get the notation I want?
I guess you can't.
Adding
Notation "a ; b" := (or a b) (at level 50) : example_scope.
at the beginning of your module has an (unintended) side-effect that cannot be workarounded afterwards.
If you really need a semicolon-like notation for or, maybe you could try using ;;, for example:
Notation "a ;; b" := (or a b) (at level 50) : example_scope.
More generally, it seems quite risky to use a mere "separator" (semicolon or comma) as a binary operator: usually, a single ; or , will only be used within (square) brackets.
Finally as an aside, using square brackets in notations (even if ListNotations do so) might confuse the parser in some cases. So regarding lists in particular, if ever you are a math-comp user, you may want to rely on the seq theory instead, which is fully compatible with the Coq standard library (Notation seq := list.), has a comprehensive set of lemmas, and introduce this alternative notation which doesn't rely on a leading single square bracket:
Notation "[ :: x1 ; x2 ; .. ; xn ]" := (x1 :: x2 :: .. [:: xn] ..)
(at level 0, format "[ :: '[' x1 ; '/' x2 ; '/' .. ; '/' xn ']' ]"
) : seq_scope.

How does one prove there is a Natural number equal to 1 in Mizar (mathematical theorem proving language)?

I wanted to write the simplest proof in Mizar mathematical theorem prover language I could think of. So I thought of the following:
there exists x \in Nat : x = 1
there isn't anything simpler that I could think of. I gave it the following attempt:
:: example of a comment
environ
vocabularies MY_MIZAR;
:: adding Natural Numbers
requirments SUBSET, NUMERALS, ARITHM;
::> *210
begin
theorem Th1:
ex x being Nat st x=1
proof
::consider x = 1
:: proof is done
x = 1;
thus Th1;
end;
::>
::> 210: Wrong item in environment declaration
but as you can see Mizar doesn't like my proof. What am I missing?
This still doesn't work:
::: example of a comment
environ
vocabularies MY_MIZAR;
::: adding Natural Numbers
requirements SUBSET, NUMERALS, ARITHM;
::> *856 *825
begin
theorem Th1:
ex x being Nat st x=1
proof
:::consider x = 1
::: proof is done
set x=1;
take x;
thus thesis;
end;
::>
::> 825: Cannot find constructors name on constructor list
::> 856: Inaccessible requirements directive
You can try the following:
1) Fix the 210: error:
x requirments (wrong spelling)
o requirements
2) There will probably be some new errors
about the contents of that line now, so when
you are starting out, it is usually good to
"borrow" an environ that already works, e.g.,
you can use the environ lines from one of the
Mizar articles on natural numbers like
NAT_1.miz:
environ
:: adding Natural Numbers
vocabularies NUMBERS, ORDINAL1, REAL_1, SUBSET_1, CARD_1, ARYTM_3, TARSKI,
RELAT_1, XXREAL_0, XCMPLX_0, ARYTM_1, XBOOLE_0, FINSET_1, FUNCT_1, NAT_1,
FUNCOP_1, PBOOLE, PARTFUN1, FUNCT_7, SETFAM_1, ZFMISC_1;
notations TARSKI, XBOOLE_0, ENUMSET1, ZFMISC_1, SUBSET_1, SETFAM_1, ORDINAL1,
FINSET_1, CARD_1, PBOOLE, NUMBERS, XCMPLX_0, XREAL_0, XXREAL_0, RELAT_1,
FUNCT_1, PARTFUN1, FUNCOP_1, FUNCT_2, BINOP_1;
constructors NUMBERS, XCMPLX_0, XXREAL_0, XREAL_0, CARD_1, WELLORD2, FUNCT_2,
PARTFUN1, FUNCOP_1, FUNCT_4, ENUMSET1, RELSET_1, PBOOLE, ORDINAL1,
SETFAM_1, ZFMISC_1, BINOP_1;
registrations SUBSET_1, ORDINAL1, NUMBERS, XXREAL_0, XREAL_0, CARD_1,
RELSET_1, FUNCT_2, PBOOLE;
requirements REAL, NUMERALS, SUBSET, BOOLE, ARITHM;
definitions SETFAM_1, TARSKI, XBOOLE_0, RELAT_1;
equalities ORDINAL1, XBOOLE_0, CARD_1;
expansions SETFAM_1, ORDINAL1, TARSKI, XBOOLE_0;
theorems AXIOMS, ORDINAL1, XCMPLX_1, XREAL_1, XXREAL_0, TARSKI, ORDINAL2,
XBOOLE_0, CARD_1, FUNCT_2, FUNCT_1, FUNCOP_1, PBOOLE, RELSET_1, RELAT_1,
PARTFUN1, SUBSET_1, NUMBERS, ENUMSET1, XBOOLE_1;
schemes SUBSET_1, ORDINAL2, FUNCT_2, PBOOLE, BINOP_1;
3) To use "1" as your example, you can use "set", "take":
proof
set x=1;
take x;
thus thesis;
end;
Hope this helps.
There are several ways to do this:
Although it is not quite your statement here is an example (It is not quite your statement because you use a "Nat" type).
environ
vocabularies NUMBERS;
constructors ARYTM_0;
notations NUMBERS;
registrations ORDINAL1;
requirements NUMERALS, SUBSET, BOOLE;
begin
1 in NAT;
ex x be object st x = 1;
ex x be object st x in NAT & x = 1;
The 3 statements are verified by mizar as valid, true, demonstrate.
If this is not demonstrated (in the mizar sense), it would indicate the *4 error or even sometimes the *1 error.
In the case of the 3 statements here, the evidence is not explicitly stated. It is contained in the environment because Mizar does not require you to indicate all the steps, some of them are automatic.
It is possible to present in this way, acceptable also to Mizar.
environ
vocabularies NUMBERS;
constructors ARYTM_0;
notations NUMBERS;
registrations ORDINAL1;
requirements NUMERALS, SUBSET, BOOLE;
begin
1 in NAT
proof
thus thesis;
end;
ex x be object st x = 1
proof
thus thesis;
end;
ex x be object st x in NAT & x = 1
proof
thus thesis;
end;
But in this situation, the full expression
proof
thus thesis;
end;
is redundant.
To return to the initial problem, and using the suggestion (user10715283 & user10715216). "can we take an environ that is smaller [...]": yes with a specific tool (clearenv.pl, provide with Mizar-System)
environ
vocabularies NAT_1;
constructors NUMBERS, XCMPLX_0, XREAL_0, BINOP_1;
notations ORDINAL1;
registrations ORDINAL1;
requirements NUMERALS, SUBSET;
begin
theorem Th1:
ex x being Nat st x=1
proof
set x=1;
take x;
thus thesis;
end;

Finding the error in this code

I keep receiving error,';' unexpected in this piece of maple code. I have looked and looked and just can't seem to find where I'm going wrong. Can anyone spot it?
QSFactorization := proc (n::(And(posint, odd)), mult::nonnegint := 0, { mindeps::posint := 5, c := 1.5 })
local mfb, m, x, fb, nfb, r, M, d;
if isprime(n) then
return "(n)"
elif issqr(n) then
return "(isqrt(n))"*"(isqrt(n))"
elif n < 1000000 then
return ifactor(n)
end if;
if mult = 0 then
mfb := MultSelect(n, ':-c' = c)
else mfb := [mult, FactorBase(mult*n, c)]
end if;
m := mfb[1];
if 1 < m then
print('Using*multiplier; -1');
print(m)
end if;
x := m*n*print('Using*smoothness*bound; -1');
print(ceil(evalf(c*sqrt(exp(sqrt(ln(n)*ln(ln(n))))))));
fb := Array(mfb[2], datatype = integer[4]);
nfb := ArrayNumElems(fb);
print('Size*of*factor*base; -1');
print(nfb);
r := Relations(x, fb, ':-mindeps' = mindeps);
M := r[3]; print('Smooth*values*found; -1');
print(nfb+mindeps);
print('Solving*a*matrix*of*size; -1');
print(LinearAlgebra:-Dimension(M));
d := Dependencies(M);
print('Number*of*linear*dependencies*found; -1');
print(nops(d));
print('Factors; -1');
FindFactors(n, r, d)
end proc
I'd really appreciate any insight.
You basic problem is that you are using the wrong quotes inside your print statements. This is invalid,
print('Using*multiplier; -1');
You are using single right-quotes (tick), which in Maple is used for unevaluation. In this case the semicolons inside your print statements are syntax errors.
Use either double-quotes or single left-quotes instead. The former delimits a string, and the latter delimits a name. Eg,
print("Using*multiplier; -1");
print(`Using*multiplier; -1`);
If you choose to go with name-quotes then the print command will prettyprint the output in the Maple GUI with the name in an italic font by default, but you won't see the quotes in the output.
If you choose to go with string-quotes then the print command will show the quotes in the output, but will use an upright roman font by default.
Some other comments/answers (since deleted) on your post suggest that you are missing statement terminators (colon or semicolon) for these two statements,
print(m)
FindFactors(n, r, d)
That is not true. Those statements appear right before end if and end proc respectively, and as such statement terminators are optional for them. Personally I dislike coding Maple with such optional terminator instances left out, as it can lead to confusion when you add intermediate lines or pass the code to someone else, etc.

New Scope in Coq

I'd like my own scope, to play around with long distfixes.
Declare Scope my_scope.
Delimit Scope my_scope with my.
Open Scope my_scope.
Definition f (x y a b : nat) : nat := x+y+a+b.
Notation "x < y * a = b" := (f x y a b)
(at level 100, no associativity) : my_scope.
Check (1 < 2 * 3 = 4)%my.
How do you make a new scope?
EDIT: I chose "x < y * a = b" to override Coq's operators (each with a different precedence).
The command Declare Scope does not exist. The various commands about scopes are described in section 12.2 of the Coq manual.
Your choice of an example notation has inherent problems, because it clashes with pre-defined notations, which seem to be used before your notation.
When looking at the first components the parser sees _ < _ and thinks that you are actually talking about comparison of integers, then it sees the second part as being an instance of the notation _ * _, then it sees that all that is the left hand side of an equality. And all along the parser is happy, it constructs an expression of the form:
(1 < (2 * 3)) = 4
This is constructed by the parser, and the type system has not been solicited yet. The type checker sees a natural number as the first child of (_ < _) and is happy. It sees (_ * _) as the second child and it is happy, it now knows that the first child of that product should be a nat number and it is still happy; in the end it has an equality, and the first component of this equality is in type Prop, but the second component is in type nat.
If you type Locate "_ < _ * _ = _". the answer tells you that you did define a new notation. The problem is that this notation never gets used, because the parser always finds another notation it can use before. Understanding why a notation is preferred to another one requires more knowledge of parsing technology, as alluded to in Coq's manual, chapter 12, in the sentence (obscure to me):
Coq extensible parsing is performed by Camlp5 which is essentially a LL1 parser.
You have to choose the levels of the various variables, x, y, a, and b so that none of these variables will be able to match too much of the text. For instance, I tried defining a notation close to yours, but with a starting and an ending bracket (and I guess this simplifies the task greatly).
Notation "<< x < y * a = b >>" := (f x y a b)
(x at level 59, y at level 39, a at level 59) : my_scope.
The level of x is chosen to be lower than the level of =, the level of y is chosen to be lower than the level of *, the level of a is chosen to be lower than =. The levels were obtained by reading the answer of the command Print Grammar constr. It seems to work, as the following command is accepted.
Check << 1 < 2 * 3 = 4 >>.
But you may need to include a little more engineering to have a really good notation.
To answer the actual question in your title:
The new scope gets created when you declare a notation that uses it. That is, you don’t declare a new scope my_scope separately. You just write
Notation "x <<< y" := (f x y) (at level 100, no associativity) : my_scope.
and that declares a new scope my_scope.
The answers for this question only apply to older versions of Coq. I'm not sure when it started but in at least Coq 8.13.2, Coq prefers the user to first use Declare Scope create a new scope. What the OP has in their code is Coq's preferred way to declare scopes now.
See the current manual

How do I determine if *exactly* one boolean is true, without type conversion?

Given an arbitrary list of booleans, what is the most elegant way of determining that exactly one of them is true?
The most obvious hack is type conversion: converting them to 0 for false and 1 for true and then summing them, and returning sum == 1.
I'd like to know if there is a way to do this without converting them to ints, actually using boolean logic.
(This seems like it should be trivial, idk, long week)
Edit: In case it wasn't obvious, this is more of a code-golf / theoretical question. I'm not fussed about using type conversion / int addition in PROD code, I'm just interested if there is way of doing it without that.
Edit2: Sorry folks it's a long week and I'm not explaining myself well. Let me try this:
In boolean logic, ANDing a collection of booleans is true if all of the booleans are true, ORing the collection is true if least one of them is true. Is there a logical construct that will be true if exactly one boolean is true? XOR is this for a collection of two booleans for example, but any more than that and it falls over.
You can actually accomplish this using only boolean logic, although there's perhaps no practical value of that in your example. The boolean version is much more involved than simply counting the number of true values.
Anyway, for the sake of satisfying intellectual curiosity, here goes. First, the idea of using a series of XORs is good, but it only gets us half way. For any two variables x and y,
x ⊻ y
is true whenever exactly one of them is true. However, this does not continue to be true if you add a third variable z,
x ⊻ y ⊻ z
The first part, x ⊻ y, is still true if exactly one of x and y is true. If either x or y is true, then z needs to be false for the whole expression to be true, which is what we want. But consider what happens if both x and y are true. Then x ⊻ y is false, yet the whole expression can become true if z is true as well. So either one variable or all three must be true. In general, if you have a statement that is a chain of XORs, it will be true if an uneven number of variables are true.
Since one is an uneven number, this might prove useful. Of course, checking for an uneven number of truths is not enough. We additionally need to ensure that no more than one variable is true. This can be done in a pairwise fashion by taking all pairs of two variables and checking that they are not both true. Taken together these two conditions ensure that exactly one if the variables are true.
Below is a small Python script to illustrate the approach.
from itertools import product
print("x|y|z|only_one_is_true")
print("======================")
for x, y, z in product([True, False], repeat=3):
uneven_number_is_true = x ^ y ^ z
max_one_is_true = (not (x and y)) and (not (x and z)) and (not (y and z))
only_one_is_true = uneven_number_is_true and max_one_is_true
print(int(x), int(y), int(z), only_one_is_true)
And here's the output.
x|y|z|only_one_is_true
======================
1 1 1 False
1 1 0 False
1 0 1 False
1 0 0 True
0 1 1 False
0 1 0 True
0 0 1 True
0 0 0 False
Sure, you could do something like this (pseudocode, since you didn't mention language):
found = false;
alreadyFound = false;
for (boolean in booleans):
if (boolean):
found = true;
if (alreadyFound):
found = false;
break;
else:
alreadyFound = true;
return found;
After your clarification, here it is with no integers.
bool IsExactlyOneBooleanTrue( bool *boolAry, int size )
{
bool areAnyTrue = false;
bool areTwoTrue = false;
for(int i = 0; (!areTwoTrue) && (i < size); i++) {
areTwoTrue = (areAnyTrue && boolAry[i]);
areAnyTrue |= boolAry[i];
}
return ((areAnyTrue) && (!areTwoTrue));
}
No-one mentioned that this "operation" we're looking for is shortcut-able similarly to boolean AND and OR in most languages. Here's an implementation in Java:
public static boolean exactlyOneOf(boolean... inputs) {
boolean foundAtLeastOne = false;
for (boolean bool : inputs) {
if (bool) {
if (foundAtLeastOne) {
// found a second one that's also true, shortcut like && and ||
return false;
}
foundAtLeastOne = true;
}
}
// we're happy if we found one, but if none found that's less than one
return foundAtLeastOne;
}
With plain boolean logic, it may not be possible to achieve what you want. Because what you are asking for is a truth evaluation not just based on the truth values but also on additional information(count in this case). But boolean evaluation is binary logic, it cannot depend on anything else but on the operands themselves. And there is no way to reverse engineer to find the operands given a truth value because there can be four possible combinations of operands but only two results. Given a false, can you tell if it is because of F ^ F or T ^ T in your case, so that the next evaluation can be determined based on that?.
booleanList.Where(y => y).Count() == 1;
Due to the large number of reads by now, here comes a quick clean up and additional information.
Option 1:
Ask if only the first variable is true, or only the second one, ..., or only the n-th variable.
x1 & !x2 & ... & !xn |
!x1 & x2 & ... & !xn |
...
!x1 & !x2 & ... & xn
This approach scales in O(n^2), the evaluation stops after the first positive match is found. Hence, preferred if it is likely that there is a positive match.
Option 2:
Ask if there is at least one variable true in total. Additionally check every pair to contain at most one true variable (Anders Johannsen's answer)
(x1 | x2 | ... | xn) &
(!x1 | !x2) &
...
(!x1 | !xn) &
(!x2 | !x3) &
...
(!x2 | !xn) &
...
This option also scales in O(n^2) due to the number of possible pairs. Lazy evaluation stops the formula after the first counter example. Hence, it is preferred if its likely there is a negative match.
(Option 3):
This option involves a subtraction and is thus no valid answer for the restricted setting. Nevertheless, it argues how looping the values might not be the most beneficial solution in an unrestricted stetting.
Treat x1 ... xn as a binary number x. Subtract one, then AND the results. The output is zero <=> x1 ... xn contains at most one true value. (the old "check power of two" algorithm)
x 00010000
x-1 00001111
AND 00000000
If the bits are already stored in such a bitboard, this might be beneficial over looping. Though, keep in mind this kills the readability and is limited by the available board length.
A last note to raise awareness: by now there exists a stack exchange called computer science which is exactly intended for this type of algorithmic questions
It can be done quite nicely with recursion, e.g. in Haskell
-- there isn't exactly one true element in the empty list
oneTrue [] = False
-- if the list starts with False, discard it
oneTrue (False : xs) = oneTrue xs
-- if the list starts with True, all other elements must be False
oneTrue (True : xs) = not (or xs)
// Javascript
Use .filter() on array and check the length of the new array.
// Example using array
isExactly1BooleanTrue(boolean:boolean[]) {
return booleans.filter(value => value === true).length === 1;
}
// Example using ...booleans
isExactly1BooleanTrue(...booleans) {
return booleans.filter(value => value === true).length === 1;
}
One way to do it is to perform pairwise AND and then check if any of the pairwise comparisons returned true with chained OR. In python I would implement it using
from itertools import combinations
def one_true(bools):
pairwise_comp = [comb[0] and comb[1] for comb in combinations(bools, 2)]
return not any(pairwise_comp)
This approach easily generalizes to lists of arbitrary length, although for very long lists, the number of possible pairs grows very quickly.
Python:
boolean_list.count(True) == 1
OK, another try. Call the different booleans b[i], and call a slice of them (a range of the array) b[i .. j]. Define functions none(b[i .. j]) and just_one(b[i .. j]) (can substitute the recursive definitions to get explicit formulas if required). We have, using C notation for logical operations (&& is and, || is or, ^ for xor (not really in C), ! is not):
none(b[i .. i + 1]) ~~> !b[i] && !b[i + 1]
just_one(b[i .. i + 1]) ~~> b[i] ^ b[i + 1]
And then recursively:
none(b[i .. j + 1]) ~~> none(b[i .. j]) && !b[j + 1]
just_one(b[i .. j + 1] ~~> (just_one(b[i .. j]) && !b[j + 1]) ^ (none(b[i .. j]) && b[j + 1])
And you are interested in just_one(b[1 .. n]).
The expressions will turn out horrible.
Have fun!
That python script does the job nicely. Here's the one-liner it uses:
((x ∨ (y ∨ z)) ∧ (¬(x ∧ y) ∧ (¬(z ∧ x) ∧ ¬(y ∧ z))))
Retracted for Privacy and Anders Johannsen provided already correct and simple answers. But both solutions do not scale very well (O(n^2)). If performance is important you can stick to the following solution, which performs in O(n):
def exact_one_of(array_of_bool):
exact_one = more_than_one = False
for array_elem in array_of_bool:
more_than_one = (exact_one and array_elem) or more_than_one
exact_one = (exact_one ^ array_elem) and (not more_than_one)
return exact_one
(I used python and a for loop for simplicity. But of course this loop could be unrolled to a sequence of NOT, AND, OR and XOR operations)
It works by tracking two states per boolean variable/list entry:
is there exactly one "True" from the beginning of the list until this entry?
are there more than one "True" from the beginning of the list until this entry?
The states of a list entry can be simply derived from the previous states and corresponding list entry/boolean variable.
Python:
let see using example...
steps:
below function exactly_one_topping takes three parameter
stores their values in the list as True, False
Check whether there exists only one true value by checking the count to be exact 1.
def exactly_one_topping(ketchup, mustard, onion):
args = [ketchup,mustard,onion]
if args.count(True) == 1: # check if Exactly one value is True
return True
else:
return False
How do you want to count how many are true without, you know, counting? Sure, you could do something messy like (C syntax, my Python is horrible):
for(i = 0; i < last && !booleans[i]; i++)
;
if(i == last)
return 0; /* No true one found */
/* We have a true one, check there isn't another */
for(i++; i < last && !booleans[i]; i++)
;
if(i == last)
return 1; /* No more true ones */
else
return 0; /* Found another true */
I'm sure you'll agree that the win (if any) is slight, and the readability is bad.
It is not possible without looping. Check BitSet cardinality() in java implementation.
http://fuseyism.com/classpath/doc/java/util/BitSet-source.html
We can do it this way:-
if (A=true or B=true)and(not(A=true and B=true)) then
<enter statements>
end if