Matrix Applet

<< Guassian Elimination | OtherProjectsTrailIndex | Determinant >>

See a working version here

Download the Application MatrixApp.jar

Download the Java Web Start application here

Rational.java

public class Rational {
	private int numerator;
	private int denominator;
	public Rational(String s){
		int fBar=s.indexOf("/");
		if (fBar==-1){
			numerator=Integer.parseInt(s);
			denominator=1;			
		} else {
			numerator=Integer.parseInt(s.substring(0,fBar));
			denominator=Integer.parseInt(s.substring(fBar+1));
			simplify();
		}
	}
	public Rational(int n, int d){
		numerator=n;
		denominator=d;
		simplify();
	}
	public Rational(int n){
		numerator=n;
		denominator=1;
	}
	public Rational(){
		numerator=0;
		denominator=1;
	}
	public Rational (Rational r){
		this.numerator=r.getNumerator();
		this.denominator=r.getDenominator();
	}
	public void setNumerator(int numerator) {
		this.numerator = numerator;
	}
	public int getNumerator() {
		return numerator;
	}
	public void setDenominator(int denominator) {
		this.denominator = denominator;
	}
	public int getDenominator() {
		return denominator;
	}
	public double value(){
		return (double)(numerator)/denominator;
	}
	public Rational reciprocal(){
		return new Rational(this.getDenominator(),this.getNumerator());
	}
	public String toString(){
		if (denominator ==1)
			return Integer.toString(numerator);
		return Integer.toString(numerator)+"/"+Integer.toString(denominator);
	}
	public String toString(int n){
		String result= Integer.toString(numerator)+"/"+Integer.toString(denominator);
		if (denominator ==1)
			result= Integer.toString(numerator);
		while (result.length()<n)
			result=" "+result;
		return result;
	}
	public Rational multiply(Rational other){
		int n=this.getNumerator()*other.getNumerator();
		int d=this.getDenominator()*other.getDenominator();
		Rational result=new Rational(n,d);
		return result;
	}
	public Rational add(Rational other){
		int n=this.getNumerator()*other.getDenominator()+
		      other.getNumerator()*this.getDenominator();
		int d=this.getDenominator()*other.getDenominator();
		Rational result=new Rational(n,d);
		return result;
	}

	public void simplify(){
		int p=2;
		if (denominator<0){
			numerator*=-1;
			denominator*=-1;
		}
		while (p<= Math.max(numerator, denominator)){
			while(numerator%p==0 && denominator%p==0){
				numerator/=p;
				denominator/=p;	
			}
			if (p==2) p++; else p+=2;
		}
		if (numerator==0 )
			denominator=1;
		if (numerator==denominator ){
			denominator=1;
			numerator=1;
		}
	}
}

Matrix.java

