DM559/DM545 – Linear and Integer Programming
Using IPython for interactive work¶You can work interactively with Python using:
See this tutorial Tutorial for an introduction to interactive Python. This is a syntetic tutorial only about the tools that can be useful for the digital tests during the course. Preamble for working with Arrays and Fractions¶Copy this preamble in your script to load the needed modules and implement a function In [1]:
from numpy import *
from fractions import Fraction as f
set_printoptions(precision=3,suppress=True)
def printm(a):
"""Prints the array as strings
:a: numpy array
:returns: prints the array
"""
def p(x):
return str(x)
p = vectorize(p,otypes=[str])
print(p(a))
def tableau(a,W=7):
"""Returns a string for verbatim printing
:a: numpy array
:returns: a string
"""
if len(a.shape) != 2:
raise ValueError('verbatim displays two dimensions')
rv = []
rv+=[r'|'+'+'.join('{:-^{width}}'.format('',width=W) for i in range(a.shape[1]))+"+"]
rv+=[r'|'+'|'.join(map(lambda i: '{0:>{width}}'.format("x"+str(i+1)+" ",width=W), range(a.shape[1]-2)) )+"|"+
'{0:>{width}}'.format("-z ",width=W)+"|"
'{0:>{width}}'.format("b ",width=W)+"|"]
rv+=[r'|'+'+'.join('{:-^{width}}'.format('',width=W) for i in range(a.shape[1]))+"+"]
for i in range(a.shape[0]-1):
rv += [r'| '+' | '.join(['{0:>{width}}'.format(str(a[i,j]),width=W-2) for j in range(a.shape[1])])+" |"]
rv+=[r'|'+'+'.join('{:-^{width}}'.format('',width=W) for i in range(a.shape[1]))+"+"]
i = a.shape[0]-1
rv += [r'| '+' | '.join(['{0:>{width}}'.format(str(a[i,j]),width=W-2) for j in range(a.shape[1])])+" |"]
rv+=[r'|'+'+'.join('{:-^{width}}'.format('',width=W) for i in range(a.shape[1]))+"+"]
print('\n'.join(rv))
Elementary row operations¶To do elementary row operations on a matrix one can do as follows: In [2]:
A = array( [[1, f(9,4), 2, f(4,5)],
[f(3,4), 1, f(5,4), 0]])
A[0,:] = f(4,9) * A[0,:]
printm(A)
In [3]:
tableau(A)
Note that indices start from 0, hence a vector of size $n$ has indices from $0$ to $n-1$. Matrix Operations¶Construct an array of zeros¶In [4]:
zeros((3,1))
Out[4]:
Concatenate an identity matrix to a matrix¶In [5]:
A_1 = concatenate([A,identity(2)],axis=1)
printm(A_1)
Insert a row in between other two:¶In [6]:
A_2 = concatenate([ A[0:1,:], array( [[0,2,1,0]] ), A[1:2,:] ],axis=0)
printm(A_2)
Ask for the dimensions of an array:¶In [7]:
A.shape
Out[7]:
Multiply matrices¶The operations In [8]:
A = ones((4,2)) # a matrix of 1s of size 4x2
b = array([1,2])
A*b
Out[8]:
which is element-wise and hence not matrix-vector multiplication. The correct way to do matrix-vector and matrix-matrix multiplication is: In [9]:
dot(A,b)
Out[9]:
Inverse¶In [10]:
A = random.randint(1,10,size=(4,4))
A_i = linalg.inv(A)
around( dot(A,A_i), decimals=2) # let's verify
Out[10]:
Transpose¶In [11]:
A.T
Out[11]:
Rank¶In [12]:
linalg.matrix_rank(A)
Out[12]:
Reduced row echelon form¶You should calculate the reduced row echelon form by applying elementary row operations In [13]:
A=array([[f(3,1),1,1,1],
[2,4,1,1],
[2,1,2,2]])
b=array([2,2,1])
AA=column_stack([A,b])
AA[0,:] = f(1,3) * AA[0,:] # remember indices start from 0
AA[1,:] = -2 * AA[0,:] + AA[1,:]
AA[2,:] = -2 * AA[0,:] + AA[2,:]
printm(AA)
AA[1,:] = f(3,10)* AA[1,:]
AA[2,:] += -f(1,3) * AA[1,:]
printm(AA)
AA[2,:] = f(10,13) * AA[2,:]
printm(AA)
AA[1,:] += -f(1,10) * AA[2,:]
AA[0,:] += -f(1,3) * AA[2,:]
printm(AA)
AA[0,:] += -f(1,3) * AA[1,:]
printm(AA)
You can check your result by importing the module for symbolic computation In [14]:
import sympy as sy
# np.linalg.solve(A,b)
sy.Matrix(AA).rref()
Out[14]:
|