Revised: December 1, 2003
You will create a C++ program that lets you compute the inverse of a matrix in PSL(2,F), where F is a finite field, or to multiply two such matrices. Then you will associate a permutation with each such matrix and let the user verify that the group of permutations is isomorphic to the group of matrices. If you are feeling ambitious, you could even display the two isomorphic groups SL(2,F4) and PSL(2,Z5) at the same time and have a four-way isomorphism.
These instructions will explain how to create the user-interface parts of the program that you may not have seen before. After that, you are on your own. You can reuse your previous code for multiplying permutations and for doing arithmetic in finite fields.
The programs used in class that multiply 2x2 matrices over F4 and
Z5, "SL2F.exe and GL2Z5.exe", can be downloaded from the
course
Web site.
You can also download a copy of this document, from which you can paste
code into your project as you are creating it.
1. By following steps 1-6 of the previous project with "GF" replaced by "Iso" (and "gf" by "iso" in file names), create a widget-based project named Iso.
2. Open up isobase.ui in Qt Designer. Change the caption of the form to "Isomorphism Demonstration." If you are not working on the Science Center network, change the font to 12-point Lucidatypewriter.
3. In the upper right-hand corner of the dialog, place a button
group
box (icon to the right of Group Box), about 150x100, with the title
"Galois
Field". Inside the group box, place two radio buttons (icon is a black
circle inside a white circle). The top one should have the name
RadioF4
and the text SL(2,F4). The second one should have the name
RadioF5
and the text PSL(2,Z5). Choose Edit...Slots from the menu and add
slots slotF4() and slotZ5().
Press F3 to enter connection mode and connect clicked() for RadioF4
to slotF4().
Again press F3 to enter connection mode and connect clicked() for
RadioZ5
to slotZ5().
4. In the upper left-hand corner of the dialog, place a group box,
about
180x270, with the title Matrix A. At the upper left corner of this
group
box, place a combo box (icon, to the left of the slider, looks like a
list
box with something on top of it). Make this 20 pixels high and half the
width of the group box. Change its name to ComboA11.
With this combo box selected, press Ctrl-C to copy it. Press
Ctrl-V to paste a copy, and drag it to the right side of the top row of
the group box. Change the name to ComboA12, and Adjust the size
of
the group box so that the two combo boxes fit neatly. Now copy
two
more combo boxes under the first two to complete the 2x2 matrix. Change
their names to ComboA21 and ComboA22.
Beneath the two combo boxes, place a button with name ButtonCheck and
text Read and Check.
Under the button, place a text label, large enough to show two lines
of 10 characters, with name TextShowA. Change its palette background
color
to white. Beneath this, put a text label with text "Permutation"
and under that, a line edit with name EditPermA.
Choose Edit...Slots from the menu and add slot slotCheck().
Press F3 to enter connection mode and connect clicked() for
ButtonCheck()
to slotCheck().
Close QtDesigner, saving the .ui file.
5. Under the Classes tab, right-click on Classes. Choose New
Class...
from the drop-down menu. For the name of the class, choose Matrix2x2.
There
is no base class Press OK to create the class. Right-click
on the name of this new class under the Classes taband add the
following
member variables:
GFElement el11;
GFElement el12;
GFElement el21;
GFElement el22;
int prime;
int power;
Just above the class declaration in Matrix2x2.h, insert the line
#include "gfelement.h"
From the main menu, choose Project...Add Existing Files... and insert
the files gfelement.h and gfelement.cpp from your GF directory into the
Iso directory.
As the last line of the function GFElement::init(), add
setValue();
This will initialize the element to [0]
Build your project. If you have followed instructions
carefully,
you should see the class GFElement under the Classes Tab.
6. Add the following function to the class Matrix2x2 to initialize
all
the elements of a matrix for a specific finite field.
void Matrix2x2::init(int pr, int pow){
prime = pr;
power = pow;
el11.init(pr,pow);
el21.init(pr,pow);
el12.init(pr,pow);
el22.init(pr,pow);
}
7. In class Iso, insert the member variable
Matrix2x2 matrixA;
Then add slotCheckA() with the following code:
void Iso::slotCheckA()
{
int index = ComboA11->currentItem();
matrixA.el11.setValue(index%matrixA.prime,index/matrixA.prime);
index = ComboA12->currentItem();
matrixA.el12.setValue(index%matrixA.prime,index/matrixA.prime);
index = ComboA21->currentItem();
matrixA.el21.setValue(index%matrixA.prime,index/matrixA.prime);
index = ComboA22->currentItem();
matrixA.el22.setValue(index%matrixA.prime,index/matrixA.prime);
if (matrixA.checkDeterminant()) {
TextShowA->setText(matrixA.boxText());
}
else QMessageBox::warning(this,"Invalid Matrix","This matrix
does not have determinant 1. Change an entry so that the the
determinant
is 1");
}
At the top of iso.cpp
#include <qlabel.h>
#include <qmessagebox.h>
8. In the class Matrix2x2, add the member functions
GFElement Matrix2x2::determinant(){
GFElement det = el11*el22 - el21*el12;
return det;
}
bool Matrix2x2::checkDeterminant(){
//The following assumes power < 3
return (determinant().c[0] == 1 &&
determinant().c[1]
== 0 );
}
The job of the second function is to check the data supplied by the user to make sure that the matrix has determinant 1.
In the case of Z5 you may also want to multiply the
entire matrix by [4] if necessary to make it be the standard
representative
of its equivalence class. A reasonable criterion for "standard"
is
that the first nonzero entry should be [1] or [2] in the case of Z5.
If you do not do this you will end up with a homomorphism of SL(2,Z5)
with A5, which is still OK.
9. Add the following functions to the class Matrix2x2. These
format
a matrix so that it can be displayed in a text label.
QString Matrix2x2::extend(QString s, uint size){
while (s.length() < size)
s += " ";
return s;
}
QString Matrix2x2::boxText(){
return extend(el11.asText(),6) + el12.asText() + "\n"
+
extend(el21.asText(),6) + el22.asText();
}
10. Add the following function to the class Iso. This puts the correct strings for the chosen Galois field into a combo box.
void Iso::fillComboBox(QComboBox* box, Matrix2x2& m){
GFElement entry;
entry.init(m.prime,m.power);
int c1max = 1;
if (m.power > 1) {
c1max = m.prime;
}
box->clear();
for (int i = 0; i < c1max; i++) {
for (int j = 0; j < m.prime; j++) {
entry.setValue(j,i);
box->insertItem(entry.asText());
}
}
}
At the top of iso.h
#include <qcombobox.h>
#include "matrix2x2.h"
12. In class Iso, override the two remaining virtual slot functions from IsoBase, with the following code:
void Iso::slotF4(){
matrixA.init(2,2);
fillComboBox(ComboA11, matrixA);
fillComboBox(ComboA12, matrixA);
fillComboBox(ComboA21, matrixA);
fillComboBox(ComboA22, matrixA);
}
/** No descriptions */
void Iso::slotZ5(){
matrixA.init(5,1);
fillComboBox(ComboA11, matrixA);
fillComboBox(ComboA12, matrixA);
fillComboBox(ComboA21, matrixA);
fillComboBox(ComboA22, matrixA);
}
13. At this point you can build and run the project. For either field, if you type in a matrix whose determinant is [1], you should see it nicely displayed in the two-line edit control. Otherwise you will see a message box complaining that the determinant is not [1].
14. From this point you are on your own! Here are some
features
that you might include:
For 6 points, add a class Vector2 that represents a two-component
vector
over a finite field. It might be a good idea to add a function to
this class that returns a "line name" for each vector. A good way to
number
the lines is to the first one be ([1] [0]), with name "0" and the
others
be ( [0] [1]), ([1], [1]), etc. with names '1', '2',.... This is
slightly
different from the numbering that was done in class, bt it is more
systematic.
A constructor that constructs a Vector2 with specified power, prime,
and line name may also be useful.
For 7 points, compute the action of MatrixA on each of the lines in
the 2x2 vector space over the field and thereby associate a permutation
with the matrix. A function like
char Matrix2x2::actOnLine(char i)
where i is the "line name," will be all that you need. The code
to convert the results of this function into the cycle representation
of
the permutation is something that you wrote for project 1, though you
may
need to make a tiny modification for the symbol '0'.
For 8 points, have the slotCheckA() function also report the order of the matrix in a text label and compute and display the inverse of the matrix..
For 9 points, add a second matrix B and compute the product AB and the product of the corresponding permutations. You can copy the code that multiplies permutations from project 1, with small modifications to take account of the symbol '0'. In Qt Designer, you can use Ctrl-C and Ctrl-V to copy the Matrix A group box and all its contents.
For 10 points, add Z7 as an additional choice for the finite field. This may be very easy!
For 11 points, make it possible for the user to type in the permutation instead of the matrix and press a button to generate a matrix of determinant 1 that gives rise to the specified permutation. This presents an interesting mathematical problem, since the permutation only tells you a vector proportional to the result of a matrix acting on a given vector.
For 12 points, add F9 .The permutations now involve ten lines, and you have reached the limit of what you can do with the symbols 0 through 9.
For 14 points, add F8 .This will be messy, since some of
the existing code assumes power < 3 and F8 has
prime
=2, power = 3.