public class Matrix 
{
	private int rows;
	private int cols;
	Rational[][] m;
	public Matrix(int r, int c){
		rows=r;
		cols=c;
		m=new Rational[rows][cols];
		for(int i=0;i<rows;i++)
			for(int j=0;j<cols;j++){
				m[i][j]=new Rational();
			}
	}
	public Matrix(Matrix o){
		rows=o.getRows();
		cols=o.getCols();
		m=new Rational[rows][cols];
		for(int i=0;i<rows;i++)
			for(int j=0;j<cols;j++){
				m[i][j]=o.get(i, j);
			}
	}
	public Matrix(String s){
	    String[] r=s.split("\n"); 
	    rows = r.length;
	    String[] c=r[0].split(" ");
		cols = c.length;
		m=new Rational[rows][cols];
		for(int i=0;i<rows;i++){
			c=r[i].split(" ");
			cols = c.length;
			for (int j=0;j<cols;j++){
				this.set(i, j, new Rational(c[j]));				
			}			
		}  
	}
	public int getRows(){
		return rows;
	}
	public int getCols(){
		return cols;
	}
	public void set(int r, int c, Rational q){
		m[r][c]=q;
	}
	public Rational get(int r, int c){
		return m[r][c];
	}
	public String toString(){
		String result="";
		for (int i=0;i<rows;i++){
			for(int j=0;j<cols;j++){
				result+=m[i][j].toString()+" ";
			}
			result+="\n";
		}
		return result;
	}
	public String toString(int n){
		String result="";
		for (int i=0;i<rows;i++){
			for(int j=0;j<cols;j++){
				result+=m[i][j].toString(n);
			}
			result+="\n";
		}
		return result;
	}
	public void swap(int row1, int row2) {		
		for (int j=0; j<cols;j++){
			Rational q=this.get(row1, j);
			this.set(row1, j, this.get(row2, j));
			this.set(row2, j, q);
		}
	}
	public void multiply(int row, Rational number) {
		for (int j=0; j<cols;j++){	
			Rational q = number.multiply(this.get(row, j));
			this.set(row, j, q);			
		}
	}
	public void addMultiple(int row1, Rational number, int row2) {
		for (int j=0; j<cols;j++){	
			Rational q = number.multiply(this.get(row1, j));
			q=q.add(this.get(row2, j));
			this.set(row2, j, q);			
		}
	}
	/**
	 * 
	 * @return determinant or null if matrix is not square 
	 */
	public Rational det(){
		if (rows!=cols) return null;
		return det(this);
	}
	public Rational det(Matrix m1){
		if (m1.getRows()==1) return m1.get(0, 0);
		Rational result = new Rational(0);
		for(int j=0;j<m1.getCols();j++){
			Rational cofactor=new Rational((int)Math.pow(-1, j));
			cofactor=cofactor.multiply(m1.get(0, j));
			cofactor=cofactor.multiply(det(m1.minor(0,j)));
			result=result.add(cofactor);
		}
		return result;
	}
	public Matrix minor(int r, int c){
		Matrix result= new Matrix(this.rows-1, this.cols-1);
		//top 
		for (int i=0; i<r;i++){
			//left
			for (int j=0; j<c; j++){
				result.set(i, j, this.get(i, j));
			}
			//right
			for (int j=c+1; j<cols;j++)
				result.set(i, j-1, this.get(i, j));
		}
		//bottom
		for(int i=r+1; i<rows;i++){
			//left
			for (int j=0; j<c;j++)
				result.set(i-1,j,this.get(i, j));
			//right
			for (int j=c+1; j<cols;j++)
				result.set(i-1, j-1, this.get(i, j));
		}

		return result;
	}
	/**
	 * for rref, we mult 1/n to the leading coeff
	 * then add -1*the number below and add this multiple to 
	 * it untill there is no other
	 */
	public void rref(){
		if (rows<2) return;
		for (int i=0; i<rows; i++){
			Rational r=this.get(i, i);
			if (r.value()!=0){
				r=r.reciprocal();
			} else if(i!=rows-1){
				this.swap(i, i+1);
				r=this.get(i, i);
				if (r.value()!=0)
					r=r.reciprocal();
			}
			this.multiply(i, r);

			for (int k=i+1;k<rows; k++){
				Rational q=this.get(k, i);
				q=q.multiply(new Rational(-1));

				this.addMultiple(i, q, k);

			}
		}

		for(int i=rows-1; i>=0; i--){
			Rational r=this.get(i, i);
			for (int k=i-1; k>=0; k--){
				Rational q=this.get(k, i);
				q=q.multiply(new Rational(-1));
				this.addMultiple(i, q, k);
			}
		}
	}
}

MatrixApp.java

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;


@SuppressWarnings("serial")
public class MatrixApp extends Frame implements ActionListener{
    TextArea t;
    Button editButton,detButton, invButton, rrefButton,swapButton, multButton, addButton, undoButton;

    int rows,cols;
    Matrix a,b;
    final int WIDTH=7;
    //making these global will 'remember' the order of the last matrix
    JTextField r=new JTextField("2");
    JTextField c=new JTextField("2");

