| 653 | } |
| 654 | |
| 655 | bool RotationAveragingSolver::SolveL1Regression( |
| 656 | RotationAveragingProblem& problem) { |
| 657 | LeastAbsoluteDeviationSolver::Options l1_solver_options; |
| 658 | l1_solver_options.max_num_iterations = 10; |
| 659 | l1_solver_options.solver_type = |
| 660 | LeastAbsoluteDeviationSolver::Options::SolverType::SupernodalCholmodLLT; |
| 661 | l1_solver_options.ridge_regularization = options_.ridge_regularization; |
| 662 | |
| 663 | LeastAbsoluteDeviationSolver l1_solver(l1_solver_options, |
| 664 | problem.ConstraintMatrix()); |
| 665 | if (!l1_solver.Valid()) { |
| 666 | LOG(ERROR) << "L1 regression linear solver factorization failed"; |
| 667 | return false; |
| 668 | } |
| 669 | |
| 670 | double prev_norm = 0; |
| 671 | double curr_norm = 0; |
| 672 | |
| 673 | Eigen::VectorXd step(problem.NumParameters()); |
| 674 | |
| 675 | int iteration = 0; |
| 676 | |
| 677 | for (; iteration < options_.max_num_l1_iterations; iteration++) { |
| 678 | VLOG(2) << "L1 ADMM iteration: " << iteration; |
| 679 | |
| 680 | problem.ComputeResiduals(); |
| 681 | |
| 682 | prev_norm = curr_norm; |
| 683 | |
| 684 | step.setZero(); |
| 685 | if (!l1_solver.Solve(problem.Residuals(), &step) || |
| 686 | step.array().isNaN().any()) { |
| 687 | LOG(ERROR) << "L1 regression solve failed (iteration " << iteration |
| 688 | << ")"; |
| 689 | return false; |
| 690 | } |
| 691 | |
| 692 | if (VLOG_IS_ON(2)) |
| 693 | LOG(INFO) << "residual:" |
| 694 | << (problem.ConstraintMatrix() * step - problem.Residuals()) |
| 695 | .array() |
| 696 | .abs() |
| 697 | .sum(); |
| 698 | |
| 699 | curr_norm = step.norm(); |
| 700 | problem.UpdateState(step); |
| 701 | |
| 702 | // Check convergence. |
| 703 | constexpr double kEps = 1e-12; |
| 704 | if (problem.AverageStepSize(step) < |
| 705 | options_.l1_step_convergence_threshold || |
| 706 | std::abs(prev_norm - curr_norm) < kEps) { |
| 707 | if (std::abs(prev_norm - curr_norm) < kEps) |
| 708 | LOG(INFO) << "std::abs(prev_norm - curr_norm) < " << kEps; |
| 709 | iteration++; |
| 710 | break; |
| 711 | } |
| 712 | l1_solver_options.max_num_iterations = |
nothing calls this directly
no test coverage detected