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

docplex issue: CPO expression can not be used as boolean. #68

Open
zhuoling163 opened this issue May 23, 2022 · 1 comment
Open

docplex issue: CPO expression can not be used as boolean. #68

zhuoling163 opened this issue May 23, 2022 · 1 comment

Comments

@zhuoling163
Copy link

I tried to compare CPO expression with a constant, the CPD expression had some calculation from variable before comparison. The code is as below, please help to advice how to work around.

`def make_model(tbl_cnt,rel_cnt,join_tbl,join_strength):

mdl = CpoModel()
x = [mdl.integer_var(0, 1, "Join_Included_{}".format(i)) for i in range(rel_cnt)]
a=mdl.integer_var(0,0,"const_0")
mdl.add(a==0)

#minimize cnt of join included
cnt_join_included=mdl.count(x,1)
mdl.add(cnt_join_included > 0) #at least include 1 join relationship

#max average of join strength
avg_join_strength=mdl.scal_prod(x,join_strength)/cnt_join_included

#max count of joined table
cnt_tbl_joined = 0

for tbl_id in range(tbl_cnt):  # For each dimension
    # select if tbl is included in all join
    tbl_included = join_tbl[:, tbl_id]

    # Calculate the included total count for the tbl_id
    tbl_included_sum = mdl.scal_prod(x, tbl_included)

    if tbl_included_sum>0:#>0
    #if tbl_included_sum.compare(a)>0:
        cnt_tbl_joined+=1

mdl.add(cnt_tbl_joined-cnt_join_included==1)

w = dict({})
w['cnt_join_included'] = -0.3
w['avg_join_strength'] = 0.2
w['cnt_tbl_joined'] = 0.5

obj=w['cnt_join_included'] * cnt_join_included\
    +w['avg_join_strength'] * avg_join_strength\
    +w['cnt_tbl_joined'] * cnt_tbl_joined
mdl.maximize(obj)
return mdl`

The error happened at
if tbl_included_sum>0:#>0
#if tbl_included_sum.compare(a)>0:
cnt_tbl_joined+=1

When use 1st line, it raise error "CPO expression can not be used as boolean." When I tried 2nd line, it always true.

@HuguesJuille
Copy link

HuguesJuille commented May 23, 2022

Indeed, tbl_included_sum is an expression that is based on constrained variables. The value of these constrained variables will be known only after solve is performed. Therefore, it does not make sense to compare this expression to a constant.
This being said, the solution is to find another formulation. There are several ways to do this.
The most trivial one consists in adding as many constrained variables as there are tbl_included_sum expressions, to add logical constraints to assign the desired value to these variables, and sum them up at the end to cnt_tbl_joined which MUST BE a constrained variable or a CPO expression (but cannot be a python variable).
This could look like this:

tbl_included_sum_is_pos = [mdl.integer_var(0, 1) for _ in range(tbl_cnt)]

for tbl_id in range(tbl_cnt):  # For each dimension
    # select if tbl is included in all join
    tbl_included = join_tbl[:, tbl_id]

    # Calculate the included total count for the tbl_id
    tbl_included_sum = mdl.scal_prod(x, tbl_included)

    # Logical constraint
    mdl.add(tbl_included_sum_is_pos[tbl_id] == (tbl_included_sum > 0))

cnt_tbl_joined = mdl.sum(tbl_included_sum_is_pos)

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

No branches or pull requests

2 participants