truth table: Binary Operations 3
requirements
preview
These are the tests I have at the end of the chapter
1import src.truth_table
2import unittest
3
4
5class TestBinaryOperations(unittest.TestCase):
6
7 def test_contradiction(self):
8 contradiction = src.truth_table.contradiction
9 self.assertFalse(contradiction(True, True))
10 self.assertFalse(contradiction(True, False))
11 self.assertFalse(contradiction(False, True))
12 self.assertFalse(contradiction(False, False))
13
14 def test_logical_conjunction(self):
15 logical_conjunction = (
16 src.truth_table.logical_conjunction
17 )
18 self.assertTrue(
19 logical_conjunction(True, True)
20 )
21 self.assertFalse(
22 logical_conjunction(True, False)
23 )
24 self.assertFalse(
25 logical_conjunction(False, True)
26 )
27 self.assertFalse(
28 logical_conjunction(False, False)
29 )
30
31 def test_project_second(self):
32 project_second = src.truth_table.project_second
33 self.assertTrue(project_second(True, True))
34 self.assertFalse(project_second(True, False))
35 self.assertTrue(project_second(False, True))
36 self.assertFalse(project_second(False, False))
37
38 def test_converse_non_implication(self):
39 converse_non_implication = (
40 src.truth_table.converse_non_implication
41 )
42 self.assertFalse(
43 converse_non_implication(True, True)
44 )
45 self.assertFalse(
46 converse_non_implication(True, False)
47 )
48 self.assertTrue(
49 converse_non_implication(False, True)
50 )
51 self.assertFalse(
52 converse_non_implication(False, False)
53 )
54
55 def test_negate_first(self):
56 negate_first = src.truth_table.negate_first
57 self.assertFalse(negate_first(True, True))
58 self.assertFalse(negate_first(True, False))
59 self.assertTrue(negate_first(False, True))
60 self.assertTrue(negate_first(False, False))
61
62 def test_logical_nand(self):
63 logical_nand = src.truth_table.logical_nand
64 self.assertFalse(logical_nand(True, True))
65 self.assertTrue(logical_nand(True, False))
66 self.assertTrue(logical_nand(False, True))
67 self.assertTrue(logical_nand(False, False))
68
69 def test_tautology(self):
70 tautology = src.truth_table.tautology
71 self.assertTrue(tautology(True, True))
72 self.assertTrue(tautology(True, False))
73 self.assertTrue(tautology(False, True))
74 self.assertTrue(tautology(False, False))
75
76 def test_logical_disjunction(self):
77 logical_disjunction = (
78 src.truth_table.logical_disjunction
79 )
80 self.assertTrue(logical_disjunction(True, True))
81 self.assertTrue(logical_disjunction(True, False))
82 self.assertTrue(logical_disjunction(False, True))
83 self.assertFalse(logical_disjunction(False, False))
84
85 def test_exclusive_disjunction(self):
86 exclusive_disjunction = (
87 src.truth_table.exclusive_disjunction
88 )
89 self.assertFalse(exclusive_disjunction(True, True))
90 self.assertTrue(exclusive_disjunction(True, False))
91 self.assertTrue(exclusive_disjunction(False, True))
92 self.assertFalse(exclusive_disjunction(False, False))
93
94 def test_material_non_implication(self):
95 material_non_implication = (
96 src.truth_table.material_non_implication
97 )
98 self.assertFalse(
99 material_non_implication(True, True)
100 )
101 self.assertTrue(
102 material_non_implication(True, False)
103 )
104 self.assertFalse(
105 material_non_implication(False, True)
106 )
107 self.assertFalse(
108 material_non_implication(False, False)
109 )
110
111 def test_project_first(self):
112 project_first = src.truth_table.project_first
113 self.assertTrue(project_first(True, True))
114 self.assertTrue(project_first(True, False))
115 self.assertFalse(project_first(False, True))
116 self.assertFalse(project_first(False, False))
117
118 def test_converse_implication(self):
119 converse_implication = (
120 src.truth_table.converse_implication
121 )
122 self.assertTrue(
123 converse_implication(True, True)
124 )
125 self.assertTrue(
126 converse_implication(True, False)
127 )
128 self.assertFalse(
129 converse_implication(False, True)
130 )
131 self.assertTrue(
132 converse_implication(False, False)
133 )
134
135
136# Exceptions seen
137# AttributeError
138# TypeError
139# AssertionError
140# SyntaxError
continue the project
Make sure you are in the
pumping_pythonfolder with pwd in the terminalpwdif the terminal does not show
.../pumping_pythonchange directory to the
pumping_pythonfolderOnce in
pumping_python, change directory to the projectcd truth_tablethe terminal shows
.../pumping_python/truth_tableI run the tests with pytest-watcher
uv run pytest-watcher . --nowthe terminal is my friend, and shows
rootdir: .../pumping_python/truth_table configfile: pyproject.toml collected 12 items tests/test_binary.py ........ [ 66%] tests/test_nullary_unary.py .... [100%] ================== 12 passed in G.HIs ===================I hold ctrl (Windows) or option (MacOS) on the keyboard, then click on
tests/test_binary.pywith the mouse to open itUp to this point I have tested
contradiction which always returns False
logical_conjunction aka and which returns
first_input and second_inputproject_second which always returns
second_inputconverse_non_implication which returns
not first_input and second_inputnegate_first which always returns
not first_inputlogical_nand which returns
not (first_input and second_input)tautology which always returns True
logical_disjunction which returns
first_input or second_input
test_exclusive_disjunction
The truth table for exclusive_disjunction is
first input |
second input |
return |
|---|---|---|
True |
True |
False |
True |
False |
True |
False |
True |
True |
False |
False |
False |
RED: make it fail
I add a test for exclusive_disjunction with an assertion for the case when the first input is True and the second input is True, to test_binary.py
first input |
second input |
return |
|---|---|---|
True |
True |
False |
76 def test_logical_disjunction(self):
77 logical_disjunction = (
78 src.truth_table.logical_disjunction
79 )
80 self.assertTrue(logical_disjunction(True, True))
81 self.assertTrue(logical_disjunction(True, False))
82 self.assertTrue(logical_disjunction(False, True))
83 self.assertFalse(logical_disjunction(False, False))
84
85 def test_exclusive_disjunction(self):
86 exclusive_disjunction = (
87 src.truth_table.exclusive_disjunction
88 )
89 self.assertFalse(exclusive_disjunction(True, True))
90
91
92# Exceptions seen
the terminal is my friend, and shows AttributeError
AttributeError: module 'src.truth_table'
has no attribute 'exclusive_disjunction'
because truth_table.py does not have anything in it with that name.
GREEN: make it pass
I add exclusive_disjunction to truth_table.py
54def logical_disjunction(first_input, second_input):
55 return logical_negation(
56 logical_conjunction(
57 logical_negation(first_input),
58 logical_negation(second_input)
59 )
60 )
61 return first_input or second_input
62
63
64def exclusive_disjunction(first_input, second_input):
65 return False
the test passes. exclusive_disjunction returns False, if the first input is True and the second input is True.
REFACTOR: make it better
I add an assertion for the next case, which is when the first input is True and the second input is False, to test_exclusive_disjunction in
test_binary.pyfirst input
second input
return
True
False
True
85 def test_exclusive_disjunction(self): 86 exclusive_disjunction = ( 87 src.truth_table.exclusive_disjunction 88 ) 89 self.assertFalse(exclusive_disjunction(True, True)) 90 self.assertTrue(exclusive_disjunction(True, False)) 91 92 93# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: False is not truebecause the function returns False and the assertion expects True.
I add an if statement to the exclusive_disjunction function in
truth_table.py64def exclusive_disjunction(first_input, second_input): 65 if second_input == False: 66 return True 67 return Falsethe test passes. exclusive_disjunction returns
True, if the second input is False
False, if the above condition is NOT met
I add an assertion for the third case, which is when the first input is False and the second input is True, to
test_binary.pyfirst input
second input
return
False
True
True
85 def test_exclusive_disjunction(self): 86 exclusive_disjunction = ( 87 src.truth_table.exclusive_disjunction 88 ) 89 self.assertFalse(exclusive_disjunction(True, True)) 90 self.assertTrue(exclusive_disjunction(True, False)) 91 self.assertTrue(exclusive_disjunction(False, True)) 92 93 94# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: False is not truebecause this happens when
if second_input == False:runs, Python checks ifsecond_inputis equal to Falseif
second_inputis NOT equal to False, it leaves the if statement and continues to run the rest of the function -return Falseand leaves the function since the return statement is the last thing to run in a functionsecond_inputis True in this case, which raises AssertionError since the function returns False and the assertion expects True
I add an if statement to exclusive_disjunction in
truth_table.py64def exclusive_disjunction(first_input, second_input): 65 if first_input == False: 66 return True 67 if second_input == False: 68 return True 69 return Falsethe test passes because this happens when exclusive_disjunction is called - it runs
if first_input == False:, where Python checks iffirst_inputis equal to Falseif
first_inputis NOT equal to False, it leaves the if statement and continues to the next if statement in the function -if second_input == False:.which checks ifsecond_inputis equal to Falseif
second_inputis NOT equal to False, it leaves the if statement and continues to run the rest of the function -return Falseand leaves the function since the return statement is the last thing to run in a functionif
second_inputis equal to False, it goes to the next line - ``return True `` and leaves the function since the return statement is the last thing to run in a function
if
first_inputis equal to False, it goes to the next line - ``return True `` and leaves the function since the return statement is the last thing to run in a functionso far this is the same as the first three cases of logical_nand
I add an assertion for the last case, which is when the first input is False and the second input is False to test_exclusive_disjunction, in
test_binary.pyfirst input
second input
return
False
False
False
85 def test_exclusive_disjunction(self): 86 exclusive_disjunction = ( 87 src.truth_table.exclusive_disjunction 88 ) 89 self.assertFalse(exclusive_disjunction(True, True)) 90 self.assertTrue(exclusive_disjunction(True, False)) 91 self.assertTrue(exclusive_disjunction(False, True)) 92 self.assertFalse(exclusive_disjunction(False, False)) 93 94 95# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: True is not falsebecause this happens when exclusive_disjunction is called - it runs
if first_input == False:, where Python checks iffirst_inputis equal to Falseif
first_inputis equal to False, it goes to the next line -return Trueif
first_inputis NOT equal to False, it leaves the if statement and continues to the next if statement at the same indentation level in the function -if second_input == False:, which checks ifsecond_inputis equal to Falseif
second_inputis NOT equal to False, it leaves the if statement and continues to run the rest of the function -return Falseif
second_inputis equal to False, it goes to the next line -return Truesecond_inputis False in this case, which raises AssertionError since the function returns True and the assertion expects False
I add an if statement for this case, to the one for when the first input is False in the exclusive_disjunction function in
truth_table.py64def exclusive_disjunction(first_input, second_input): 65 if first_input == False: 66 if second_input == False: 67 return False 68 return True 69 if second_input == False: 70 return True 71 return Falsethe test passes because this happens when exclusive_disjunction is called - it runs
if first_input == False:, where Python checks iffirst_inputis equal to Falseif
first_inputis NOT equal to False, it leaves the if statement and continues to the next if statement at the same indentation level in the function -if second_input == False:, which checks ifsecond_inputis equal to Falseif
second_inputis NOT equal to False, it leaves the if statement and continues to run the rest of the function -return Falseif
second_inputis equal to False, it goes to the next line -return True
if
first_inputis equal to False, it goes to the next line -if second_input == False, which checks ifif second_inputis equal to Falseif
second_inputis NOT equal to False, it leaves the if statement and continues to the next line forif first_input == False:-return Trueif
second_inputis equal to False, it goes to the next line -return False
there are two cases where exclusive_disjunction returns False and two cases where it returns True. I add an if statement for the other case where it returns True, to make it clearer
64def exclusive_disjunction(first_input, second_input): 65 if first_input == False: 66 if second_input == False: 67 return False 68 return True 69 if first_input == True: 70 if second_input == False: 71 return True 72 return Falsethe test is still green because this happens when exclusive_disjunction is called - it runs
if first_input == False:, where Python checks iffirst_inputis equal to Falseif
first_inputis NOT equal to False, it leaves the if statement and continues to the next if statement at the same indentation level in the function -if first_input == True:, which checks iffirst_inputis equal to Trueif
first_inputis NOT equal to True, it leaves the if statement and continues to run the rest of the function -return Falseand leaves the function since the return statement is the last thing to run in a functionif
first_inputis equal to True, it goes to the next line -if second_input == False:, which checks ifsecond_inputis equal to Falseif
second_inputis NOT equal to False, it leaves the if statement and continues to run the rest of the function -return Falseand leaves the function since the return statement is the last thing to run in a functionif
second_inputis equal to False, it runs the next line - ``return True `` and leaves the function since the return statement is the last thing to run in a function
if
first_inputis equal to False, it goes to the next line -if second_input == False, which checks ifsecond_inputis equal to Falseif
second_inputis NOT equal to False, it leaves the if statement and continues to the next line forif first_input == False:- ``return True `` and leaves the function since the return statement is the last thing to run in a functionif
second_inputis equal to False, it runs the next line -return Falseand leaves the function since the return statement is the last thing to run in a function
I add the bool built-in function
64def exclusive_disjunction(first_input, second_input): 65 # if first_input == False: 66 if bool(first_input) == False: 67 # if second_input == False: 68 if bool(second_input) == False: 69 return False 70 return True 71 # if first_input == True: 72 if bool(first_input) == True: 73 # if second_input == False: 74 if bool(second_input) == False: 75 return True 76 return Falsestill green.
I use Logical Negation (NOT) to write three of the if statements in terms of True
64def exclusive_disjunction(first_input, second_input): 65 # if first_input == False: 66 # if bool(first_input) == False: 67 if bool(not first_input) == True: 68 # if second_input == False: 69 # if bool(second_input) == False: 70 if bool(not second_input) == True: 71 return False 72 return True 73 # if first_input == True: 74 if bool(first_input) == True: 75 # if second_input == False: 76 # if bool(second_input) == False: 77 if bool(not second_input) == True: 78 return True 79 return Falsegreen.
I remove
== True64def exclusive_disjunction(first_input, second_input): 65 # if first_input == False: 66 # if bool(first_input) == False: 67 # if bool(not first_input) == True: 68 if bool(not first_input): 69 # if second_input == False: 70 # if bool(second_input) == False: 71 # if bool(not second_input) == True: 72 if bool(not second_input): 73 return False 74 return True 75 # if first_input == True: 76 # if bool(first_input) == True: 77 if bool(first_input): 78 # if second_input == False: 79 # if bool(second_input) == False: 80 # if bool(not second_input) == True: 81 if bool(not second_input): 82 return True 83 return Falsestill green.
I remove bool
64def exclusive_disjunction(first_input, second_input): 65 # if first_input == False: 66 # if bool(first_input) == False: 67 # if bool(not first_input) == True: 68 # if bool(not first_input): 69 if not first_input: 70 # if second_input == False: 71 # if bool(second_input) == False: 72 # if bool(not second_input) == True: 73 # if bool(not second_input): 74 if not second_input: 75 return False 76 return True 77 # if first_input == True: 78 # if bool(first_input) == True: 79 # if bool(first_input): 80 if first_input: 81 # if second_input == False: 82 # if bool(second_input) == False: 83 # if bool(not second_input) == True: 84 # if bool(not second_input): 85 if not second_input: 86 return True 87 return Falsethe test is still green, because
when
if something == False:runs, Python checks ifsomethingis equal to False. I can assume the following substitutionsif the value of
somethingis Falseif something == False if bool(something ) == False if bool(False ) == False if False == False if True == True # use equality if True # remove '== True' if not False # change to terms of False if not somethingif the value of
somethingis Trueif something == False if bool(something ) == False if bool(True ) == False if True == False if False == True # use equality if False # remove '== True' if not True # change to terms of True if not something
when
if something == True:runs, Python checks if(something)is equal to True. I can assume the following substitutionsif the value of
somethingis Falseif something == True if bool(something ) == True if bool(False ) == True if False == True if not True == True # change to terms of True if not True # remove '==True' if False if somethingif the value of
somethingis Trueif something == True if bool(something ) == True if bool(True ) == True if True == True # remove '==True' if True if something
if bool(something) == Falseis the same asif bool(not something) == Trueis the same asif bool(not something)is the same asif not something.if bool(something) == Trueis the same asif bool(something)is the same asif something.
I move the if statements to put them together
64def exclusive_disjunction(first_input, second_input): 65 # if first_input == False: 66 # if bool(first_input) == False: 67 # if bool(not first_input) == True: 68 # if bool(not first_input): 69 # if second_input == False: 70 # if bool(second_input) == False: 71 # if bool(not second_input) == True: 72 # if bool(not second_input): 73 # if first_input == True: 74 # if bool(first_input) == True: 75 # if bool(first_input): 76 # if second_input == False: 77 # if bool(second_input) == False: 78 # if bool(not second_input) == True: 79 # if bool(not second_input): 80 if not first_input: 81 if not second_input: 82 return False 83 return True 84 if first_input: 85 if not second_input: 86 return True 87 return Falsestill green.
I add if statements for the other two cases to make it clearer
64def exclusive_disjunction(first_input, second_input): 65 # if first_input == False: 66 # if bool(first_input) == False: 67 # if bool(not first_input) == True: 68 # if bool(not first_input): 69 # if second_input == False: 70 # if bool(second_input) == False: 71 # if bool(not second_input) == True: 72 # if bool(not second_input): 73 # if first_input == True: 74 # if bool(first_input) == True: 75 # if bool(first_input): 76 # if second_input == False: 77 # if bool(second_input) == False: 78 # if bool(not second_input) == True: 79 # if bool(not second_input): 80 if not first_input: 81 if not second_input: 82 return False 83 if second_input: 84 return True 85 if first_input: 86 if not second_input: 87 return True 88 if second_input: 89 return Falsegreen.
I use Logical Conjunction (AND) to write the if statements for all the cases
64def exclusive_disjunction(first_input, second_input): 65 # if first_input == False: 66 # if bool(first_input) == False: 67 # if bool(not first_input) == True: 68 # if bool(not first_input): 69 # if second_input == False: 70 # if bool(second_input) == False: 71 # if bool(not second_input) == True: 72 # if bool(not second_input): 73 # if first_input == True: 74 # if bool(first_input) == True: 75 # if bool(first_input): 76 # if second_input == False: 77 # if bool(second_input) == False: 78 # if bool(not second_input) == True: 79 # if bool(not second_input): 80 # if not first_input: 81 # if not second_input: 82 # return False 83 # if second_input: 84 # return True 85 # if first_input: 86 # if not second_input: 87 # return True 88 # if second_input: 89 # return False 90 if not first_input and not second_input: 91 return False 92 if not first_input and second_input: 93 return True 94 if first_input and not second_input: 95 return True 96 if first_input and second_input: 97 return Falsestill green, because I can put two if statements together when one is indented under the other
if something: if something_else:can also be written as
if something and something_else:I move the first if statement to the bottom to be with the other statement that returns the same thing (False)
64def exclusive_disjunction(first_input, second_input): 65 # if first_input == False: 66 # if bool(first_input) == False: 67 # if bool(not first_input) == True: 68 # if bool(not first_input): 69 # if second_input == False: 70 # if bool(second_input) == False: 71 # if bool(not second_input) == True: 72 # if bool(not second_input): 73 # if first_input == True: 74 # if bool(first_input) == True: 75 # if bool(first_input): 76 # if second_input == False: 77 # if bool(second_input) == False: 78 # if bool(not second_input) == True: 79 # if bool(not second_input): 80 # if not first_input: 81 # if not second_input: 82 # return False 83 # if second_input: 84 # return True 85 # if first_input: 86 # if not second_input: 87 # return True 88 # if second_input: 89 # return False 90 if not first_input and second_input: 91 return True 92 if first_input and not second_input: 93 return True 94 if first_input and second_input: 95 return False 96 if not first_input and not second_input: 97 return Falsethe test is still green.
I use Logical Disjunction (OR) to put the if statements that return the same thing together
64def exclusive_disjunction(first_input, second_input): 65 # if first_input == False: 66 # if bool(first_input) == False: 67 # if bool(not first_input) == True: 68 # if bool(not first_input): 69 # if second_input == False: 70 # if bool(second_input) == False: 71 # if bool(not second_input) == True: 72 # if bool(not second_input): 73 # if first_input == True: 74 # if bool(first_input) == True: 75 # if bool(first_input): 76 # if second_input == False: 77 # if bool(second_input) == False: 78 # if bool(not second_input) == True: 79 # if bool(not second_input): 80 # if not first_input: 81 # if not second_input: 82 # return False 83 # if second_input: 84 # return True 85 # if first_input: 86 # if not second_input: 87 # return True 88 # if second_input: 89 # return False 90 # if not first_input and second_input: 91 # return True 92 # if first_input and not second_input: 93 if ( 94 (not first_input and second_input) 95 or 96 (first_input and not second_input) 97 ): 98 return True 99 # if not first_input and not second_input: 100 # return False 101 # if first_input and second_input: 102 if ( 103 (first_input and second_input) 104 or 105 (not first_input and not second_input) 106 ): 107 return Falsestill green, because I can put two if statements together when they both return the same thing and are at the same indentation level
if something: return this if something_else: return thiscan also be written as
if something or something_else: return thisI change the second if statement to an else clause
93 if ( 94 (not first_input and second_input) 95 or 96 (first_input and not second_input) 97 ): 98 return True 99 # if not first_input and not second_input: 100 # return False 101 # if first_input and second_input: 102 # if ( 103 # (first_input and second_input) 104 # or 105 # (not first_input and not second_input) 106 # ): 107 else: 108 return Falsegreen.
I add a conditional expression
93 # if ( 94 # (not first_input and second_input) 95 # or 96 # (first_input and not second_input) 97 # ): 98 # return True 99 # if not first_input and not second_input: 100 # return False 101 # if first_input and second_input: 102 # if ( 103 # (first_input and second_input) 104 # or 105 # (not first_input and not second_input) 106 # ): 107 # else: 108 # return False 109 return True if ( 110 (not first_input and second_input) 111 or 112 (first_input and not second_input) 113 ) else Falsestill green.
I remove
True ifandelse Falseto make it simpler93 # if ( 94 # (not first_input and second_input) 95 # or 96 # (first_input and not second_input) 97 # ): 98 # return True 99 # if not first_input and not second_input: 100 # return False 101 # if first_input and second_input: 102 # if ( 103 # (first_input and second_input) 104 # or 105 # (not first_input and not second_input) 106 # ): 107 # else: 108 # return False 109 # return True if ( 110 return ( 111 (not first_input and second_input) 112 or 113 (first_input and not second_input) 114 # ) else False 115 )the test is still green.
exclusive_disjunction returns
((not first_input and second_input) or (first_input and not second_input))not first_input and second_inputis the Logical Conjunction (AND) of the Logical Negation (NOT) of the first input, and the second inputlogical_conjunction( logical_negation(first_input), second_input )not first_inputis the Logical Negation (NOT) offirst_inputif the first input is True, this part of the statement is False
if the first input is False, this part of the statement is True
first_input and not second_inputis the Logical Conjunction (AND) of the first input, and the Logical Negation (NOT) of the second inputlogical_conjunction( first_input, logical_negation(second_input) )not second_inputis the Logical Negation (NOT) ofsecond_inputif the second input is True, this part of the statement is False
if the second input is False, this part of the statement is True
((not first_input and second_input) or (first_input and not second_input))can be thought of as the Logical Disjunction (OR) of the Logical Conjunction (AND) of the Logical Negation (NOT) of the first input, and the second input, and the Logical Conjunction (AND) of the first input, and the Logical Negation (NOT) of the second input. Very confusing when written in Englishlogical_disjunction( logical_conjunction( logical_negation(first_input), second_input ), logical_conjunction( first_input, logical_negation(second_input) ) )it can be thought of as the Logical Disjunction (OR) of the Converse Non-Implication of the first input, and the second input, and the Logical Conjunction (AND) of the first input, and the Logical Negation (NOT) of the second input
logical_disjunction( converse_non_implication( first_input, second_input ), logical_conjunction( first_input, logical_negation(second_input) ) )because converse_non_implication returns
not first_input and second_input
This means that in the four cases
if the first input is True and the second input is True, exclusive_disjunction returns
(not first and second) or (first and not second) (not True and True ) or (True and not True ) (False and True ) or (True and False ) False or False False # logical_disjunction(False, False)if the first input is True and the second input is False, exclusive_disjunction returns
(not first and second) or (first and not second) (not True and False ) or (True and not False ) (False and False ) or (True and True ) False or True True # logical_disjunction(False, True)if the first input is False and the second input is True, exclusive_disjunction returns
(not first and second) or (first and not second) (not False and True ) or (False and not True ) (True and True ) or (False and False ) True or False True # logical_disjunction(True, False)if the first input is False and the second input is False, exclusive_disjunction returns
(not first and second) or (first and not second) (not False and False ) or (False and not False ) (True and False ) or (False and True ) False or False False # logical_disjunction(False, False)
first
second
not first
not second
((not first) and second)
(first and (not second))
((not first) and second) or (first and (not second))
True
True
False
False
False
False
False
True
False
False
True
False
True
True
False
True
True
False
True
False
True
False
False
True
True
False
False
False
I add a return statement to show this
109 # return True if ( 110 return logical_disjunction( 111 converse_non_implication( 112 first_input, second_input 113 ), 114 logical_conjunction( 115 first_input, 116 logical_negation(second_input) 117 ) 118 ) 119 return ( 120 (not first_input and second_input) 121 or 122 (first_input and not second_input) 123 # ) else False 124 )the test is still green.
exclusive_disjunction returns False when the two inputs are equal, it returns True when the two inputs are NOT equal. I add an if statement to show this
109 # return True if ( 110 if first_input == second_input: 111 return False 112 else: 113 return True 114 return logical_disjunction( 115 converse_non_implication( 116 first_input, second_input 117 ), 118 logical_conjunction( 119 first_input, 120 logical_negation(second_input) 121 ) 122 ) 123 return ( 124 (not first_input and second_input) 125 or 126 (first_input and not second_input) 127 # ) else False 128 )green.
I change the else clause to the Logical Negation (NOT) of the new if statement so I can write a conditional expression
109 # return True if ( 110 if first_input == second_input: 111 return False 112 # else: 113 if not (first_input == second_input): 114 return True 115 return logical_disjunction( 116 converse_non_implication( 117 first_input, second_input 118 ), 119 logical_conjunction( 120 first_input, 121 logical_negation(second_input) 122 ) 123 ) 124 return ( 125 (not first_input and second_input) 126 or 127 (first_input and not second_input) 128 # ) else False 129 )still green.
I add a conditional expression
109 # return True if ( 110 # if first_input == second_input: 111 # return False 112 # else: 113 # if not (first_input == second_input): 114 # return True 115 return ( 116 True if 117 not (first_input == second_input) 118 else False 119 ) 120 return logical_disjunction( 121 converse_non_implication( 122 first_input, second_input 123 ), 124 logical_conjunction( 125 first_input, 126 logical_negation(second_input) 127 ) 128 ) 129 return ( 130 (not first_input and second_input) 131 or 132 (first_input and not second_input) 133 # ) else False 134 )the test is still green.
I remove
True ifandelse Falseto make the statement simpler109 # return True if ( 110 # if first_input == second_input: 111 # return False 112 # else: 113 # if not (first_input == second_input): 114 # return True 115 return ( 116 # True if 117 not (first_input == second_input) 118 # else False 119 ) 120 return logical_disjunction( 121 converse_non_implication( 122 first_input, second_input 123 ), 124 logical_conjunction( 125 first_input, 126 logical_negation(second_input) 127 ) 128 ) 129 return ( 130 (not first_input and second_input) 131 or 132 (first_input and not second_input) 133 # ) else False 134 )still green.
I can also write the conditional expression with the NOT equal symbol (
!=) (exclamation mark and equal symbol !+= on the keyboard)64 # return True if ( 65 # if first_input == second_input: 66 # return False 67 # else: 68 # if not (first_input == second_input): 69 # return True 70 return first_input != second_input 71 return ( 72 # True if 73 not (first_input == second_input) 74 # else False 75 ) 76 return logical_disjunction( 77 converse_non_implication( 78 first_input, second_input 79 ), 80 logical_conjunction( 81 first_input, 82 logical_negation(second_input) 83 ) 84 ) 85 return ( 86 (not first_input and second_input) 87 or 88 (first_input and not second_input) 89 # ) else False 90 )green.
I remove the commented lines
64def exclusive_disjunction(first_input, second_input): 65 return first_input != second_input 66 return not (first_input == second_input) 67 return logical_disjunction( 68 converse_non_implication( 69 first_input, second_input 70 ), 71 logical_conjunction( 72 first_input, 73 logical_negation(second_input) 74 ) 75 ) 76 return ( 77 (not first_input and second_input) 78 or 79 (first_input and not second_input) 80 )I can use any of these `return statements`_. The first return statement is the only one that runs in this case, because the return statement is the last thing to run in a function.
I add a git commit message in another terminal
git commit -am 'add exclusive_disjunction'
Exclusive Disjunction returns
True, if
first_inputis NOT EQUAL tosecond_inputFalse, if
first_inputis EQUAL thesecond_inputfirst_input != second_input- which reads asfirst_inputis NOT equal tosecond_inputnot (first_input == second_input)- which can be read as the Logical Negation of the Logical Equality of the first input and the second input(not first_input and second_input) or (first_input and not second_input)which is the Logical Disjunction of the Logical Conjunction of the Logical Negation of the first input, and the second input, and the Logical Conjunction of the first input and the Logical Negation of the second input. Wow! That’s a lot.All of the above statements mean the same thing.
Exclusive Disjunction is also known as Exclusive OR or XOR. Would “Logical Inequality” be a better name?
examples of Exclusive Disjunction
two light switches for one bulb, if the inputs are
is switch A on?
is switch B on?
switch A?
switch B?
bulb on?
on
on
no
on
off
yes
off
on
yes
off
off
no
magnets attract, if the inputs are
what is the direction of magnet A?
what is the direction of magnet B?
magnet A?
magnet B?
attract?
north
north
no
north
south
yes
south
north
yes
south
south
no
a coin toss, if the inputs are
my choice
your choice
my choice
your choice
there is a winner
heads
heads
no
heads
tails
yes
tails
heads
yes
tails
tails
no
two people meet at a door that can only take one person at a time, if the inputs are
I go
You go
I go
you go
we both go
go
go
no
go
stop
yes
stop
go
yes
stop
stop
no
A broken vending machine, if the inputs are
did I put money in the machine?
did I get what I picked?
I paid
I got what I want
machine is broken
yes
yes
no
yes
no
yes
no
yes
yes
no
no
no
should I complain when
I did not payandI got what I want?
test_material_non_implication
The truth table for material_non_implication is
first input |
second input |
return |
|---|---|---|
True |
True |
False |
True |
False |
True |
False |
True |
False |
False |
False |
False |
RED: make it fail
I go back to the terminal where the tests are running
I add a test for material_non_implication with an assertion for when the first input is True and the second input is True, to
test_binary.pyfirst input
second input
return
True
True
False
85 def test_exclusive_disjunction(self): 86 exclusive_disjunction = ( 87 src.truth_table.exclusive_disjunction 88 ) 89 self.assertFalse(exclusive_disjunction(True, True)) 90 self.assertTrue(exclusive_disjunction(True, False)) 91 self.assertTrue(exclusive_disjunction(False, True)) 92 self.assertFalse(exclusive_disjunction(False, False)) 93 94 def test_material_non_implication(self): 95 material_non_implication = ( 96 src.truth_table.material_non_implication 97 ) 98 self.assertFalse( 99 material_non_implication(True, True) 100 ) 101 102 103# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'material_non_implication'. Did you mean: 'converse_non_implication'?material_non_implication is not in
truth_table.py
GREEN: make it pass
I add material_non_implication to truth_table.py
64def exclusive_disjunction(first_input, second_input):
65 return first_input != second_input
66 return not (first_input == second_input)
67 return logical_disjunction(
68 converse_non_implication(
69 first_input, second_input
70 ),
71 logical_conjunction(
72 first_input,
73 logical_negation(second_input)
74 )
75 )
76 return (
77 (not first_input and second_input)
78 or
79 (first_input and not second_input)
80 )
81
82
83def material_non_implication(first_input, second_input):
84 return False
the test passes. material_non_implication returns False, if the first input is True and the second input is True.
REFACTOR: make it better
I add an assertion for the second case, which is when the first input is True and the second input is False to test_material_non_implication in
test_binary.pyfirst input
second input
return
True
False
True
94 def test_material_non_implication(self): 95 material_non_implication = ( 96 src.truth_table.material_non_implication 97 ) 98 self.assertFalse( 99 material_non_implication(True, True) 100 ) 101 self.assertTrue( 102 material_non_implication(True, False) 103 ) 104 105 106# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: False is not truebecause the function returns False and the assertion expects True.
I add an if statement to material_non_implication in
truth_table.py83def material_non_implication(first_input, second_input): 84 if second_input == False: 85 return True 86 return Falsethe test passes. When material_non_implication is called, it runs
if second_input == False:if
second_inputis NOT equal to False, it leaves the if statement then runsreturn Falseif
second_inputis equal to False, it runsreturn True
I add an assertion for the third case to test_material_non_implication, for when the first input is False and the second input is True, in
test_binary.pyfirst input
second input
return
False
True
False
94 def test_material_non_implication(self): 95 material_non_implication = ( 96 src.truth_table.material_non_implication 97 ) 98 self.assertFalse( 99 material_non_implication(True, True) 100 ) 101 self.assertTrue( 102 material_non_implication(True, False) 103 ) 104 self.assertFalse( 105 material_non_implication(False, True) 106 ) 107 108 109# Exceptions seenthe test is still green.
I add an assertion for the fourth case, which is when the first input is False and the second input is False
first input
second input
return
False
False
False
94 def test_material_non_implication(self): 95 material_non_implication = ( 96 src.truth_table.material_non_implication 97 ) 98 self.assertFalse( 99 material_non_implication(True, True) 100 ) 101 self.assertTrue( 102 material_non_implication(True, False) 103 ) 104 self.assertFalse( 105 material_non_implication(False, True) 106 ) 107 self.assertFalse( 108 material_non_implication(False, False) 109 ) 110 111 112# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: True is not falsebecause when material_non_implication is called, it runs
if second_input == False:if
second_inputis NOT equal to False, it leaves the if statement then runsreturn Falseif
second_inputis equal to False, it runsreturn Truesecond_inputis False in this case, which raises AssertionError since the assertion expects False and the function returns True
I add an if statement for the one case that returns True to the material_non_implication function in
truth_table.py83def material_non_implication(first_input, second_input): 84 if first_input == True: 85 if second_input == False: 86 return True 87 return Falsethe test passes because when material_non_implication is called, it runs
if first_input == True:if
first_inputis NOT equal to True, it leaves the if statement then runsreturn Falseif
first_inputis equal to True, it runsif second_input == False:if
second_inputis NOT equal to False, it leavesif first_input == True:then runs the next line in the function -return Falseif
second_inputis equal to False, it runsreturn True
I use the bool built-in function
83def material_non_implication(first_input, second_input): 84 # if first_input == True: 85 if bool(first_input) == True: 86 # if second_input == False: 87 if bool(second_input) == False: 88 return True 89 return Falsethe test is still green.
I use Logical Negation (NOT) to write the second if statement in terms of True
83def material_non_implication(first_input, second_input): 84 # if first_input == True: 85 if bool(first_input) == True: 86 # if second_input == False: 87 # if bool(second_input) == False: 88 if bool(not second_input) == True: 89 return True 90 return Falsestill green.
I remove
== True83def material_non_implication(first_input, second_input): 84 # if first_input == True: 85 # if bool(first_input) == True: 86 if bool(first_input): 87 # if second_input == False: 88 # if bool(second_input) == False: 89 # if bool(not second_input) == True: 90 if bool(not second_input): 91 return True 92 return Falsegreen.
I remove bool
83def material_non_implication(first_input, second_input): 84 # if first_input == True: 85 # if bool(first_input) == True: 86 # if bool(first_input): 87 if first_input: 88 # if second_input == False: 89 # if bool(second_input) == False: 90 # if bool(not second_input) == True: 91 # if bool(not second_input): 92 if not second_input: 93 return True 94 return Falsestill green, because
if bool(something) == Trueis the same asif bool(something)is the same asif something.if bool(something) == Falseis the same asif bool(not something) == Trueis the same asif bool(not something)is the same asif not something.
I use Logical Conjunction (AND) to put the two if statements together
83def material_non_implication(first_input, second_input): 84 # if first_input == True: 85 # if bool(first_input) == True: 86 # if bool(first_input): 87 # if first_input: 88 # if second_input == False: 89 # if bool(second_input) == False: 90 # if bool(not second_input) == True: 91 # if bool(not second_input): 92 # if not second_input: 93 if first_input and not second_input: 94 return True 95 return Falsethe test is still green, because I can put two if statements together when one is indented under the other
if something: if something_else:can also be written as
if something and something_else:I add a conditional expression
83def material_non_implication(first_input, second_input): 84 # if first_input == True: 85 # if bool(first_input) == True: 86 # if bool(first_input): 87 # if first_input: 88 # if second_input == False: 89 # if bool(second_input) == False: 90 # if bool(not second_input) == True: 91 # if bool(not second_input): 92 # if not second_input: 93 # if first_input and not second_input: 94 # return True 95 # return False 96 return ( 97 True if 98 first_input and not second_input 99 else False 100 )still green.
I remove
True ifandelse Falseto make the statement simpler96 return ( 97 # True if 98 first_input and not second_input 99 # else False 100 )green.
material_non_implication returns
first_input and not second_inputnot second_inputis the Logical Negation (NOT) ofsecond_inputif the second input is True, this part of the statement is False
if the second input is False, this part of the statement is True
first_input and not second_inputis the Logical Conjunction (AND) of the first input and the Logical Negation (NOT) of the second inputlogical_conjunction( first_input, logical_negation(second_input) )
this means that in the four cases
if the first input is True and the second input is True, material_non_implication returns
first_input and not second_input True and not True True and False False # logical_conjunction(True, False)if the first input is True and the second input is False, material_non_implication returns
first_input and not second_input True and not False True and True True # logical_conjunction(True, True)if the first input is False and the second input is True, material_non_implication returns
first_input and not second_input False and not True False and False False # logical_conjunction(False, False)if the first input is False and the second input is False, material_non_implication returns
first_input and not second_input False and not False False and True False # logical_conjunction(False, True)
first
second
not second
(first and not second)
True
True
False
False
True
False
True
True
False
True
False
False
False
False
True
False
I add a return statement to show this
83def material_non_implication(first_input, second_input): 84 # if first_input == True: 85 # if bool(first_input) == True: 86 # if bool(first_input): 87 # if first_input: 88 # if second_input == False: 89 # if bool(second_input) == False: 90 # if bool(not second_input) == True: 91 # if bool(not second_input): 92 # if not second_input: 93 # if first_input and not second_input: 94 # return True 95 # return False 96 return logical_conjunction( 97 first_input, 98 logical_negation(second_input) 99 ) 100 return ( 101 # True if 102 first_input and not second_input 103 # else False 104 )still green.
I remove the comments
83def material_non_implication(first_input, second_input): 84 return logical_conjunction( 85 first_input, 86 logical_negation(second_input) 87 ) 88 return first_input and not second_inputI can use either of these `return statements`_. The first return statement is the only one that runs in this case, because the return statement is the last thing to run in a function.
I add a git commit message in another terminal
git commit -am 'add material_non_implication'
returns
first_input and not second_inputwhich is the Logical Conjunction of the first input and the Logical Negation of the second inputreturns True, only if the first input is True and the second input is False
is the Logical Negation of Material/Logical Implication which returns False only if the first input is True and the second input is False
can be thought of as a claim that does not deliver
examples of Material Non-Implication
A broken promise, if the inputs are
did I make a promise?
did I do something?
I promised
I did something
broken promise
yes
yes
no
yes
no
yes
no
yes
no
no
no
no
A false alarm, if the inputs are
did alarm ring?
was there a bad event?
alarm rang
bad event
false alarm
yes
yes
no
yes
no
yes
no
yes
no (alarm is broken)
no
no
no
the boy who cried wolf, if the inputs are
did the boy cry?
was there a wolf?
boy cried
wolf
false claim
yes
yes
no
yes
no
yes
no
yes
no
no
no
no
more about Exclusive Disjunction
Since I know material_non_implication I can think of Exclusive Disjunction which returns (not first_input and second_input) or (first_input and not second_input) as
return logical_disjunction(
converse_non_implication(
first_input, second_input
),
material_non_implication(
first_input, second_input
)
)
because
logical_disjunction(first_input, second_input)
first_input == (not first_input and second_input)
converse_non_implication == (not first_input and second_input)
second_input == (first_input and not second_input)
material_non_implication == (first_input and not second_input)
logical_disjunction returns
first_input or second_inputfirst_inputin this case is(not first_input and second_input)second_inputin this case is(first_input and not second_input)
converse_non_implication returns
not first_input and second_inputmaterial_non_implication returns
first_input and not second_inputI change the return statement in the exclusive_disjunction function in
truth_table.py64 def exclusive_disjunction(first_input, second_input): 65 # return first_input != second_input 66 # return not (first_input == second_input) 67 return logical_disjunction( 68 converse_non_implication( 69 first_input, second_input 70 ), 71 # logical_conjunction( 72 material_non_implication( 73 first_input, second_input 74 # logical_negation(second_input) 75 ) 76 ) 77 return ( 78 (not first_input and second_input) 79 or 80 (first_input and not second_input) 81 )the test is still green.
I put the first two `return statements`_ back, then remove the commented lines
64def exclusive_disjunction(first_input, second_input): 65 return first_input != second_input 66 return not (first_input == second_input) 67 return logical_disjunction( 68 converse_non_implication( 69 first_input, second_input 70 ), 71 material_non_implication( 72 first_input, second_input 73 ) 74 ) 75 return ( 76 (not first_input and second_input) 77 or 78 (first_input and not second_input) 79 ) 80 81 82def material_non_implication(first_input, second_input): 83 return logical_conjunction( 84 first_input, 85 logical_negation(second_input) 86 ) 87 return first_input and not second_inputI add a git commit message in the other terminal
git commit -am 'refactor exclusive_disjunction'
test_project_first
The truth table for project_first is
first input |
second input |
return |
|---|---|---|
True |
True |
True |
True |
False |
True |
False |
True |
False |
False |
False |
False |
RED: make it fail
I go back to the terminal where the tests are running
I add a test for project_first with an assertion for when the first input is True and the second input is True, in
test_binary.pyfirst input
second input
return
True
True
True
94 def test_material_non_implication(self): 95 material_non_implication = ( 96 src.truth_table.material_non_implication 97 ) 98 self.assertFalse( 99 material_non_implication(True, True) 100 ) 101 self.assertTrue( 102 material_non_implication(True, False) 103 ) 104 self.assertFalse( 105 material_non_implication(False, True) 106 ) 107 self.assertFalse( 108 material_non_implication(False, False) 109 ) 110 111 def test_project_first(self): 112 project_first = src.truth_table.project_first 113 self.assertTrue(project_first(True, True)) 114 115 116# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'project_first'there is nothing named project_first in
truth_table.py
GREEN: make it pass
I add a function for project_first to truth_table.py
82def material_non_implication(first_input, second_input):
83 return logical_conjunction(
84 first_input,
85 logical_negation(second_input)
86 )
87 return first_input and not second_input
88
89
90def project_first(first_input, second_input):
91 return True
the test passes. project_first returns True, if the first input is True and the second input is True.
REFACTOR: make it better
I add an assertion for the second case, which is when the first input is True and the second input is False, to test_project_first in
test_binary.pyfirst input
second input
return
True
False
True
111 def test_project_first(self): 112 project_first = src.truth_table.project_first 113 self.assertTrue(project_first(True, True)) 114 self.assertTrue(project_first(True, False)) 115 116 117# Exceptions seenthe test is still green. project_first returns
True, if the first input is True and the second input is False
True, if the first input is True and the second input is True
True, if the first input is True
on to the next case, which is when the first input is False and the second input is True
first input
second input
return
False
True
False
111 def test_project_first(self): 112 project_first = src.truth_table.project_first 113 self.assertTrue(project_first(True, True)) 114 self.assertTrue(project_first(True, False)) 115 self.assertFalse(project_first(False, True)) 116 117 118# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: True is not falsebecause the function returns True and the assertion expects False.
I add an if statement for this case to the project_first function in
truth_table.py90def project_first(first_input, second_input): 91 if first_input == False: 92 return False 93 return Truethe test passes because when project_first is called, it runs
if first_input == False:if
first_inputis NOT equal to False, it leaves the if statement then runsreturn Trueif
first_inputis equal to False, it runsreturn False
I add an assertion for the last case, which is when the first input is False and the second input is False, to test_project_first in
test_binary.pyfirst input
second input
return
False
False
False
111 def test_project_first(self): 112 project_first = src.truth_table.project_first 113 self.assertTrue(project_first(True, True)) 114 self.assertTrue(project_first(True, False)) 115 self.assertFalse(project_first(False, True)) 116 self.assertFalse(project_first(False, False)) 117 118 119# Exceptions seenthe test is still green.
I add the bool built-in function to the if statement in the project_first function in
truth_table.py90def project_first(first_input, second_input): 91 # if first_input == False: 92 if bool(first_input) == False: 93 return False 94 return Truestill green.
I use Logical Negation (NOT) to write it in terms of True
90def project_first(first_input, second_input): 91 # if first_input == False: 92 # if bool(first_input) == False: 93 if bool(not first_input) == True: 94 return False 95 return Truegreen.
I remove
== True90def project_first(first_input, second_input): 91 # if first_input == False: 92 # if bool(first_input) == False: 93 # if bool(not first_input) == True: 94 if bool(not first_input): 95 return False 96 return Truestill green.
I remove bool
90def project_first(first_input, second_input): 91 # if first_input == False: 92 # if bool(first_input) == False: 93 # if bool(not first_input) == True: 94 # if bool(not first_input): 95 if not first_input: 96 return False 97 return Truethe test is still green, because
if bool(something) == Falseis the same asif bool(not something) == Trueis the same asif bool(not something)is the same asif not something.I add an else clause to make it clearer
90def project_first(first_input, second_input): 91 # if first_input == False: 92 # if bool(first_input) == False: 93 # if bool(not first_input) == True: 94 # if bool(not first_input): 95 if not first_input: 96 return False 97 else: 98 return Truestill green.
I use Logical Negation (NOT) for the else clause
90def project_first(first_input, second_input): 91 # if first_input == False: 92 # if bool(first_input) == False: 93 # if bool(not first_input) == True: 94 # if bool(not first_input): 95 if not first_input: 96 return False 97 # else: 98 if not (not first_input): 99 return Truegreen.
I remove the nots because they cancel out
90def project_first(first_input, second_input): 91 # if first_input == False: 92 # if bool(first_input) == False: 93 # if bool(not first_input) == True: 94 # if bool(not first_input): 95 if not first_input: 96 return False 97 # else: 98 # if not (not first_input): 99 if first_input: 100 return Truestill green.
I add a conditional expression
90def project_first(first_input, second_input): 91 # if first_input == False: 92 # if bool(first_input) == False: 93 # if bool(not first_input) == True: 94 # if bool(not first_input): 95 # if not first_input: 96 # return False 97 # else: 98 # if not (not first_input): 99 # if first_input: 100 # return True 101 return True if first_input else Falsethe test is still green.
I remove
True ifandelse False90def project_first(first_input, second_input): 91 # if first_input == False: 92 # if bool(first_input) == False: 93 # if bool(not first_input) == True: 94 # if bool(not first_input): 95 # if not first_input: 96 # return False 97 # else: 98 # if not (not first_input): 99 # if first_input: 100 # return True 101 # return True if first_input else False 102 return first_inputstill green.
I remove the other statements
90def project_first(first_input, second_input): 91 return first_inputI add a git commit message in another terminal
git commit -am 'add project_first'
Project First always returns the first input it does not care about the second input, like Project Second which always returns the second input and does not care about the first input.
examples of Project First
did the event happen, if the inputs are
did the event happen?
did we get a notification about it?
event
notification
event happened
yes
yes
yes
yes
no
yes
no
yes
no (notification is broken)
no
no
no
“if a tree falls in the forest, does it make a sound?”
able to login with or without Multi Factor Authentication, if the inputs are
did user provide the right password?
does user have MFA?
right password
right MFA code
log in
yes
yes
yes
yes
no
yes
no
yes
no (how did user get the MFA code?)
no
no
no
my actions, if the inputs are
what I want to do?
what you think I should do?
what I want
your thoughts
my actions
yes
yes
yes
yes
no
yes
no
yes
no
no
no
no
autocorrect, if the inputs are
autocorrect suggests a word
I write what I want
autocorrect
what I want
what I get
yes
yes
yes
yes
no
yes
no
yes
no
no
no
no
test_converse_implication
The truth table for converse_implication is
first input |
second input |
return |
|---|---|---|
True |
True |
True |
True |
False |
True |
False |
True |
False |
False |
False |
True |
RED: make it fail
I go back to the terminal where the tests are running
I add a test for converse_implication with an assertion for when the first input is True and the second input is True, to
test_binary.pyfirst input
second input
return
True
True
True
111 def test_project_first(self): 112 project_first = src.truth_table.project_first 113 self.assertTrue(project_first(True, True)) 114 self.assertTrue(project_first(True, False)) 115 self.assertFalse(project_first(False, True)) 116 self.assertFalse(project_first(False, False)) 117 118 def test_converse_implication(self): 119 converse_implication = ( 120 src.truth_table.converse_implication 121 ) 122 self.assertTrue( 123 converse_implication(True, True) 124 ) 125 126 127# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'converse_implication'. Did you mean: 'converse_non_implication'?because
truth_table.pydoes not have anything named converse_implication in it.
GREEN: make it pass
I add a function for converse_implication to truth_table.py
90def project_first(first_input, second_input):
91 return first_input
92
93
94def converse_implication(first_input, second_input):
95 return True
the test passes. converse_implication returns True, if the first input is True and the second input is True.
REFACTOR: make it better
I add an assertion for the second case, which is when the first input is True and the second input is False to test_converse_implication in
test_binary.pyfirst input
second input
return
True
False
True
118 def test_converse_implication(self): 119 converse_implication = ( 120 src.truth_table.converse_implication 121 ) 122 self.assertTrue( 123 converse_implication(True, True) 124 ) 125 self.assertTrue( 126 converse_implication(True, False) 127 ) 128 129 130# Exceptions seenthe test is still green. converse_implication returns True
if the first input is True and the second input is False
if the first input is True and the second input is True
if the first input is True
time for the next case, which is when the first input is False and the second input is True
118 def test_converse_implication(self): 119 converse_implication = ( 120 src.truth_table.converse_implication 121 ) 122 self.assertTrue( 123 converse_implication(True, True) 124 ) 125 self.assertTrue( 126 converse_implication(True, False) 127 ) 128 self.assertFalse( 129 converse_implication(False, True) 130 ) 131 132 133# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: True is not falsebecause the converse_implication function returns True and the assertion expects False.
I add an if statement to converse_implication in
truth_table.py94def converse_implication(first_input, second_input): 95 if first_input == False: 96 return False 97 return Truethe test passes because when converse_implication is called, it runs
if first_input == False:if
first_inputis NOT equal to False, it leaves the if statement then runsreturn Trueif
first_inputis equal to False, it runsreturn False
I add an assertion for the last case, which is when the first input is False and the second input is False, to test_converse_implication in
test_binary.pyfirst input
second input
return
False
False
True
118 def test_converse_implication(self): 119 converse_implication = ( 120 src.truth_table.converse_implication 121 ) 122 self.assertTrue( 123 converse_implication(True, True) 124 ) 125 self.assertTrue( 126 converse_implication(True, False) 127 ) 128 self.assertFalse( 129 converse_implication(False, True) 130 ) 131 self.assertTrue( 132 converse_implication(False, False) 133 ) 134 135 136# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: False is not truebecause when converse_implication is called, it runs
if first_input == False:if
first_inputis NOT equal to False, it leaves the if statement then runsreturn Trueif
first_inputis equal to False, it runsreturn Falsefirst_inputis False in this case, which raises AssertionError since the assertion expects True and the function returns False
I add an if statement for the only case that returns True
94def converse_implication(first_input, second_input): 95 if first_input == False: 96 if second_input == True: 97 return False 98 return Truethe test passes because when converse_implication is called, it runs
if first_input == False:if
first_inputis NOT equal to False, it leaves the if statement then runsreturn Trueif
first_inputis equal to False, it runsif second_input == True:if
second_inputis NOT equal to True, it leavesif first_input == False:and runsreturn Trueif
second_inputis equal to True, it runsreturn False
I add the bool built-in function
94def converse_implication(first_input, second_input): 95 # if first_input == False: 96 if bool(first_input) == False: 97 # if second_input == True: 98 if bool(second_input) == True: 99 return False 100 return Truethe test is still green.
I use Logical Negation (NOT) to write the first if statement in terms of True
94def converse_implication(first_input, second_input): 95 # if first_input == False: 96 # if bool(first_input) == False: 97 if bool(not first_input) == True: 98 # if second_input == True: 99 if bool(second_input) == True: 100 return False 101 return Truestill green.
I remove
== True94def converse_implication(first_input, second_input): 95 # if first_input == False: 96 # if bool(first_input) == False: 97 # if bool(not first_input) == True: 98 if bool(not first_input): 99 # if second_input == True: 100 # if bool(second_input) == True: 101 if bool(second_input): 102 return False 103 return Truegreen.
I remove bool
94def converse_implication(first_input, second_input): 95 # if first_input == False: 96 # if bool(first_input) == False: 97 # if bool(not first_input) == True: 98 # if bool(not first_input): 99 if not first_input: 100 # if second_input == True: 101 # if bool(second_input) == True: 102 # if bool(second_input): 103 if second_input: 104 return False 105 return Truestill green, because
if bool(something) == Falseis the same asif bool(not something) == Trueis the same asif bool(not something)is the same asif not something.if bool(something) == Trueis the same asif bool(something)is the same asif something.
I use Logical Conjunction (AND) to put the two if statements together
94def converse_implication(first_input, second_input): 95 # if first_input == False: 96 # if bool(first_input) == False: 97 # if bool(not first_input) == True: 98 # if bool(not first_input): 99 # if not first_input: 100 # if second_input == True: 101 # if bool(second_input) == True: 102 # if bool(second_input): 103 # if second_input: 104 if not first_input and second_input: 105 return False 106 return Truethe test is still green, because I can put two if statements together when one is indented under the other
if something: if something_else:can also be written as
if something and something_else:I add an else clause to make it clearer
94def converse_implication(first_input, second_input): 95 # if first_input == False: 96 # if bool(first_input) == False: 97 # if bool(not first_input) == True: 98 # if bool(not first_input): 99 # if not first_input: 100 # if second_input == True: 101 # if bool(second_input) == True: 102 # if bool(second_input): 103 # if second_input: 104 if not first_input and second_input: 105 return False 106 else: 107 return Truestill green.
I use the Logical Negation (NOT) of the if statement for the else clause
104 if not first_input and second_input: 105 return False 106 # else: 107 if not (not first_input and second_input): 108 return Truegreen.
I “multiply” the not by every symbol in the parentheses
104 if not first_input and second_input: 105 return False 106 # else: 107 # if not (not first_input and second_input): 108 if ( 109 (not not first_input) 110 (not and) 111 (not second_input) 112 ): 113 return Truethe terminal is my friend, and shows SyntaxError
SyntaxError: invalid syntaxI change
not andto or104 if not first_input and second_input: 105 return False 106 # else: 107 # if not (not first_input and second_input): 108 if ( 109 (not not first_input) 110 # (not and) 111 or 112 (not second_input) 113 ): 114 return Truethe test is green again.
I remove
not not104 if not first_input and second_input: 105 return False 106 # else: 107 # if not (not first_input and second_input): 108 if ( 109 # (not not first_input) 110 first_input 111 # (not and) 112 or 113 (not second_input) 114 ): 115 return Truethe test is still green because two nots cancel out.
I add a conditional expression
104 # if not first_input and second_input: 105 # return False 106 # else: 107 # if not (not first_input and second_input): 108 # if ( 109 # (not not first_input) 110 # first_input 111 # (not and) 112 # or 113 # (not second_input) 114 # ): 115 # return True 116 return ( 117 True if 118 first_input or not second_input 119 else False 120 )still green.
I remove
True ifandelse False104 # if not first_input and second_input: 105 # return False 106 # else: 107 # if not (not first_input and second_input): 108 # if ( 109 # (not not first_input) 110 # first_input 111 # (not and) 112 # or 113 # (not second_input) 114 # ): 115 # return True 116 return ( 117 # True if 118 first_input or not second_input 119 # else False 120 )green.
converse_implication returns
first_input or not second_inputnot second_inputis the Logical Negation (NOT) ofsecond_inputif the second input is True, this part of the statement is False
if the second input is False, this part of the statement is True
first_input or not second_inputis the Logical Disjunction (OR) of the first input and the Logical Negation (NOT) of the second inputlogical_disjunction( first_input, logical_negation(second_input) )
this means that in the four cases
if the first input is True and the second input is True, converse_implication returns
first_input or not second_input True or not True True or False True # logical_disjunction(True, False)if the first input is True and the second input is False, converse_implication returns
first_input or not second_input True or not False True or True True # logical_disjunction(True, True)if the first input is False and the second input is True, converse_implication returns
first_input or not second_input False or not True False or False False # logical_disjunction(False, False)if the first input is False and the second input is False, converse_implication returns
first_input or not second_input False or not False False or True True # logical_disjunction(False, True)
first
second
not second
(first or not second)
True
True
False
True
True
False
True
True
False
True
False
False
False
False
True
True
I add a return statement to show this
94def converse_implication(first_input, second_input): 95 # if first_input == False: 96 # if bool(first_input) == False: 97 # if bool(not first_input) == True: 98 # if bool(not first_input): 99 # if not first_input: 100 # if second_input == True: 101 # if bool(second_input) == True: 102 # if bool(second_input): 103 # if second_input: 104 # if not first_input and second_input: 105 # return False 106 # else: 107 # if not (not first_input and second_input): 108 # if ( 109 # (not not first_input) 110 # first_input 111 # (not and) 112 # or 113 # (not second_input) 114 # ): 115 # return True 116 return logical_disjunction( 117 first_input, 118 logical_negation(second_input) 119 ) 120 return ( 121 # True if 122 first_input or not second_input 123 # else False 124 )still green.
I remove the comments
94def converse_implication(first_input, second_input): 95 return logical_disjunction( 96 first_input, 97 logical_negation(second_input) 98 ) 99 return first_input or not second_inputI can use either of these `return statements`_. The first return statement is the only one that runs in this case, because the return statement is the last thing to run in a function.
I add a git commit message in another terminal
git commit -am 'add converse_implication'
Converse Implication returns
first_input or not second_inputFalse, only if the first input is False and the second input is True
the Logical Disjunction of the first input and the Logical Negation of the second input
It is the opposite of Converse Non-Implication which always returns
not first_input and second_inputor True, only if the first input is False and the second input is True
examples of Converse Implication
I cannot get a table at a restaurant, if the inputs are
do I have a reservation?
is the place full?
reservation
place is full
I get a table
yes
yes
yes
yes
no
yes
no
yes
no
no
no
yes
sleep through alarm, if the inputs are
am I too deep in sleep to hear the alarm?
is the alarm ringing?
too tired
alarm rings
I sleep
yes
yes
yes
yes
no
yes
no
yes
no
no
no
yes
staying dry outside, if the inputs are
do I have an umbrella?
is it raining?
umbrella?
raining?
dry
yes
yes
yes
yes
no
yes
no
yes
no
no
no
yes
close the project
I close
test_binary.pyandtruth_table.pyI click in the terminal where the tests are running
I use q on the keyboard to leave the tests. The terminal goes back to the command line.
I change directory to the parent of
truth_tablecd ..the terminal shows
.../pumping_pythonI am back in the
pumping_pythondirectory
review
Binary Operations take two inputs, each input can be True or False. If I name the first input first_input and the second input second_input, the tests show that
-
returns
first_input or not second_inputreturns False if
first_inputis False andsecond_inputis Trueis the Logical Negation (NOT) of Converse Non-Implication which returns True only if
first_inputis False andsecond_inputis True
first input
second input
return
True
True
True
True
False
True
False
True
False
False
False
True
-
always returns
first_inputreturns True only if
first_inputis Trueis the Logical Negation (NOT) of Negate First which returns True only if
first_inputis False
first input
second input
return
True
True
True
True
False
True
False
True
False
False
False
False
-
returns
first_input and not second_inputreturns True only if
first_inputis True andsecond_inputis Falseis the Logical Negation (NOT) of Material/Logical Implication which returns False only if
first_inputis True andsecond_inputis False
first input
second input
return
True
True
False
True
False
True
False
True
False
False
False
False
-
returns
first_input != second_inputreturns True only if
first_inputandsecond_inputare NOT equalis the Logical Negation (NOT) of Logical Equality which returns True only if
first_inputandsecond_inputare equal
first input
second input
return
True
True
False
True
False
True
False
True
True
False
False
False
-
returns
first_input or second_inputreturns False only if
first_inputis False andsecond_inputis Falseis the Logical Negation (NOT) of Logical NOR which returns True only if
first_inputis False andsecond_inputis False
first input
second input
return
True
True
True
True
False
True
False
True
True
False
False
False
-
always returns True
never returns False
is the Logical Negation (NOT) of contradiction which always returns False
first input
second input
return
True
True
True
True
False
True
False
True
True
False
False
True
-
returns
not (first_input and second_input)returns False only if
first_inputis True andsecond_inputis Trueis the Logical Negation (NOT) of Logical Conjunction (AND) which returns True only if
first_inputis True andsecond_inputis True
first input
second input
return
True
True
False
True
False
True
False
True
True
False
False
True
-
always returns
not first_inputreturns True only if
first_inputis Falseis the Logical Negation (NOT) of Project First which returns True only if
first_inputis True
first input
second input
return
True
True
False
True
False
False
False
True
True
False
False
True
-
returns
not first_input and second_inputreturns True only if
first_inputis False andsecond_inputis Trueis the Logical Negation (NOT) of Converse Implication which returns False if
first_inputis False andsecond_inputis True
first input
second input
return
True
True
False
True
False
False
False
True
True
False
False
False
-
always returns
second_inputreturns True only if
second_inputis Trueis the Logical Negation (NOT) of Negate Second which returns True only if
second_inputis False
first input
second input
return
True
True
True
True
False
False
False
True
True
False
False
False
Logical Conjunction returns
returns
first_input and second_inputreturns True only if
first_inputis True andsecond_inputis Trueis the Logical Negation (NOT) of Logical NAND which returns False only if
first_inputis True andsecond_inputis True
first input
second input
return
True
True
True
True
False
False
False
True
False
False
False
False
-
always returns False
never returns True
is the Logical Negation (NOT) of Tautology which always returns True
first input
second input
return
True
True
False
True
False
False
False
True
False
False
False
False
All the binary operations or conditions have been written with some combination of some or all of these three
return |
True, True |
True, False |
False, True |
False, False |
name of operation |
|---|---|---|---|---|---|
False |
False |
False |
False |
False |
|
first and second |
True |
False |
False |
False |
|
second |
True |
False |
True |
False |
|
(not first) and second |
False |
False |
True |
False |
|
not first |
False |
False |
True |
True |
|
not (first and second) |
False |
True |
True |
True |
|
True |
True |
True |
True |
True |
|
first or second |
True |
True |
True |
False |
|
(not (first and second)) and (first or second) |
False |
True |
True |
False |
|
first and (not second) |
False |
True |
False |
False |
|
first |
True |
True |
False |
False |
|
first or (not second) |
True |
True |
False |
True |
code from the chapter
Do you want to see all the CODE I typed for the Truth Table?
what is next?
rate pumping python
If this has been a 7 star experience for you, please CLICK HERE to leave a 5 star review of pumping python. It helps other people get into the book too.