    public MatrixApp(){
        super("Matrix App 1.0");
        setSize(800,600);
        this.addWindowListener(
                   new WindowListener() {
                          public void windowClosing(WindowEvent e) {System.exit(0);}
                          public void windowClosed(WindowEvent e) {}
                          public void windowOpened(WindowEvent e) {}
                          public void windowIconified(WindowEvent e) {}
                          public void windowDeiconified(WindowEvent e) {}
                          public void windowActivated(WindowEvent e) {}
                          public void windowDeactivated(WindowEvent e) {}
                     });       
        t=new TextArea();
        t.setFont(new Font("Courier", Font.BOLD,20));
        t.setForeground(new Color(251,182,0));
        t.setBackground(new Color(44,23,0));
        t.setEditable(false);
        rows=2;
        cols=2;
        a=new Matrix(2,2);
        parseMatrix(identityString(2,2));
        b=new Matrix(a);
        editButton=new Button("Edit Matrix");
        editButton.addActionListener(this);
        detButton=new Button("Determinant");
        detButton.addActionListener(this);
        invButton=new Button("Inverse");
        invButton.addActionListener(this);
        rrefButton=new Button("rref");
        rrefButton.addActionListener(this);
        swapButton=new Button("Swap");
        swapButton.addActionListener(this);
        multButton=new Button("Multiply");
        multButton.addActionListener(this);
        addButton=new Button("Add a Multiple");
        addButton.addActionListener(this);
        undoButton=new Button("Undo");
        undoButton.addActionListener(this);
        this.setLayout(new BorderLayout());
        this.add(t, BorderLayout.CENTER);
        Panel buttonPanel=new Panel(new FlowLayout());
        buttonPanel.add(editButton);
        buttonPanel.add(detButton);
        buttonPanel.add(invButton);
        buttonPanel.add(swapButton);
        buttonPanel.add(multButton);
        buttonPanel.add(addButton);
        buttonPanel.add(rrefButton);
        buttonPanel.add(undoButton);

        this.add(buttonPanel, BorderLayout.NORTH);
    }
     public static void main(String[] args)
        {
            MatrixApp app= new MatrixApp();
            app.setVisible(true);
        }
    @Override
    public void actionPerformed(ActionEvent e) {
        Object buttonPressed=e.getSource();
        if (buttonPressed==editButton){
            doEditDialog();
            t.append("\n");
        } else if(buttonPressed==swapButton){
            doSwapDialog();
            t.append("\n");
        } else if(buttonPressed==detButton){
            if (a.getRows()!=a.getCols())
                t.append("The determinent is undefined for non-square matrices\n");
            else 
                t.append("The Determinant is "+a.det()+"\n");
        } else if(buttonPressed==invButton){
            if (a.getRows()!=a.getCols())
                t.append("This matrix is not square\n");
            else if (a.det().value()==0){
                t.append("This matrix is singular\n");
            } else {
                t.append("The Inverse of this matrix is \n"+Matrix.inverse(a).toString(WIDTH)+"\n");
            }
        } else if(buttonPressed==multButton){
            doMultDialog();
            t.append("\n");
        } else if(buttonPressed==rrefButton){
            Matrix d=new Matrix(a);
            d.rref();
            t.append("The row reduced echelon form of this matrix is\n"+d.toString(WIDTH)+"\n");
        } else if(buttonPressed==addButton){
            doAddDialog();
            t.append("\n");
        } else if(buttonPressed==undoButton){
            Matrix c=new Matrix(a);
            a=new Matrix(b);
            b=new Matrix(c);
            t.append("Undo selected\n"+a.toString(WIDTH));
        } 

    }
    public String identityString(int r, int c){
        String result="";
        for (int i=0;i<r;i++){
            for (int j=0; j<c;j++){
                if (i==j) result+="1 ";
                else result+="0 ";
            }
            result+="\n";            
        }
        return result;
    }
    public void doEditDialog(){

        final JComponent[] order = new JComponent[] {
                new JLabel("rows: "),
                r,
                new JLabel("cols: "),
                c,

        };
        JOptionPane.showMessageDialog(this, order, "Order of Matrix", JOptionPane.PLAIN_MESSAGE);
        try{
         rows=Integer.parseInt(r.getText());
         cols=Integer.parseInt(c.getText());
         doMatrixDialog();
         t.append("\n");
        }catch( Exception exception){
          t.append("\nHuh? try again - only one space between columns");
        }
    }
    public void doSwapDialog(){
        JTextField r1=new JTextField("1");
        JTextField r2=new JTextField("2");
        final JComponent[] swap = new JComponent[] {
                new JLabel("Swap row: "),
                r1,
                new JLabel("with row: "),
                r2,

        };
        JOptionPane.showMessageDialog(this, swap, "Swap 2 Rows", JOptionPane.PLAIN_MESSAGE);
        int row1,row2;
        try{
         row1=Integer.parseInt(r1.getText());
         row2=Integer.parseInt(r2.getText());
         b=new Matrix(a);
         a.swap(row1-1,row2-1);
         t.append("r"+row1+" <-> r"+row2+"\n"+a.toString(WIDTH));
        }catch( Exception exception){
          t.append("\nCan't swap those rows. Try again\n");
        }
    }
    public void doMultDialog(){
        JTextField r=new JTextField("1");
        JTextField q=new JTextField("1");
        final JComponent[] mult = new JComponent[] {
                new JLabel("Multiply row: "),
                r,
                new JLabel("by what number: "),
                q,

        };
        JOptionPane.showMessageDialog(this, mult, "Multiply a Row", JOptionPane.PLAIN_MESSAGE);
        int row;
        Rational number;
        try{
         row=Integer.parseInt(r.getText());
         number=new Rational(q.getText());
         b=new Matrix(a);
         a.multiply(row-1, number);
         t.append("R"+row+" = "+number.toString()+" * r"+row+"\n"+a.toString(WIDTH));
        }catch( Exception exception){
          t.append("\nSomething is wrong: bad row or malformed number. Try again\n");
        }
    }
    public void doAddDialog(){
        JTextField r1=new JTextField("1");
        JTextField q=new JTextField("1");
        JTextField r2=new JTextField("2");
        final JComponent[] addDialog = new JComponent[] {
                new JLabel("Multiply row: "),
                r1,
                new JLabel("by what number: "),
                q,
                new JLabel("and add it to what row: "),
                r2,

        };
        JOptionPane.showMessageDialog(this, addDialog, "Add a Multiple of a Row and Add it to Another Row", JOptionPane.PLAIN_MESSAGE);
        int row1, row2;
        Rational number;
        try{
         row1=Integer.parseInt(r1.getText());
         row2=Integer.parseInt(r2.getText());
         number=new Rational(q.getText());
         b=new Matrix(a);
         a.addMultiple(row1-1, number, row2-1);
         t.append("R"+row2+" = "+number.toString()+" * r"+row1+" + r"+row2+"\n"+a.toString(WIDTH));
        }catch( Exception exception){
          t.append("\nSomething is wrong: bad row or malformed number. Try again\n");
        }
    }
    public void doMatrixDialog(){
        String sample=identityString(rows,cols);
        if (rows==a.getRows()&&cols==a.getCols())
            sample=a.toString();

        Object[] o=new Object[1];
        TextArea m=new TextArea(sample);
        m.setFont(new Font("Courier", Font.BOLD,20));
        o[0]=m;
        int res = JOptionPane.showConfirmDialog(this, o, "Enter Matrix Values (separate columns with a single space)", 
                JOptionPane.OK_CANCEL_OPTION);
        if (res ==  JOptionPane.CANCEL_OPTION) return;
        parseMatrix(m.getText());
    }
    public void parseMatrix(String s){
        b=new Matrix(a);
        a=new Matrix(rows,cols);
        t.setText("Order of this matrix is "+rows+" x "+cols+"\n");
        String[] r=s.split("\n"); 
        for(int i=0;i<rows;i++){
            String[] c=r[i].split(" ");
            for (int j=0;j<cols;j++){
                a.set(i, j, new Rational(c[j]));                
            }            
        }
        t.append(a.toString(WIDTH));
        t.append("\n");
    }
}

