Skip to content

Variable creation for Data types #11

@JulStraus

Description

@JulStraus

So far, we did not have a functionality for adding variables for Data types except through dispatching on the model type. That may lead to issues with respect to method ambiguities. Hence, a new method is sought after.

Introducing variables for Data types should follow the following three standards:

  1. they should be only introduced for the required nodes that require them,
  2. they should be indexed over the node and not the data, and
  3. they should not require changes to the core code.

Point 2 is the reason we cannot use the same approach as applied for Node types as we would in this case index over the data, and not the node.

A potential solution for this problem, still utilizing the core structure developed for Node types, is outlined below. It requires the introduction of a function variables_data(m, 𝒩, 𝒯, 𝒫, modeltype) to the function create_model given by:

function variables_data(m, 𝒩::Vector{<:Node}, 𝒯, 𝒫, modeltype::EnergyModel)

    # Extract all Data types within all Nodes
    𝒟 = reduce(vcat, [node_data(n) for n  𝒩])
    if isempty(𝒟) return end
    # Vector of the unique data types in 𝒟.
    data_composite_types = unique(typeof.(𝒟))
    # Get all `Data`-types in the type-hierarchy that the nodes 𝒟 represents.
    data_types = collect_types(data_composite_types)
    # Sort the `Data`-types such that a supertype will always come before its subtypes.
    data_types = sort_types(data_types)

    for data_type  data_types
        # All nodes of the given sub type.
        𝒟ˢᵘᵇ = filter(data -> isa(data, data_type), 𝒟)
        # Convert to a Vector of common-type instad of Any.
        𝒟ˢᵘᵇ = convert(Vector{data_type}, 𝒟ˢᵘᵇ)
        try
            variables_data(m, 𝒟ˢᵘᵇ, 𝒩, 𝒯, 𝒫, modeltype)
        catch e
            # Parts of the exception message we are looking for.
            pre1 = "An object of name"
            pre2 = "is already attached to this model."
            if isa(e, ErrorException)
                if occursin(pre1, e.msg) && occursin(pre2, e.msg)
                    # 𝒟ˢᵘᵇ was already registered by a call to a supertype, so just continue.
                    continue
                end
            end
            # If we make it to this point, this means some other error occured. This should
            # not be ignored.
            throw(e)
        end
    end

    # Add the variables for the required nodes.
    for n  𝒩, data  node_data(n)
        variables_data(m, data, n, 𝒯, 𝒫, modeltype)
    end
end

In addition, we have to create two additional functions:

function variables_data(m, 𝒟ˢᵘᵇ::Vector{<:Data}, 𝒩::Vector{<:Node}, 𝒯, 𝒫, modeltype::EnergyModel)
end

function variables_data(m, data::Data, n::Node, 𝒯, 𝒫, modeltype::EnergyModel)
end

The first function is used to create empty variable containers through the application of SparseVariables, while the second would only inserts the variables for the nodes that have the corresponding data.

Another required change is to define the following function.

node_data(n::Availability) = Data[]

This function may be in general dangerous as it requires that if one wants to define a new composite subtype of Availability, one has to define as well the function for this type. However, the throught process is that Availability nodes should not include the data field.

The code runs with these functions added, but I have not tested it for additional variable creation. The function for looping through the types is however working. I have not added SparseVariables either, as it is not yet registered.

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions