MultiDimEquations.jl

Documentation for the MultiDimEquations.jl package

The MultiDimEquations Module

MultiDimEquationsModule
MultiDimEquations

The package provides handy functions to work with NDSparse (from IndexedTables.jl package) or standard arrays in order to write equations in a concise and readable way. The formers can be accessed by name, but are somehow slower, the latters are faster but need to be accessed by position.

defVars() defines either empty NDSparse with the dimensions (axis) required or arrays with the required size and prefilled with missing values. More variables can be defined at once.

defLoadVar() and defLoadVars() allow to define and import the variables from a DataFrame in long format (dim1|dim2|...|value), with the second one allowing to import more varaibles at once, given the presence of a column in the database with the variable names.

@meq is a macro that allows to write your "model equations" more concisely, e.g. @meq par1[d1 in DIM1, d2 in DIM2, dfix3] = par2[d1,d2]+par3[d1,d2] would be expanded to use the list comprehension expression above: [par1[d1,d2,dfix3] = par2[d1,d2]+par3[d1,d2] for d1 in DIM1, d2 in DIM2]

source

Module Index

Example

Input data...

df = CSV.read(IOBuffer("""
reg prod var value
us banana production 10
us banana transfCoef    0.6
us banana trValues      2
us apples production    7
us apples transfCoef    0.7
us apples trValues      5
us juice production     missing
us juice transfCoef     missing
us juice trValues       missing
eu banana production    5
eu banana transfCoef    0.7
eu banana trValues      1
eu apples production    8
eu apples transfCoef    0.8
eu apples trValues 4
eu juice production missing
eu juice transfCoef missing
eu juice trValues missing
"""), DataFrame, delim=" ", ignorerepeated=true, copycols=true, missingstring="missing")

...using NDSparse:

reg      = unique(df.reg)
products = unique(df.prod)
primPr   = products[1:2]
secPr    = [products[3]]

(production,transfCoef,trValues) = defLoadVars(["production","transfCoef","trValues"], df,["reg","prod"], varNameCol="var", valueCol="value",sparse=true)
consumption                      = defVars(["reg","prod"],[String,String])

# equivalent to [production[r, sp] = sum(trValues[r,pp] * transfCoef[r,pp]  for pp in primPr) for r in reg, sp in secPr]
@meq production[r in reg, sp in secPr]   = sum(trValues[r,pp] * transfCoef[r,pp]  for pp in primPr)
@meq consumption[r in reg, pp in primPr] = production[r,pp] - trValues[r,pp]
@meq consumption[r in reg, sp in secPr]  = production[r, sp]

...using normal arrays:

reg      = unique(df.reg)
products = unique(df.prod)
primPrIdx = [1,2]
secPrIdx  = [3]

