Boolean Algebra help: duals - math

I consistently keep getting this question wrong, and I cant figure out why
(a+b)(b+c)=ac+b
I put this as the answer:
ab+bc=a+cb
I do not understand why that is wrong

(a || b) && (b || c) = (a && c) || b
It's written in c style (may be better for understanding). It means that if we have b = true the result is true, if b = false the result is depends of a and c in couple. Also we can find result for each tuple of (a, b, c) and for identical tuple we have identical results.

Related

Simplifying the boolean expression (A && B) || (A && !B && C)

I'm so confused currently while trying to simplify a boolean expression. I know the solution but not the correct way to achieve it.
What law makes (A && B) || (A && !B && C) the same as (A && B) || (A && C)
Why can i leave the !B?
Since (in simplified notation):
B+B'C = B+B+B'C = B(C+C')+B(C'+C)+B'C = BC+BC'+BC'+BC+B'C = BC+BC'+BC'+(B+B')C = BC+BC'+1C = B(C+C')+C = B+C
we have
AB + AB'C = A (B + B'C) = A(B+C) = AB + AC
I don't know of any law, but I will try to explain it.
For us to reach the check of !B we must acknowledge two things:
A must be TRUE
B must be FALSE
If A is false we can short-circuit out of both checks (A && B) and (A && !B && C) because A is evaluated first and we are only comparing with &&.
If A is true and B is true, the second condition is not evaluated.
Therefore, to reach !B, A must be true and B must be false as stated above. If that's the case then !B will always evaluate to TRUE in the second condition, and can be removed.

Swapping Variables by pattern matching?

Assume you have 2 Integer Variables a and b
How would you swap them only if a > b by using a match expression?
If a <= b do not swap the ints.
In an imperative language:
if (a > b){
int temp=a;
a=b;
b=temp;
}
Doing the same in ocaml seems surprisingly hard.
I tried
let swap a b =
match a,b with
| a,b when a > b -> b,a
| a,b when a <= b -> a,b
I am trying to do this because in the following function call, I want to make sure that x is the bigger of the two variables.
One easy way :
let swap a b =
if (a>b) then (b,a)
else (a,b)
But this is not equivalent to the C code, your C code is swapping the value of the variable - this is how imperative language are doing.
In Ocaml, there is no side-effect (except if you use reference to some int). This swap function will return a tuple whose members are always ordered (the first member will be always smaller than the second order).
Without state, you cannot "swap" the values of the variables since the variables are immutable. Your best bet is to use a tuple and introduce new variables in the scope. Example:
let diff a b =
let (min, max) = if a <= b then (a, b) else (b, a)
in max - min
You can of course use the same identifiers and shadow the original variables:
let diff a b =
let (a, b) = if a <= b then (a, b) else (b, a)
in b - a
It doesn't really help with readability though.
Just for reference, if you'd like to swap the values in two refs, it would look like the following:
let swap a_ref b_ref =
let a, b = !a_ref, !b_ref in
a_ref := b;
b_ref := a
;;
which has the type val swap : 'a ref -> 'a ref -> unit.

Ocaml pattern matching for "square" tuple?

In attempting to learn Ocaml and functional languages in general, I have been looking into pattern matching. I was reading this documentation, and decided to try the following exercise for myself:
Make an expression that evaluates to true when an integer 4-tuple is input such that each element in the 4-tuple is equal.
(4, 4, 4, 4) -> true
(4, 2, 4, 4) -> false
I find that doing pattern matching for the specificity of the value of the elements to not be obvious. This is the code I wrote.
let sqr x = match x with
(a, a, a, a) -> true
| (_, _, _, _) -> false ;;
Of course, this code throws the following error:
Error: Variable a is bound several times in this matching
How else can I not only enforce that x is a 4-tuple, but also of strictly integers that are equal?
(Also, of course a "square" tuple should not allow non-positive integers, but I'm more concerned with the aforementioned problem as of now).
`
As you found out, unlike some other languages' pattern-matching systems, you can't do this in OCaml. What you can do is match each element of the tuple separately while using guards to only succeed if some property (like equivalence) holds across them:
let sqr x =
match x with
| (a, b, c, d) when a = b && b = c && c = d -> `Equal
| (a, b, c, d) when (a < b && b < c && c < d)
|| (a > b && b > c && c > d) -> `Ordered
| _ -> `Boring
You have many ways to do pattern-matching, pattern matching is not only when using the match keyword
let fourtuple_equals (a,b,c,d) = List.for_all ((=) a) [b;c;d]
val fourtuple_equals : 'a * 'a * 'a * 'a -> bool = <fun>
Here you have a pattern matching directly in the parameter in order to access your four elements tuple.
In this example I use a list to have a more concise code, but is not the more efficient.

How to eliminate division inside code like "a/b>c/d"?

For example, if I don't want division in "a/b==c/d",I can rewrite it as "ad==bc".
But "a/b>c/d" is not always = "ad>bc", for example:
a=20, b=5, c=9,d=3 : a/b>c/d is true and ad>bc is true
but
a=-20, b=-5, c=9,d=3 : a/b>c/d is true but ad>bc is false
I started to found the patten, it seems (I am not sure if it is right):
if b and d has same sign, a/b>c/d = ad > bc
if b and d has different sign, a/b > c/d = ad < bc
if I rewrite "a/b>c/d" as
(( (b>0 && d>0 || b<0 && d<0) && a*d>b*c) || ( ((b>0 && d<0) || b<0 && d>0) && a*d<b*c)
,it needs type more characters, also I need to type each variable more than 1 time,and this form is very hard to maintain if I want to change to
a/b>=c/d
or
a/b<c/d
Is there any method to eliminate division in a/b>c/d in simpler way?
You can rewrite it as:
a*d*b*d > b*c*b*d
This way if b and d have different signs then b*d will be a negative number and the comparison will be flipped back the correct way. Be careful about overflows however. To make the code equivalent to a/b > c/d you will also need to check if b or d are zeros.
May be you can get the signs of b and d by bitwise operation, and then rewrite "a/b>c/d" as
(((b>>31)&1) ^ ((d>>31)&1)) ^ (ad > bc)
which is equivalent to
((b>0) ^ (d>0)) ^ (ad > bc)
say b and d are 32-bits integers
When you multiply both sides of an inequality by some non-zero number v, then if v is negative you must reverse the direction of the inequality.
So in your case you are multiplying by b*d so
if (a/b > c/d) {
...
}
is equivalent to
v = b * d;
if(v==0) {
error
}
if ( ( (v>0) && (a*d > c*b) ) ||
( (v<0) && (a*d < c*b) ) ) {
...
}
If you don't care whether you're using > or >=, or care about the handling of v==0 you can rewrite this as
if ( (v>0) ^ (a*d > c*b ) ) {
...
}
There's further considerations required if a, b, c and d are floating point numbers as you need to consider the behaviour of positive and negative infinity, signed zeros and "not a number" values.

Query on Booleans in Lambda Calculus

This is the lambda calculus representation for the AND operator:
lambda(m).lambda(n).lambda (a).lambda (b). m(n a b) b
Can anyone help me in understanding this representation?
To understand how to represent Booleans in lambda calculus, it helps to think about an IF expression, "if a then b else c". This is an expression which chooses the first branch, b, if it is true, and the second, c, if it is false. Lambda expressions can do that very easily:
lambda(x).lambda(y).x
will give you the first of its arguments, and
lambda(x).lambda(y).y
gives you the second. So if a is one of those expressions, then
a b c
gives either b or c, which is just what we want the IF to do. So define
true = lambda(x).lambda(y).x
false = lambda(x).lambda(y).y
and a b c will behave like if a then b else c.
Looking inside your expression at (n a b), that means if n then a else b.
Then m (n a b) b means
if m then (if n then a else b) else b
This expression evaluates to a if both m and n are true, and to b otherwise. Since a is the first argument of your function and b is the second, and true has been defined as a function that gives the first of its two arguments, then if m and n are both true, so is the whole expression. Otherwise it is false. And that's just the definition of and!
All this was invented by Alonzo Church, who invented the lambda calculus.
In the lambda calculus, a Boolean is represented by a function that takes two arguments, one for success and one for failure. The arguments are called continuations, because they continue with the rest of the computation; the boolean True calls the success continuation and the Boolean False calls the failure continuation. This coding is called the Church encoding, and the idea is that a Boolean is very much like an "if-then-else function".
So we can say
true = \s.\f.s
false = \s.\f.f
where s stands for success, f stands for failure, and the backslash is an ASCII lambda.
Now I hope you can see where this is going. How do we code and? Well, in C we could expand it to
n && m = n ? m : false
Only these are functions, so
(n && m) s f = (n ? m : false) s f = n ? (m s f) : (false s f) = n ? (m s f) : f
BUT, the ternary construct, when coded in the lambda calculus, is just function application, so we have
(n && m) s f = (n m false) s f = n (m s f) (false s f) = n (m s f) f
So finally we arrive at
&& = \n . \m . \s . \f . n (m s f) f
And if we rename the success and failure continuations to a and b we return to your original
&& = \n . \m . \a . \b . n (m a b) b
As with other computations in lambda calculus, especially when using Church encodings, it is often easier to work things out with algebraic laws and equational reasoning, then convert to lambdas at the end.
Actually it's a little more than just the AND operator. It's the lambda calculus' version of if m and n then a else b. Here's the explanation:
In lambda calculus true is represented as a function taking two arguments* and returning the first. False is represented as function taking two arguments* and returning the second.
The function you showed above takes four arguments*. From the looks of it m and n are supposed to be booleans and a and b some other values. If m is true, it will evaluate to its first argument which is n a b. This in turn will evaluate to a if n is true and b if n is false. If m is false, it will evaluate to its second argument b.
So basically the function returns a if both m and n are true and b otherwise.
(*) Where "taking two arguments" means "taking an argument and returning a function taking another argument".
Edit in response to your comment:
and true false as seen on the wiki page works like this:
The first step is simply to replace each identifier with its definition, i.e. (λm.λn. m n m) (λa.λb. a) (λa.λb. b). Now the function (λm.λn. m n m) is applied. This means that every occurrence of m in m n m is replaced with the first argument ((λa.λb. a)) and every occurrence of n is replaced with the second argument ((λa.λb. b)). So we get (λa.λb. a) (λa.λb. b) (λa.λb. a). Now we simply apply the function (λa.λb. a). Since the body of this function is simply a, i.e. the first argument, this evaluates to (λa.λb. b), i.e. false (as λx.λy. y means false).

Resources