gx
chenyc
2025-02-12 ea42ff3ebee1eeb3fb29423aa848a249441db81c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
 * @license
 * Copyright 2020 Google LLC. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =============================================================================
 */
import * as tf from '../../index';
import { ALL_ENVS, describeWithFlags } from '../../jasmine_util';
import { expectArraysClose } from '../../test_util';
describeWithFlags('gramSchmidt-tiny', ALL_ENVS, () => {
    it('2x2, Array of Tensor1D', async () => {
        const xs = [
            tf.randomNormal([2], 0, 1, 'float32', 1),
            tf.randomNormal([2], 0, 1, 'float32', 2)
        ];
        const ys = tf.linalg.gramSchmidt(xs);
        const y = tf.stack(ys);
        // Test that the results are orthogonalized and normalized.
        expectArraysClose(await y.transpose().matMul(y).array(), await tf.eye(2).array());
        // Test angle between xs[0] and ys[0] is zero, i.e., the orientation of the
        // first vector is kept.
        expectArraysClose(await tf.sum(xs[0].mul(ys[0])).array(), await tf.norm(xs[0]).mul(tf.norm(ys[0])).array());
    });
    it('3x3, Array of Tensor1D', async () => {
        const xs = [
            tf.randomNormal([3], 0, 1, 'float32', 1),
            tf.randomNormal([3], 0, 1, 'float32', 2),
            tf.randomNormal([3], 0, 1, 'float32', 3)
        ];
        const ys = tf.linalg.gramSchmidt(xs);
        const y = tf.stack(ys);
        expectArraysClose(await y.transpose().matMul(y).array(), await tf.eye(3).array());
        expectArraysClose(await tf.sum(xs[0].mul(ys[0])).array(), await tf.norm(xs[0]).mul(tf.norm(ys[0])).array());
    });
    it('3x3, Matrix', async () => {
        const xs = tf.randomNormal([3, 3], 0, 1, 'float32', 1);
        const y = tf.linalg.gramSchmidt(xs);
        expectArraysClose(await y.transpose().matMul(y).array(), await tf.eye(3).array());
    });
    it('2x3, Matrix', async () => {
        const xs = tf.randomNormal([2, 3], 0, 1, 'float32', 1);
        const y = tf.linalg.gramSchmidt(xs);
        const yT = y.transpose();
        expectArraysClose(await y.matMul(yT).array(), await tf.eye(2).array());
    });
    it('3x2 Matrix throws Error', () => {
        const xs = tf.tensor2d([[1, 2], [3, -1], [5, 1]]);
        expect(() => tf.linalg.gramSchmidt(xs))
            .toThrowError(/Number of vectors \(3\) exceeds number of dimensions \(2\)/);
    });
    it('Mismatching dimensions input throws Error', () => {
        const xs = [tf.tensor1d([1, 2, 3]), tf.tensor1d([-1, 5, 1]), tf.tensor1d([0, 0])];
        expect(() => tf.linalg.gramSchmidt(xs)).toThrowError(/Non-unique/);
    });
    it('Empty input throws Error', () => {
        expect(() => tf.linalg.gramSchmidt([])).toThrowError(/empty/);
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JhbV9zY2htaWR0X3Rlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi90ZmpzLWNvcmUvc3JjL29wcy9saW5hbGcvZ3JhbV9zY2htaWR0X3Rlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUgsT0FBTyxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbEMsT0FBTyxFQUFDLFFBQVEsRUFBRSxpQkFBaUIsRUFBQyxNQUFNLG9CQUFvQixDQUFDO0FBRS9ELE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBRWxELGlCQUFpQixDQUFDLGtCQUFrQixFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUU7SUFDbkQsRUFBRSxDQUFDLHdCQUF3QixFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3RDLE1BQU0sRUFBRSxHQUFlO1lBQ3JCLEVBQUUsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7WUFDeEMsRUFBRSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztTQUN6QyxDQUFDO1FBQ0YsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFlLENBQUM7UUFDbkQsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQWEsQ0FBQztRQUNuQywyREFBMkQ7UUFDM0QsaUJBQWlCLENBQ2IsTUFBTSxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFD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QUM7SUFDckUsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsMEJBQTBCLEVBQUUsR0FBRyxFQUFFO1FBQ2xDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNoRSxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG5pbXBvcnQgKiBhcyB0ZiBmcm9tICcuLi8uLi9pbmRleCc7XG5pbXBvcnQge0FMTF9FTlZTLCBkZXNjcmliZVdpdGhGbGFnc30gZnJvbSAnLi4vLi4vamFzbWluZV91dGlsJztcbmltcG9ydCB7VGVuc29yMUQsIFRlbnNvcjJEfSBmcm9tICcuLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtleHBlY3RBcnJheXNDbG9zZX0gZnJvbSAnLi4vLi4vdGVzdF91dGlsJztcblxuZGVzY3JpYmVXaXRoRmxhZ3MoJ2dyYW1TY2htaWR0LXRpbnknLCBBTExfRU5WUywgKCkgPT4ge1xuICBpdCgnMngyLCBBcnJheSBvZiBUZW5zb3IxRCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB4czogVGVuc29yMURbXSA9IFtcbiAgICAgIHRmLnJhbmRvbU5vcm1hbChbMl0sIDAsIDEsICdmbG9hdDMyJywgMSksXG4gICAgICB0Zi5yYW5kb21Ob3JtYWwoWzJdLCAwLCAxLCAnZmxvYXQzMicsIDIpXG4gICAgXTtcbiAgICBjb25zdCB5cyA9IHRmLmxpbmFsZy5ncmFtU2NobWlkdCh4cykgYXMgVGVuc29yMURbXTtcbiAgICBjb25zdCB5ID0gdGYuc3RhY2soeXMpIGFzIFRlbnNvcjJEO1xuICAgIC8vIFRlc3QgdGhhdCB0aGUgcmVzdWx0cyBhcmUgb3J0aG9nb25hbGl6ZWQgYW5kIG5vcm1hbGl6ZWQuXG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoXG4gICAgICAgIGF3YWl0IHkudHJhbnNwb3NlKCkubWF0TXVsKHkpLmFycmF5KCksIGF3YWl0IHRmLmV5ZSgyKS5hcnJheSgpKTtcbiAgICAvLyBUZXN0IGFuZ2xlIGJldHdlZW4geHNbMF0gYW5kIHlzWzBdIGlzIHplcm8sIGkuZS4sIHRoZSBvcmllbnRhdGlvbiBvZiB0aGVcbiAgICAvLyBmaXJzdCB2ZWN0b3IgaXMga2VwdC5cbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgdGYuc3VtKHhzWzBdLm11bCh5c1swXSkpLmFycmF5KCksXG4gICAgICAgIGF3YWl0IHRmLm5vcm0oeHNbMF0pLm11bCh0Zi5ub3JtKHlzWzBdKSkuYXJyYXkoKSk7XG4gIH0pO1xuXG4gIGl0KCczeDMsIEFycmF5IG9mIFRlbnNvcjFEJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHhzOiBUZW5zb3IxRFtdID0gW1xuICAgICAgdGYucmFuZG9tTm9ybWFsKFszXSwgMCwgMSwgJ2Zsb2F0MzInLCAxKSxcbiAgICAgIHRmLnJhbmRvbU5vcm1hbChbM10sIDAsIDEsICdmbG9hdDMyJywgMiksXG4gICAgICB0Zi5yYW5kb21Ob3JtYWwoWzNdLCAwLCAxLCAnZmxvYXQzMicsIDMpXG4gICAgXTtcbiAgICBjb25zdCB5cyA9IHRmLmxpbmFsZy5ncmFtU2NobWlkdCh4cykgYXMgVGVuc29yMURbXTtcbiAgICBjb25zdCB5ID0gdGYuc3RhY2soeXMpIGFzIFRlbnNvcjJEO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCB5LnRyYW5zcG9zZSgpLm1hdE11bCh5KS5hcnJheSgpLCBhd2FpdCB0Zi5leWUoMykuYXJyYXkoKSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoXG4gICAgICAgIGF3YWl0IHRmLnN1bSh4c1swXS5tdWwoeXNbMF0pKS5hcnJheSgpLFxuICAgICAgICBhd2FpdCB0Zi5ub3JtKHhzWzBdKS5tdWwodGYubm9ybSh5c1swXSkpLmFycmF5KCkpO1xuICB9KTtcblxuICBpdCgnM3gzLCBNYXRyaXgnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgeHM6IFRlbnNvcjJEID0gdGYucmFuZG9tTm9ybWFsKFszLCAzXSwgMCwgMSwgJ2Zsb2F0MzInLCAxKTtcbiAgICBjb25zdCB5ID0gdGYubGluYWxnLmdyYW1TY2htaWR0KHhzKSBhcyBUZW5zb3IyRDtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgeS50cmFuc3Bvc2UoKS5tYXRNdWwoeSkuYXJyYXkoKSwgYXdhaXQgdGYuZXllKDMpLmFycmF5KCkpO1xuICB9KTtcblxuICBpdCgnMngzLCBNYXRyaXgnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgeHM6IFRlbnNvcjJEID0gdGYucmFuZG9tTm9ybWFsKFsyLCAzXSwgMCwgMSwgJ2Zsb2F0MzInLCAxKTtcbiAgICBjb25zdCB5ID0gdGYubGluYWxnLmdyYW1TY2htaWR0KHhzKSBhcyBUZW5zb3IyRDtcbiAgICBjb25zdCB5VDogVGVuc29yMkQgPSB5LnRyYW5zcG9zZSgpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHkubWF0TXVsKHlUKS5hcnJheSgpLCBhd2FpdCB0Zi5leWUoMikuYXJyYXkoKSk7XG4gIH0pO1xuXG4gIGl0KCczeDIgTWF0cml4IHRocm93cyBFcnJvcicsICgpID0+IHtcbiAgICBjb25zdCB4cyA9IHRmLnRlbnNvcjJkKFtbMSwgMl0sIFszLCAtMV0sIFs1LCAxXV0pO1xuICAgIGV4cGVjdCgoKSA9PiB0Zi5saW5hbGcuZ3JhbVNjaG1pZHQoeHMpKVxuICAgICAgICAudG9UaHJvd0Vycm9yKFxuICAgICAgICAgICAgL051bWJlciBvZiB2ZWN0b3JzIFxcKDNcXCkgZXhjZWVkcyBudW1iZXIgb2YgZGltZW5zaW9ucyBcXCgyXFwpLyk7XG4gIH0pO1xuXG4gIGl0KCdNaXNtYXRjaGluZyBkaW1lbnNpb25zIGlucHV0IHRocm93cyBFcnJvcicsICgpID0+IHtcbiAgICBjb25zdCB4czogVGVuc29yMURbXSA9XG4gICAgICAgIFt0Zi50ZW5zb3IxZChbMSwgMiwgM10pLCB0Zi50ZW5zb3IxZChbLTEsIDUsIDFdKSwgdGYudGVuc29yMWQoWzAsIDBdKV07XG5cbiAgICBleHBlY3QoKCkgPT4gdGYubGluYWxnLmdyYW1TY2htaWR0KHhzKSkudG9UaHJvd0Vycm9yKC9Ob24tdW5pcXVlLyk7XG4gIH0pO1xuXG4gIGl0KCdFbXB0eSBpbnB1dCB0aHJvd3MgRXJyb3InLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHRmLmxpbmFsZy5ncmFtU2NobWlkdChbXSkpLnRvVGhyb3dFcnJvcigvZW1wdHkvKTtcbiAgfSk7XG59KTtcbiJdfQ==