Skip to content

Enhance symbolic onnx parsing via sym_eval - #5148

Draft
shivadbhavsar wants to merge 15 commits into
developfrom
core_symbolic_evaluation
Draft

Enhance symbolic onnx parsing via sym_eval#5148
shivadbhavsar wants to merge 15 commits into
developfrom
core_symbolic_evaluation

Conversation

@shivadbhavsar

Copy link
Copy Markdown
Contributor

No description provided.

CharlieL7 and others added 15 commits August 4, 2026 18:32
Bring the PR #5112-based parser prerequisite branch onto the current development baseline before applying its remaining changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the merged resolver regression compatible with the dynamic-slice interface introduced by PR #5112.

Co-authored-by: Cursor <cursoragent@cursor.com>
Track exact integral shape values through parser operations so dynamic consumers retain symbolic output relationships without changing runtime dataflow.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the symbolic-value change focused by restoring existing resolver diagnostics and simplifying the signed Gather size declaration.

Co-authored-by: Cursor <cursoragent@cursor.com>
if(output_shape.type() != shape::int64_type)
return std::nullopt;
return compute_symbolic_binary(
output_shape, input_values, [](const auto& x, const auto& y) { return x + y; });

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be added to the add operator. This should be added to the binary class and call the apply method in the derived. Same for unary.

if(input_values.size() != 2 or not input_values[0].has_value() or
not input_values[1].has_value())
return std::nullopt;
auto result = broadcast_symbolic_values(*input_values[0], *input_values[1], std::move(f));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes it more complicated having to reimplement broadcasting(and this will only work on pointwise ops).

Thinking about it more, I think we should keep the shape, and use tensor_view<sym::expr> to iterate the data. We can have a sym_argument class like this:

struct sym_argument
{
    bool empty() const
    {
        return m_data.empty();
    }
    shape get_shape() const
    {
        return m_shape;
    }

    tensor_view<sym::expr> get()
    {
        return make_view(m_shape, m_data.data());
    }

    tensor_view<const sym::expr> get() const
    {
        return make_view(m_shape, m_data.data());
    }
    std::vector<sym::expr> m_data;
    shape m_shape;
};

{
return [](auto x, auto y) { return x + y; };
}
std::optional<symbolic_tensor_value>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think we need to wrap it on an std::optional as empty() also means no value which we can use.

Comment thread src/instruction.cpp

std::optional<symbolic_tensor_value> result;
const auto& output_shape = ins.get_shape();
if(shape::is_integral(output_shape.type()) and not output_shape.dynamic())

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Symbolics support floats so there is no reason to limit it to integrals.

Comment thread src/instruction.cpp
return;
}
transform(input, std::back_inserter(result), [](auto x) { return sym::lit(x); });
converted = true;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This flag is not needed as you can just check if the vector is empty.

Comment thread src/instruction.cpp
if constexpr(std::is_unsigned<type>{} and sizeof(type) >= sizeof(int64_t))
{
if(any_of(input, [](auto x) {
return x > static_cast<type>(std::numeric_limits<int64_t>::max());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should just clip instead of returning none.

Comment thread src/instruction.cpp
Comment on lines +489 to +492
if(ins.name() == "@literal")
{
result = lift_symbolic_tensor_value(ins.get_literal().get_argument());
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should const fold the input if its possible:

Suggested change
if(ins.name() == "@literal")
{
result = lift_symbolic_tensor_value(ins.get_literal().get_argument());
}
if(ins.can_eval())
{
result = lift_symbolic_tensor_value(ins.eval());
}

register_op_parser(opd.onnx_name, [opd, parser](auto&&... xs) {
return implicit_multi_op(parser.parse(opd, xs...));
});
register_op_parser(opd.onnx_name,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this changes needed now?

Comment thread src/sym.cpp

static bool scalar_equal(const scalar& a, const scalar& b)
{
return not scalar_less(a, b) and not scalar_less(b, a);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this to avoid float comparison warnings?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants