master-thesis/package/src/ExpressionProcessing.jl
Daniel c871487a55
Some checks failed
CI / Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} (x64, ubuntu-latest, 1.10) (push) Has been cancelled
CI / Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} (x64, ubuntu-latest, 1.6) (push) Has been cancelled
CI / Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} (x64, ubuntu-latest, pre) (push) Has been cancelled
layed groundwork for implementing interpretation
2024-07-21 13:45:57 +02:00

147 lines
4.4 KiB
Julia

module ExpressionProcessing
export expr_to_postfix
export PostfixType
export Operator, ADD, SUBTRACT, MULTIPLY, DIVIDE, POWER, ABS, LOG, EXP, SQRT
export ElementType, EMPTY, FLOAT64, OPERATOR, INT64
export ExpressionElement
@enum Operator::Int64 ADD=1 SUBTRACT=2 MULTIPLY=3 DIVIDE=4 POWER=5 ABS=6 LOG=7 EXP=8 SQRT=9
@enum ElementType EMPTY=0 FLOAT64=1 OPERATOR=2 INT64=3
struct ExpressionElement
Type::ElementType
Value::Int64 # Reinterpret the stored value to type "ElementType" when using it
end
const PostfixType = Vector{ExpressionElement}
"Converts a julia expression to its postfix notation"
function expr_to_postfix(expr::Expr)::PostfixType
postfix = PostfixType()
operator = get_operator(expr.args[1])
# push!(postfix, expr.args[2], expr.args[3], operator)
for j in 2:length(expr.args)
arg = expr.args[j]
if typeof(arg) === Expr
# exprElement = convert_to_ExpressionElement()
append!(postfix, expr_to_postfix(arg))
elseif typeof(arg) === Symbol # variables/parameters
exprElement = convert_to_ExpressionElement(convert_var_to_int(arg))
push!(postfix, exprElement)
else
exprElement = convert_to_ExpressionElement(convert(Float64, arg))
push!(postfix, exprElement)
end
if length(postfix) >= 2
exprElement = convert_to_ExpressionElement(operator)
push!(postfix, exprElement)
end
end
return postfix
end
function get_operator(op::Symbol)::Operator
if op == :+
return ADD
elseif op == :-
return SUBTRACT
elseif op == :*
return MULTIPLY
elseif op == :/
return DIVIDE
elseif op == :^
return POWER
elseif op == :abs
return ABS
elseif op == :log
return LOG
elseif op == :exp
return EXP
elseif op == :sqrt
return SQRT
end
end
"Extracts the number from a variable/parameter and returns it. If the symbol is a parameter ```pn```, the resulting value will be negativ.
```x0 and p0``` are not allowed."
function convert_var_to_int(var::Symbol)::Int
varStr = String(var)
number = parse(Int32, SubString(varStr, 2))
if varStr[1] == 'p'
number = -number
end
return number
end
function convert_to_ExpressionElement(element)::ExpressionElement
Value = reinterpret(Int64, element)
if element isa Float64
return ExpressionElement(FLOAT64, Value)
elseif element isa Int64
return ExpressionElement(INT64, Value)
elseif element isa Operator
return ExpressionElement(OPERATOR, Value)
else
error("Element was of type '$(typeof(element))', which is not supported.")
end
end
#
# Everything below is currently not needed. Left here for potential future use
#
const SymbolTable64 = Dict{Tuple{Expr, Symbol},Float64}
"Replaces all the variables and parameters of the given expression with their corresponding Value stored in the symtable
# Arguments
- `symtable::SymbolTable64`: Contains the values of all variables for each expression
- `originalExpr::Expr`: Contains a deep copy of the original expression. It is used to link the expression and variables to their according Value stored in the symtable
"
function replace_variables!(ex::Expr, symtable::SymbolTable64, originalExpr::Expr)
for i in 1:length(ex.args)
arg = ex.args[i]
if typeof(arg) === Expr
replace_variables!(arg, symtable, originalExpr)
elseif haskey(symtable, (originalExpr,arg)) # We found a variable/parameter and can replace it with the actual Value
ex.args[i] = symtable[(originalExpr,arg)]
end
end
end
# TODO: Completly rewrite this function because I misunderstood it. Not every column is linked to an expression. therefore all other functions need to be reworked as well. Probably can't replace the variables in julia anymore, look into this. (see ExpressionExecutorCuda.jl for more info)
# Before rewriting, proceed with just creating a postfix notation and sending the variable matrix as well as the parameter "matrix" to the GPU to perform first calculations
function construct_symtable(expressions::Vector{Expr}, mat::Matrix{Float64}, params::Vector{Vector{Float64}})::SymbolTable64
symtable = SymbolTable64()
for i in eachindex(expressions)
expr = expressions[i]
values = mat[i,:]
parameters = params[i]
fill_symtable!(expr, symtable, values, "x")
fill_symtable!(expr, symtable, parameters, "p")
end
return symtable
end
function fill_symtable!(expr::Expr, symtable::SymbolTable64, values::Vector{Float64}, symbolPrefix::String)
varIndex = 1
for j in eachindex(values)
val = values[j]
sym = Symbol(symbolPrefix, varIndex)
symtable[expr,sym] = val
varIndex += 1
end
end
end