truth table: Binary Operations part 1


The last chapter covered 2 types of operations. Nullary Operations which do not take input, and Unary Operations which take 1 input.

There are also Binary Operations, these take 2 inputs. Each of the inputs in this exercise will be True or False which means there are 4 possible ways the inputs can be sent to an operation

preview

These combinations give 16 binary operations each of which returns True or False based on the inputs it receives. Here are the 16 operations that are covered in these chapters and what they return


requirements

truth table: Nullary and Unary Operations

how to get back to the automated tests

If your tests stopped after the previous chapter, heres’s how to get back to the tests


test_contradiction

RED: make it fail

I add a new TestCase to test_truth_table.py

 1import unittest
 2import src.truth_table
 3
 4
 5class TestNullaryOperations(unittest.TestCase):
 6
 7    def test_logical_true(self):
 8        self.assertTrue(src.truth_table.logical_true())
 9
10    def test_logical_false(self):
11        self.assertFalse(src.truth_table.logical_false())
12
13
14class TestUnaryOperations(unittest.TestCase):
15
16    def test_logical_identity(self):
17        self.assertTrue(src.truth_table.logical_identity(True))
18        self.assertFalse(src.truth_table.logical_identity(False))
19
20    def test_logical_negation_aka_not(self):
21        self.assertFalse(src.truth_table.logical_negation(True))
22        self.assertTrue(src.truth_table.logical_negation(False))
23
24
25class TestBinaryOperations(unittest.TestCase):
26
27    def test_contradiction(self):
28        self.assertFalse(src.truth_table.contradiction(True, True))
29
30
31# Exceptions seen

the terminal shows AttributeError

AttributeError: module 'src.truth_table' has no attribute 'contradiction'

GREEN: make it pass

I add a function definition to truth_table.py

13def logical_negation(the_input):
14    return not the_input
15
16
17def contradiction(the_input):
18    return not the_input

the terminal shows TypeError

TypeError: contradiction() takes 1 positional argument but 2 were given

The definition only takes one input, but the test sent two. I add second_input as the second name in parentheses then change argument to first_input for the first input given when the function is called by the test

Tip

In Visual Studio Code I can change all the places that a name is in the file, by using

  • Find and Replace - ctrl+H on Windows or option+command+F on MacOS or with

  • Rename Symbol

    • Right click on the name you want to change, for example the_input then select Rename Symbol or

    • Select the name you want to change then hit :kbd:F2 on your keyboard to rename it

17def contradiction(first_input, second_input):
18    return not first_input

the test passes. When contradiction gets True as its first input and True as its second input, it returns the opposite of the first input, that means it returns not True which is False

REFACTOR: make it better

  • I add the second case to test_contradiction in test_truth_table.py, this is when the first input is True and the second input is False

    27    def test_contradiction(self):
    28        self.assertFalse(src.truth_table.contradiction(True, True))
    29        self.assertFalse(src.truth_table.contradiction(True, False))
    

    the test is still green. contradiction returns False in the two cases where the first input is True

  • I add the third case, which is when the first input is False and the second input is True

    27    def test_contradiction(self):
    28        self.assertFalse(src.truth_table.contradiction(True, True))
    29        self.assertFalse(src.truth_table.contradiction(True, False))
    30        self.assertFalse(src.truth_table.contradiction(False, True))
    

    the terminal shows AssertionError

    AssertionError: True is not false
    

    so far all three cases of the test expect False, which means contradiction should return False when

    • the first input is True and the second input is True

    • the first input is True and the second input is False

    • the first input is False and the second input is True

  • I change the return statement in the contradiction function in truth_table.py to return the expectation

    17def contradiction(first_input, second_input):
    18    return False
    

    the test passes

  • I add the fourth case to test_contradiction in test_truth_table.py, this is when the two inputs are False

    27    def test_contradiction(self):
    28        self.assertFalse(src.truth_table.contradiction(True, True))
    29        self.assertFalse(src.truth_table.contradiction(True, False))
    30        self.assertFalse(src.truth_table.contradiction(False, True))
    31        self.assertFalse(src.truth_table.contradiction(False, False))
    32
    33
    34# Exceptions seen
    

    the test is still green!

