What is the correct way to simplify a xnor - boolean-logic

I was reading over a resource https://www.mi.mun.ca/users/cchaulk/misc/boolean.htm and I noticed the xnor simplification seems to have mixed outputs.
15a, 15b, 15c are all focusing on xnor but only 15b seems to be correct when I attempt to check.
For reference:
15a = (X + Y) • '(X • Y)
15b = 'X'Y + XY
15c = (X + Y) • ('X + 'Y)
The expected truth table for all of them are:
x
y
output
0
0
true
0
1
false
1
0
false
1
1
true
But only 15b is giving that as the truth table.
Am I solving 15a,15c incorrectly or is the resource incorrect?

15b is the definition of XNOR in conjunctive normal form. 15c is the negation of XNOR (i.e., XOR) in disjunctive normal form. You can derive this using De Morgan's laws, which state
'(XY) == 'X + 'Y
'(X + Y) == 'X'Y
Using these laws, we can first write 15b
'X'Y + XY = '('('X'Y)'(XY))
= '((X + Y)('X + 'Y))
to get the negation of 15c. Using it again, we get the negation of 15a.
= '(X + Y) + '('X + 'Y)
= '(X + Y) + XY
= '((X+Y) '(XY))

Related

If statement doesn't evaluate

I know that questions like these seem to be looked down upon, but I haven't been able to find answers on the internet. I have the following function:
fun count :: "'a ⇒ 'a list ⇒ nat" where
"count a [] = 0"
| "count a (b # xs) = (count a xs) + (if a = b then 1 else 0)"
It counts the number of elements in a list that match with the given item. Simple enough, however, when I do the following:
value "count x [x,x,y,x,y]"
I get this as the output
"(if x = y then 1 else 0) + 1 + (if x = y then 1 else 0) + 1 + 1" :: "nat"
So you can see that there are hanging "if" statements and unevaluated additions in the output. Is it possible to make Isabelle simplify this?
I don't think so. The value command is more of a purely diagnostic tool and it is mostly meant for evaluation of ground terms (i.e. no free variables). The reason why you get a result at all is that it falls back from its standard method (compiling to ML, running the ML code, and converting the result back to HOL terms) to NBE (normalisation by evaluation, which is much slower and, at least in my experience, not that useful most of the time).
One trick that I do sometimes is to set up a lemma
lemma "count x [x, x, y, x, y] = myresult"
where the myresult on the right-hand side is just a dummy variable. Then I do
apply simp
and look at the resulting proof state (in case you don't see anything: try switching on "Editor Output State" in the options):
proof (prove)
goal (1 subgoal):
1. (x = y ⟶ Suc (Suc (Suc (Suc (Suc 0)))) = myresult) ∧
(x ≠ y ⟶ Suc (Suc (Suc 0)) = myresult)
It's a bit messy, but you can read of the result fairly well: if x = y, then the result is 5, otherwise it's 3. A simple hack to get rid of the Suc in the output is to cast to int, i.e. lemma "int (count x [x, x, y, x, y]) = myresult". Then you get:
(x = y ⟶ myresult = 5) ∧ (x ≠ y ⟶ myresult = 3)

Build x XOR (y XOR z) with NAND port

I need to make x xor(y xor z) with only NAND ports.
Notation: NOT(y) = ~y.
My first steps were to identify the output of that stuff, so:
x xor(y xor z) = x xor (y~z + ~yz) = ~x(y~z + ~yz) + x~(y~z + ~yz) = ~xy~z + ~x~yz + x~y~z + xyz
So the final output of my NAND construction should be: ~xy~z + ~x~yz + x~y~z + xyz
I tried to attack this by first making y XOR z:
y XOR z = y~z + ~yz = NAND[NAND(y,NAND(z,z)),NAND(z,NAND(y,y))]
Since
NAND(y,NAND(z,z)) = NOT(y * NOT(z*z)) = NOT(y) + z which I'll call g1 and
NAND(z,NAND(y,y)) = NOT(z * NOT(y*y)) = NOT(z) + y as g2
then the outside NAND[g1,g2] = z~y + y~z.
So now I have a XOR with just NANDs and doing the x xor (y xor z) should be just matter of treating (y xor z) as a single variable which gives me:
x xor (y xor z) = NAND[NAND(x,NAND(NAND[NAND(y,NAND(z,z)),NAND(z,NAND(y,y))],NAND[NAND(y,NAND(z,z)),NAND(z,NAND(y,y))])),NAND(NAND[NAND(y,NAND(z,z)),NAND(z,NAND(y,y))],NAND(x,x))]
Am I correct? I feel like the xor could be made in a more efficient way than using 5 NANDs ports.
Thanks guys.
Your final expression is correct.
The 20 NAND gates can be reduced to eight:
This circuit makes use of XOR(x,y,z) = XOR(XOR(x,y),z). It is a combination of two two-input XOR gates, each of them composed of four NAND gates.

Explain why x == ~(~x + 1) + 1 (two's complement and back!)

As we all know usually negative numbers in memory represents as two's complement numbers like that
from x to ~x + 1
and to get back we don't do the obvious thing like
~([~x + 1] - 1)
but instead we do
~[~x + 1] + 1
can someone explain why does it always work? I think I can proof it with 1-bit, 2-bit, 3-bit numbers and then use Mathematical induction but it doesn't help me understand how exactly that works.
Thanks!
That's the same thing anyway. That is, ~x + 1 == ~(x - 1). But let's put that aside for now.
f(x) = ~x + 1 is its own inverse. Proof:
~(~x + 1) + 1 =
(definition of subtraction: a - b = ~(~a + b))
x - 1 + 1 =
(you know this step)
x
Also, ~x + 1 == ~(x - 1). Why? Well,
~(x - 1) =
(definition of subtraction: a - b = ~(~a + b))
~(~(~x + 1)) =
(remove double negation)
~x + 1
And that (slightly unusual) definition of subtraction, a - b = ~(~a + b)?
~(~a + b) =
(use definition of two's complement, ~x = -x - 1)
-(~a + b) - 1 =
(move the 1)
-(~a + b + 1) =
(use definition of two's complement, ~x = -x - 1)
-(-a + b) =
(you know this step)
a - b
This is because if you increment ~x (assuming no overflow). Then converting it to back to x, you've incremented relative to ~x, but decremented relative to x. Same thing applies vice versa. Assuming your variable x has a specific value, every time you increment it, relative to ~x you'll notice it decrements.
From a programmer's point of view, this is what you'd essentially witness.
Let short int x = 1 (0x0001)
then ~x = 65534 (0xFFFE)
~x + 1 = 65534 + 1 (0xFFFF)
~(~x+1) = 0 (0x0000)
~(~x+1) + 1 = 0 + 1 (0x0001)

Maxima - Substitutions in Equations - let() and letsimp() without effect

My own equation is a bit longer, but the following example shows perfectly where I struggle at the moment.
So far I have been using the let() and letsimp() function
to substitute longer terms in an equation,
but in this example they have no effect:
(%i1) eq: ((2*u+a^2+d) * y+x)/2*a = x;
2
a ((2 u + d + a ) y + x)
(%o1) ------------------------ = x
2
(%i2) let(2*u+a^2+d, %beta);
2
(%o2) 2 u + d + a --> %beta
(%i3) letsimp(eq);
2
a ((2 u + d + a ) y + x)
(%o3) ------------------------ = x
2
What is the preferred way to replace 2*u+a^2+d with %beta in this sample equation?
And why has letsimp() no effect?
Thank you very much!
letsimp applies only to "*" expressions. You could try subst.

Intersection of parabolic curve and line segment

I have an equation for a parabolic curve intersecting a specified point, in my case where the user clicked on a graph.
// this would typically be mouse coords on the graph
var _target:Point = new Point(100, 50);
public static function plot(x:Number, target:Point):Number{
return (x * x) / target.x * (target.y / target.x);
}
This gives a graph such as this:
I also have a series of line segments defined by start and end coordinates:
startX:Number, startY:Number, endX:Number, endY:Number
I need to find if and where this curve intersects these segments (A):
If it's any help, startX is always < endX
I get the feeling there's a fairly straight forward way to do this, but I don't really know what to search for, nor am I very well versed in "proper" math, so actual code examples would be very much appreciated.
UPDATE:
I've got the intersection working, but my solution gives me the coordinate for the wrong side of the y-axis.
Replacing my target coords with A and B respectively, gives this equation for the plot:
(x * x) / A * (B/A)
// this simplifies down to:
(B * x * x) / (A * A)
// which i am the equating to the line's equation
(B * x * x) / (A * A) = m * x + b
// i run this through wolfram alpha (because i have no idea what i'm doing) and get:
(A * A * m - A * Math.sqrt(A * A * m * m + 4 * b * B)) / (2 * B)
This is a correct answer, but I want the second possible variation.
I've managed to correct this by multiplying m with -1 before the calculation and doing the same with the x value the last calculation returns, but that feels like a hack.
SOLUTION:
public static function intersectsSegment(targetX:Number, targetY:Number, startX:Number, startY:Number, endX:Number, endY:Number):Point {
// slope of the line
var m:Number = (endY - startY) / (endX - startX);
// where the line intersects the y-axis
var b:Number = startY - startX * m;
// solve the two variatons of the equation, we may need both
var ix1:Number = solve(targetX, targetY, m, b);
var ix2:Number = solveInverse(targetX, targetY, m, b);
var intersection1:Point;
var intersection2:Point;
// if the intersection is outside the line segment startX/endX it's discarded
if (ix1 > startX && ix1 < endX) intersection1 = new Point(ix1, plot(ix1, targetX, targetY));
if (ix2 > startX && ix2 < endX) intersection2 = new Point(ix2, plot(ix2, targetX, targetY));
// somewhat fiddly code to return the smallest set intersection
if (intersection1 && intersection2) {
// return the intersection with the smaller x value
return intersection1.x < intersection2.x ? intersection1 : intersection2;
} else if (intersection1) {
return intersection1;
}
// this effectively means that we return intersection2 or if that's unset, null
return intersection2;
}
private static function solve(A:Number, B:Number, m:Number, b:Number):Number {
return (m + Math.sqrt(4 * (B / (A * A)) * b + m * m)) / (2 * (B / (A * A)));
}
private static function solveInverse(A:Number, B:Number, m:Number, b:Number):Number {
return (m - Math.sqrt(4 * (B / (A * A)) * b + m * m)) / (2 * (B / (A * A)));
}
public static function plot(x:Number, targetX:Number, targetY:Number):Number{
return (targetY * x * x) / (targetX * targetX);
}
Or, more explicit yet.
If your parabolic curve is
y(x)= A x2+ B x + C (Eq 1)
and your line is
y(x) = m x + b (Eq 2)
The two possible solutions (+ and -) for x are
x = ((-B + m +- Sqrt[4 A b + B^2 - 4 A C - 2 B m + m^2])/(2 A)) (Eq 3)
You should check if your segment endpoints (in x) contains any of these two points. If they do, just replace the corresponding x in the y=m x + b equation to get the y coordinate for the intersection
Edit>
To get the last equation you just say that the "y" in eq 1 is equal to the "y" in eq 2 (because you are looking for an intersection!).
That gives you:
A x2+ B x + C = m x + b
and regrouping
A x2+ (B-m) x + (C-b) = 0
Which is a quadratic equation.
Equation 3 are just the two possible solutions for this quadratic.
Edit 2>
re-reading your code, it seems that your parabola is defined by
y(x) = A x2
where
A = (target.y / (target.x)2)
So in your case Eq 3 becomes simply
x = ((m +- Sqrt[4 A b + m^2])/(2 A)) (Eq 3b)
HTH!
Take the equation for the curve and put your line into y = mx +b form. Solve for x and then determine if X is between your your start and end points for you line segment.
Check out: http://mathcentral.uregina.ca/QQ/database/QQ.09.03/senthil1.html
Are you doing this often enough to desire a separate test to see if an intersection exists before actually computing the intersection point? If so, consider the fact that your parabola is a level set for the function f(x, y) = y - (B * x * x) / (A * A) -- specifically, the one for which f(x, y) = 0. Plug your two endpoints into f(x,y) -- if they have the same sign, they're on the same side of the parabola, while if they have different signs, they're on different sides of the parabola.
Now, you still might have a segment that intersects the parabola twice, and this test doesn't catch that. But something about the way you're defining the problem makes me feel that maybe that's OK for your application.
In other words, you need to calulate the equation for each line segment y = Ax + B compare it to curve equation y = Cx^2 + Dx + E so Ax + B - Cx^2 - Dx - E = 0 and see if there is a solution between startX and endX values.