Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Matrix Arithmetic in Swift

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Matrix Arithmetic in Swift

Avatar for USAMI Kosuke

USAMI Kosuke

May 15, 2019
Tweet

More Decks by USAMI Kosuke

Other Decks in Programming

Transcript

  1. ࣗݾ঺հ • Ӊࠤݟެี • ϑΣϯϦϧגࣜձࣾ • iOS ΞϓϦ։ൃ : Swift

    / C# • ֶੜ࣌୅͸਺ֶઐ߈ • ࠷ۙɺ·ͨগ͠ਅ໘໨ʹ΍Γͩͨ͠
  2. ԿΛ࣮૷͢Δ͔ • ࠓճ͸ɺߦྻͷԋࢉʹண໨ͨ͠ • ଍͠ࢉ / εΧϥʔഒ / ͔͚ࢉ •

    ߦྻʹ͸ɺϕΫτϧΛϕΫτϧʹҠ͢ઢܕࣸ૾Λදݱ͢Δͱ͍ ͏ॏཁͳҙຯ͕͋Δ͕ɺࠓճ͸ѻΘͳ͍ʢͦΕʹ͸ϕΫτϧ΋ ࣮૷͢Δඞཁ͕͋ΔͷͰɾɾɾʣ
  3. Matrix ϓϩτίϧ protocol MatrixProtocol { associatedtype Scalar: Numeric var rows:

    Int { get } var columns: Int { get } subscript(row: Int, column: Int) -> Scalar { get set } func vector(row: Int) -> [Scalar] func vector(column: Int) -> [Scalar] }
  4. ॳظԽ (1) struct Matrix : MatrixProtocol { typealias Scalar =

    Float private var grid: [Scalar] init(rows: Int, columns: Int, grid: [Scalar]) { self.rows = rows self.columns = columns self.grid = grid } }
  5. ॳظԽ (2) // ΍ͬͺΓɺ͜͏ॻ͖͍ͨΑͶ let a = Matrix(elements: [[1, 2],

    [3, 4]]) struct Matrix { init(elements: [[Scalar]]) { let rows = elements.count let columns = elements.first?.count ?? 0 let grid = elements.flatMap { $0 } self.init(rows: rows, columns: columns, grid: grid) } }
  6. ੒෼ͷऔಘͱઃఆ struct Matrix : MatrixProtocol { subscript(row: Int, column: Int)

    -> Scalar { get { return grid[row * columns + column] } set { grid[row * columns + column] = newValue } } }
  7. ߦϕΫτϧ / ྻϕΫτϧ struct Matrix : MatrixProtocol { func vector(row:

    Int) -> [Scalar] { return (0..<columns).map { self[row, $0] } } func vector(column: Int) -> [Scalar] { return (0..<rows).map { self[$0, column] } } }
  8. ԋࢉͷ࣮૷ • ߦྻͷԋࢉ • ଍͠ࢉ / εΧϥʔഒ / ͔͚ࢉ •

    ͜ΕΒΛఆٛ͢Δϓϩτίϧ͕طʹ͋ΔͳΒ४ڌ͍ͤͨ͞ • ඪ४ͷ API ʹͳΔ΂͋͘Θ͍ͤͨ • ͳ͍৔߹Ͱ΋ɺϓϩτίϧΛఆٛͯ͠४ڌͤ͞ΔΑ͏ʹ͢Δ
  9. ଍͠ࢉͷ࣮૷ extension Matrix : AdditiveArithmetic { static func + (lhs:

    Matrix, rhs: Matrix) -> Matrix { return Matrix( rows: lhs.rows, columns: lhs.columns, grid: zip(lhs.grid, rhs.grid).map(+)) } static func - (lhs: Matrix, rhs: Matrix) -> Matrix { return Matrix( rows: lhs.rows, columns: lhs.columns, grid: zip(lhs.grid, rhs.grid).map(-)) } }
  10. ՝୊ : zero ͸Ͳ͏͢Δʁ protocol AdditiveArithmetic { static var zero:

    Self } • ͢΂ͯͷ੒෼͕ 0 ͷߦྻ͕θϩߦྻͰ͸͋Δͷ͕ͩɾɾɾ • ߦྻͷαΠζʹΑͬͯมΘΔͷͰɺstatic Ͱఆٛͮ͠Β͍ • ݱࡏɺྑ͍ղܾ͕ͳ͍ɾɾɾ
  11. εΧϥʔഒͷϓϩτίϧͷఆٛ • Swift for TensorFlow ʹ͋ΔͷͰͦͷ··ਅࣅ͢Δ protocol VectorNumeric { associatedtype

    Scalar: Numeric static func * (lhs: Scalar, rhs: Self) -> Self static func *= (lhs: inout Self, rhs: Scalar) }
  12. εΧϥʔഒͷ࣮૷ extension Matrix : VectorNumeric { static func * (lhs:

    Scalar, rhs: Matrix) -> Matrix { return Matrix( rows: rhs.rows, columns: rhs.columns, grid: rhs.grid.map { lhs * $0 }) } }
  13. ͔͚ࢉͷϓϩτίϧ • Swift ඪ४ͷ Numeric ͰͲ͏͔ʁ ҎԼͷϓϩύςΟ͕໰୊ protocol Numeric {

    associatedtype Magnitude : Comparable, Numeric var magnitude: Self.Magnitude { get } } • magnitude ͸ઈର஋Λฦ͢ɾɾɾߦྻʹ͸ͳ͍֓೦ • ͕ͨͬͯ͠ɺߦྻ͸ Numeric ͡Όͳ͍
  14. ͔͚ࢉͷϓϩτίϧͷఆٛ • Numeric ͔Β magnitude Λ͸ͣ͢ protocol MultiplicativeArithmetic { static

    func * (lhs: Self, rhs: Self) -> Self static func *= (lhs: inout Self, rhs: Self) }
  15. ͔͚ࢉͷ࣮૷ extension Matrix : MultiplicativeArithmetic { static func * (lhs:

    Matrix, rhs: Matrix) -> Matrix { return Matrix( rows: lhs.rows, columns: rhs.columns, grid: (0..<lhs.rows).flatMap { row in (0..<rhs.columns).map { column in zip(lhs.vector(row: row), rhs.vector(column: column)) .map(*).reduce(0, +) }}) } }
  16. ࠓޙͷ՝୊ • associatedtype ΑΓδΣωϦΫεͷ΄͏͕ྑ͍͔ʁ • ΍ͬͺΓ Numeric ʹ͍͕ͨ͠ʁ • magnitude

    ͸ߦྻ͕ࣜߟ͑ΒΕΔ͕ਖ਼ํߦྻͷΈ • ߦྻΛϕΫτϧʹ࡞༻͍ͤͨ͞ • ͜ͷߦྻΛ਌࿨͢ΔΑ͏ʹϕΫτϧΛఆٛͯ͠΍Δ