Contradiction always returns False it does not matter what inputs it gets


test_logical_conjunction

RED: make it fail

I add a test for logical_conjunction in test_truth_table.py with the first case where the two inputs are True

31          self.assertFalse(src.truth_table.contradiction(False, False))
32
33      def test_logical_conjunction(self):
34          self.assertTrue(src.truth_table.logical_conjunction(True, True))
35
36
37# Exceptions seen

the terminal shows AttributeError

AttributeError: module 'src.truth_table' has no attribute 'logical_conjunction'. Did you mean: 'logical_negation'?

GREEN: make it pass

I add the function in truth_table.py

17def contradiction(first_input, second_input):
18    return False
19
20
21def logical_conjunction(first_input, second_input):
22    return True

the test . logical_conjunction returns True when the first and second input are both True

REFACTOR: make it better

  • I add the next case - when the first input is True and the second input is False, to test_logical_conjunction in test_truth_table.py

    33    def test_logical_conjunction(self):
    34        self.assertTrue(src.truth_table.logical_conjunction(True, True))
    35        self.assertFalse(src.truth_table.logical_conjunction(True, False))
    

    the terminal shows AssertionError

    AssertionError: True is not false
    
  • I make the logical_conjunction function in truth_table.py return False

    21def logical_conjunction(first_input, second_input):
    22    return False
    23    return True
    

    the terminal shows AssertionError

    AssertionError: False is not true
    

    The line that was passing before is now failing

logical_conjunction has to make a choice. It should return

  • False when the first input and second input are both True

  • True when the first input is True and the second input is False

I can make it do that with if statements

if statements

An if statement is a way for a program to do something based on something else. I can use them to make a function choose between 2 things, there are written as

