Skip to content

Comments

Moved IteHandler into the preprocessing pipeline#858

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

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

Conversation

@Tomaqa
Copy link
Member

@Tomaqa Tomaqa commented Aug 26, 2025

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
Copy link
Member

@blishko blishko left a comment

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
Copy link
Member Author

Tomaqa commented Aug 27, 2025

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
Copy link
Member Author

Tomaqa commented Aug 27, 2025

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
Copy link
Member Author

Tomaqa commented Aug 27, 2025

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
Copy link
Member Author

Tomaqa commented Aug 27, 2025

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
Copy link
Member Author

Tomaqa commented Aug 28, 2025

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
Copy link
Member Author

Tomaqa commented Oct 23, 2025

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
Copy link
Member Author

Tomaqa commented Oct 23, 2025

(#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
Copy link
Member

blishko commented Nov 7, 2025

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

@Tomaqa
Copy link
Member Author

Tomaqa commented Nov 10, 2025

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
Copy link
Member Author

Tomaqa commented Nov 13, 2025

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.

Copy link
Member

@blishko blishko left a comment

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 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
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
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
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
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
Copy link
Member Author

Tomaqa commented Nov 14, 2025

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
Copy link
Member Author

Tomaqa commented Nov 18, 2025

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
Copy link
Member Author

Tomaqa commented Dec 6, 2025

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 from a82384e to 451af98 Compare December 6, 2025 13:35
@Tomaqa Tomaqa force-pushed the fix-internal-term-names branch from 451af98 to b1a0787 Compare December 6, 2025 14:05
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