Fix bugs from 5-2 code review
This commit is contained in:
@@ -23,7 +23,6 @@
|
||||
|
||||
use nalgebra::{DMatrix, DVector};
|
||||
|
||||
|
||||
/// Wrapper around `nalgebra::DMatrix<f64>` for Jacobian operations.
|
||||
///
|
||||
/// The Jacobian matrix J represents the partial derivatives of the residual vector
|
||||
@@ -142,11 +141,11 @@ impl JacobianMatrix {
|
||||
// For square systems, use LU decomposition
|
||||
if self.0.nrows() == self.0.ncols() {
|
||||
let lu = self.0.clone().lu();
|
||||
|
||||
|
||||
// Solve J·Δx = -r
|
||||
let r_vec = DVector::from_row_slice(residuals);
|
||||
let neg_r = -r_vec;
|
||||
|
||||
|
||||
match lu.solve(&neg_r) {
|
||||
Some(delta) => Some(delta.iter().copied().collect()),
|
||||
None => {
|
||||
@@ -162,10 +161,10 @@ impl JacobianMatrix {
|
||||
self.0.nrows(),
|
||||
self.0.ncols()
|
||||
);
|
||||
|
||||
|
||||
let r_vec = DVector::from_row_slice(residuals);
|
||||
let neg_r = -r_vec;
|
||||
|
||||
|
||||
// Use SVD for robust least-squares solution
|
||||
let svd = self.0.clone().svd(true, true);
|
||||
match svd.solve(&neg_r, 1e-10) {
|
||||
@@ -283,10 +282,10 @@ impl JacobianMatrix {
|
||||
pub fn condition_number(&self) -> Option<f64> {
|
||||
let svd = self.0.clone().svd(false, false);
|
||||
let singular_values = svd.singular_values;
|
||||
|
||||
|
||||
let max_sv = singular_values.max();
|
||||
let min_sv = singular_values.min();
|
||||
|
||||
|
||||
if min_sv > 1e-14 {
|
||||
Some(max_sv / min_sv)
|
||||
} else {
|
||||
@@ -310,7 +309,10 @@ impl JacobianMatrix {
|
||||
/// - Row/col ranges are inclusive-start, exclusive-end: `row_start..row_end`.
|
||||
///
|
||||
/// # AC: #6
|
||||
pub fn block_structure(&self, system: &crate::system::System) -> Vec<(usize, usize, usize, usize)> {
|
||||
pub fn block_structure(
|
||||
&self,
|
||||
system: &crate::system::System,
|
||||
) -> Vec<(usize, usize, usize, usize)> {
|
||||
let n_circuits = system.circuit_count();
|
||||
let mut blocks = Vec::with_capacity(n_circuits);
|
||||
|
||||
@@ -335,7 +337,7 @@ impl JacobianMatrix {
|
||||
|
||||
let col_start = *indices.iter().min().unwrap();
|
||||
let col_end = *indices.iter().max().unwrap() + 1; // exclusive
|
||||
// Equations mirror state layout for square systems
|
||||
// Equations mirror state layout for square systems
|
||||
let row_start = col_start;
|
||||
let row_end = col_end;
|
||||
|
||||
@@ -583,7 +585,7 @@ mod tests {
|
||||
let mut j = JacobianMatrix::zeros(2, 2);
|
||||
j.set(0, 0, 5.0);
|
||||
j.set(1, 1, 7.0);
|
||||
|
||||
|
||||
assert_relative_eq!(j.get(0, 0).unwrap(), 5.0);
|
||||
assert_relative_eq!(j.get(1, 1).unwrap(), 7.0);
|
||||
assert_relative_eq!(j.get(0, 1).unwrap(), 0.0);
|
||||
@@ -606,7 +608,7 @@ mod tests {
|
||||
// r[0] = x0^2 + x0*x1
|
||||
// r[1] = sin(x0) + cos(x1)
|
||||
// J = [[2*x0 + x1, x0], [cos(x0), -sin(x1)]]
|
||||
|
||||
|
||||
let state: Vec<f64> = vec![0.5, 1.0];
|
||||
let residuals: Vec<f64> = vec![
|
||||
state[0].powi(2) + state[0] * state[1],
|
||||
@@ -623,13 +625,13 @@ mod tests {
|
||||
|
||||
// Analytical values
|
||||
let j00 = 2.0 * state[0] + state[1]; // 2*0.5 + 1.0 = 2.0
|
||||
let j01 = state[0]; // 0.5
|
||||
let j10 = state[0].cos(); // cos(0.5)
|
||||
let j11 = -state[1].sin(); // -sin(1.0)
|
||||
let j01 = state[0]; // 0.5
|
||||
let j10 = state[0].cos(); // cos(0.5)
|
||||
let j11 = -state[1].sin(); // -sin(1.0)
|
||||
|
||||
assert_relative_eq!(j_num.get(0, 0).unwrap(), j00, epsilon = 1e-5);
|
||||
assert_relative_eq!(j_num.get(0, 1).unwrap(), j01, epsilon = 1e-5);
|
||||
assert_relative_eq!(j_num.get(1, 0).unwrap(), j10, epsilon = 1e-5);
|
||||
assert_relative_eq!(j_num.get(1, 1).unwrap(), j11, epsilon = 1e-5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user