1
Posted February 25, 2013 by Hunter in Python Programming
 
 

Graphing Linear Inequalities with Python

alg2_ineq
alg2_ineq

Here is a practical example of the matplotlib.pyplot module in use. This code generates a list of linear inequalities, prints them in numbered groups (such as if you were to be creating worksheets for students), and then displays the graphs of each inequality in order. The code makes use of pyplot’s simple syntax and versatility to create it’s own shading.

import matplotlib.pyplot as plt
import random

## List containing all the equations already used
test = []

## Sets the size of the graph, also adds lines on the axes and
## a grid.  There is a grid function build in to matplotlib.pyplot,
## but it isn't very flexable.  With this, you can make the grid
## solid lines or dashed, or of any thickness or interval.
def buildplane():

    xy = [-11,11,-11,11]
    plt.axis(xy)
    xy_axes = plt.plot([-11,11],[0,0],[0,0],[-11,11])

    for yline in range(-11,12):
        plt.plot([-11,11],[yline,yline],'k',lw=0.5)
    for xline in range(-11,12):
        plt.plot([xline,xline],[-11,11],'k',lw=0.5)

    plt.setp(xy_axes,color='black',lw=2)
    plt.text(10.5,0.5,'x')
    plt.text(0.5,10.5,'y')

## Returns a random number from -high to high, or a fraction
def randomnumber(high):
    gogogo = 0
    while gogogo != 1:
        temp = random.randrange(2,5)
        if temp != 3:
            gogogo = 1
    frac = random.randrange(1,temp)/temp
    if random.random() < .4:
        frac *= -1
    if random.random() <= 0.1:
        num = frac
    else:
        num = random.randrange(1,high)
        if random.random() <= 0.075:
            num += frac
        if random.random() < .4:
            num *= -1
    return num

## Returns two points - and since any line can be defined by two points,
## this really returns the data for a new equation
def point():
    a_0 = float(random.randrange(-10,10))
    a_1 = float(random.randrange(-10,10))
    a_2 = float(random.randrange(-10,10))
    a_3 = float(random.randrange(-10,10))
    return [[a_0,a_1],[a_2,a_3]]

## Given two points, returns the slope and y-intercept of the line
## defined by those points - or returns 'undefined' if the slope
## is undefined
def m_b_form(point_1,point_2):
    if point_1[0]-point_2[0] != 0:
        m = ( point_1[1] - point_2[1] ) / ( point_1[0] - point_2[0] )
        b = ( point_1[0] * point_2[1] - point_2[0] * point_1[1] ) / ( point_1[0] - point_2[0] )
        return [m,b]
    else:
        return 'undefined'

## Returns 1 if the equation is both unique and has 'nice' and easy numbers.
## Returns 0 otherwise
def goodandunique(line):
    good = 0
    unique = 0
    m = line[0]
    b = line[1]
    if (m!=0)&(m<8)&(m>-8)&((m%1==0)|(m*2%1==0)|(m*4%1==0)|(m*5%1==0))&(b<8)&(b>-8)&((b%1==0)|(b*2%1==0)):
        good = 1
    if line not in test:
        test.append(line)
        unique = 1
    if (good == 1) & (unique == 1):
        return 1
    else:
        return 0

## Plots a line passed in the form [m,b]
def plotline(line):
    m = line[0]
    b = line[1]
    plt.plot([-11,11],[m*-11+b,m*11+b],'k')

## Returns a string containing a readable expression of the inequality
## passed to it
def y_string(line,inequal):
    if inequal == 1:
        ymxb = 'y >= '
    elif inequal == 2:
        ymxb = 'y > '
    elif inequal == 3:
        ymxb = 'y <= '
    else:
        ymxb = 'y < '
    if line[0] == 1:
        ymxb += 'x'
    elif line[0] == -1:
        ymxb += '-x'
    else:
        ymxb += str(line[0])+'x'
    if line[1] != 0:
        if line[1] < 0:
            ymxb += ' - '+str(line[1])[1:]
        else:
            ymxb += ' + '+str(line[1])
    return ymxb