if something:
    do this
  • I add if statements to the logical_conjunction function in truth_table.py

    21def logical_conjunction(first_input, second_input):
    22    if first_input == True:
    23        if second_input == False:
    24            return False
    25    return True
    

    the test passes. logical_conjunction returns

  • I add the case where the first input is False and the second input is True to test_logical_conjunction in test_truth_table.py

    33    def test_logical_conjunction(self):
    34        self.assertTrue(src.truth_table.logical_conjunction(True, True))
    35        self.assertFalse(src.truth_table.logical_conjunction(True, False))
    36        self.assertFalse(src.truth_table.logical_conjunction(False, True))
    

    the terminal shows AssertionError

    AssertionError: True is not false
    
  • I add another if statement for this case to logical_conjunction in truth_table.py

    21def logical_conjunction(first_input, second_input):
    22    if first_input == False:
    23        if second_input == True:
    24            return False
    25    if first_input == True:
    26        if second_input == False:
    27            return False
    28    return True
    

    the test passes. logical_conjunction returns

  • I add the last case, which is when the two inputs are False, to test_logical_conjunction in test_truth_table.py

    33    def test_logical_conjunction(self):
    34        self.assertTrue(src.truth_table.logical_conjunction(True, True))
    35        self.assertFalse(src.truth_table.logical_conjunction(True, False))
    36        self.assertFalse(src.truth_table.logical_conjunction(False, True))
    37        self.assertFalse(src.truth_table.logical_conjunction(False, False))
    38
    39
    40# Exceptions seen
    

    the terminal shows AssertionError

    AssertionError: True is not false
    
  • I add if statements for the new case to logical_conjunction in truth_table.py

    21def logical_conjunction(first_input, second_input):
    22    if first_input == False:
    23        if second_input == False:
    24            return False
    25    if first_input == False:
    26        if second_input == True:
    27            return False
    28    if first_input == True:
    29        if second_input == False:
    30            return False
    31    return True
    

    the test passes. logical_conjunction returns

  • I have the same if statement twice - if first_input == False for the 3rd and 4th cases where the first input is False

    21def logical_conjunction(first_input, second_input):
    22    if first_input == False:
    23        if second_input == False:
    24            return False
    25    if first_input == False:
    26        if second_input == True:
    27            return False
    28    if first_input == True:
    29        if second_input == False:
    30            return False
    31    return True
    

    I remove the second one

    21def logical_conjunction(first_input, second_input):
    22    if first_input == False:
    23        if second_input == False:
    24            return False
    25        if second_input == True:
    26            return False
    27    if first_input == True:
    28        if second_input == False:
    29            return False
    30    return True
    

    the test is still green

  • I add an if statement for the first case, where the first and second inputs are both True

    21def logical_conjunction(first_input, second_input):
    22    if first_input == False:
    23        if second_input == False:
    24            return False
    25        if second_input == True:
    26            return False
    27    if first_input == True:
    28        if second_input == False:
    29            return False
    30        if second_input == True:
    31            return True
    

    the terminal still shows green

  • there are only 2 results for this operation, in the first case the function returns True. In the other 3 cases it returns False.

    21def logical_conjunction(first_input, second_input):
    22    if first_input == False:
    23        if second_input == False:
    24            return False
    25        if second_input == True:
    26            return False
    27    if first_input == True:
    28        if second_input == False:
    29            return False
    30        if second_input == True:
    31            return True
    

    Tip

    I can put two if statements together when one is under the other. For example

    if something:
        if something_else:
    

    can also be written as

    if something and something_else:
    
  • I put the two if statements for the one case where the result is True together and use an else clause for the other cases where the first and second inputs are not both True

    21def logical_conjunction(first_input, second_input):
    22    if first_input == True and second_input == True:
    23        return True
    24    else:
    25        return False
    26    if first_input == False:
    27        if second_input == False:
    28            return False
    29        if second_input == True:
    30            return False
    31    if first_input == True:
    32        if second_input == False:
    33            return False
    34        if second_input == True:
    35            return True
    

    the test is still green

  • I remove the other if statements then use bool in the first if statement

    21def logical_conjunction(first_input, second_input):
    22    if bool(first_input) and bool(second_input):
    23    # if first_input == True and second_input == True:
    24        return True
    25    else:
    26        return False
    

    still green. bool checks if the thing in parentheses is True in the background

  • I remove the commented line then change the first line to make it simpler

    21def logical_conjunction(first_input, second_input):
    22    if first_input and second_input:
    23    # if bool(first_input) and bool(second_input):
    24        return True
    25    else:
    26        return False
    

    the test is still green

    Tip

    these if statements are the same

    • if something == True:

    • if bool(something): == True

    • ``if bool(something):

    • if something:

    Python checks if something is True in the background when I type if something:

    I remove the commented line

conditional expressions

  • Python has ternary operators or conditional expressions which allow me to write the if statement and the else clause as one line

    21def logical_conjunction(first_input, second_input):
    22    return True if first_input and second_input else False
    23    if first_input and second_input:
    24        return True
    25    else:
    26        return False
    

    the terminal shows green

  • I remove the other if statements then change the return statement to a simpler form

    21def logical_conjunction(first_input, second_input):
    22    return first_input and second_input
    23    return True if first_input and second_input else False
    

    still green!

  • I remove the second return statement

    21def logical_conjunction(first_input, second_input):
    22    return first_input and second_input
    

Logical Conjunction also known as and, returns

  • first_input and second_input

  • True when the two inputs are both True

Tip

All of the statements below give the same result

  • this checks if something is True

    if something == True:
        return True
    else:
        return False
    
  • this uses bool to get the boolean of something then checks if the result is True

    if bool(something) == True:
        return True
    else:
        return False
    
  • this checks if bool(something) is True in the background

    if bool(something):
        return True
    else:
        return False
    
  • this checks if something is True in the background

    if something:
        return True
    else:
        return False
    
  • this returns True if something is True

    return True if something else False
    
  • this also returns True after checking if something is True in the background

    return something
    

the last one works because Python tests if something is True in the background same as it does when I type if something:


test_project_second

RED: make it fail

I add a test for another Binary Operation in test_truth_table.py

37        self.assertFalse(src.truth_table.logical_conjunction(False, False))
38
39    def test_project_second(self):
40        self.assertTrue(src.truth_table.project_second(True, True))
41
42
43# Exceptions seen

the terminal shows AttributeError

AttributeError: module 'src.truth_table' has no attribute 'project_second'

GREEN: make it pass

I add a definition for the function in truth_table.py

21def logical_conjunction(first_input, second_input):
22    return first_input and second_input
23
24
25def project_second(first_input, second_input):
26    return True

the test passes. When the first input is True and the second input is False, this function returns True

REFACTOR: make it better

  • I add the second case - where the first input is True and the second input False, to test_project_second in test_truth_table.py

    39    def test_project_second(self):
    40        self.assertTrue(src.truth_table.project_second(True, True))
    41        self.assertFalse(src.truth_table.project_second(True, False))
    

    the terminal shows AssertionError

    AssertionError: True is not false
    
  • I add an if statement for the case to project_second in truth_table.py

    25def project_second(first_input, second_input):
    26    if first_input == True:
    27        if second_input == False:
    28            return False
    29    return True
    

    the test

    • project_second returns False when the first input is True and the second input False

    • it returns True in every other case

  • I add the next case, which is when the first input is False and the second input is True to test_project_second in test_truth_table.py

    39    def test_project_second(self):
    40        self.assertTrue(src.truth_table.project_second(True, True))
    41        self.assertFalse(src.truth_table.project_second(True, False))
    42        self.assertTrue(src.truth_table.project_second(False, True))
    

    the test is still green

  • I add the last case - when the two inputs are False

    39    def test_project_second(self):
    40        self.assertTrue(src.truth_table.project_second(True, True))
    41        self.assertFalse(src.truth_table.project_second(True, False))
    42        self.assertTrue(src.truth_table.project_second(False, True))
    43        self.assertFalse(src.truth_table.project_second(False, False))
    44
    45
    46# Exceptions seen
    

    the terminal shows AssertionError

    AssertionError: True is not false
    
  • I add an if statement for this case to project_second in truth_table.py

    25def project_second(first_input, second_input):
    26    if first_input == False:
    27        if second_input == False:
    28            return False
    29    if first_input == True:
    30        if second_input == False:
    31            return False
    32    return True
    

    the test passes

  • project_second returns

    It returns the same value as the second input. I add a new return statement to show this

    25def project_second(first_input, second_input):
    26    return second_input
    27    if first_input == False:
    28        if second_input == False:
    29            return False
    30    if first_input == True:
    31        if second_input == False:
    32            return False
    33    return True
    

    the test is still green

  • I remove the other statements

    25def project_second(first_input, second_input):
    26    return second_input
    

Project Second returns the second input, it always returns


test_converse_non_implication

RED: make it fail

I add a test for converse_non_implication in test_truth_table.py

43        self.assertFalse(src.truth_table.project_second(False, False))
44
45    def test_converse_non_implication(self):
46        self.assertFalse(src.truth_table.converse_non_implication(True, True))
47
48
49# Exceptions seen

the terminal shows AttributeError

AttributeError: module 'src.truth_table' has no attribute 'converse_non_implication'

GREEN: make it pass

I add the function to truth_table.py

25def project_second(first_input, second_input):
26    return second_input
27
28
29def converse_non_implication(first_input, second_input):
30    return False

