The art of a good argument

In the book, I describe the way Charlie and Aisha interact in terms of a model. We determine whether Charlie will start shouting is using the following table.

../../_images/GoodArgument.png

On this page we implement the model in Python.

Setting up rules

We start by setting up these rules.

import numpy as np
import pandas as pd

Charlie_shout =np.array([[0.1, 0.5],[0.7,0.95]])
Charlie_rules = pd.DataFrame(data= Charlie_shout,index=['Aisha calm', 'Aisha shouting'], columns=['Charlie calm', 'Charlie shoting'])
print('Probability of Charlie shouting:')
print(Charlie_rules)

Aisha_shout =np.array([[0.1, 0.7],[0.5,0.95]])
Aisha_rules = pd.DataFrame(data= Aisha_shout,index=['Aisha calm', 'Aisha shouting'], columns=['Charlie calm', 'Charlie shoting'])
print('Probability of Aisha shouting:')
print(Aisha_rules)

# Initially, neither of them are shouting

Charlie=[0]
Aisha=[0]

# Number of time steps
T = 25
Probability of Charlie shouting:
                Charlie calm  Charlie shoting
Aisha calm               0.1             0.50
Aisha shouting           0.7             0.95
Probability of Aisha shouting:
                Charlie calm  Charlie shoting
Aisha calm               0.1             0.70
Aisha shouting           0.5             0.95

Simulating arguments

We now set up a computer simulation and look at how the two interact. To do this, we loop over 25 steps of discussion according to the rules above.

def argument(T,Charlie_rules,Aisha_rules,print_out=1):
    for i in range(T):

        Prob_Charlie = Charlie_rules.iloc[Charlie[i]][Aisha[i]]
        if np.random.rand()<Prob_Charlie:
            describe_Charlie = 'Charlie shouts. '
            Charlie.append(1)
        else:
            describe_Charlie = "Charlie doesn't shout. "
            Charlie.append(0)

        Prob_Aisha = Aisha_rules.iloc[Charlie[i]][Aisha[i]]
        if np.random.rand()<Prob_Aisha:
            describe_Aisha = 'Aisha shouts.'
            Aisha.append(1)
        else:
            describe_Aisha = "Aisha doesn't shout."
            Aisha.append(0)

        if print_out:
            print('Time step %d:' % (i+1) + describe_Charlie +describe_Aisha)

    return Aisha,Charlie

Aisha,Charlie = argument(T,Charlie_rules,Aisha_rules)
/home/docs/checkouts/readthedocs.org/user_builds/fourways/checkouts/latest/course/lessons/lesson2/plot_theartofagoodargument.py:53: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  Prob_Charlie = Charlie_rules.iloc[Charlie[i]][Aisha[i]]
/home/docs/checkouts/readthedocs.org/user_builds/fourways/checkouts/latest/course/lessons/lesson2/plot_theartofagoodargument.py:61: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  Prob_Aisha = Aisha_rules.iloc[Charlie[i]][Aisha[i]]
Time step 1:Charlie doesn't shout. Aisha doesn't shout.
Time step 2:Charlie doesn't shout. Aisha doesn't shout.
Time step 3:Charlie doesn't shout. Aisha doesn't shout.
Time step 4:Charlie doesn't shout. Aisha doesn't shout.
Time step 5:Charlie doesn't shout. Aisha doesn't shout.
Time step 6:Charlie doesn't shout. Aisha doesn't shout.
Time step 7:Charlie doesn't shout. Aisha doesn't shout.
Time step 8:Charlie doesn't shout. Aisha doesn't shout.
Time step 9:Charlie doesn't shout. Aisha doesn't shout.
Time step 10:Charlie doesn't shout. Aisha doesn't shout.
Time step 11:Charlie doesn't shout. Aisha doesn't shout.
Time step 12:Charlie doesn't shout. Aisha doesn't shout.
Time step 13:Charlie doesn't shout. Aisha doesn't shout.
Time step 14:Charlie doesn't shout. Aisha doesn't shout.
Time step 15:Charlie doesn't shout. Aisha doesn't shout.
Time step 16:Charlie doesn't shout. Aisha doesn't shout.
Time step 17:Charlie doesn't shout. Aisha doesn't shout.
Time step 18:Charlie doesn't shout. Aisha doesn't shout.
Time step 19:Charlie doesn't shout. Aisha doesn't shout.
Time step 20:Charlie doesn't shout. Aisha doesn't shout.
Time step 21:Charlie doesn't shout. Aisha doesn't shout.
Time step 22:Charlie doesn't shout. Aisha doesn't shout.
Time step 23:Charlie doesn't shout. Aisha doesn't shout.
Time step 24:Charlie doesn't shout. Aisha doesn't shout.
Time step 25:Charlie doesn't shout. Aisha doesn't shout.

