アレアレ

お役立ち情報、お悩み解決情報を発信!

xcode

Swiftでの行列の和・差・積の計算方法

Swiftでの行列の和・差・積の計算方法

今回は、Swiftで行列計算をしたい人に向けて、その実装方法をご紹介します。

Swfitには、そのような行列を表現するクラスが標準でないため、「それを自作してみました」というのが、今回ご紹介したい内容です。

動作環境

はじめに、今回ご紹介する方法の動作確認が取れている環境をご紹介すると、次の通りです。

  • OS: OS X El Capitan (Version 10.11.5)
  • Xcode: 7.3.1 (7D1014)
  • swift: 2.2 (swiftlang-703.0.18.8 clang-703.0.31)

開発環境には、Xcodeを使います。今回ご紹介のプログラムは、そのXcodeのPlaygroundと呼ばれる、Swiftのプログラムを簡単に実行できる環境で実行できるものです。

自作のMatrixクラスのコード

では本題のSwiftでの行列計算を実装したコードを紹介すると次の通りです。

import UIKit

//行列クラス
public class Matrix{
    var data:[[Double]]=[]
    
    //コンストラクタ
    public init(data:[[Double]]){
        
        self.assertElementCount(data)
        self.data = data
    }
    
    //各行の要素の数が一致するかを確認する
    private func assertElementCount(data: [[Double]]){
        for i in 0 ..< data.count {
            
            if i==0 {
                continue
            }
            assert(data[i].count == data[i-1].count, "各行に含まれる要素の数が一致していません。")
        }
    }
    
    //行列データを見やすい形の文字列にする
    public func showData()->String{
        
        var buff = "\n"
        for i in 0 ..< data.count {
            let row = data[i]
            
            for j in 0 ..< row.count {
                    buff = buff + "\(row[j]) "
            }
            
            buff = buff + "\n"
        
        }
        
        return buff
    }
}

//行列同士の和の定義
func +(left: Matrix, right: Matrix) -> Matrix {
    assert(left.data.count==right.data.count, "行列同士の行数が一致しません。")
    assert(left.data[0].count==right.data[0].count, "行列同士の列数が一致しません。")
    
    var result: [[Double]] = []
    
    for i in 0 ..< left.data.count {
        
        var row = [Double]()
        for j in 0 ..< left.data[0].count {
            row.append(left.data[i][j]+right.data[i][j])
        }
        
        result.append(row)
    }
    
    
    return Matrix(data: result)
    
}

//行列同士の差の定義
func -(left: Matrix, right: Matrix) -> Matrix {
    
    assert(left.data.count==right.data.count, "行列同士の行数が一致しません。")
    assert(left.data[0].count==right.data[0].count, "行列同士の列数が一致しません。")
    
    var result: [[Double]] = []
    
    for i in 0 ..< left.data.count {
        
        var row = [Double]()
        for j in 0 ..< left.data[0].count {
            row.append(left.data[i][j]-right.data[i][j])
        }
        
        result.append(row)
    }
    
    return Matrix(data: result)
    
}

//行列同士の積の定義
func *(left: Matrix, right: Matrix) -> Matrix {
    assert(left.data[0].count==right.data.count, "左の列数と右の行数が一致しません。")

    var result: [[Double]] = []

    for i in 0 ..< left.data.count {
        
        var row = [Double]()
        for j in 0 ..< right.data[i].count{
            
            var c = 0.0
            for k in 0 ..< right.data.count{
                let a = left.data[i][k]
                let b = right.data[k][j]
                c = c + (a*b)
            }
            
            row.append(c)
            
        }
        
        result.append(row)
        
    }
    
    return Matrix(data: result)
}

//以下、Matrixクラスの使用例
//左の行列
var m1 = Matrix(data:[
    [1,2,3],
    [4,5,6],
    [7,8,9]])

//右行列
var m2 = Matrix(data:[
    [1,2],
    [3,4],
    [5,6]])
 
 //行列の積を行い結果を表示する
 var m = m1*m2
 NSLog(m.showData())

さて、上のコードで、「以下、Matrixクラスの使用例」と書いているところを見ると、このクラスの使い方がわかります。

このMatrixクラスですが、このように二次元配列を使って、初期化して利用します。初期化の際には、二次元配列の各行に含まれる要素数が全て一致しているかをチェックしています。

そのため、次のような初期化を行おうとするとエラーになります。

初期化がエラーとなる例

Matrix(data:[
    [1,2,3],
    [4,5],
    [7,8,9]])	

この場合、2行目の[4,5]の要素数が2つで、他の行の要素数と異なっているため、エラーとなります。

また上の例では、行列同士の積のみを行っていますが、このクラスでは和や差も計算することができます。次のようなイメージです。

和と差の計算例

//左の行列
var m1 = Matrix(data:[
    [1,2],
    [4,5],
    [7,8]])

//右行列
var m2 = Matrix(data:[
    [1,2],
    [3,4],
    [5,6]])

m1+m2
m1-m2

この例のように、和や差を行うためには、行列同士の行数と列数が一致している必要があります。一致していないものを計算しようとするとエラーになります。

また、積の計算を行うためには、左の行列の列数と右の行列の行数が一致している必要があります。そのため、次のような積を行おうとするとエラーになります。

エラーとなる積の計算例

//左の行列
var m1 = Matrix(data:[
    [1,2],
    [4,5],
    [7,8]])

//右行列
var m2 = Matrix(data:[
    [1,2],
    [3,4],
    [5,6]])

//m1の列数とm2の行数が一致していためエラーとなる
m1*m2 

ちなみに、このMatrixクラスでは、行列のスカラー倍には対応していません。

Return Top