the test passes. converse_non_implication returns False when the first input is True and the second input is False

REFACTOR: make it better

  • I add the next case to test_converse_non_implication in test_truth_table.py, when the first input is True and the second input is False

    45    def test_converse_non_implication(self):
    46        self.assertFalse(src.truth_table.converse_non_implication(True, True))
    47        self.assertFalse(src.truth_table.converse_non_implication(True, False))
    

    the test is still green, because it expects False in both cases

  • I add the third case - where the first input is False and the second input is True

    45    def test_converse_non_implication(self):
    46        self.assertFalse(src.truth_table.converse_non_implication(True, True))
    47        self.assertFalse(src.truth_table.converse_non_implication(True, False))
    48        self.assertTrue(src.truth_table.converse_non_implication(False, True))
    

    the terminal shows AssertionError

    AssertionError: False is not true
    
  • I add an if statement to converse_non_implication in truth_table.py

    29def converse_non_implication(first_input, second_input):
    30    if first_input == False:
    31        if second_input == True:
    32            return True
    33    return False
    

    the test passes. The converse_non_implication function returns

    • True when the first input is False and the second input is True

    • False in all other cases

  • I add the next case - when the first and second inputs are both False, to test_converse_non_implication in test_truth_table.py

    45    def test_converse_non_implication(self):
    46        self.assertFalse(src.truth_table.converse_non_implication(True, True))
    47        self.assertFalse(src.truth_table.converse_non_implication(True, False))
    48        self.assertTrue(src.truth_table.converse_non_implication(False, True))
    49        self.assertFalse(src.truth_table.converse_non_implication(False, False))
    50
    51
    52# Exceptions seen
    

    the test is still passing

  • I use and aka logical_conjunction to put the two if statements together in converse_non_implication in truth_table.py

    29def converse_non_implication(first_input, second_input):
    30    if first_input == False and second_input == True:
    31    # if first_input == False:
    32    #    if second_input == True:
    33            return True
    34    return False
    

    the terminal still shows green

  • I remove the commented lines then change the first line with logical negation and bool

    29def converse_non_implication(first_input, second_input):
    30    if not first_input == True and bool(second_input):
    31    # if first_input == False and second_input == True:
    32        return True
    33    return False
    

    still green

  • I add an else clause

    
    
    29def converse_non_implication(first_input, second_input):
    30    if not first_input == True and bool(second_input):
    31    # if first_input == False and second_input == True:
    32        return True
    33    else:
    34        return False
    

    the test is still green

  • I remove the comment and use bool with the first part of the if statement to make it simpler

    29def converse_non_implication(first_input, second_input):
    30    if not bool(first_input) and second_input:
    31    # if not first_input == True and bool(second_input):
    32        return True
    33    else:
    34        return False
    

    the test is still green

  • I remove the commented line and make the if statement simpler

    29def converse_non_implication(first_input, second_input):
    30    if not first_input and second_input:
    31    # if not bool(first_input) and second_input:
    32        return True
    33    else:
    34        return False
    

    the terminal still shows green

  • I use a conditional expression

    29def converse_non_implication(first_input, second_input):
    30    return True if not first_input and second_input else False
    31    if not first_input and second_input:
    32        return True
    33    else:
    34        return False
    

    still green

  • I remove the if statements then use the simpler return statement

    29def converse_non_implication(first_input, second_input):
    30    return not first_input and second_input
    31    return True if not first_input and second_input else False
    

    all tests are still passing

  • I remove the second return statement

    29def converse_non_implication(first_input, second_input):
    30    return not first_input and second_input
    

Converse NonImplication always returns


review

Binary Operations take 2 inputs, each input can be True or False, if the first input is named first_input and the second input is named second_input, the tests show that

and

All the logic statements or conditions have been written with some or all of the above 2.


code from the chapter

Do you want to see all the CODE I typed for the Truth Table?


what is next?

Would you like to test more binary operations?