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]: Using custom dimensions using DynamicQuantities #335

Open
HenryDane opened this issue Jul 22, 2024 · 2 comments
Open

[Feature]: Using custom dimensions using DynamicQuantities #335

HenryDane opened this issue Jul 22, 2024 · 2 comments

Comments

@HenryDane
Copy link

Feature Request

(Originally a discussion post on the PySR github repository).

I think that it would be useful to be able to use custom AbstractDimensions with this library.

An example of this usecase could be:

# create our dimensions
struct ExtendedDimensions{R} <: AbstractDimensions{R}
    length::R
    mass::R
    time::R
    current::R
    temperature::R
    luminosity::R
    amount::R
    angle::R
    mass_h2o::R
    mass_air::R
    count::R
end

# ... 

const mmr   = Quantity(1.0, ExtendedDimensions(mass_h2o=1, mass_air=-1))
const nconc = Quantity(1.0, ExtendedDimensions(count=1, mass_air=-1))
const dens  = Quantity(1.0, ExtendedDimensions(mass_air=1, length=-3))

X = (; A=data.A * mmr, B=data.B * nconc)
y = data.C * mmr

# create model
model = SRRegressor(
	binary_operators=[*,^,/],
	dimensional_constraint_penalty=10^5,
	nested_constraints=[(^) => [(^) => 0]],
	constraints=[(^) => (-1,1)]
)

Please let me know if there is anything I can do to help with this feature.

@MilesCranmer
Copy link
Owner

Just copying my comment for anybody else reading this:

as a quick hack, you could treat the other existing units as the units you are interested in. So, e.g., luminosity (cd) could be mass_h20.

But would be nice to allow actual custom dimensions.

@MilesCranmer
Copy link
Owner

Here's a reduced test that fails:

using SymbolicRegression.InterfaceDynamicQuantitiesModule: get_units, get_si_units
using DynamicQuantities

struct AngleDimensions{R} <: AbstractDimensions{R}
    length::R
    mass::R
    time::R
    current::R
    temperature::R
    luminosity::R
    amount::R
    rad::R
end

const rad = Quantity(1.0, AngleDimensions(; rad=1))

get_si_units(Float64, [dimension(y)])

Basically this code:

"""
get_units(T, D, x, f)
Gets unit information from a vector or scalar. The first two
types are the default numeric type and dimensions type, respectively.
The third argument is the value to get units from, and the fourth
argument is a function for parsing strings (in case a string is passed)
"""
function get_units(args...)
return error(
"Unit information must be passed as one of `AbstractDimensions`, `AbstractQuantity`, `AbstractString`, `Function`.",
)
end
function get_units(_, _, ::Nothing, ::Function)
return nothing
end
function get_units(::Type{T}, ::Type{D}, x::AbstractString, f::Function) where {T,D}
isempty(x) && return one(Quantity{T,D})
return convert(Quantity{T,D}, f(x))
end
function get_units(::Type{T}, ::Type{D}, x::Quantity, ::Function) where {T,D}
return convert(Quantity{T,D}, x)
end
function get_units(::Type{T}, ::Type{D}, x::AbstractDimensions, ::Function) where {T,D}
return convert(Quantity{T,D}, Quantity(one(T), x))
end
function get_units(::Type{T}, ::Type{D}, x::Real, ::Function) where {T,D}
return Quantity(convert(T, x), D)::Quantity{T,D}
end
function get_units(::Type{T}, ::Type{D}, x::AbstractVector, f::Function) where {T,D}
return Quantity{T,D}[get_units(T, D, xi, f) for xi in x]
end
# TODO: Allow for AbstractQuantity output here
"""
get_si_units(::Type{T}, units)
Gets the units with Dimensions{DEFAULT_DIM_BASE_TYPE} type from a vector or scalar.
"""
function get_si_units(::Type{T}, units) where {T}
return get_units(T, Dimensions{DEFAULT_DIM_BASE_TYPE}, units, uparse)
end
assumes Dimensions is the only AbstractDimensions for units.

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

No branches or pull requests

2 participants