Skip to content

Moved IteHandler into the preprocessing pipeline - #858

Draft
Tomaqa wants to merge 8 commits into
preprocess-countersfrom
fix-internal-term-names
Draft

Moved IteHandler into the preprocessing pipeline#858
Tomaqa wants to merge 8 commits into
preprocess-countersfrom
fix-internal-term-names

Conversation

@Tomaqa

@Tomaqa Tomaqa commented Aug 26, 2025

Copy link
Copy Markdown
Member

Fixes TermNames to also consider the mapping of internal terms to original user terms.
So far, I have only identified IteHandler to change the PTRef of the inserted formula in insertFormula and at the same time store it into the assertions, so that the changed PTRef is retrieved via getting the assertions or via PartitionaManager.
Without this, the UnsatCoreBuilder would consider some terms to be unnamed because it would not recognize them.

Resolves #857

@Tomaqa
Tomaqa force-pushed the fix-internal-term-names branch from 3284d3b to 76953cc Compare August 26, 2025 13:47
@Tomaqa
Tomaqa requested a review from blishko August 26, 2025 13:55
@Tomaqa
Tomaqa force-pushed the fix-internal-term-names branch from 76953cc to c5bc8ba Compare August 26, 2025 15:12

@blishko blishko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Seems good, but I am not sure I fully understand the underlying problem.
There should be some very minimal example to reproduce the problem, no?
Can we find it and use it as the regression test, instead of these large files?
It would also help me to understand the problem properly.
ITEHandler has always been a bit of a hack.
Wouldn't it help if we resolved the TODO associated with its usage, and incorporate the ite processing to the preprocessing pipeline?

@Tomaqa
Tomaqa force-pushed the fix-internal-term-names branch from c5bc8ba to 6596c52 Compare August 27, 2025 09:25
@Tomaqa

Tomaqa commented Aug 27, 2025

Copy link
Copy Markdown
Member Author

Wouldn't it help if we resolved the TODO associated with its usage, and incorporate the ite processing to the preprocessing pipeline?

Are you referring to the comment at IteHandler.cc:45?

I am not too familiar with how the overall preprocessing and substitutions work. But I assume that in general, the top-level asserted PTRefs can be internally replaced by a different, potentially better term. For this reason, I introduced InternalToUserTermMap such that MainSolver can use it at whatever place and time.

I am not sure how this concept changes with incorporating or not incorporating ITEs into the preprocessing pipeline.

@Tomaqa

Tomaqa commented Aug 27, 2025

Copy link
Copy Markdown
Member Author

There should be some very minimal example to reproduce the problem, no?

I identified some very small examples and added them. I believe that the problem appears when the top-level assertion is an ITE. I will also try to make some similar unit tests.

@Tomaqa
Tomaqa force-pushed the fix-internal-term-names branch from 6596c52 to 9d7a2bc Compare August 27, 2025 11:25
@Tomaqa

Tomaqa commented Aug 27, 2025

Copy link
Copy Markdown
Member Author

I also included unit tests. As a consequence, I also added to possibility to retrieve the names from NamedUnsatCore and added several tests on this in the unit tests.

Even with the fix, we correctly handle the unsat cores such that the names are kept, but not the terms themselves. See e.g. test_UnsatCore.cc:395 (in the Bool_Trivial_ITE test).
Hence, for example, in the case of full cores where the names are ignored, the user cannot track which of the terms he/she asserted are kept/discarded from the core. That does not seem right, but I can fix it by storing the original terms instead of the internals into the core.

@Tomaqa

Tomaqa commented Aug 27, 2025

Copy link
Copy Markdown
Member Author

My current feeling is that the transformation of internal terms to the original should already happen inside of api/PartitionManager.h:51 :

inline std::vector<PTRef> getPartitions() const { return partitionInfo.getTopLevelFormulas(); }

I am not sure if this is always the desired behavior, or if it should be optional - a parameter in PartitionManager would allow to do the mapping.
But since getPartitions() refers to top-level assertions, I think it should refer to the original PTRef provided to the insertFormula.

