Skip to content

ShortTable decomposition#997

Draft
WoutPiessens wants to merge 1 commit into
masterfrom
short_table_decomp
Draft

ShortTable decomposition#997
WoutPiessens wants to merge 1 commit into
masterfrom
short_table_decomp

Conversation

@WoutPiessens
Copy link
Copy Markdown
Collaborator

This branch continues on #981 and implements a linear decomposition of the ShortTable global constraint into Tables, which can then be further decomposed into MDDs.

For every "star pattern" (set of columns in which STAR appears) occurring in the original ShortTable, an auxiliary table is constructed with auxiliary variables, which are channelled back to the original variables. The advantage of this is that in the auxiliary table, the columns containing STAR can be ignored.

@WoutPiessens WoutPiessens mentioned this pull request May 27, 2026
23 tasks
Copy link
Copy Markdown
Collaborator

@tias tias left a comment

Choose a reason for hiding this comment

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

request for discussion, I'm not sure the current version is worth it


# Since the tables use auxiliary variables not used anywhere else, they always admit a solution
# The ShortTable constraint is satisfied iff at least one channelling constraint is satisfied
return [cp.sum(channelling_cons) != 0], tables
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.

mip solvers will appreciate that you write > 0 (we might do ugly things, because they dont support !=)

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.

actually, isn't this cp.exists??

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.

because of this part, I'm not sure its actually going to be faster...

an exists over all(iv==iv) requires an additional boolean variable for each aux==iv, and you already introduced all these aux's...

if you think about the MDD encoding of each of those tables, would the real flow encoding not have an in flow of 1, then unlabelled branches to the sources of each projected table's MDD, then (in parallel) the flow constraints on those mdds with the original variables, then from each of the sink nodes again unlabbeled branches to the real sink node, with the requirement that out flow=1 from this sink, e.g. over this parallel MDD (always using the original variables)?

I'm not sure we have an easy way to build this, I'm also not sure if you want to actually do it : ) but I wonder

groups: defaultdict[tuple[int, ...], list[list[int]]] = defaultdict(list)

for row in tab.tolist(): # converts to Python ints
# Determine STAR pattern
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 need a bit more pedagogical documentation here...

the 'star pattern' is the columns in this row that contain a star?
so why do you group by pattern?

then you will project those out and create shadow variables? and... one of those tables must match?

does this also contain the rows without star?

@WoutPiessens
Copy link
Copy Markdown
Collaborator Author

WoutPiessens commented May 29, 2026

@tias @IgnaceBleukx

To explain the current decomposition:

For every row in the ShortTable, consider the columns in which a STAR appears as a tuple, e.g. () for a row with no STARs, (2), (3,4), ... I call these the "patterns". All rows in the ShortTable with the same pattern are grouped together, and all the columns in the tuple of the pattern can be skipped over (this is the reason for grouping by pattern) : as a consequence we obtain a (normal) Table for every group.

For example: [[1, STAR], [2, STAR], [STAR, 3], [0,0]] results in three tables: [[1], [2]] and [[3]] and [[0,0]], with respective patterns (1), (0), ().

Now all these Table constraints use an auxiliary variable array. Then it must hold that the original array is equal to at least one auxiliary array (for all columns in the original array that are included in the auxiliary array).

An alternative decomposition is to construct one MDD, namely the MDD obtained by decomposing the Table that is equivalent with the ShortTable. This will likely only work well if the MDD is reduced, otherwise a very large number of paths in the MDD may exist. I'm looking into a way to do this without having to construct the full Table / non-reduced MDD first, but it's not trivial. Essentially it comes down to performing reduce steps already during construction of the MDD. But I will further look into implementing this.

I think the advantage of the current method compared to the alternative method is the fact that STARs can be fully skipped over, and the disadvantage is the use of auxiliary variables and channelling constraints. But when I have them both I would like to compare them and choose one.

@WoutPiessens
Copy link
Copy Markdown
Collaborator Author

Implementing the alternative decomposition (with one MDD) will likely be significantly easier if we have a non-deterministic MDD, where in any node, there can be multiple outgoing edges with the same value. However, this raises the question if we want to support this for the current MDD global, or if it should be a separate global (presumably only in the competition branch).

@tias
Copy link
Copy Markdown
Collaborator

tias commented May 29, 2026

right, I'm not sure we should actually go all that way... we might be going a bit too far in a rabbit hole here, given that shorttable is rarely used...

for the current decomposition; I'm not going to put it in master. We would need an experiment that shows that it is worth increasing our codebase (anything added must be maintained). You can add it in the xcsp3 branch if you wish...

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.

2 participants