MatrixApplet.java

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;


@SuppressWarnings("serial")
public class MatrixApplet extends Applet implements ActionListener{
	TextArea t;
	Button editButton,detButton,swapButton, multButton, addButton, undoButton;

	int rows,cols;
	Matrix a,b;
	final int WIDTH=7;
	//making these global will 'remember' the order of the last matrix
	JTextField r=new JTextField("2");
	JTextField c=new JTextField("2");

	public void init(){
		t=new TextArea();
		t.setFont(new Font("Courier", Font.BOLD,20));
		t.setForeground(new Color(251,182,0));
		t.setBackground(new Color(44,23,0));
		t.setEditable(false);
		rows=2;
		cols=2;
		a=new Matrix(2,2);
		parseMatrix(identityString(2,2));
		b=new Matrix(a);
		editButton=new Button("Edit Matrix");
		editButton.addActionListener(this);
		detButton=new Button("Determinant");
		detButton.addActionListener(this);
		swapButton=new Button("Swap");
		swapButton.addActionListener(this);
		multButton=new Button("Multiply");
		multButton.addActionListener(this);
		addButton=new Button("Add a Multiple");
		addButton.addActionListener(this);
		undoButton=new Button("Undo");
		undoButton.addActionListener(this);
		this.setLayout(new BorderLayout());
		this.add(t, BorderLayout.CENTER);
		Panel buttonPanel=new Panel(new FlowLayout());
		buttonPanel.add(editButton);
		buttonPanel.add(detButton);
		buttonPanel.add(swapButton);
		buttonPanel.add(multButton);
		buttonPanel.add(addButton);
		buttonPanel.add(undoButton);

		this.add(buttonPanel, BorderLayout.NORTH);
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		Object buttonPressed=e.getSource();
		if (buttonPressed==editButton){
			doEditDialog();
			t.append("\n");
		} else if(buttonPressed==swapButton){
			doSwapDialog();
			t.append("\n");
		}else if(buttonPressed==detButton){
			if (a.getRows()!=a.getCols())
				t.append("The determinent is undefined for non-square matrices\n");
			else 
				t.append("The Determinant is "+a.det()+"\n");
		} else if(buttonPressed==multButton){
			doMultDialog();
			t.append("\n");
		} else if(buttonPressed==addButton){
			doAddDialog();
			t.append("\n");
		} else if(buttonPressed==undoButton){
			Matrix c=new Matrix(a);
			a=new Matrix(b);
			b=new Matrix(c);
			t.append("Undo selected\n"+a.toString(WIDTH));
		} 

	}
	public String identityString(int r, int c){
		String result="";
		for (int i=0;i<r;i++){
			for (int j=0; j<c;j++){
				if (i==j) result+="1 ";
				else result+="0 ";
			}
			result+="\n";			
		}
		return result;
	}
	public void doEditDialog(){

		final JComponent[] order = new JComponent[] {
	            new JLabel("rows: "),
	            r,
	            new JLabel("cols: "),
	            c,

		};
		JOptionPane.showMessageDialog(this, order, "Order of Matrix", JOptionPane.PLAIN_MESSAGE);
		try{
		 rows=Integer.parseInt(r.getText());
	     cols=Integer.parseInt(c.getText());
	     doMatrixDialog();
	     t.append("\n");
		}catch( Exception exception){
		  t.append("\nHuh? try again - only one space between columns");
		}
	}
	public void doSwapDialog(){
		JTextField r1=new JTextField("1");
		JTextField r2=new JTextField("2");
		final JComponent[] swap = new JComponent[] {
	            new JLabel("Swap row: "),
	            r1,
	            new JLabel("with row: "),
	            r2,

		};
		JOptionPane.showMessageDialog(this, swap, "Swap 2 Rows", JOptionPane.PLAIN_MESSAGE);
		int row1,row2;
		try{
		 row1=Integer.parseInt(r1.getText());
	     row2=Integer.parseInt(r2.getText());
	     b=new Matrix(a);
	     a.swap(row1-1,row2-1);
	     t.append("r"+row1+" <-> r"+row2+"\n"+a.toString(WIDTH));
		}catch( Exception exception){
		  t.append("\nCan't swap those rows. Try again\n");
		}
	}
	public void doMultDialog(){
		JTextField r=new JTextField("1");
		JTextField q=new JTextField("1");
		final JComponent[] mult = new JComponent[] {
	            new JLabel("Multiply row: "),
	            r,
	            new JLabel("by what number: "),
	            q,

		};
		JOptionPane.showMessageDialog(this, mult, "Multiply a Row", JOptionPane.PLAIN_MESSAGE);
		int row;
		Rational number;
		try{
		 row=Integer.parseInt(r.getText());
	     number=new Rational(q.getText());
	     b=new Matrix(a);
	     a.multiply(row-1, number);
	     t.append("R"+row+" = "+number.toString()+" * r"+row+"\n"+a.toString(WIDTH));
		}catch( Exception exception){
		  t.append("\nSomething is wrong: bad row or malformed number. Try again\n");
		}
	}
	public void doAddDialog(){
		JTextField r1=new JTextField("1");
		JTextField q=new JTextField("1");
		JTextField r2=new JTextField("2");
		final JComponent[] addDialog = new JComponent[] {
	            new JLabel("Multiply row: "),
	            r1,
	            new JLabel("by what number: "),
	            q,
	            new JLabel("and add it to what row: "),
	            r2,

		};
		JOptionPane.showMessageDialog(this, addDialog, "Add a Multiple of a Row and Add it to Another Row", JOptionPane.PLAIN_MESSAGE);
		int row1, row2;
		Rational number;
		try{
		 row1=Integer.parseInt(r1.getText());
		 row2=Integer.parseInt(r2.getText());
	     number=new Rational(q.getText());
	     b=new Matrix(a);
	     a.addMultiple(row1-1, number, row2-1);
	     t.append("R"+row2+" = "+number.toString()+" * r"+row1+" + r"+row2+"\n"+a.toString(WIDTH));
		}catch( Exception exception){
		  t.append("\nSomething is wrong: bad row or malformed number. Try again\n");
		}
	}
	public void doMatrixDialog(){
		String sample=identityString(rows,cols);
		if (rows==a.getRows()&&cols==a.getCols())
			sample=a.toString();

		Object[] o=new Object[1];
		TextArea m=new TextArea(sample);
		m.setFont(new Font("Courier", Font.BOLD,20));
		o[0]=m;
		int res = JOptionPane.showConfirmDialog(this, o, "Enter Matrix Values (separate columns with a single space)", 
                JOptionPane.OK_CANCEL_OPTION);
	    if (res ==  JOptionPane.CANCEL_OPTION) return;
	    parseMatrix(m.getText());
	}
	public void parseMatrix(String s){
		b=new Matrix(a);
		a=new Matrix(rows,cols);
		t.setText("Order of matrix is "+rows+" x "+cols+"\n");
		String[] r=s.split("\n"); 
		for(int i=0;i<rows;i++){
			String[] c=r[i].split(" ");
			for (int j=0;j<cols;j++){
				a.set(i, j, new Rational(c[j]));				
			}			
		}
		t.append(a.toString(WIDTH));
		t.append("\n");
	}
}