IBMDecisionOptimization / docplex-examples

These samples demonstrate how to use the DOcplex library to model and solve optimization problems.
https://ibmdecisionoptimization.github.io/
Apache License 2.0
392 stars 228 forks source link

Blackbox feature #65

Open SHosseini94 opened 2 years ago

SHosseini94 commented 2 years ago

Hi,

I am using the beta version of CP optimizer and its black-box class. I need to send a sequence variable to the black-box function and then return a dictionary containing some values.

I have read the example of stochastic-job-shop using black-box, but my model is a little bit different.

First, in my black-box function, I need to get the start of each interval in the sequence variable, but when I use method "get_start" while iterating in this sequence variable in the implemented black box function, it returns a tuple, which is (min_start, max_start) for that interval var.

Second, in my function, I get some values and I put them in a dictionary to use them later in CP model, but I cannot return a dictionary while using BlackBox. The dimension should be an integer of the number of returning values.

I appreciate you helping me in this regard.

Best,

p-shaw commented 2 years ago

Hello,

I assume that you are using Python. You shouldn't need to use get_start though. That is an accessor on the modelling object and you want to have access to the current partial solution projected onto your black box variables. This happens automatically when you specify the arguments of your black box function. I've included an example below. I am not sure what you mean by wanting to return a dictionary. A black box expression needs to be something that can be incorporated into your CP Optimizer model, and CP Optimizer does not understand dictionaries. So, whatever value you return needs to be a numerical value or a vector of numerical values.

Regards.

from docplex.cp.model import CpoModel, CpoBlackboxFunction
import functools

def my_bb(seq, interval, interval_ids):
    sid = tuple(id(itv) for itv in seq)
    order = tuple(interval_ids.index(id(itv)) for itv in seq)
    # Do what you want with the order and intervals
    return max(i.end for i in interval)

N = 5

mdl = CpoModel()
task = [ mdl.interval_var(size = 1) for _ in range(N) ]
seq = mdl.sequence_var(task)
mdl.add(mdl.no_overlap(seq))
task_ids = tuple(id(t) for t in task)
bbf = CpoBlackboxFunction(functools.partial(my_bb, interval_ids = task_ids))
obj = bbf(seq, task)

mdl.add(mdl.minimize(obj))
mdl.add(obj >= N)

mdl.solve()
SHosseini94 commented 2 years ago

Thanks so much for your clarification.

So, you mean it's possible only to return a vector when we have many values to return to the model? I was supposed to put these values in a dictionary format, making the results more interpretable.

In addition, Isn't the returned value a kind of integer expression? because while I use it in "element" command, it couldn't handle it, and it says you should put an integer expression as index.

Best

p-shaw commented 2 years ago

Hello,

If you return a vector, that is not the value of an integer expression, but the value of multiple integer expressions. You then need to subscript to get the actual values. Like below.

Regards,

Paul


def my_bb(seq, interval, interval_ids):
   # Stuff ...
   return (val1, val2, val3) # Return 3 values!

# some things removed (see my previous post)

bbf = CpoBlackboxFunction(functools.partial(my_bb, interval_ids = task_ids), 3) # Specify three return values expected.
obj = bbf(seq, task)

# Subscript obj (0..2)
mdl.add(mdl.minimize(obj[0] + 2 * obj[1] + 4 * obj[2]))
SHosseini94 commented 2 years ago

Hello,

I did this way, but there is a problem. I am going to use the return value, an integer expression, in this command:

bbf = CpoBlackboxFunction(functools.partial(my_bb, interval_ids = task_ids), 3) # Specify three return values expected. obj = bbf(seq, task) **y=element(task,obj [0])**

But, I got this error: AssertionError: At least one argument should be an integer expression representing index

I appreciate you guiding me on this.

Best,

p-shaw commented 2 years ago

Hello,

You don't say it, but I imagine that you get an error creating the element expression. An element expression should take an array of integer expressions and an integer expression to index them. From what I understand task is an array of interval variables, so this cannot work.

Regards,

Paul