Code Monkey home page Code Monkey logo

Comments (4)

rasmusgo avatar rasmusgo commented on June 29, 2024 1

The problem seems to be in the bidiagonalization:

#[test]
fn bidiagonal_regression_issue_1313() {
    let s = 6.123234e-16_f32;
    let mut m = nalgebra::dmatrix![
        10.0,   0.0, 0.0,  0.0, -10.0, 0.0, 0.0, 0.0;
        s,     10.0, 0.0, 10.0,     s, 0.0, 0.0, 0.0;
        20.0, -20.0, 0.0, 20.0,  20.0, 0.0, 0.0, 0.0;
    ];
    m.unscale_mut(m.camax());
    let bidiagonal = m.clone().bidiagonalize();
    let (u, d, v_t) = bidiagonal.unpack();
    let m2 = &u * d * &v_t;
    println!("m = {:.1}", m);
    println!("m2 = {:.1}", m2);
    assert_relative_eq!(m, m2, epsilon = 1e-6);
}
m = 
  ┌                                         ┐
  │  0.5  0.0  0.0  0.0 -0.5  0.0  0.0  0.0 │
  │  0.0  0.5  0.0  0.5  0.0  0.0  0.0  0.0 │
  │  1.0 -1.0  0.0  1.0  1.0  0.0  0.0  0.0 │
  └                                         ┘


m2 = 
  ┌                                         ┐
  │  0.5  0.0  0.0  0.0 -0.5  0.0  0.0  0.0 │
  │ -0.0 -0.5 -0.0 -0.5 -0.0 -0.0 -0.0 -0.0 │
  │ -1.0  1.0 -0.0 -1.0 -1.0  0.0  0.0  0.0 │
  └                                         ┘

from nalgebra.

rasmusgo avatar rasmusgo commented on June 29, 2024

The result is not a proper pseudo inverse for this matrix. Here is a test that fails for the given matrix:

#[test]
fn test_pseudo_inverse() {
    let s = 6.123234e-16;
    // let s = 0.0;
    let m = nalgebra::DMatrix::from_column_slice(
        3,
        8,
        &[
            10.0f32, s, 20.0, 0.0, 10.0, -20.0, 0.0, 0.0, 0.0, 0.0, 10.0, 20.0, -10.0, s, 20.0,
            0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
        ],
    );
    let m_inv = m.clone().pseudo_inverse(1.0e-6).unwrap();
    println!("m: {:}", m);
    println!("m†: {:}", &m_inv);
    println!("mm†: {:}", &m * &m_inv);
    println!("mm†m: {:}", &m * &m_inv * &m);
    // Assert distance to identity matrix is small
    assert!(
        (&m * &m_inv).apply_metric_distance(&nalgebra::Matrix3::identity(), &nalgebra::UniformNorm)
            < 0.0001
    );
}

Also available as two tests in this rust playground.

mm† gets two -1 instead of 1 on the diagonal.

mm†: 
  ┌                                                                                                          ┐
  │                                  1                                  0                                  0 │
  │ -0.0000000000000000000000033087225                                 -1        -0.000000000000000007654043 │
  │                 -0.000000059604645                 -0.000000059604645                         -1.0000001 │

from nalgebra.

rasmusgo avatar rasmusgo commented on June 29, 2024

Here is a test demonstrating that the problem comes from the SVD:

#[test]
// Exercises bug reported in issue #1313 of nalgebra (https://github.com/dimforge/nalgebra/issues/1313)
fn svd_regression_issue_1313() {
    let s = 6.123234e-16_f32;
    let m = nalgebra::dmatrix![
        10.0,   0.0, 0.0,  0.0, -10.0, 0.0, 0.0, 0.0;
           s,  10.0, 0.0, 10.0,     s, 0.0, 0.0, 0.0;
        20.0, -20.0, 0.0, 20.0,  20.0, 0.0, 0.0, 0.0;
    ];
    let svd = m.clone().svd(true, true);
    let m2 = svd.recompose().unwrap();
    assert_relative_eq!(&m, &m2, epsilon = 1e-5);
}

Printing the matrices (rounded to one decimal) reveals that the last row has been negated:

m: 
  ┌                                                 ┐
  │  10.0   0.0   0.0   0.0 -10.0   0.0   0.0   0.0 │
  │   0.0  10.0   0.0  10.0   0.0   0.0   0.0   0.0 │
  │  20.0 -20.0   0.0  20.0  20.0   0.0   0.0   0.0 │
  └                                                 ┘


m2: 
  ┌                                                 ┐
  │  10.0   0.0   0.0   0.0 -10.0   0.0   0.0   0.0 │
  │  -0.0 -10.0  -0.0 -10.0  -0.0  -0.0  -0.0  -0.0 │
  │ -20.0  20.0  -0.0 -20.0 -20.0   0.0   0.0   0.0 │
  └                                                 ┘

from nalgebra.

Ralith avatar Ralith commented on June 29, 2024

Fixed by #1314.

from nalgebra.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.