Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New advanced example: CPMpyXplain algorithm #253

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

VincentDeBoulle
Copy link

No description provided.

@tias
Copy link
Collaborator

tias commented Mar 16, 2023

Thanks for the contribution; I confirm it runs fine. We will wait till after the project deadline to do a detailed review or changes, but it already looks solid as is.

Copy link
Collaborator

@IgnaceBleukx IgnaceBleukx left a comment

Choose a reason for hiding this comment

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

Nice demonstration of the QuickXplain algorithm!
The logic looks good for the most part but the style of the example can use some love, I left some comments on what could be good to change before we merge it into master.

I really like the "iteration mode" as indeed the original paper relies heavily on the (actually arbitrary) ordering of the constraints...
When I use the "iteration mode", I get multiple of the same explanations, is that considered correct? Maybe you can check if the explanation is already found and not print it again?

Lastly: we have added a .set_description() option for constraints, maybe you can use it to nicely print the constraint relaxations here?

life = intvar(0, 1100)
price = intvar(0, 300000)

global size_cons
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please do not use global variables, use them as arguments to your functions!

import itertools

## This variable is responsible for the use cases
enable_iteration = False
Copy link
Collaborator

Choose a reason for hiding this comment

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

Better name could be "enumeration" imho

- Default: One explanation, the order in which the constraints are considered is the same order as in which the user_constraints are mentioned in the 'user_constraints'-variable
- An explanation for every possible order in which the constraints can be considered
"""
from cpmpy import *
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use import cpmpy as cp instead

Format: [Size, Memory, Life, Price]
All numbers must be multiplied by 100 since CPMpy can only work with Integer values. When creating the explanations, the values are automatically divided by 100.
"""
laptops = [[1540, 102400, 220, 149999], # Unsatisfiable, relax life time to get a satisfiable result
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe overkill but you can also structure this using a Pandas DataFrame, it might clean up the code later as you can simply index the columns you want using the name of the attribute of the laptop

[1400, 51200, 1000, 189999]
]

size = intvar(0, 2000)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also give the name of the variable

order_indices = list(range(0, len(user_constraints)))
orders = list(itertools.permutations(order_indices))

for nb_explanation, order in enumerate(orders):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Performance suggestion: itertools.permutations returns a generator which means the next item is only generated on demand. Hence, instead of materializing each element to a list like you do on line 90, you can simply iterate over the generator directly:

for nb_expl, order in enumerate(permutations(order_indices)):



def no_sufficient_relax_space():
for space in relaxation_spaces:
Copy link
Collaborator

Choose a reason for hiding this comment

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

return all(len(space) > 1 for space in relaxation_spaces))


def relax_problem(order):
# Create a new model step by step until we find a satisfiable result (bottom-up)
new_model = Model(Table([size, memory, life, price], laptops))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually I would consider the Table constraint also to be a background constraint


def remove_duplicates(indices):
"""
Removes the duplicates from the given list
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it not easier converting to a set?

return result


def relax_constraint(index):
Copy link
Collaborator

Choose a reason for hiding this comment

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

If you pass as argument constraint and relaxation_spaces here, it will become much nicer : )

@Dimosts
Copy link
Collaborator

Dimosts commented Mar 19, 2024

Are there any news about it? It has been open for long time with minimal requested changes

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.

4 participants