@Tomaqa
Tomaqa changed the base branch from master to get-names-from-ucores August 27, 2025 12:42
@Tomaqa
Tomaqa marked this pull request as draft August 28, 2025 08:18
@Tomaqa

Tomaqa commented Aug 28, 2025

Copy link
Copy Markdown
Member Author

I checked that the current fix resolves all the issues reported in #857 regarding the named terms, including minimal cores, except the cases reported in #859 where the issue is probably not related to the one discussed here.

However, the issue with not identifying the original PTRefs as a part of the core remains unresolved.

@Tomaqa
Tomaqa force-pushed the get-names-from-ucores branch from e21f02f to 08eb18e Compare September 16, 2025 11:07
@Tomaqa
Tomaqa changed the base branch from get-names-from-ucores to master September 16, 2025 11:23
@Tomaqa
Tomaqa marked this pull request as ready for review September 16, 2025 11:23
@Tomaqa
Tomaqa marked this pull request as draft September 16, 2025 11:24
@Tomaqa
Tomaqa force-pushed the fix-internal-term-names branch from 9d7a2bc to 9e2516f Compare September 16, 2025 12:11
@Tomaqa
Tomaqa force-pushed the fix-internal-term-names branch from 9e2516f to 741459e Compare October 23, 2025 12:21
@Tomaqa

Tomaqa commented Oct 23, 2025

Copy link
Copy Markdown
Member Author

ITEHandler has always been a bit of a hack. Wouldn't it help if we resolved the TODO associated with its usage, and incorporate the ite processing to the preprocessing pipeline?

I moved the use of the IteHandler into preprocessing, and it seems to resolve the issues.
Now, the partition manager knows the mapping and should always return the original PTRefs - which comprises both unsat cores and interpolants, which both could have returned internal PTRef, thus unknown to the user.

@Tomaqa
Tomaqa marked this pull request as ready for review October 23, 2025 12:26
@Tomaqa

Tomaqa commented Oct 23, 2025

Copy link
Copy Markdown
Member Author

