<commit_before>//
//  DiagonalEliminator.swift
//  SwiftyAlgebra
//
//  Created by <NAME> on 2017/11/08.
//  Copyright © 2017年 <NAME>. All rights reserved.
//

import Foundation

public final class DiagonalEliminator<R: EuclideanRing>: MatrixEliminator<R> {
    internal override var resultType: MatrixEliminationResult<R>.Type {
        return DiagonalEliminationResult.self
    }
    
    override func iteration() -> Bool {
        if target.isDiagonal {
            return true
        }
        
        run(RowHermiteEliminator.self)
        
        if target.isDiagonal {
            return true
        }
        
        run(ColHermiteEliminator.self)
        
        return false
    }
}

public final class DiagonalEliminationResult<R: EuclideanRing>: MatrixEliminationResult<R> {
    public override lazy var diagonal: [R] = { [unowned self] in
        return result.diagonal
    }()
    
    public override var rank: Int {
        return diagonal.count
    }
    
    public override lazy var determinant: R = { [unowned self] in
        assert(result.rows == result.cols)
        assert(diagonal.forAll{ $0 == R.identity })
        
        if rank == result.rows {
            return rowOps.multiply { $0.determinant }.inverse!
                * colOps.multiply { $0.determinant }.inverse!
                * diagonal.multiplyAll()
        } else {
            return 0
        }
    }()
    
    public override lazy var inverse: ComputationalMatrix<R>? = {
        assert(result.rows == result.cols)
        assert(determinant.isInvertible)
        return (rank == result.rows) ? right * left : nil
    }()
    
    // The matrix made by the basis of Ker(A).
    // Z = (z1, ..., zk) , k = col(A) - rank(A).
    //
    // P * A * Q = [D_r; O_k]
    // =>  Z = Q[:, r ..< m] = Q * [O_r; I_k]
    
    public override lazy var kernelMatrix: ComputationalMatrix<R> = { [unowned self] in
        return right.submatrix(colRange: rank ..< result.cols)
    }()
    
    // The matrix made by the basis of Im(A).
    // B = (b1, ..., br) , r = rank(A)
    //
    // P * A * Q = [D_r; O_k]
    // => D is the imageMatrix with basis P.
    // => P^-1 * D is the imageMatrix with the standard basis.
    
    public override lazy var imageMatrix: ComputationalMatrix<R> = { [unowned self] in
        let A = _leftInverse(restrictedToCols: 0 ..< rank)
        
        for (j, a) in diagonal.enumerated() {
            if j >= rank { break }
            A.multiplyCol(at: j, by: a)
        }
        
        return A
    }()
    
    // T: The basis transition matrix from (ei) to (zi),
    // i.e. T * zi = ei.
    //
    // P * A * Q = [D_r; O_k]
    // =>  Z = Q[:, r ..< m] = Q * [O_r; I_k]
    // =>  Q^-1 * Z = [O; I_k]
    //
    // T = Q^-1[:, r ..< m]  gives  T * Z = I_k.
    
    public override lazy var kernelTransitionMatrix: ComputationalMatrix<R> = { [unowned self] in
        return _rightInverse(restrictedToRows: rank ..< result.cols)<commit_msg>a little improve.<commit_after>//
//  DiagonalEliminator.swift
//  SwiftyAlgebra
//
//  Created by <NAME> on 2017/11/08.
//  Copyright © 2017年 <NAME>. All rights reserved.
//

import Foundation

public final class DiagonalEliminator<R: EuclideanRing>: MatrixEliminator<R> {
    internal override var resultType: MatrixEliminationResult<R>.Type {
        return DiagonalEliminationResult.self
    }
    
    override func iteration() -> Bool {
        if target.isDiagonal {
            return true
        }
        
        run(RowHermiteEliminator.self)
        
        if target.isDiagonal {
            return true
        }
        
        run(ColHermiteEliminator.self)
        
        return false
    }
}

public final class DiagonalEliminationResult<R: EuclideanRing>: MatrixEliminationResult<R> {
    public override lazy var diagonal: [R] = { [unowned self] in
        return result.diagonal
    }()
    
    public override var rank: Int {
        return diagonal.count
    }
    
    public override lazy var determinant: R = { [unowned self] in
        assert(result.rows == result.cols)
        assert(diagonal.forAll{ $0 == R.identity })
        
        if rank == result.rows {
            return rowOps.multiply { $0.determinant }.inverse!
                * colOps.multiply { $0.determinant }.inverse!
                * diagonal.multiplyAll()
        } else {
            return 0
        }
    }()
    
    public override lazy var inverse: ComputationalMatrix<R>? = {
        assert(result.rows == result.cols)
        assert(determinant.isInvertible)
        return (rank == result.rows) ? right * left : nil
    }()
    
    // The matrix made by the basis of Ker(A).
    // Z = (z1, ..., zk) , k = col(A) - rank(A).
    //
    // P * A * Q = [D_r; O_k]
    // =>  Z := Q[:, r ..< m], then A * Z = O_k
    
    public override lazy var kernelMatrix: ComputationalMatrix<R> = { [unowned self] in
        return right.submatrix(colRange: rank ..< result.cols)
    }()
    
    // The matrix made by the basis of Im(A).
    // B = (b1, ..., br) , r = rank(A)
    //
    // P * A * Q = [D_r; O_k]
    // => D is the imageMatrix with basis P.
    // => P^-1 * D is the imageMatrix with the standard basis.
    
    public override lazy var imageMatrix: ComputationalMatrix<R> = { [unowned self] in
        let A = _leftInverse(restrictedToCols: 0 ..< rank)
        return A * result.submatrix(0 ..< rank, 0 ..< rank)
    }()
    
    // T: The basis transition matrix from (ei) to (zi),
    // i.e. T * zi = ei.
    //
    // P * A * Q = [D_r; O_k]
    // =>  Z = Q[:, r ..< m] = Q * [O_r; I_k]
    // =>  Q^-1 * Z = [O; I_k]
    //
    // T = Q^-1[r ..< m, :]  gives  T * Z = I_k.
    
    public override lazy var kernelTransitionMatrix: ComputationalMatrix<R> = { [unowned self] in
        return _rightInverse(restrictedToRows: rank ..< result.cols)
{'fraction_non_alphanumeric': 0.13115595075239397, 'fraction_numerical': 0.00786593707250342, 'mean_word_length': 1.8133718133718133, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2124374', 'n_tokens_mistral': 1970, 'n_tokens_neox': 1898, 'n_words': 522}