JuMP set start values in new model with solution of smaller model

In the JuMP docs it shows how to efficiently set start values using one model:

x = all_variables(model)
x_solution = value.(x)
set_start_value.(x, x_solution)

However, I am looking for an efficient way to do this with two models, where the first model (with a solution) includes a subset of the variables in a second model.

Here is my very slow attempt:

# ... build model1
optimize!(model1)

x1 = all_variables(model1);
x1_solution = value.(x1);

d = Dict(string(n)=>v for (n,v) in zip(x1, x1_solution))

model2 = JuMP.Model()
# ... create second model that has more variables than model1
# and also shares variable names with model1

x2 = all_variables(model2);

for (n1,v) in d # this loop is very slow, like one variable/second 
    x2_index = findfirst(n2 -> string(n2) == n1, x2)
    if !(isnothing(x2_index))
        set_start_value(x2[x2_index], v)
        @info("Set start value for $(x2[x2_index])")
    end
end

I also question if I am doing this correctly?

The problem is this loop:

for (n1,v) in d # this loop is very slow, like one variable/second 
    x2_index = findfirst(n2 -> string(n2) == n1, x2)
    if !(isnothing(x2_index))
        set_start_value(x2[x2_index], v)
        @info("Set start value for $(x2[x2_index])")
    end
end

Remove the if block and just look at what it is doing:

for (n1, v) in d
    x2_index = findfirst(n2 -> string(n2) == n1, x2)
end

The outer loop is O(N) because it loops over every variable in model1.

So for every variable in model1, you have a (short-circuited) loop over (potentially) every variable in x2. And for every variable in the inner loop, you are converting it to a string. So you’re calling string(n2) O(N^2) times.

I haven’t tested (be wary of typos, etc), but I assume something like this would be faster

d1 = Dict{String,Float64}(
    JuMP.name(x) => value for
    (x, value) in zip(x1, x1_solution) if !isempty(JuMP.name(x))    
)
d2 = Dict{String,VariableRef}(
    JuMP.name(x) => x for x in x2 if !isempty(JuMP.name(x))
)
for (name_1, start) in d
    x_2 = get(d2, name_1, nothing)
    if x2_i !== nothing
        set_start_value(x2_i, start)
    end
end

or even

model1 = JuMP.Model()
model2 = JuMP.Model()
x1 = all_variables(model1)
x1_solution = value.(x1)
for (x, start) in zip(x1, x1_solution)
    name = JuMP.name(x)
    if isempty(name)
        continue
    end
    x2 = variable_by_name(model2, name)
    if x2 !== nothing
        set_start_value(x2, start)
    end
end