codex/past-exam-of-the-computer-science-course-of-the-university-of-oxford/2015/formal-verification-2015-transition-system.py

past-exam-of-the-computer-science-course-of-the-university-of-oxford/2015/formal-verification-2015-transition-system.py
"""Plot the synthesized four-state relation in Oxford CAFV 2015 Q1(f).

Output in cwd. Tested with Python 3.14.4, matplotlib 3.10.7, numpy 2.3.5.
"""
from pathlib import Path
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, FancyArrowPatch


def main():
    fig, ax = plt.subplots(figsize=(7.6, 6.3), dpi=100, facecolor='white')
    positions = {'00':(-1.25,1.1), '01':(1.25,1.1), '10':(-1.25,-1.1), '11':(1.25,-1.1)}
    for s in positions:
        for t in positions:
            if not (t[0] == '1' or (s[1] == '1' and t[1] == '1')):
                continue
            p, q = positions[s], positions[t]
            if s == t:
                x, y = p
                direction = -1 if x < 0 else 1
                start = (x + direction * .20, y + .20)
                end = (x + direction * .20, y - .20)
                path = f'arc3,rad={-1.8 * direction}'
                shrink = 0
            else:
                start, end = p, q
                path = 'arc3,rad=0.17' if (s, t) in [('01','11'),('11','01'),('10','11'),('11','10')] else 'arc3,rad=0'
                shrink = 24
            ax.add_patch(FancyArrowPatch(start,end,arrowstyle='-|>',mutation_scale=16,
                linewidth=1.6,connectionstyle=path,shrinkA=shrink,shrinkB=shrink,color='#222222',zorder=1))
    for name, (x, y) in positions.items():
        ax.add_patch(Circle((x,y),.27,facecolor='white',edgecolor='black',lw=1.5,zorder=3))
        ax.text(x,y,f'$q_{{{name}}}$',ha='center',va='center',fontsize=18,zorder=4)
    ax.text(0,-1.95,'Current state: (u, x)     Next state: (y, z)',ha='center',fontsize=13)
    ax.set_title('Transition relation: y or (x and z)', fontsize=17, pad=18)
    ax.set_xlim(-2.35,2.35)
    ax.set_ylim(-2.2,1.9)
    ax.set_aspect('equal')
    ax.axis('off')
    fig.tight_layout(pad=1.3)
    fig.savefig(Path('formal-verification-2015-transition-system.png'),facecolor='white')
    plt.close(fig)


if __name__ == '__main__':
    main()