restart;
RowOpsMaplet := module()
############################################################
#
# Elementary Row Operations Maplet
# Andrew Martin, University of Kent, England
# agm5@kent.ac.uk, agmweb@ilovemaths.co.uk
# Date of publication of this code: August 28, 2003
# Version 0.2
#
# Structure of code based on:
# Step-by-Step Differentiation Problem Solver Maplet
# Copyright 2002 Waterloo Maple Inc.
#
############################################################
# TODO LIST
# Error checking on back substitution, on error that says needs rowreducd matris, pass this error to user
# Spell check everything and make nice titles
# Sort out unused variable names
# sort out why the mathml viewie scrools but the view doenst so one has to scroll down to see it.
# change input mechanism so that matrix() bit etc isn't required use fullMatrixStr
# write a sheet on how to use this
export iniMathML, addMathML, runRowOpsMaplet,
startRule, clearSteps:
local helpStr:
global errorSwitch;
errorSwitch:=2;
############################################################
helpStr :=
"You can apply elementary row operations one at a time to an augmented matrix and view the resulting matrix.
Enter a matrix using the usual Maple synatx. Click the 'Start' button to initialize the problem.
To apply elementary row operations, enter appropriate values in the boxes and click the corresponding button.
You can undo steps by clicking the undo button.
When you apply a row operation, the 'Problem Status' box is updated with the result of the row operation.
To clear the problem history, click the 'Clear' button.
To obtain the matrix in Gaussian form, Gauss-Jordan form (row reduced echelon form) or to perform back substitution on a matrix, click the approproate button.
Please report bugs, send comments and suggestions for improvements to Andrew Martin via e-mail agmweb@ilovemaths.co.uk
":
############################################################
############################################################
iniMathML := proc(iniEqn)
global errorSwitch, infoStr;
try
MathML:-ExportPresentation(iniEqn);
catch: infoStr := "MathML conversion error - possibly due to a missing matrix entry"; errorSwitch:=1;
end try;
end proc:
############################################################
############################################################
# pre: mathMLStr :: string, in form of Presentation MathML
# addEqn :: algebraic expression
addMathML := proc(mathMLStr, addEqn)
local tree, cmc, child, children, nl, eqnSign;
use XMLTools in
tree := FromString(mathMLStr);
cmc := ContentModelCount(tree);
child := FromString(MathML:-ExportPresentation(addEqn));
children := ContentModel(child);
nl := FromString("
");
eqnSign := Element("mo","=");
tree := AddChild(tree,nl,cmc);
tree := AddChild(tree,eqnSign,cmc+1);
for child in children do
cmc := ContentModelCount(tree);
tree := AddChild(tree,child,cmc);
end do:
tree := MakeElement("mrow", [], ContentModel(tree) ):
tree := Element("math", tree):
ToString(tree):
end use:
end proc:
############################################################
clearSteps := proc()
global errorSwitch;
use Maplets:-Tools in
Set('ML'=""): Set('TB'=""):
Clear(all):
errorSwitch:=2;
end use:
end proc: # end clearSteps:
############################################################
# TODO
#
# need to check that the multiply and add boxes have entries in
# need to check how big matrix is and adujust pull down list to reflect this.
# when matrixExpr is acted on need to change this to try catch stuff.
# check spellings
startRule := proc()
local mlStr, matrixStr, fullMatrixStr:
global matrixExpr, errorSwitch, infoStr:
use Maplets:-Tools, Maplets:-Elements in
clearSteps():
matrixExpr:='matrixExpr';
mlStr :="";
errorSwitch:=0; # by setting errorSwitch to 0 it shows that start has been pressed, if an error occurs it goes to 1.
infoStr := "Initializing":
Set('TB'=infoStr):
matrixStr := Get('TF_fun'):
if matrixStr="" then
infoStr := "Nothing has been entered":
errorSwitch:=1;
Set('TB'=infoStr):
# error "No matrix has been entered":
end if:
fullMatrixStr := matrixStr; #cat("matrix(",matrixStr,")"):
#matrixExpr := parse(fullMatrixStr):
try
matrixExpr := parse(fullMatrixStr):
catch: infoStr := "Parsing error, enter a valid matrix"; errorSwitch:=1;
end try;
if errorSwitch<>1 then
if type(eval(matrixExpr), matrix)
then infoStr := "Apply a row operation"; errorSwitch:=0; #switch this back to 0 upon success don't think this is needed tho
else infoStr := "Input not of type matrix"; errorSwitch:=1;
fi;
fi:
if errorSwitch<>1 then
mlStr := iniMathML(eval(matrixExpr)):
fi:
# I guess I should check if the matrix is
# already in reduced from or is degenreate
# in some way.
Set('ML'=mlStr):
Set('TB'=infoStr):
#Maplets:-Display(Maplet(MessageDialog(mlStr))):
#Set('TB'=mlStr):
end use:
end proc: # end startRule
#
#########################################################
Xswap := proc(r1,r2)
local mlStr, infoStr:
global matrixExpr:
use Maplets:-Tools, Maplets:-Elements in
if noErrors() then
mlStr := Get('ML'): infoStr := Get('TB'):
matrixExpr:=linalg[swaprow](eval(matrixExpr),r1,r2);
mlStr := addMathML(mlStr,eval(matrixExpr)):
infoStr := cat(infoStr, "\n", "Interchange row ", r1, " and row ", r2):
Set('TB'=infoStr):
Set('ML'=mlStr):
fi:
#Maplets:-Display(Maplet(MessageDialog(mlStr))):
#Set('TB'=mlStr):
end use:
end proc:
#########################################################
Xmultiply := proc(r1,expr1)
local mlStr, infoStr:
global matrixExpr:
use Maplets:-Tools, Maplets:-Elements in
if noErrors() then
mlStr := Get('ML'): infoStr := Get('TB'):
matrixExpr:=linalg[mulrow](eval(matrixExpr),r1,expr1);
mlStr := addMathML(mlStr,eval(matrixExpr)):
infoStr := cat(infoStr, "\n", "Multiply row ", r1, " by ", expr1):
Set('TB'=infoStr):
Set('ML'=mlStr):
fi:
end use:
end proc:
#########################################################
Xadd := proc(r1,r2,expr1)
local mlStr, infoStr:
global matrixExpr:
use Maplets:-Tools, Maplets:-Elements in
if noErrors() then
mlStr := Get('ML'): infoStr := Get('TB'):
matrixExpr:=linalg[addrow](eval(matrixExpr),r1,r2,expr1);
mlStr := addMathML(mlStr,eval(matrixExpr)):
infoStr := cat(infoStr, "\n", "Add ", expr1, " times row ", r1, " to row ", r2 ):
Set('TB'=infoStr):
Set('ML'=mlStr):
fi:
end use:
end proc:
#########################################################
Xgausselim := proc()
local mlStr, infoStr:
global matrixExpr:
use Maplets:-Tools, Maplets:-Elements in
if noErrors() then
mlStr := Get('ML'): infoStr := Get('TB'):
matrixExpr:=linalg[gausselim](eval(matrixExpr));
mlStr := addMathML(mlStr,eval(matrixExpr)):
infoStr := cat(infoStr, "\n", "Gaussian form"):
Set('TB'=infoStr):
Set('ML'=mlStr):
fi:
end use:
end proc:
#########################################################
Xgaussjord := proc()
local mlStr, infoStr:
global matrixExpr:
use Maplets:-Tools, Maplets:-Elements in
if noErrors() then
mlStr := Get('ML'): infoStr := Get('TB'):
matrixExpr:=linalg[rref](eval(matrixExpr));
mlStr := addMathML(mlStr,eval(matrixExpr)):
infoStr := cat(infoStr, "\n", "Gauss-Jordon form"):
Set('TB'=infoStr):
Set('ML'=mlStr):
fi:
end use:
end proc:
#########################################################
Xbacksub := proc()
local mlStr, infoStr:
global matrixExpr:
use Maplets:-Tools, Maplets:-Elements in
if noErrors() then
# also need to check that it can be back subsituted, or just trap errors
mlStr := Get('ML'): infoStr := Get('TB'):
matrixExpr:=linalg[backsub](eval(matrixExpr));
mlStr := addMathML(mlStr,eval(matrixExpr)):
infoStr := cat(infoStr, "\n", "Back substituted"):
Set('TB'=infoStr):
Set('ML'=mlStr):
fi:
end use:
end proc:
#########################################################
Xundo := proc()
# search infoStr backwards for last \n and then cut so it removes last statement
#
# Since only a simple matrix is used, we can use the Import command on the parsed presentation MathML
#
# This is probably not a very good way to allow an undo function but I think it is better than
# storing the matrix at each stage, or storing the steps in a way so they can be reversed.
#
local mlStr, infoStr,
revStr, lastMatrixStart, lastMatrixEnd, mlStrRev, lastNewline:
global matrixExpr:
use Maplets:-Tools, Maplets:-Elements in
if noErrors() then
# also need to check for other errors
mlStr := Get('ML'): infoStr := Get('TB'):
#### this code removes the last matrix from the displayed MathML
revStr:=StringTools[Reverse](mlStr):
lastMatrixStart:=searchtext(StringTools[Reverse]("
="),revStr)+length("
=")-1;
lastMatrixEnd:=searchtext(StringTools[Reverse](""),revStr);
mlStrRev:=cat(substring(revStr,1..lastMatrixEnd-1), substring(revStr,lastMatrixStart+1..-1));
mlStr:=StringTools[Reverse](mlStrRev);
##### end
##### this code now parses the NEW mlStr (uses the mlStrREv to be more efficient)
## to find the last 'good' matrix and imports it
lastMatrixStart:=searchtext(StringTools[Reverse](""),mlStrRev)+length("")-1;
lastMatrixEnd:=searchtext(StringTools[Reverse](""),mlStrRev);
matrixExpr:=MathML[Import](cat("" ));
##### end
##### now the easy bit, look in the comments string to remove the last comment
lastNewline:=searchtext("\n",StringTools[Reverse](infoStr));
infoStr:=substring(infoStr,1..length(infoStr)-lastNewline);
#####
#infoStr := cat(infoStr, "\n", "last step undone"): # later change this so that the comment is removed too
Set('TB'=infoStr):
Set('ML'=mlStr):
fi:
end use:
end proc:
########################################################
noErrors := proc()
local mlStr, infoStr:
global errorSwitch:
use Maplets:-Tools, Maplets:-Elements in
if errorSwitch=0 then
return true;
else
startRule();
if errorSwitch=0 then
return true;
else
return false;
fi;
fi;
end use:
end proc:
############################################################
runRowOpsMaplet := proc()
local maplet, color, lightcolor, darkcolor:
color := 'background'="#DDFFFF":
lightcolor := 'background'="#EEFFFF":
darkcolor := 'background'="#CCFFFF":
use Maplets, Maplets:-Elements in
maplet := Maplet(
'onstartup'=RunWindow('rowOpsWin'),
Font['F1']('family'="Default",italic='true','size'=12),
Font['F2']('family'="Default", 'bold'='true', 'size'=14),
Window['rowOpsWin']('menubar'='rowOpsMB', 'resizable'='false',
'title'="Row operations Maplet",
BoxColumn(color, 'inset'=0, 'spacing'=0,
BoxRow(color, 'border'='true','inset'=0,'spacing'=3,
'caption'="Enter a matrix",
Label('caption'="Enter a matrix ", 'font'=F2,'background'="#DDFFFF"),
TextField['TF_fun']('value'="matrix([[2,-1,-2,2],[-1,2,3,2],[3,5,1,0]])", lightcolor, 'width'=36),
Label('caption'=" ", 'font'=F2,'background'="#DDFFFF"),
Button("Start", 'onclick'='A_start', lightcolor,
'tooltip'="Initialize")
), # end BoxRow
BoxRow(color, 'inset'=0,'spacing'=0,
BoxColumn(color, 'border'='true', 'inset'=0, 'spacing'=0,
'caption'="Problem Status",
BoxRow(color,
MathMLViewer['ML'](#'value' = MathML:-ExportPresentation(matrix([[2,-1,-2,2],[-1,2,3,2],[3,5,1,0]])),
'height'=470, 'width'=400, lightcolor)
# MathMLViewer['ML']('value' = "",'height'=470, 'width'=400, lightcolor)
) # end BoxRow
), # end BoxColumn
BoxColumn(color, 'inset'=0, 'inset'=0, 'spacing'=0,
BoxRow(color, 'border'='true', 'caption'="Messages",
'inset'=0, 'spacing'=0,
BoxCell(
TextBox['TB'](lightcolor, 'editable'='false',
'value'="",
'tooltip'="Messages", 'font'='F1', 'height'=3
) # end TextBox
) # end BoxCell
), # end BoxRow
BoxColumn(color, 'border'='true', 'inset'=0, 'spacing'=0,
'caption'="Row operations",
# swap
BoxRow(color, 'halign'='left', 'inset'=0, 'spacing'=0,
BoxCell('halign'='left',
Button['B_swap']("Swap",
'onclick'='A_swap', lightcolor,
'tooltip'="Intercahange rows")
), # BoxCell
Label('caption'=" row ", 'font'=F2,'background'="#DDFFFF"),
DropDownBox['swapr1'](["1", "2", "3", "4"]),
Label('caption'=" and row ", 'font'=F2,'background'="#DDFFFF"),
DropDownBox['swapr2'](["1", "2", "3", "4"])
), # BoxRow
# multiply
BoxRow(color, 'halign'='left', 'inset'=0, 'spacing'=0,
BoxCell('halign'='left',
Button['B_multiply']("Multiply",
'onclick'='A_multiply', lightcolor,
'tooltip'="Multiply row by an expression")
), # BoxCell
Label('caption'=" row ", 'font'=F2,'background'="#DDFFFF"),
DropDownBox['mrow'](["1", "2", "3", "4"]),
Label('caption'=" by ", 'font'=F2,'background'="#DDFFFF"),
TextField['mexpr'](5, 'value' ="1")
), # BoxRow
# add
BoxRow(color, 'halign'='left', 'inset'=0, 'spacing'=0,
BoxCell('halign'='left',
Button['B_add']("Add",
'onclick'='A_add', lightcolor,
'tooltip'="Add a row to another")
), # BoxCell
Label('caption'=" ", 'font'=F2,'background'="#DDFFFF"),
TextField['aexpr'](5, 'value' ="0"),
Label('caption'=" times row ", 'font'=F2,'background'="#DDFFFF"),
DropDownBox['arow1'](["1", "2", "3", "4"]),
Label('caption'=" to row ", 'font'=F2,'background'="#DDFFFF"),
DropDownBox['arow2'](["1", "2", "3", "4"])
) # BoxRow
), # end BoxLayout
# gaussian elimination, row reduced, back subsituted A_gauselim, A_gaussjord, A_backsub,
BoxColumn(color, 'border'='true', 'inset'=0, 'spacing'=0,
# 'caption'="Eliminations",
BoxRow(color, 'halign'='left', 'inset'=0, 'spacing'=0,
BoxCell('halign'='left',
Button['B_el']("G elimin",
'onclick'='A_gausselim', lightcolor,
'tooltip'="Gaussian elimination on a matrix")
), # BoxCell
Label('caption'=" ", 'font'=F2,'background'="#DDFFFF"),
BoxCell('halign'='left',
Button['B_el2']("G-J elim", #Gauss-Jordanelimination
'onclick'='A_gaussjord', lightcolor,
'tooltip'="Gauss-Jordan elimination (Reduced row echelon form)")
), # BoxCell
Label('caption'=" ", 'font'=F2,'background'="#DDFFFF"),
BoxCell('halign'='left',
Button['B_el3']("Back sub", #Backsubstitution
'onclick'='A_backsub', lightcolor,
'tooltip'="Back substitution on a matrix")
) # BoxCell
) # BoxRow
), # end BoxColumn
# clear and close and undo butoons
BoxColumn(color, 'border'='true', 'inset'=0, 'spacing'=0,
# 'caption'="",
BoxRow(color, 'halign'='left', 'inset'=0, 'spacing'=0,
BoxCell('halign'='left',
Button("Undo", 'onclick'='A_undo', lightcolor,
'tooltip'="Undo the previous operation")
), # BoxCell
Label('caption'=" ", 'font'=F2,'background'="#DDFFFF"),
BoxCell('halign'='left',
Button("Clear", 'onclick'='A_clear', lightcolor,
'tooltip'="Clear the problem history")
), # BoxCell
Label('caption'=" ", 'font'=F2,'background'="#DDFFFF"),
BoxCell('halign'='left',
Button("Close", Shutdown(), 'tooltip'="Close the maplet", lightcolor)
) # BoxCell
) # BoxRow
) # end BoxLayout
) # end BoxColumn
) # end BoxRow
) # end BoxColumn
), # end Window
############################################################
MenuBar['rowOpsMB'](
Menu("File",
MenuItem("Clear", 'onclick'='A_clear'),
MenuSeparator(),
MenuItem("Close", Shutdown())
), # end Menu/File
Menu("Help",
MenuItem("Using this Maplet", 'onclick'=RunWindow('helpWin'))
) # end Menu/Help
), # end MenuBar
############################################################
Window['helpWin']( 'resizable'='false',
'title'="Using the Elementary Row Operations Maplet",
BoxColumn(color, 'border'='true', 'inset'=0, 'spacing'=8,
BoxCell(
TextBox('height'=24, 'width'=40,
lightcolor, 'foreground'="#333399",
'editable'='false', 'font'='F2',
'value'=helpStr
) # end TextBox
), # end BoxCell
BoxRow(color, 'inset'=0, 'spacing'=0,
Button("Close", lightcolor,
CloseWindow('helpWin'))
) # end BoxRow
) # end BoxColumn
), # end helpWin
############################################################
Action['A_start'](
Evaluate('function'='startRule()')
), # end A_start
Action['A_clear'](
Evaluate('function'='clearSteps()')
), # end A_clear
############################################################
Action['A_swap'](
Evaluate('function'='Xswap(swapr1,swapr2)')
),
Action['A_multiply'](
Evaluate('function'='Xmultiply(mrow,mexpr)')
),
Action['A_add'](
Evaluate('function'='Xadd(arow1,arow2,aexpr)')
),
Action['A_gausselim'](
Evaluate('function'='Xgausselim()')
),
Action['A_gaussjord'](
Evaluate('function'='Xgaussjord()')
),
Action['A_backsub'](
Evaluate('function'='Xbacksub()')
),
Action['A_undo'](
Evaluate('function'='Xundo()')
),
############################################################
Action['A']()
) : # end maplet
Maplets[Display](maplet) :
end use: # end use
end proc: # end runRowOpsMaplet
############################################################
end module: # end RowOpsMaplet()
RowOpsMaplet:-runRowOpsMaplet();