V
V
Vsevolod Rodionov2014-11-20 04:45:26
JavaScript
Vsevolod Rodionov, 2014-11-20 04:45:26

How to quickly find the angle between vectors in JS? (22-dimensional vectors, min/max angle search of 5,000 entries)?

Actually, the title is the whole question.
There is a client application in JS, inside it it is necessary (within the framework of the recommender algorithm) from approximately 5k records to select certain ones that are most suitable by the criterion. There are already sample optimizations, I would like to optimize them.
Now I am calculating according to the standard formula cos α = a b / |a|·|b|.
The code looks something like this:

function getScaledAngleForVectors(vec1, vec2) { //cos α = a·b / |a|·|b|
    var length = Math.max(vec1.length, vec2.length);
    var scalarMulti = 0;
    for (var i = 0; i < length; i++)
        scalarMulti += vec1[i] * vec2[i] || 0;
    var cosAlpha = scalarMulti / (getLength(vec1) * getLength(vec2));
    var alpha = Math.acos(cosAlpha);
    return 1 - cosAlpha;
}
function getLength(vec) {
    var n = vec.length;
    var length = 0;
    for (var i = 0; i < n; i++)
        length += Math.pow(vec[i] || 0, 2);
    return Math.pow(length, .5);
}

Promising directions are using integer values ​​and working with Uint16Array, or converting vectors to single ones - in this case, the step "cos α = a b / |a|·|b| " can be reduced to "cos α = a b".
Perhaps someone else can suggest something else?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
A
Armenian Radio, 2014-11-20
@gbg

Finding the scalar product of all possible pairs of vectors is, in fact, multiplying the matrix whose rows are the coordinates of these vectors by itself transposed.
The world's fastest algorithm that does this - Coppersmith-Winograd - Williams

A
Alexander Sydorenko, 2014-11-20
@San40

Here in this code, you have a logical error somewhere

...
    var cosAlpha = scalarMulti / (getLength(vec1) * getLength(vec2));
    var alpha = Math.acos(cosAlpha);
    return 1 - cosAlpha;
}

Why consider alpha if it does not affect the result? Therefore, I still think that the return is not correct .. but something like return alpha;

A
Alexey, 2015-11-14
@Qwal

My version

"use strict";
// Функция для вычисления угла между 2 векторами
var angleBetweenTwoVectors = function(vector1, vector2) {
    // скалярное произведение векторов
    var scalMultVectors = vector1.reduce(function(sum, current, i) {
        return sum + (current * vector2[i])
    }, 0);
    // модуль вектора равен квадратному корню из суммы квадратов его координат
    var moduleVector = function(v) {
        // Находим квадраты слагаемых
        var step1 = v.map(function(currentValue) {
            return Math.pow(currentValue, 2)
        });
        // Складываем их
        var step2 = step1.reduce(function(sum, current) {
            return sum + current
        });
        // Вычисляем квадратный корень
        return Math.sqrt(step2, 2)
    };
    // Вычисляем косинус угла между векторами
    var cosA = scalMultVectors / (moduleVector(vector1) * moduleVector(vector2));
    console.log("cos(" + cosA + ")");
    return Math.acos(cosA);

}
// test
var v1 = [4, 3, 4];
var v2 = [4, 4, 4];
console.log(angleBetweenTwoVectors(v1, v2) + " радиан");

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question