Verification: combining correctness statements - assert

The question is:
P1 {C} Q1
-------------------------
P1 && P2 {C} Q1||Q2
Is this rule valid?
How would I go about tackling something like this? All I can think of is to try to find an example where it would be false.
I've been trying to come up with it so that the combination of P1 && P2 make both Q1 and Q2 false but I cant think of any. So im leaning towards this being valid, but I dont know where to go about proving it... The text for this class is absolute rubbish and I can't find any resources online for combination of correctness statements...

I'm assuming these are Hoare triples, normally denoted {P} C {Q}; I also use Wikipedia as a reference.
So your rule:
{P1} C {Q1}
-----------------------
{P1 && P2} C {Q1 || Q2}
is valid!
Intuitively it is quite clear if you unterstand the logic:
{P1} C {Q1} means: Whenever P1 holds, Q1 will hold after executing command C.
You know that if P1 && P2 holds, P1 holds.
You know that if Q1 holds, Q1 || Q2 holds.
You can piece these statements together to see, why your rule must be valid: P1 && P2 implies P1, so when you execute C, you get by assumptionQ1, which implies Q1 || Q2.
Therefore {P1 && P2} C {Q1 || Q2}, whenever you assume {P1} C {Q1}, which is exactly what your rule states.
Formally you can use the following rule (excerpt from Wikipedia):
Consequence rule
P' -> P, {P} C {Q}, Q -> Q'
---------------------------
{P'} C {Q'}
where you simply set P' as P1 && P2, P as P1, Q as Q1 and finally Q' as Q1 || Q2.

Related

May Leetcode Speedrun Question: Single element in a Sorted Array

So I was watching Errichto complete these challenges and I was amazed at how fast he solved the "Single element in a Sorted Array". From a beginner's perspective, it does look impressive - maybe for senior devs the speed is quite normal.
You are given a sorted array where all elements are integers, and all elements appear exactly twice in the array, except for one element, which appears exactly once. (i.e., all elements are duplicated, except one.) You need to find the element appearing exactly once.
I am just here to understand how said code works:
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
long long a = 0;
for(int x : nums) {
a ^= x
}
return a;
}
};
Here's what I've got so far:
for every single integer "x" in the vector/array "nums", a is equal to a^x (if what I said is correct).
And here are my questions:
Wouldn't a^x be equal to 0 because a is 0 since the beginning?
int singleNonDuplicate(vector<int> nums) {
//...
}
and
int singleNonDuplicate(vector<int>& nums) {
//...
}
I've understood this: vector<int> nums is pass by value (you're working with a "copy" of nums inside the function) and vector<int>& nums is pass by reference (you're working with nums itself inside the function).
Does the "&" matter if you were to solve the problem just like Errichto?
ps:
sorry for possible mistakes from a programming perspective, I might've accidentally said some wrong things.
yes I will learn C++ sooner or later, 2020 is the first year in my life where I actually have an actual "programming" class in my schedule, these videos are entertaining and I'm curious to see why said code works & try understand etc.
Casual proof:
(If you're interested in areas of study that help you to come up with solutions like this and understand them, I'd suggest Discrete Mathematics and Group Theory / Abstract Algebra.)
I think I know the question you were referencing. It goes something like,
You are given an unsorted array where all elements are integers, and all elements appear exactly twice in the array, except for one element, which appears exactly once. (i.e., all elements are duplicated, except one.)
You're on the right track for the first part, why the algorithm works. It takes advantage of a few properties of XOR:
X^0=X
X^X=0
The XOR operation is commutative and associative.
# proof
# since XOR is commutative, we can take advantage
# of the fact that all elements except our target
# occur in pairs of two:
P1, P1 = Two integers of the same value in a pair.
T = Our target.
# sample unsorted order, array size = 7 = (3*2)+1
[ P3, P1, T, P1, P2, P3, P2 ]
# since XOR is commutative, we can re-arrange the array
# to our liking, and still get the same value as
# the XOR algorithm.
# here, we move our target to the front, and then group
# each pair together. I've arranged them in ascending
# order, but that's not important:
[ T, P1, P1, P2, P2, P3, P3 ]
# write out the equation our algorithm is solving:
solution = 0 ^ T ^ P1 ^ P1 ^ P2 ^ P2 ^ P3 ^ P3
# because XOR is associative, we can use parens
# to indicate elements of the form X^X=0:
solution = T ^ (P1 ^ P1) ^ (P2 ^ P2) ^ (P3 ^ P3) ^ 0
# substitute X^X=0
solution = T ^ 0 ^ 0 ^ 0 ^ 0
# use X^0=X repeatedly
solution = T
So we know that running that algorithm will give us our target, T.
On using & to pass-by-reference instead of pass-by-value:
Your understanding is correct. Here, it doesn't make a real difference.
Pass-by-reference lets you modify the original value in place, which he doesn't do.
Pass-by-value copies the vector, which wouldn't meaningfully impact performance here.
So he gets style points for using pass-by-reference, and if you're using leetcode to demonstrate your diligence as a software developer it's good to see, but it's not pertinent to his solution.
^ is XOR operation in the world of coding, not the power operation (which you are assuming I guess).
I don't know about which problem you are talking about, if its finding the only unique element in array (given every other element occurs twice),
then the logic behind solving is
**a XOR a equals 0 **
**a XOR 0 equals a**
So if we XOR all the elements present in array, we will get 0 corresponding to the elements occurring twice.
The only element remaining will be XORed with 0 and hence we get the element.
Answer to second query is that whenever you want to modify the array we pass it by reference .
PS: I am also new to programming.I hope I answered your queries.

Boolean rules are bugging me

I just encountered a propably simple problem with booleans
If I have an if statement like this one: !(!A && !B) && B, how does it exactly go?
I thought it was the same as A && B (inverts the conditions inside the brackets), but it obviously wasn't.. which is bugging me
So, would someone like to elaborate how it really goes because I think I'm missing something here?
!(!A && !B) && B is the sams as (A || B) && B you forgot to invert the and to or. Which in turn btw is just B.
!(!A && !B) = (A || B)
so
!(!A && !B) && B = (A || B) && B = A && B || B = B
The final result is simply B
Unfortunately, in general case you cannot use logic identities in programming as you do that at discrete mathematics class.
As it was mentioned by HashPsi and Bas van Stein, from the logical point of view your expression is equivalent to B. In the real world you can have the following code:
def A():
throw StupidException()
def B():
return True
!(!A() && !B()) && B() # throws exception
B() # returns True
So technically your expression differs significantly from just B. You can argue that this is very specific example, but in practice most of your functions have some side effects, so in general you can never assume that mathematical logic works for boolean expressions.
As a real-world example where ordering of boolean expressions matters, you can consider a following idiomatic C++ code:
if (foo && foo->bar()) {do something}
The code above would check that foo is not null before calling bar method. If you just rearrange that expression, you'll get a crush:
if (foo->bar() && foo) {do something}
If foo==nullptr, foo->bar will cause termination of program, since foo->bar() will try to be called before check of foo value.

Checking if a list of arbitrary inequalities are satisfied

I am writing some code in C++ and need to check whether or not a list of inequalities in two unknown variables are satisfied.
For example, one possible list could be P = Q, Q < S, P = S which should NOT be satisfied
Another example, P = Q, Q < S, R = P, S > R should be satisfied
I have thought long and hard how to do this but I cannot seem to find any method other then a long, tedious one which involves checking if every new inequality added satisfies all the previous ones.
This is more of an exercise in boolean logic than C++. If you know Python use it.
A faster way would be to construct an "ordering" (in the maths sense) one statement at a time. That is where you have a sequence, a b c suppose and a
Suppose now each thing in the sequence is a vector of things equal to each other. In the above example:
P=Q
Our ordering looks like:
[P,Q]
Next Q
So now as we have an ordering:
[P,Q],[S]
We know [P,Q]<[S]
So P=S is an obvious contradiction.
First, remove all equalities P = Q by replacing all occurrences of Q with P.
This reduces P = Q, Q < S, R = P, S > R to R < S, S > R.
Second, build a directed graph with the variables as vertices and an edge from P to Q if your list constains P < Q or Q > P.
Third, check if the graph contains cycles. The inequalities are satisfiable iff the graph contains no cycles.
You might want to google for 2-SAT, which is related to this problem.

getting unknown result with a trivial forall

I am using th z3 C++ API. if I create this simple false expression:
z3::expr x = C->int_const("x");
z3::expr p = z3::forall(x, x==0);
and try to solve, I get an unknown outcome. I am not an expert of strategies and tactics, but I am sure that z3 can solve this, if I use the right tactic.
I also tried
z3::expr p = !z3::forall(x, x==0);
with, of course, the same runknown esult.
I'm not familiar with z3, but from a general C++ perspective, wouldn't x==0 evaluate first, i.e. wouldn't your call be equivalent to implies(x, 1)? From a quick search it seems you may have to construct each piece of the statement as a z3 object, for example:
Z3_ast consequent = Z3_mk_eq(ctx, x, 0);
Z3_ast theorem = Z3_mk_implies(ctx, x, consequent);
But the above is not correct, either. I believe the parameters x and 0 themselves have to be instances of Z3_ast that encapsulate the statement you mean (as opposed to their interpolated values or references).

Comparing two vectors of maps

I've got two ways of fetching a bunch of data. The data is stored in a sorted vector<map<string, int> >.
I want to identify whether there are inconsistencies between the two vectors.
What I'm currently doing (pseudo-code):
for i in 0... min(length(vector1), length(vector2)):
for (k, v) in vector1[i]:
if v != vector2[i][k]:
// report that k is bad for index i,
// with vector1 having v, vector2 having vector2[i][k]
for i in 0... min(length(vector1), length(vector2)):
for (k, v) in vector2[i]:
if v != vector1[i][k]:
// report that k is bad for index i,
// with vector2 having v, vector1 having vector1[i][k]
This works in general, but breaks horribly if vector1 has a, b, c, d and vector2 has a, b, b1, c, d (it reports brokenness for b1, c, and d). I'm after an algorithm that tells me that there's an extra entry in vector2 compared to vector1.
I think I want to do something where when I encountered mismatches entries, I look at the next entries in the second vector, and if a match is found before the end of the second vector, store the index i of the entry found in the second vector, and move to matching the next entry in the first vector, beginning with vector2[i+1].
Is there a neater way of doing this? Some standard algorithm that I've not come across?
I'm working in C++, so C++ solutions are welcome, but solutions in any language or pseudo-code would also be great.
Example
Given the arbitrary map objects: a, b, c, d, e, f and g;
With vector1: a, b, d, e, f
and vector2: a, c, e, f
I want an algorithm that tells me either:
Extra b at index 1 of vector1, and vector2's c != vector1's d.
or (I'd view this as an effectively equivalent outcome)
vector1's b != vector2's c and extra d at index 2 of vector1
Edit
I ended up using std::set_difference, and then doing some matching on the diffs from both sets to work out which entries were similar but different, and which had entries completely absent from the other vector.
Something like the std::mismatch algorithm
You could also use std::set_difference
It sounds like you're looking for the diff algorithm. The idea is to identify the longest common subsequence of the two vectors (using map equality), then recurse down the non-common portions. Eventually you'll have an alternating list of vector sub-sequences that are identical, and sub-sequences that have no common elements. You can then easily produce whatever output you like from this.
Apply it to the two vectors, and there you go.
Note that since map comparison is expensive, if you can hash the maps (use a strong hash - collisions will result in incorrect output) and use the hashes for comparisons you'll save a lot of time.
Once you're down to the mismatched subsequences at the end, you'll have something like:
Input vectors: a b c d e f, a b c' d e f
Output:
COMMON a b
LEFT c
RIGHT c'
COMMON d e f
You can then individually compare the maps c and c' to figure out how they differ.
If you have a mutation and insertion next to each other, it gets more complex:
Input vectors: a b V W d e f, a b X Y d e f
Output:
COMMON a b
LEFT V W
RIGHT X Y
COMMON d e f
Determining whether to match V and W against X or Y (or not at all) is something you'll have to come up with a heuristic for.
Of course, if you don't care about how the content of the maps differ, then you can stop here, and you have the output you want.
What exactly are you trying to achieve? Could you please define precisely what output you expect in terms of the input? Your pseudo code compares maps at the vector index. If that is not the correct semantics, then what is?
Can you associate with each map some kind of checksum (or Blumen filter) - that at single check you could be able to decide if comparison has a sense.
In your example, note that is not possible to differentiate between
Extra b at index 1 of vector1, and
vector2's c != vector1's d.
and
Extra b at index 1 of vector 1, extra
d at index 2 of v1, and extra c at 1
in v2
because it is not clear that "c" shoud be compared to "d", it could be compared to "b" either. I assume the vectors are not sorted, because std::map doesn't provide a relational operator. Rather are the maps, which is as far as I see completly irrelevant ;-)
So your example is slightly misreading. It could even be
Compare
b f e a d
with
a c f e
You can check each element of the first vector against each element of the second vector.
This has quadratic runtime.
for i in 0... length(vector1):
foundmatch = false;
for j in 0... length(vector2):
mismatch = false;
for (k, v) in vector1[i]:
if v != vector2[j][k]:
mismatch = true;
break; // no need to compare against the remaining keys.
if (!mismatch) // found matching element j in vector2 for element i in vector1
foundmatch = true;
break; // no need to compare against the remaining elements in vector2
if (foundmatch)
continue;
else
// report that vector1[i] has no matching element in vector2[]
// "extra b at i"
If you want the find the missing elements, just swap vector1 and vector2.
If you want to check in a element in vector2 mismatches to a element in vector1 in only a single key, you have to add additional code around "no need to compare against the remainig keys".