## Graphs an inequality
def graphinequal(line,inequal):
    m = line[0]
    b = line[1]
    ## If the inequality is >= or >
    if (inequal == 1) | (inequal == 2):
        ## If the inequality is >=
        if inequal == 1:
            ## Plot the line as a solid line
            plt.plot([-11,11],[m*-11+b,m*11+b],'k')
        ## If the inequality is >
        if inequal == 2:
            ## Plot the line as a dotted line
            plt.plot([-11,11],[m*-11+b,m*11+b],'k--')
        ## If the slope is negative
        if m > 0:
            y = 11
            ## Starting at the top of graph, graph thin lines from the left
            ## edge of the graph to the x-position of the line given
            ## our current y position
            while y >= -11:
                x = (y-b)/m
                plt.plot([-11,x],[y,y],'k',lw=0.25)
                y -= 0.25
            x = 11
            ## Starting at the right of the graph, graph thin lines
            ## from the top of the graph down to the y-position of
            ## the line given our current x position
            while x >= -11:
                y = m*x+b
                plt.plot([x,x],[y,11],'k',lw=0.25)
                x -= 0.25
        ## If the slope is positive, do the same as for if
        ## the slope were negative, except drawing the thin lines
        ## on the other side of the line
        if m < 0:
            y = 11
            while y >= -11:
                x = (y-b)/m
                plt.plot([x,11],[y,y],'k',lw=0.25)
                y -= 0.25
            x = 11
            while x >= -11:
                y = m*x+b
                plt.plot([x,x],[y,11],'k',lw=0.25)
                x -= 0.25

    ## If the inequality is <= or <
    if (inequal == 3) | (inequal == 4):
        if inequal == 3:
            plt.plot([-11,11],[m*-11+b,m*11+b],'k')
        if inequal == 4:
            plt.plot([-11,11],[m*-11+b,m*11+b],'k--')
        if m < 0:
            y = 11
            while y >= -11:
                x = (y-b)/m
                plt.plot([-11,x],[y,y],'k',lw=0.25)
                y -= 0.25
            x = 11
            while x >= -11:
                y = m*x+b
                plt.plot([x,x],[-11,y],'k',lw=0.25)
                x -= 0.25
        if m > 0:
            y = 11
            while y >= -11:
                x = (y-b)/m
                plt.plot([x,11],[y,y],'k',lw=0.25)
                y -= 0.25
            x = 11
            while x >= -11:
                y = m*x+b
                plt.plot([x,x],[-11,y],'k',lw=0.25)
                x -= 0.25

## The number of worksheets you wish to create
ws = 5

## List of all the points used during the running of this program
points_final = []
## List of all the lines used during the running of this program
lines_final = []
## List of readable y=mx+b forms of the equations
ymxb_final = []
## List of integers, 1 to 4, representing which inequality
## (>, <, <=, >=) has been used
inequal_final = []

## Creates the equations
for k in range(0,ws):

    for i in range(0,13):
        hold = 1
        ## Repeates until the line created is a unique line
        ## and has 'nice' and easy numbers
        while hold == 1:
            ## Creates two points, stores them as points
            points = point()
            ## Redescribes the line represented by points
            ## in the form of the slope and y-intercept
            line = m_b_form(points[0],points[1])
            ## If the line has a defined slope
            if line != 'undefined':
                ## If the line is unique and has 'nice' and easy numbers
                if goodandunique(line) == 1:
                    hold = 0
                    points_final.append(points)
                    lines_final.append(line)
                    inequal_final.append(random.randrange(1,5))
                    ymxb_final.append(y_string(line,inequal_final[len(inequal_final)-1]))

## Prints the equations
for k in range(0,ws):

    print ''
    print 'Run #'+str(k+1)
    print 'Ex: '+ymxb_final[k*13]
    for i in range(1,13):
        print str(i)+': '+ymxb_final[i+k*13]

## Displays the graphs, one at a time
for k in range(0,ws):

    for i in range(0,13):
        buildplane()
        graphinequal(lines_final[i+k*13],inequal_final[i+k*13])
        plt.show()

Hunter