Multiple dimensional sampling with first element string

Hi,

My equation g below is a function of the variable d which is indexed by s,n. I would like to sampling points to be of d[s,n]. how do I create the correct lb and ub.

using DataStructures
using JuMP
using Surrogates

S = ["s1","s2","s3","s4"]
N = [1:10]

price = OrderedDict(
"s1" => 0,
"s2" => 0,
"s3" => 0,
"s4" => 5
)

m = Model()

@variables m begin
  d[s in S, n in N] >= 0
end

g= d -> 

@objective m Max begin
sum((price[s]*d[s,n]) for n in N for s in S)
end

lb = [S[1],1]
ub = [S[4],10]
x_train = sample(10, lb,ub, SobolSample())

y_train = g.(x_train);

This is my attempt but it is not working out when inputting into x_train.

This is the error being returned:

MethodError: no method matching +(::String, ::Int64)
Closest candidates are:
+(::Any, ::Any, ::Any, ::Any…) at operators.jl:538
+(::ChainRulesCore.DoesNotExist, ::Any) at C:\Users\glmab.julia\packages\ChainRulesCore\D0go7\src\differential_arithmetic.jl:23
+(::Complex{Bool}, ::Real) at complex.jl:301

Stacktrace:
[1] add_sum(::String, ::Int64) at .\reduce.jl:24
[2] _mapreduce(::typeof(identity), ::typeof(Base.add_sum), ::IndexLinear, ::Array{Any,1}) at .\reduce.jl:408
[3] _mapreduce_dim at .\reducedim.jl:318 [inlined]
[4] #mapreduce#620 at .\reducedim.jl:310 [inlined]
[5] mapreduce at .\reducedim.jl:310 [inlined]
[6] _sum at .\reducedim.jl:727 [inlined]
[7] _sum at .\reducedim.jl:726 [inlined]
[8] #sum#627 at .\reducedim.jl:722 [inlined]
[9] sum at .\reducedim.jl:722 [inlined]
[10] Sobol.SobolSeq(::Int64, ::Array{Any,1}, ::Array{Any,1}) at C:\Users\glmab.julia\packages\Sobol\l4iL1\src\Sobol.jl:121
[11] SobolSeq at C:\Users\glmab.julia\packages\Sobol\l4iL1\src\Sobol.jl:124 [inlined]
[12] sample(::Int64, ::Array{Any,1}, ::Array{Any,1}, ::SobolSample) at C:\Users\glmab.julia\packages\Surrogates\wJbFN\src\Sampling.jl:77
[13] top-level scope at In[66]:1
[14] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1091

Your example is confusing. Where exactly does it fail? Can you remove all the unnecessary lines from your example?

You are not inputting anything into x_train in your example.

1 Like

I fixed it. I am inputting lb and ub into x_train. That is where it is failing. My variable d has indices s,n.
I want x_train to return eg. d[s1,1], d[s2,3]

Hope I am making sense now

There’s something off here. You’re not inputting anything into x_train. You are inputting lb and ub into sample, then you input x_train into g.

Presumably, you mean that your code fails here?

x_train = sample(10, lb,ub, SobolSample())

Where does SobolSample come from? It doesn’t seem to belong to either JuMP or DataStructures.

Yes.

But I am rather trying to understand how to input the correct type of data to x_train/y_train. This is dependent on how I formulate lb and ub (lower and upper bounds respectively).

From the error that y_train is returning (see below). I believe it is expecting a Tuple{Float64,Float64} but I am giving it (::String, ::Int64).

MethodError: no method matching getindex(::Tuple{Float64,Float64}, ::String, ::Int64)
Closest candidates are:
getindex(::Tuple, ::Int64) at tuple.jl:24
getindex(::Tuple, ::Real) at tuple.jl:25
getindex(::Tuple, ::UnitRange) at range.jl:293

Sorry it is part of the package Surrogates. I forgot to include it in the MWE

We are somehow misunderstanding each other. You are not inputting anything into x_train or y_train. They are outputs from sample and g, respectively.

Can you confirm on which line your code fails?

Oh yes. My mistake. My wording was not communicating that.
My code is failing here.

y_train = g.(x_train);

With this error:

MethodError: no method matching getindex(::Tuple{Float64,Float64}, ::String, ::Int64)
Closest candidates are:
getindex(::Tuple, ::Int64) at tuple.jl:24
getindex(::Tuple, ::Real) at tuple.jl:25
getindex(::Tuple, ::UnitRange) at range.jl:293