(#859 seems to remain unresolved - but it can be caused by something completely different.)

@Tomaqa Tomaqa changed the title Map internally introduced term names to the user-provided in TermNames Moved IteHandler into the preprocessing pipeline Nov 7, 2025
@Tomaqa
Tomaqa requested a review from blishko November 7, 2025 13:25
@blishko

blishko commented Nov 7, 2025

Copy link
Copy Markdown
Member

Can you split this PR?
Can the changes to the ITE preprocessing be separated from the unsat-core changes?

@Tomaqa

Tomaqa commented Nov 10, 2025

Copy link
Copy Markdown
Member Author

Can you split this PR? Can the changes to the ITE preprocessing be separated from the unsat-core changes?

I do not see the benefit here.
There are no tests that would identify the wrong behavior except for the new ones related to unsat cores.
Prepending the IteHandler as a standalone PR would prevent us from seeing that there was a point when the tests were failing.

@Tomaqa
Tomaqa force-pushed the fix-internal-term-names branch from 741459e to fc07b9c Compare November 10, 2025 14:28
@Tomaqa

Tomaqa commented Nov 13, 2025

Copy link
Copy Markdown
Member Author

I would like to keep the order of having the tests first and the patch later.
Having this order, it is not possible to split the PR, because the first part would fail the tests without the final patch.

@blishko blishko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have to refresh my memory why IteHandler needs a number.
I am not sure about the simplifiedFormulasCount.

What I don't quite like is that now, the same original formula can be preprocessed with IteHandler multiple times.
I am afraid this could lead to some performance regression in incremental solving.

Comment thread src/api/MainSolver.cc Outdated
Comment on lines +176 to +182
vec<PTRef> frameFormulas;
for (PTRef fla : frames[i].formulas) {
fla = IteHandler(logic, simplifiedFormulasCount++).rewrite(fla);
frameFormulas.push(fla);
}

PTRef frameFormula = logic.mkAnd(std::move(frameFormulas));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why not apply IteHandler once on the conjunction?
Wouldn't that be better?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I have not realized that it works recursively. Yes, it's better!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need this file in tests?
One, the core issue should be caught by the smaller tests, no?
Two, this one seems brittle, if the minimal unsat core is just smtcomp43 it seems weird to assert that OpenSMT will always find the unsat core consisting of


(
smtcomp14
smtcomp21
smtcomp43
)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, I can remove it.
Regarding how stable the tests are, this is a general issue that applies to all unsat cores and models. Even the "minimal" (irreducible) cores can be computed differently. Every time we make a change in the solver, we may need to update the expected results, or we will have to add support for multiple possible outputs in regression tests.

@Tomaqa

Tomaqa commented Nov 14, 2025

Copy link
Copy Markdown
Member Author

I have to refresh my memory why IteHandler needs a number.

The only purpose is for the name of the auxiliary '.ite' variable.

What I don't quite like is that now, the same original formula can be preprocessed with IteHandler multiple times. I am afraid this could lead to some performance regression in incremental solving.

I will need to handle this more thoroughly. I think it would be best to first implement an array of counters for remembering how many formulas per assertion level have been preprocessed, to easily detect that the preprocessing has already taken place, even with arbitrary pushes and pops.

@Tomaqa

Tomaqa commented Nov 18, 2025

Copy link
Copy Markdown
Member Author

Can you split this PR? ...

I moved one of the less related commits into a separate PR -> #887

@Tomaqa
Tomaqa marked this pull request as draft November 24, 2025 12:56
@Tomaqa
Tomaqa force-pushed the fix-internal-term-names branch 2 times, most recently from 069466c to 0425df1 Compare November 24, 2025 14:25
@Tomaqa
Tomaqa changed the base branch from master to preprocess-counters November 24, 2025 14:25
@Tomaqa
Tomaqa force-pushed the preprocess-counters branch from 223bed6 to f492e9e Compare December 2, 2025 16:22
@Tomaqa
Tomaqa force-pushed the fix-internal-term-names branch 2 times, most recently from 10406a3 to a82384e Compare December 5, 2025 12:55
@Tomaqa

Tomaqa commented Dec 6, 2025

Copy link
Copy Markdown
Member Author

What I don't quite like is that now, the same original formula can be preprocessed with IteHandler multiple times.

I will need to handle this more thoroughly. I think it would be best to first implement an array of counters ...

Counters implemented in #889.

Now IteHandler is not being called multiple times: if trackPartitions(), then it is guaranteed thanks to the counters, not preprocessing already preprocessed formulas. In the other case, all frame formulas are always put into conjunction, potentially preprocessing some formulas again. We can use caching, but I realized that since the conjunctions are always different, there may never be a cache hit. We may instead separately remember the previous preprocessed formula and use it, and apply IteHandler only on the new part of the formula.

@Tomaqa
Tomaqa force-pushed the preprocess-counters branch from f492e9e to 5d64244 Compare December 6, 2025 13:25
@Tomaqa
Tomaqa force-pushed the fix-internal-term-names branch 2 times, most recently from 451af98 to b1a0787 Compare December 6, 2025 14:05
@Tomaqa
Tomaqa force-pushed the preprocess-counters branch from 5d64244 to 16902a4 Compare May 26, 2026 14:54
@Tomaqa
Tomaqa force-pushed the fix-internal-term-names branch from b1a0787 to 9d34c41 Compare May 26, 2026 14:54
@Tomaqa
Tomaqa force-pushed the preprocess-counters branch from 16902a4 to f28f401 Compare June 26, 2026 15:53
@Tomaqa
Tomaqa force-pushed the fix-internal-term-names branch from 9d34c41 to fb8d508 Compare July 15, 2026 11:50
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.

Unsound unsat cores

2 participants