Constraint isolate()

in src/core/symbolic.cpp [598:652]


Constraint isolate(const Constraint& c, const Symbol& sym) {
  const auto& lhs = c.first;
  const auto& rhs = c.second;
  if (!lhs.contains(sym) && rhs.contains(sym)) {
    return isolate(std::make_pair(rhs, lhs), sym);
  }
  ASSERT(lhs.contains(sym) && !rhs.contains(sym))
      << "cannot isolate with variable on both rhs and lhs of constraint yet: "
      << lhs.dump() << " = " << rhs.dump() << " for sym " << Expr(sym).dump();
  if (lhs == Expr(sym)) {
    return std::make_pair(lhs, rhs);
  }

  if (lhs.type() == Expr::Type::function) {
    ASSERT(can_isolate(lhs, sym))
        << "cannot isolate " << sym.name() << " through " << lhs.dump()
        << ", you may need to update the can_isolate function";
    switch (lhs.op()) {
      case Op::add: {
        auto llhs = lhs.args().at(0);
        auto lrhs = lhs.args().at(1);
        if (llhs.contains(sym)) {
          return isolate(std::make_pair(llhs, rhs - lrhs), sym);
        }
        return isolate(std::make_pair(lrhs, rhs - llhs), sym);
      }
      case Op::multiply: {
        auto llhs = lhs.args().at(0);
        auto lrhs = lhs.args().at(1);
        if (llhs.contains(sym)) {
          return isolate(std::make_pair(llhs, rhs / lrhs), sym);
        }
        ASSERT(lrhs.contains(sym));
        return isolate(std::make_pair(lrhs, rhs / llhs), sym);
      }
      case Op::divide: {
        auto llhs = lhs.args().at(0);
        auto lrhs = lhs.args().at(1);
        if (llhs.contains(sym)) {
          return isolate(std::make_pair(llhs, rhs * lrhs), sym);
        }
        return isolate(std::make_pair(lrhs, rhs * llhs), sym);
      }
      case Op::negate:
        return isolate(std::make_pair(lhs.args().at(0), -rhs), sym);
      case Op::reciprocal:
        return isolate(std::make_pair(lhs.args().at(0), Expr(1) / rhs), sym);
      default:
        ASSERT(0) << "cannot isolate through " << lhs.dump();
    }
  }
  ASSERT(0) << "error isolating for " << sym.name() << " in constraint "
            << lhs.dump() << " = " << rhs.dump();
  return std::make_pair(Expr(0), Expr(0));
}