Stacktrace:
[1] (::var"#195#376"{Int64,Tuple{Float64,Float64},OrderedDict{String,Int64}})(::String) at .\none:0
[2] MappingRF at .\reduce.jl:93 [inlined]
[3] _foldl_impl(::Base.MappingRF{var"#195#376"{Int64,Tuple{Float64,Float64},OrderedDict{String,Int64}},Base.BottomRF{typeof(Base.add_sum)}}, ::Base._InitialValue, ::Array{String,1}) at .\reduce.jl:58
[4] FlatteningRF at .\reduce.jl:119 [inlined]
[5] MappingRF at .\reduce.jl:93 [inlined]
[6] _foldl_impl(::Base.MappingRF{var"#196#375"{Tuple{Float64,Float64},OrderedDict{String,Int64}},Base.FlatteningRF{Base.BottomRF{typeof(Base.add_sum)}}}, ::Base._InitialValue, ::UnitRange{Int64}) at .\reduce.jl:58
[7] foldl_impl at .\reduce.jl:48 [inlined]
[8] mapfoldl_impl at .\reduce.jl:44 [inlined]
[9] #mapfoldl#204 at .\reduce.jl:160 [inlined]
[10] mapfoldl at .\reduce.jl:160 [inlined]
[11] #mapreduce#208 at .\reduce.jl:287 [inlined]
[12] mapreduce at .\reduce.jl:287 [inlined]
[13] sum at .\reduce.jl:494 [inlined]
[14] sum(::Base.Iterators.Flatten{Base.Generator{UnitRange{Int64},var"#196#375"{Tuple{Float64,Float64},OrderedDict{String,Int64}}}}) at .\reduce.jl:511
[15] macro expansion at C:\Users\glmab.julia\packages\MutableArithmetics\bPWR4\src\rewrite.jl:276 [inlined]
[16] macro expansion at C:\Users\glmab.julia\packages\JuMP\y5vgk\src\macros.jl:928 [inlined]
[17] (::var"#194#374"{OrderedDict{String,Int64}})(::Tuple{Float64,Float64}) at .\In[17]:206
[18] _broadcast_getindex_evalf at .\broadcast.jl:648 [inlined]
[19] _broadcast_getindex at .\broadcast.jl:621 [inlined]
[20] getindex at .\broadcast.jl:575 [inlined]
[21] copy at .\broadcast.jl:876 [inlined]
[22] materialize(::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,var"#194#374"{OrderedDict{String,Int64}},Tuple{Array{Tuple{Float64,Float64},1}}}) at .\broadcast.jl:837
[23] top-level scope at In[51]:1
[24] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1091

I’m trying to condense your problem into a minimal working example (MWE), see here PSA: make it easier to help you for how to structure questions that are easy to understand.

It is not certain that I can help, but I can help to simplify your question, at least.

So most of your code plays no part here. I reduced your example to this:

using Surrogates
x_train = sample(10, ["s1", 1], ["s4", 10], SobolSample())

This gives an error:

ERROR: MethodError: no method matching +(::String, ::Int64)

But you are saying that this is no longer a problem, and your code now fails at the next line:

instead?

How did you get the x_train?

1 Like

So the error in this line is caused by Surrogates.sample trying to call sum(ub) when ub is ["s4", 10], so apparently it makes no sense to use ["s1", 1], and ["s4", 10] as lower and upper bounds.

I am not saying it is no longer a problem but I now want to solve it from y_train moving up.

x_train needs to be correct for y_train to be correct. Because when x_train is Float64 (or Int64 or the likes). y_train returns the below error.

MethodError: no method matching getindex(::Tuple{Float64,Float64}, ::String, ::Int64)
Closest candidates are:
getindex(::Tuple, ::Int64) at tuple.jl:24
getindex(::Tuple, ::Real) at tuple.jl:25
getindex(::Tuple, ::UnitRange) at range.jl:293

This is my current x_train

x_train = sample(10, Float64[1,10] ,Float64[10,100], SobolSample())

This is taking some time to install, but just an idea: Have you tried using

N = 1:10

instead of

N = [1:10]

They mean very different things, and it looks like it could be a problem.

Using that remains the error same, Int64 changes to UnitRange{Int64}

MethodError: no method matching getindex(::Tuple{Float64,Float64}, ::String, ::UnitRange{Int64})
Closest candidates are:
getindex(::Tuple, ::Int64) at tuple.jl:24
getindex(::Tuple, ::Real) at tuple.jl:25
getindex(::Tuple, ::UnitRange) at range.jl:293

Do you perhaps know what the getindex error means? While the packages install.

But anyway, what is your intention with [1:10]? Do you intend to create a vector of length 1, containing a single element, which is the range 1:10?

But looking further at you code now, this function:

g = d -> @objective m Max begin
    sum((price[s]*d[s,n]) for n in N for s in S)
end

Since you broadcast g over the elements of x_train, the value of d is a tuple of two numbers, lets take the first element of x_train which equals (7.1875, 83.125). Then you try to index into it like this: d[s,n], but that won’t work, that’s how you index into a two-dimensional array, a tuple only takes a single index.

This fits with the error message:

julia> t = (7.1875, 83.125);

julia> t["s1", 1:10]
ERROR: MethodError: no method matching getindex(::Tuple{Float64, Float64}, ::String, ::UnitRange{Int64})
Closest candidates are:
  getindex(::Tuple, ::Int64) at tuple.jl:29
  getindex(::Tuple, ::Real) at tuple.jl:30
  getindex(::Tuple, ::Colon) at tuple.jl:33
1 Like

My intention with 1:10 is an array of 10 values 1, 2, 3,4… 10.

In the case of g, d is supposed d[s1,1] … d[s1,10] likewise for s2,s3,s4 etc. I assume that is why the getindex error is also saying.

Then you must write 1:10, not [1:10].

Then x_train has completely the wrong structure.

Maybe more broadly, could you describe what your code is trying to do?

I find it hard to guess what’s supposed to be happening here, and I have a feeling that this might be due to you maybe being a beginner with the language and struggling to express basic things in an idiomatic way?