1

I'm finding difficulty in coding for inverse of a 3x3 matrix in tcl. do we really need packages to code for matrix , i need clear explanation for the following parts with minimal simpler coding 1.how to create matrix ? 2.how to find determinant? 3.how to find inverse of it ?

lucky
  • 11
  • 2

1 Answers1

2

We don't need packages — they're just Tcl code after all — but they do simplify things quite a bit sometimes.

Matrices are represented in Tcl as lists of lists of numbers; it's the natural representation. Think of them being like this (which is row-major form):

set myMatrix {
    { 1.0 -2.0  3.0 }
    {-4.0  5.0 -6.0 }
    { 7.0 -8.0 -9.0 }
}

But that can be rewritten like this (it's just a change of whitespace, which isn't significant):

set myMatrix {{1.0 -2.0 3.0} {-4.0 5.0 -6.0} {7.0 -8.0 -9.0}}

The code to invert such a matrix is on the Tcler's Wiki:

puts [Inverse3 $myMatrix]
# {-1.7222222222222223 -0.7777777777777778 -0.05555555555555555} {-1.4444444444444444 -0.5555555555555556 -0.1111111111111111} {-0.05555555555555555 -0.1111111111111111 -0.05555555555555555}

This is the code from the Wiki page, saved here in case the page gets edited away (and using the optimised _Cofactor3).

proc Inverse3 {matrix} {
    if {[llength $matrix] != 3 ||
        [llength [lindex $matrix 0]] != 3 || 
        [llength [lindex $matrix 1]] != 3 || 
        [llength [lindex $matrix 2]] != 3} {
        error "wrong sized matrix"
    }
    set inv {{? ? ?} {? ? ?} {? ? ?}}
 
    # Get adjoint matrix : transpose of cofactor matrix
    for {set i 0} {$i < 3} {incr i} {
        for {set j 0} {$j < 3} {incr j} {
            lset inv $i $j [_Cofactor3 $matrix $i $j]
        }
    }
    # Now divide by the determinant
    set det [expr {double([lindex $matrix 0 0]   * [lindex $inv 0 0]
                   + [lindex $matrix 0 1] * [lindex $inv 1 0]
                   + [lindex $matrix 0 2] * [lindex $inv 2 0])}]
    if {$det == 0} {
        error "non-invertable matrix"
    }
    
    for {set i 0} {$i < 3} {incr i} {
        for {set j 0} {$j < 3} {incr j} {
            lset inv $i $j [expr {[lindex $inv $i $j] / $det}]
        }
    }
    return $inv
}
proc _Cofactor3 {matrix i j} {
    set COLS {{1 2} {0 2} {0 1}}
    lassign [lindex $COLS $j] row1 row2
    lassign [lindex $COLS $i] col1 col2
    
    set a [lindex $matrix $row1 $col1]
    set b [lindex $matrix $row1 $col2]
    set c [lindex $matrix $row2 $col1]
    set d [lindex $matrix $row2 $col2]
 
    set det [expr {$a*$d - $b*$c}]
    if {($i+$j) & 1} { set det [expr {-$det}]}
    return $det
}
Donal Fellows
  • 133,037
  • 18
  • 149
  • 215