# Variable and Equation Types

Symbolics IR mirrors the Julia AST but allows for easy mathematical manipulation by itself following mathematical semantics. The base of the IR is the `Sym`

type, which defines a symbolic variable. Registered (mathematical) functions on `Sym`

s (or `istree`

objects) return an expression that `istree`

. For example, `op1 = x+y`

is one symbolic object and `op2 = 2z`

is another, and so `op1*op2`

is another tree object. Then, at the top, an `Equation`

, normally written as `op1 ~ op2`

, defines the symbolic equality between two operations.

## Types

`Sym`

, `Term`

, and `FnType`

are from SymbolicUtils.jl. Note that in Symbolics, we always use `Sym{Real}`

, `Term{Real}`

, and `FnType{Tuple{Any}, Real}`

. To get the arguments of a `istree`

object use `arguments(t::Term)`

, and to get the operation, use `operation(t::Term)`

. However, note that one should never dispatch on `Term`

or test `isa Term`

. Instead, one needs to use `SymbolicUtils.istree`

to check if `arguments`

and `operation`

is defined.

`Symbolics.@variables`

— MacroDefine one or more unknown variables.

```
@variables t α σ(..) β[1:2]
@variables w(..) x(t) y z(t, α, x)
expr = β[1]* x + y^α + σ(3) * (z - t) - β[2] * w(t - 1)
```

`(..)`

signifies that the value should be left uncalled.

Symbolics supports creating variables that denote an array of some size.

```
julia> @variables x[1:3]
1-element Vector{Symbolics.Arr{Num, 1}}:
x[1:3]
julia> @variables y[1:3, 1:6] # support for tensors
1-element Vector{Symbolics.Arr{Num, 2}}:
y[1:3,1:6]
julia> @variables t z[1:3](t) # also works for dependent variables
2-element Vector{Any}:
t
(map(#5, z))[1:3]
```

A symbol or expression that represents an array can be turned into an array of symbols or expressions using the `scalarize`

function.

```
julia> Symbolics.scalarize(z)
3-element Vector{Num}:
z[1](t)
z[2](t)
z[3](t)
```

Note that `@variables`

returns a vector of all the defined variables.

`@variables`

can also take runtime symbol values by the `$`

interpolation operator, and in this case, `@variables`

doesn't automatically assign the value, instead, it only returns a vector of symbolic variables. All the rest of the syntax also applies here.

```
julia> a, b, c = :runtime_symbol_value, :value_b, :value_c
:runtime_symbol_value
julia> vars = @variables t $a $b(t) $c[1:3](t)
4-element Vector{Any}:
t
runtime_symbol_value
value_b(t)
(map(#9, value_c))[1:3]
julia> (t, a, b, c)
(t, :runtime_symbol_value, :value_b, :value_c)
```

`Symbolics.Equation`

— Type`struct Equation`

An equality relationship between two expressions.

**Fields**

`lhs`

The expression on the left-hand side of the equation.

`rhs`

The expression on the right-hand side of the equation.

`Base.:~`

— Method```
~(lhs, rhs) -> Any
```

Create an `Equation`

out of two `Num`

instances, or an `Num`

and a `Number`

.

**Examples**

```
julia> using Symbolics
julia> @variables x y;
julia> @variables A[1:3, 1:3] B[1:3, 1:3];
julia> x ~ y
x ~ y
julia> x - y ~ 0
x - y ~ 0
julia> A ~ B
(broadcast(~, A, B))[1:3,1:3]
julia> A .~ 3x
(broadcast(~, A, 3x))[1:3,1:3]
```

## A note about functions restricted to `Number`

s

`Sym`

and `Term`

objects are NOT subtypes of `Number`

. Symbolics provides a simple wrapper type called `Num`

which is a subtype of `Real`

. `Num`

wraps either a Sym or a Term or any other object, defines the same set of operations as symbolic expressions and forwards those to the values it wraps. You can use `Symbolics.value`

function to unwrap a `Num`

.

By default, the `@variables`

macros return Num-wrapped objects so as to allow calling functions which are restricted to `Number`

or `Real`

.

```
julia> @variables t x y z(t);
julia> Symbolics.operation(Symbolics.value(x + y))
+ (generic function with 377 methods)
julia> Symbolics.operation(Symbolics.value(z))
z(::Any)::Real
julia> Symbolics.arguments(Symbolics.value(x + y))
2-element Vector{Sym{Real}}:
x
y
```

## Symbolic Control Flow

Control flow can be expressed in Symbolics.jl in the following ways:

`IfElse.ifelse(cond,x,y)`

: this is a dispatch-able version of the`ifelse`

function provided by`IfElse.jl`

which allows for encoding conditionals in the symbolic branches.

## Inspection Functions

Missing docstring for `SymbolicUtils.istree`

. Check Documenter's build log for details.

Missing docstring for `SymbolicUtils.operation`

. Check Documenter's build log for details.

Missing docstring for `SymbolicUtils.arguments`

. Check Documenter's build log for details.