We can represent the argument as a binary string, as we do in the book.

print("Charlie's shouting as a string of zeros (clam) and ones (shouting):")
print(' '.join(map(str, Charlie)))
print("Aisha's shouting as a string of zeros (clam) and ones (shouting):")
print(' '.join(map(str, Aisha)))
Charlie's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Aisha's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Now we can make them argue lots of times!

for j in range(5):

    # Both start calm.
    Charlie=[0]
    Aisha=[0]

    # Call the argument function
    print('Argument %d' % (j+1))
    print('----------')
    Aisha,Charlie = argument(T,Charlie_rules,Aisha_rules,0)
    print("Charlie's shouting as a string of zeros (clam) and ones (shouting):")
    print(' '.join(map(str, Charlie)))
    print("Aisha's shouting as a string of zeros (clam) and ones (shouting):")
    print(' '.join(map(str, Aisha)))
    print('\n')
Argument 1
----------
Charlie's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Aisha's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1


Argument 2
----------
Charlie's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Aisha's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1


Argument 3
----------
Charlie's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 1 0 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Aisha's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1


Argument 4
----------
Charlie's shouting as a string of zeros (clam) and ones (shouting):
0 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1
Aisha's shouting as a string of zeros (clam) and ones (shouting):
0 0 1 1 1 1 1 1 0 1 1 1 1 1 0 0 0 1 1 1 0 0 0 0 1 1


Argument 5
----------
Charlie's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 0 0 0 1 1 0 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1
Aisha's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 0 0 1 1 0 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0

Charlie makes a change

Charlie decides to update his rules

../../_images/CharlieUpdate.png
Charlie_shout =np.array([[0.1, 0.1],[0.1,0.95]])
Charlie_rules = pd.DataFrame(data= Charlie_shout,index=['Aisha calm', 'Aisha shouting'], columns=['Charlie calm', 'Charlie shoting'])
print('Probability of Charlie shouting:')
print(Charlie_rules)
Probability of Charlie shouting:
                Charlie calm  Charlie shoting
Aisha calm               0.1             0.10
Aisha shouting           0.1             0.95

Now let’s look at five arguments under his new rules.

for j in range(5):

    Charlie=[0]
    Aisha=[0]
    print('Argument %d' % (j+1))
    print('----------')
    Aisha,Charlie = argument(T,Charlie_rules,Aisha_rules,0)
    print("Charlie's shouting as a string of zeros (clam) and ones (shouting):")
    print(' '.join(map(str, Charlie)))
    print("Aisha's shouting as a string of zeros (clam) and ones (shouting):")
    print(' '.join(map(str, Aisha)))
    print('\n')
Argument 1
----------
/home/docs/checkouts/readthedocs.org/user_builds/fourways/checkouts/latest/course/lessons/lesson2/plot_theartofagoodargument.py:53: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  Prob_Charlie = Charlie_rules.iloc[Charlie[i]][Aisha[i]]
/home/docs/checkouts/readthedocs.org/user_builds/fourways/checkouts/latest/course/lessons/lesson2/plot_theartofagoodargument.py:61: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  Prob_Aisha = Aisha_rules.iloc[Charlie[i]][Aisha[i]]
Charlie's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1
Aisha's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 0 0 1 1 1 1 0 0 1 0 0 0 0 1 0 0 0 0 1 1 1


Argument 2
----------
Charlie's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0
Aisha's shouting as a string of zeros (clam) and ones (shouting):
0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0


Argument 3
----------
Charlie's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 0 0 0 0 0
Aisha's shouting as a string of zeros (clam) and ones (shouting):
0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 0


Argument 4
----------
Charlie's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 1 1 1 1 1 1 1 1 1 1
Aisha's shouting as a string of zeros (clam) and ones (shouting):
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1


Argument 5
----------
Charlie's shouting as a string of zeros (clam) and ones (shouting):
0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
Aisha's shouting as a string of zeros (clam) and ones (shouting):
0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Now Charlie shouts less and (as a result) so to does Aisha.

Try yourself!

Download the code and run it yourself in a Python notebook. Adjust the probabilities so that Aisha adopts the same rules as Charlie. Notice how much less they argue with one another!

Integrative behavioural couple therapy

An introduction to integrative behavioural couple therapy (IBCT) can be watched below:

The model described in this section is inspired by this approach.

To learn more about this approach see:

Andrew Christensen and Brian D. Doss, Integrative behavioral couple therapy, Current Opinion in Psychology 13 (2017): 111‒14.

Total running time of the script: (0 minutes 0.031 seconds)

Gallery generated by Sphinx-Gallery