/** * @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==