(production,transfCoef,trValues) = defLoadVars(["production","transfCoef","trValues"], df,["reg","prod"], varNameCol="var", valueCol="value",sparse=false)
consumption                      = defVars([length(reg),length(products))

@meq production[r in eachindex(reg), sp in secPrIdx]   =  sum(trValues[r,pp] * transfCoef[r,pp]  for pp in primPrIdx)
@meq consumption[r in eachindex(reg), pp in primPrIdx] = production[r,pp] - trValues[r,pp]
@meq consumption[r in eachindex(reg), sp in secPrIdx]  = production[r, sp]

Detailed API

MultiDimEquations.defLoadVarMethod
defLoadVar(df, dimsNameCols; <keyword arguments>)

Define the required IndexedTables or Arrays and load the data from a DataFrame in long format while specifing the dimensional columns.

Arguments

  • df: The source of the dataframe, that must be in the format dim1|dim2|...|value
  • dimsNameCols: The names of the columns corresponding to the dimensions over which the variables are defined (the keys)
  • valueCol (def: "value"): The name of the column in the df containing the values
  • sparse (def: "true"): Wheter to return NDSparse elements (from IndexedTable) or standard arrays
  • missingValue (def=missing): How to fill the matrix with (relevant only for arrays)

Notes

  • Sparse indexed tables can be accessed by element but are slower, standard arrays need to be accessed by position but are faster

Examples

julia> vol  = defVars(volumeData,["region","treeSpecie","year"], valueCol="value")
source
MultiDimEquations.defLoadVarsMethod
defLoadVars(vars, df, dimsNameCols; <keyword arguments>)

Define the required IndexedTables or Arrays and load the data from a DataFrame in long format while specifing the dimensional columns and the column containing the variable names.

Like varLoadVar but here we are extracting multiple variables at once, with one column of the input dataframe storing the variable name.

Arguments

  • vars: The array of variables to lookup
  • df: The source of the dataframe, that must be in the format dim1|dim2|...|varName|value
  • dimsNameCols: The name of the column containing the dimensions over which the variables are defined
  • varNameCol (def: "varName"): The name of the column in the df containing the variables names
  • valueCol (def: "value"): The name of the column in the df containing the values
  • sparse (def: "true"): Wheter to return NDSparse elements (from IndexedTable) or standard arrays
  • missingValue (def=missing): How to fill the matrix with (relevant only for arrays)
  • fullKeys (def=true): Wheter all the outputed variables should be based on the full set of keys, or look for each of them on the keys found specifically for it in the filtered input dataframe

Notes

  • Sparse indexed tables can be accessed by element but are slower, standard arrays need to be accessed by position but are faster
  • At the moment sameKeys=true is implemented only for the non-sparse case

Examples

julia> (vol,numberOfTrees)  = defVars(["vol","numberOfTrees"], forestData,["region","treeSpecie","year"], varNameCol="parName", valueCol="value")
source
MultiDimEquations.defVarsMethod
defVars(dimNames, dimTypes; <keyword arguments>)

Define empty NDSparse IndexedTable(s) with the specific dimension(s) and type.

Arguments

  • dimNames: Array of names of the dimensions to define
  • dimTypes: Array of types of the dimensions
  • valueType (def: Float64): Type of the value column of the table
  • n (def=1): Number of copies of the specified tables to return (useful to define multiple variables at once. In such cases a tuple is returned)

# Examples

```julia

julia> price,demand,supply = defVars(["region","item","class"],[String,String,Int64],valueType=Float64,n=3 )

julia> waterContent = defVars(["region","item"],[String,String])

julia> price["US","apple",1] = 3.2

julia> waterContent["US","apple"] = 0.2

```

source
MultiDimEquations.defVarsMethod
defVars(size; <keyword arguments>)

Define multidimensional array(s) with the specific dimension(s) and type filled all with missing values.

Arguments

  • size: Tuple of the dimensions required
  • valueType (def: Float64): Inner type of the array required
  • n (def=1): Number of copies of the specified tables to return (useful to define multiple variables at once. In such cases a tuple is returned)
  • missingValue (def=missing): How to fill the matrix with

# Examples

```julia

julia> price,demand,supply = defVars((3,4,5),valueType=Float64,n=3 )

julia> waterContent = defVars((3,4))

julia> price[2,3,1] = 3.2

julia> waterContent[2,3] = 0.2

```

source
MultiDimEquations.getSafeFunction
getSafe(idxtable,indices,missingValue=missing)

Return the value stored in a NDSParse table or missingValue if the specified keys are not present.

Arguments

  • idxtable: The NDSParse table to lookup
  • indices: A tuple with the indices to use (: is supported)
  • missingValue: The value to return if the specified keys are not found

Examples

julia> volBlackForest2014  = getSafe(forestVolumes,("BlackForest",2014),0.0)
source
MultiDimEquations.toDataFrameMethod
toDataFrame(idxtable::NDSparse)

Convert a single-value-column NDSParse table to DataFrame.

Arguments

  • idxtable: The NDSParse table to convert

Examples

julia> content = [["banana","banana","apple","apple","orange"],["us",missing,"us","eu","us"],[1.1,2.2,3.3,missing,5.5]]
julia> dimNames = ["item","region"]
julia> t = NDSparse(content...,names=Symbol.(dimNames))
julia> df = toDataFrame(t)
source
MultiDimEquations.@meqMacro
meq(exp)

Macro to expand functions like t[d1 in dim1, d2 in dim2, dfix,..] = value

With this macro it is possible to write:

@meq par1[d1 in DIM1, d2 in DIM2, dfix3] =  par2[d1,d2]+par3[d1,d2]

and obtain

[par1[d1,d2,dfix3] =  par2[d1,d2]+par3[d1,d2] for d1 in DIM1, d2 in DIM2]

That is, it is possible to write "model equations" in a concise and readable way.

source