12

Sweet Snippet 之 Gram-Schmidt 正交化

 3 years ago
source link: https://blog.csdn.net/tkokof1/article/details/99575394
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Sweet Snippet 之 Gram-Schmidt 正交化

Gram-Schmidt 正交化的简单实现

Gram-Schmidt(格拉姆-施密特) 正交化可以正交化一组给定的向量,使这些向量两两垂直,这里列出一份简单的实现(Lua):

-- vector add
function add(a, b)
    if a and b and #a == #b then
        local ret = {}
        
        for i = 1, #a do
            table.insert(ret, a[i] + b[i])
        end
        
        return ret
    end
end

-- vector sub
function sub(a, b)
    if a and b and #a == #b then
        local ret = {}
        
        for i = 1, #a do
            table.insert(ret, a[i] - b[i])
        end
        
        return ret
    end
end

-- dot product
function dot(a, b)
    if a and b and #a == #b then
        local ret = 0
        
        for i = 1, #a do
            ret = ret + a[i] * b[i]
        end
        
        return ret
    end
end

-- magnitude
function mag(a)
    local val = dot(a, a)
    if val then
        return math.sqrt(val)
    end
end

-- normalize, do not change param
function norm(a)
    local magnitude = mag(a)
    if magnitude and magnitude ~= 0 then
        local normalize = {}
        
        for i = 1, #a do
            table.insert(normalize, a[i] / magnitude)
        end
        
        return normalize
    end
end

-- project a to b
function proj(a, b)
    if a and b and #a == #b then
        local norm_b = norm(b)
        local val = dot(a, norm_b)
        
        if val then
            local projection = {}
            
            for i = 1, #norm_b do
                table.insert(projection, norm_b[i] * val)
            end
            
            return projection
        end
    end
end

-- perpendicular a to b
function perp(a, b)
    local projection = proj(a, b)
    if projection then
        return sub(a - projection)
    end
end

-- gram schmidt
function gram_schmidt(...)
    local vecs = { ... }
    local ret = {}
    
    if #vecs > 0 then
        table.insert(ret, vecs[1])
    end
    
    for i = 2, #vecs do
        local base = vecs[i]
        for j = 1, i - 1 do
            base = sub(base, proj(vecs[i], vecs[j]))
        end
        table.insert(ret, base)
        vecs[i] = base
    end
    
    return table.unpack(ret)
end

-- use to check gram schmidt result
function check_perp(...)
    local vecs = { ... }
    for i = 1, #vecs - 1 do
        for j = i + 1, #vecs do
            local val = dot(vecs[i], vecs[j])
            if math.abs(val) > 0.001 then
                return false
            end
        end
    end
    
    return true
end

有兴趣的朋友可以试试这组向量的 Gram-Schmidt 正交化:

a = ( 1 , 0 , 0 , 1 ) b = ( 0 , 1 , 0 , 1 ) c = ( 0 , 0 , 1 , 1 ) d = ( 0 , 1 , 1 , 1 )

amp;a=(1,0,0,1)amp;b=(0,1,0,1)amp;c=(0,0,1,1)amp;d=(0,1,1,1)amp;a=(1,0,0,1)amp;b=(0,1,0,1)amp;c=(0,0,1,1)amp;d=(0,1,1,1)
​a=(1,0,0,1)b=(0,1,0,1)c=(0,0,1,1)d=(0,1,1,1)​

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK