Skip to content

Commit

Permalink
Merge pull request #55 from jwnimmer-tri/roots
Browse files Browse the repository at this point in the history
fixup! Implements symbolic::Polynomial::Roots()
  • Loading branch information
RussTedrake authored Sep 11, 2023
2 parents e47bc20 + 32057c7 commit 2582112
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 12 deletions.
16 changes: 8 additions & 8 deletions common/symbolic/polynomial.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1056,9 +1056,9 @@ bool Polynomial::IsOdd() const {

Eigen::VectorXcd Polynomial::Roots() const {
if (indeterminates().size() != 1) {
throw std::runtime_error(fmt::format(
"{} is not a univariate polynomial; it has indeterminates {}.",
ToExpression().to_string(), indeterminates().to_string()));
throw runtime_error(fmt::format(
"{} is not a univariate polynomial; it has indeterminates {}.", *this,
indeterminates()));
}

// We find the roots by computing the eigenvalues of the companion matrix.
Expand All @@ -1074,11 +1074,11 @@ Eigen::VectorXcd Polynomial::Roots() const {
double leading_coefficient = 0;
for (const auto& [monomial, coeff] : monomial_to_coefficient_map()) {
if (!is_constant(coeff)) {
throw std::runtime_error(
fmt::format("Polynomial::Roots() only supports polynomials with "
"constant coefficients. This polynomial has coefficient "
"{} for the monomial {}.",
coeff.to_string(), monomial.ToExpression().to_string()));
throw runtime_error(fmt::format(
"Polynomial::Roots() only supports polynomials with constant "
"coefficients. This polynomial has coefficient {} for the "
"monomial {}.",
coeff, monomial));
}
const int power = monomial.total_degree();
if (power == degree) {
Expand Down
8 changes: 4 additions & 4 deletions common/symbolic/test/polynomial_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1512,7 +1512,7 @@ TEST_F(SymbolicPolynomialTest, Roots) {

// Note: the order of the roots is not guaranteed. Sort them here by real,
// then imaginary.
auto sort = [](const Eigen::VectorXcd& v) {
auto sorted = [](const Eigen::VectorXcd& v) {
Eigen::VectorXcd v_sorted = v;
std::sort(v_sorted.data(), v_sorted.data() + v_sorted.size(),
[](const std::complex<double>& a, const std::complex<double>& b) {
Expand All @@ -1526,22 +1526,22 @@ TEST_F(SymbolicPolynomialTest, Roots) {

// Include a repeated root.
p = symbolic::Polynomial{(x_ - 1.23) * (x_ - 4.56) * (x_ - 4.56)};
roots = sort(p.Roots());
roots = sorted(p.Roots());
EXPECT_TRUE(
CompareMatrices(roots.real(), Eigen::Vector3d{1.23, 4.56, 4.56}, 1e-7));
EXPECT_TRUE(CompareMatrices(roots.imag(), Eigen::Vector3d::Zero(), 1e-7));

// Complex roots. x^4 - 1 has roots {-1, -i, i, 1}.
p = symbolic::Polynomial{pow(x_, 4) - 1};
roots = sort(p.Roots());
roots = sorted(p.Roots());
EXPECT_TRUE(
CompareMatrices(roots.real(), Eigen::Vector4d{-1, 0, 0, 1}, 1e-7));
EXPECT_TRUE(
CompareMatrices(roots.imag(), Eigen::Vector4d{0, -1, 1, 0}, 1e-7));

// Leading coefficient is not 1.
p = symbolic::Polynomial{(2.1 * x_ - 1.23) * (x_ - 4.56)};
roots = sort(p.Roots());
roots = sorted(p.Roots());
EXPECT_TRUE(
CompareMatrices(roots.real(), Eigen::Vector2d{1.23 / 2.1, 4.56}, 1e-7));
EXPECT_TRUE(CompareMatrices(roots.imag(), Eigen::Vector2d::Zero(), 1e-7));
Expand Down

0 comments on commit 2582112

Please sign in to comment.