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

[FEATURE] Query expression and parameter function names. #367

Closed
DarioSlaifsteinSk opened this issue Nov 5, 2024 · 4 comments
Closed

[FEATURE] Query expression and parameter function names. #367

DarioSlaifsteinSk opened this issue Nov 5, 2024 · 4 comments
Labels
enhancement New feature or request

Comments

@DarioSlaifsteinSk
Copy link

DarioSlaifsteinSk commented Nov 5, 2024

The feature I'd like
Just as we query variables with:

    x = all_variables(model)
    name = name.(x)
    value = value.(x)

It would be nice to have something similar for parameter functions:

    fns = all_expressions/parameters(model)
    name = name.(fns)
    value = value.(fns)

What I currently do about this
Otherwise you have to know the name beforehand and hardcode it.
In particular, when summarizing results in a Dict or DataFrame

@DarioSlaifsteinSk DarioSlaifsteinSk added the enhancement New feature or request label Nov 5, 2024
@pulsipher
Copy link
Collaborator

Thanks for the recommendation. Can you provide a more precise use case for this? One thing you can always do is leverage the object dictionary:

for (sym, obj) in object_dictionary(model)
    println(name.(obj)) 
    println(value.(obj))
end

This will provide any named objects added to model.

@DarioSlaifsteinSk
Copy link
Author

yes, partially. Because when you

typeof(obj)

the type of an InfVar x(t) is GeneralVariableRef and of a parameter function fn is also a GeneralVariableRef.
Personally I like to store exogenous information (param_functions), actions and states in different dictionaries for analysis.
When making such dictionaries I store all the vars on one side and the parameter functions on another one, and to develop an automation has deemed harder than just coding:

merge!(xdict, Dict("function1"=>value.(model[:function1]),
                        "function2"=>value.(model[:function2]),
                        ...
                        "functionN"=>value.(model[:functionN]),

@pulsipher
Copy link
Collaborator

pulsipher commented Nov 5, 2024

To distinguish the underlying type, you can use dispatch_variable_ref:

# Dispatch based on object type to fill out the data dictionary
function add_to_dict(data, sym, obj::GeneralVariableRef)
    return add_to_dict(data, sym, dispatch_variable_ref(obj))
end
function add_to_dict(
    data,
    obj::Union{
        InfiniteVariableRef, 
        SemiInfiniteVariableRef, 
        PointVariableRef, 
        FiniteVariableRef
        }
    )
    data["variables"][name(obj)] = value(obj)
end
function add_to_dict(data, sym, obj::ParameterFunctionRef)
    data["parameter functions"][name(obj)] = value(obj)
end
function add_to_dict(data, sym, obj::AbstractJuMPScalar)
    data["expressions"][string(sym)] = value(obj) # expressions don't have names
end
function add_to_dict(data, sym, obj::InfOptConstraintRef)
    data["constraints"][name(obj)] = value(obj)
end
function add_to_dict(data, sym, obj::AbstractArray)
    for i in eachindex(obj)
        index_name = string(sym, "[", join(i, ", "), "]")
        add_to_dict(data, index_name, obj[i])
    end
end
function add_to_dict(data, sym, obj)
    return # fallback
end

# Initialize the dictionary and populate using `add_to_dict`
data = Dict(
    "variables" => Dict(),
    "parameter functions" => Dict(),
    "expressions" => Dict(),
    "constraints" => Dict()
)
for (sym, obj) in object_dictionary(model)
    add_to_dict(data, sym, obj)
end

For more information on the dispatch variable reference types, see https://infiniteopt.github.io/InfiniteOpt.jl/stable/guide/expression/#Variable-Hierarchy.

I think the above captures what your are looking for and shows that InfiniteOpt has the necessary API. We don't have any built-in methods for this since most people process/store the optimal results quite differently. Also an "all_expressions" would be tricky since expressions are not stored in the model like other objects (just like JuMP), nor do they have names. They are only stored in the object dictionary if a name is given.

@DarioSlaifsteinSk
Copy link
Author

oh! I forgot to click on "comment"
this is much nicer than what i was doing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants