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

Question: Correct way to do use value of an integer variable for indexing #164

Open
metanoid opened this issue May 15, 2020 · 4 comments
Open

Comments

@metanoid
Copy link

I have p products, and for each product I have a possibility of l price levels. For each such product and price level, I have the expected quantity sold, in a DataFrame called vals. I want to add a constraint that the total quantity sold must be greater than a constant.

If I used a binary programming approach, I would multiply each product's potential quantity by the binary decision variable. But I'm trying to solve this using an integer decision variable to represent the price level, and I realise I don't know how to use the value of a given variable as a lookup.

What I tried:

using JuMP
using ConstraintSolver
using DataFrames
const CS = ConstraintSolver # just to abbreviate

m = Model(CS.Optimizer)

num_products = 10
num_price_levels = 5

# make some fake data 
vals = DataFrame(ProductID = Int[], PriceLevel = Int[], Quantity = Float32[], ProfitMargin = Float32[], Profit = Float32[])
for prod in 1:num_products
    for pl in 1:num_price_levels
        q = 4 - pl/10 + rand()/10
        pm = 0.12 + pl/20 - (pl/20)^2 + rand()/10
        p = q*pm
        push!(vals, (prod, pl, q, pm, p))
    end
end
    
# one variable per product, the value of which is the index of the optimal price level
@variable(m, 1 <= price_level[p = 1:num_products] <= num_price_levels, Int)
# an expression per product which gives the quantity sold at the current price level
@expression(m, quantity[p = 1:num_products], sum(vals.Quantity[vals.ProductID .== p .& vals.PriceLevel .== price_level[p]]))     # TODO not working, figure out how to index by the value of a variable, if possible
@expression(m, profit[p = 1:num_products], sum(vals.Profit[vals.ProductID .== p .& vals.PriceLevel .== price_level[p]])) # TODO not working

# add a constraint that we must sell a minimum of quantity N overall
N = 100
@constraint(m, min_volume, 
    sum(quantity[p] for p in 1:num_products) >= N)

@objective(m, Max, sum(profit[p] for p in 1:num_products))

print(m)
optimize!(m)

However, this does not work.
Is this sort of "indexing by the value of a variable" even possible? If so, what would a good design for such a thing look like?

@Wikunia
Copy link
Owner

Wikunia commented May 15, 2020

Thanks for opening the issue. The short version: This is currently not possible.
There is currently no way to index an array by the value of a variable in JuMP.
The package JuCP.jl will eventually make it possible I think/hope and then I need to implement it here ;)
Sorry that the ConstraintSolver is currently quite limited :/

@metanoid
Copy link
Author

Is there a recommended workaround way of doing what I'm trying to do above, but without indexing by the value of the variable?

If not, I'm relatively confident I can do the above as a binary programming problem, I just wanted to use ConstraintSolver to be fancy, so no stress.

@Wikunia
Copy link
Owner

Wikunia commented May 15, 2020

I would write it as a binary problem as well. At least currently I can't think of a workaround.
Nevertheless thanks for having another try at my solver 😄

@Wikunia
Copy link
Owner

Wikunia commented Dec 12, 2020

I'm getting closer with this one as you seem to only need it for constant arrays. (#213) The problem here is also that you do some boolean logic inside the indexing which I don't have an idea for how to accomplish that kind of magic yet 😄

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