From 3f359e807e90afe6b8c23b0a2b05c131ac7ef89a Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Thu, 14 Sep 2023 15:05:52 +0000 Subject: [PATCH] build based on bf2ef05 --- dev/howto/integration/index.html | 16 ++++++++-------- dev/howto/spaces/index.html | 6 +++--- dev/reference/api/index.html | 16 ++++++++-------- dev/tutorial/getting_started/index.html | 12 ++++++------ dev/tutorial/integration/index.html | 2 +- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/dev/howto/integration/index.html b/dev/howto/integration/index.html index fd91eb0..d346865 100644 --- a/dev/howto/integration/index.html +++ b/dev/howto/integration/index.html @@ -4,7 +4,7 @@ x = rand(3) y = rand(3) -@ga 3 x::1 ∧ y::1
Bivector{Float64, 3, 3}(-0.47884135271247763, 0.11308424022653685, 0.5086515000074394)

If your type does not support indexing, and you don't want it to, overload SymbolicGA.getcomponent(::T, [i::Int, [j::Int]]):

struct MyInputType{T}
+@ga 3 x::1 ∧ y::1
Bivector{Float64, 3, 3}(0.10778455679122875, 0.18738998916198488, -0.03656452480750527)

If your type does not support indexing, and you don't want it to, overload SymbolicGA.getcomponent(::T, [i::Int, [j::Int]]):

struct MyInputType{T}
   values::Vector{T}
 end
 
@@ -13,7 +13,7 @@
 x = MyInputType(rand(3))
 y = MyInputType(rand(3))
 
-@ga 3 x::1 ∧ y::1
Bivector{Float64, 3, 3}(-0.34870365720634405, -0.6753283846608116, -0.6230627490277898)

For scalars and aggregates of objects with multiple grades, you will need to overload SymbolicGA.getcomponent(::T) and SymbolicGA.getcomponent(::T, j::Int, i::Int) respectively (see SymbolicGA.getcomponent).

Outputs

If you want to reconstruct a custom type from components, either define a constructor for a single tuple argument, e.g. T(components::Tuple)

struct MyOutputType{T}
+@ga 3 x::1 ∧ y::1
Bivector{Float64, 3, 3}(0.01969239421492358, 0.21620162459584755, 0.2374958645157515)

For scalars and aggregates of objects with multiple grades, you will need to overload SymbolicGA.getcomponent(::T) and SymbolicGA.getcomponent(::T, j::Int, i::Int) respectively (see SymbolicGA.getcomponent).

Outputs

If you want to reconstruct a custom type from components, either define a constructor for a single tuple argument, e.g. T(components::Tuple)

struct MyOutputType{T}
   values::Vector{T}
 end
 
@@ -22,7 +22,7 @@
 x = rand(3)
 y = rand(3)
 
-@ga 3 MyOutputType dual(x::1 ∧ y::1)
Main.MyOutputType{Float64}([-0.6949998090032456, -0.09606737569842556, 0.5348336220925151])

If you don't want such constructor to be defined, you can overload SymbolicGA.construct(::Type{T}, ::Tuple) directly:

struct MyOutputType2{T}
+@ga 3 MyOutputType dual(x::1 ∧ y::1)
Main.MyOutputType{Float64}([-0.18785877149582178, 0.48964283879197723, -0.28616214819530417])

If you don't want such constructor to be defined, you can overload SymbolicGA.construct(::Type{T}, ::Tuple) directly:

struct MyOutputType2{T}
   values::Vector{T}
 end
 
@@ -31,8 +31,8 @@
 x = rand(3)
 y = rand(3)
 
-@ga 3 MyOutputType2 dual(x::1 ∧ y::1)
Main.MyOutputType2{Float64}([-0.45232039924532147, 0.3282350144165946, -0.023204208293013395])

Integrations for Vector, Tuple and <:Real have already been defined:

@ga 3 Tuple dual(x::1 ∧ y::1)
(-0.45232039924532147, 0.3282350144165946, -0.023204208293013395)
@ga 3 Vector dual(x::1 ∧ y::1)
3-element Vector{Float64}:
- -0.45232039924532147
-  0.3282350144165946
- -0.023204208293013395
z = rand(3)
-@ga 3 Float16 dual(x::1 ∧ y::1 ∧ z::1)
Float16(-0.241)

This page was generated using Literate.jl.

+@ga 3 MyOutputType2 dual(x::1 ∧ y::1)
Main.MyOutputType2{Float64}([-0.2468545562328771, 0.3371653829727226, -0.044990327030699634])

Integrations for Vector, Tuple and <:Real have already been defined:

@ga 3 Tuple dual(x::1 ∧ y::1)
(-0.2468545562328771, 0.3371653829727226, -0.044990327030699634)
@ga 3 Vector dual(x::1 ∧ y::1)
3-element Vector{Float64}:
+ -0.2468545562328771
+  0.3371653829727226
+ -0.044990327030699634
z = rand(3)
+@ga 3 Float16 dual(x::1 ∧ y::1 ∧ z::1)
Float16(0.2289)

This page was generated using Literate.jl.

diff --git a/dev/howto/spaces/index.html b/dev/howto/spaces/index.html index 58283ec..bbdafe7 100644 --- a/dev/howto/spaces/index.html +++ b/dev/howto/spaces/index.html @@ -2,7 +2,7 @@ Create user-defined geometric spaces · SymbolicGA.jl

Creating user-defined geometric spaces

Create a geometric space with default definitions

using SymbolicGA
 
 @geometric_space weird_space (3, 4, 5)
@weird_space (macro with 2 methods)
x = rand(12); y = rand(12)
-@weird_space x::1 ⟑ dual(y::1)
(KVector{10, Float64, 12, 66}(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.038885084489043674, -0.602581628007592, 0.7788107253298215, -0.7954234713840794, 0.5521735372131354, -0.02669826765349625, 0.4137289605776517, -0.5347268102793443, 0.546133022878448, -0.3791190653539101, 0.038552175706838665, 0.007038075006135942, -0.10906533317246346, 0.14096223198380475, -0.1439690854939392, 0.09994163115177072, 0.6515567388840312, -0.4543327999047377, -0.035776820635212966, 0.5544145038279804, -0.7165567979351047, 0.7318416107020409, -0.5080357638402881, 0.6016626179769315, -0.3776274509735993, 0.7083738038987472, -0.004489244064050674, 0.06956744551760657, -0.08991291832453178, 0.09183084322019897, -0.06374788191493773, 0.4021488190303708, -0.2716621763812426, 0.14800921355883204, -0.3005418654572039, 0.001531627281097842, -0.02373481947312795, 0.03067622892944599, -0.031330580987696525, 0.02174931762676832, -0.7149803450617866, 0.48938273647707403, -0.15507301712600802, 0.6341300528796778, 0.06670370404940643, -0.00020372388028039616, 0.00315700143272092, -0.0040802879832467906, 0.004167324262909237, -0.00289290706365592, 0.11255486220303229, -0.07707751898585131, 0.023785655649510955, -0.10040564717315074, -0.010887437554140964, 0.0006875008168672316), KVector{12, Float64, 12, 1}(3.816222868926817))

Create a geometric space with extra definitions.

@geometric_space extra_space 3 quote
+@weird_space x::1 ⟑ dual(y::1)
(KVector{10, Float64, 12, 66}(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2534509968465547, -0.5235067035724507, 0.42860732876131025, -0.45235102722611586, 0.41702459002187797, -0.18946904983466745, 0.39135106565787986, -0.3204083800930779, 0.3381581464923444, -0.3117496234468293, 0.16330967911614006, 0.34368639244012955, -0.7098892196426002, 0.5812031060369361, -0.6134002020045475, 0.5654965996847748, -0.24611580046813442, -0.037466759729236354, -0.3883261396037723, 0.8020932637249147, -0.6566927392458863, 0.6930717587781559, -0.638946191484443, 0.5367339231269087, -0.15102347062758334, 0.3507382024709939, -0.16871516278588145, 0.34848361147381623, -0.2853117807501307, 0.30111728951304884, -0.27760147904982696, 0.49103994879188595, -0.25836968189759524, 0.5020310939283649, -0.39506057477906126, 0.02947798211071377, -0.0608871988461355, 0.04984979079563825, -0.052611335738432324, 0.04850264373525098, -0.20399215624911055, 0.13350178393355158, -0.24799401811794758, 0.2501219342210693, 0.07868070463558607, -0.24847265293485343, 0.5132238621439651, -0.42018852310578847, 0.4434658422776963, -0.4088332952367087, 0.6969034679046022, -0.36087310686655927, 0.7037383759024286, -0.5415726640503322, 0.017485891927374514, -0.11893093598515522), KVector{12, Float64, 12, 1}(3.9238482453727643))

Create a geometric space with extra definitions.

@geometric_space extra_space 3 quote
   >>(x, y) = versor_product(y, x)
   *(x, y) = geometric_product(y, x)
   I = 1.0::e123
@@ -10,6 +10,6 @@
 @extra_space begin
   yᵈ = y::1 * I
   yᵈ >> x::1
-end
KVector{1, Float64, 3, 3}(0.4732610081301954, 0.14255470390530978, 0.5911225238020889)

Create a geometric space with non-default bindings.

bindings = Bindings(refs = Dict(:* => :geometric_product))
+end
KVector{1, Float64, 3, 3}(0.33397306534362026, 0.24694179565773647, 0.48641424781062975)

Create a geometric space with non-default bindings.

bindings = Bindings(refs = Dict(:* => :geometric_product))
 @geometric_space no_defaults 3 bindings
@no_defaults (macro with 2 methods)
x = rand(3); y = rand(3)
-@no_defaults x::1 * y::1
(KVector{0, Float64, 3, 1}(1.2139783815969416), Bivector{Float64, 3, 3}(-0.0035885451012895864, 0.12268960434627724, 0.10072953573724125))

Note that you will always have access to the built-in functions.


This page was generated using Literate.jl.

+@no_defaults x::1 * y::1
(KVector{0, Float64, 3, 1}(1.2220601106009816), Bivector{Float64, 3, 3}(-0.29131262928778645, -0.0638678418158164, 0.2501102754500404))

Note that you will always have access to the built-in functions.


This page was generated using Literate.jl.

diff --git a/dev/reference/api/index.html b/dev/reference/api/index.html index 7ddb722..e777d1f 100644 --- a/dev/reference/api/index.html +++ b/dev/reference/api/index.html @@ -1,28 +1,28 @@ API · SymbolicGA.jl

API Reference

Main symbols:

Aliases:

Usage

SymbolicGA.@gaMacro
@ga <sig> <T> <ex>
-@ga <sig> <ex>

Generate Julia code which implements the computation of geometric elements from ex in an algebra defined by a signature sig (see SymbolicGA.Signature).

Supported syntax:

  • sig: Integer literal or tuple of 1, 2 or 3 integer literals corresponding to the number of positive, negative and degenerate basis vectors respectively, where unspecified integers default to zero. May also be a string literal of the form <+++--𝟎> where the number of +, - and 𝟎 correspond to the nmuber of positive, negative and degenerate basis vectors respectively.
  • T: Any arbitrary expression which evaluates to a type or to nothing.
  • ex: Any arbitrary expression that can be parsed algebraically.

See also: codegen_expression.

ex can be a single statement or a block, and uses a domain-specific language to facilitate the construction of algebraic expressions. ex is logically divided into two sections: a definition section, which defines bindings, and a final algebraic expression, which will be the object of the evaluation. It is processed in three phases:

  • A definition phase, in which bindings are defined with one or several statements for use in the subsequent phase;
  • An expansion phase, where identified bindings in the final algebraic expression are expanded. The defined bindings include the ones priorly defined and a set of default bindings.
  • An evaluation phase, in which the core algebraic expression is simplified and translated into a Julia expression.

Expression parsing

Binding definitions

All statements prior to the last can define new variables or functions with the following syntax and semantics:

  • Variables are either declared with <lhs::Symbol> = <rhs::Any> or with <lhs::Symbol>::<type>, the latter being expanded to <lhs> = <lhs>::<type>.
  • Functions are declared with a standard short or long form function definition <name>(<args...>) = <rhs> or function <name>(<args...>) <rhs> end, and are restricted to simple forms to encode simple semantics. The restrictions are as follows:
    • where clauses and output type annotations are not supported.
    • Function arguments must be untyped, e.g. f(x, y) is allowed but not f(x::Vector, y::Vector).
    • Function arguments must not be reassigned; it is assumed that any occurence of symbols declared as arguments will reference these arguments. For example, f(x, y) = x + y assumes that x + y actually means "perform + on the first and second function argument". Therefore, f(x, y) = (x = 2; x) + y will be likely to cause bugs. To alleviate this restriction, use codegen_expression with a suitable [SymbolicGA.Bindings] with function entries that contain specific calls to `:($(@arg <i>)).

Binding expansion

References and functions are expanded in a fairly straightforward copy-paste manner, where references are replaced with their right-hand side and function calls with their bodies with their arguments interpolated. Simple checks are put in place to allow for self-referencing bindings for references, such as x = x::T, leading to a single expansion of such a pattern in the corresponding expression subtree.

See SymbolicGA.Bindings for more information regarding the expansion of such variables and functions.

Function calls will be assumed to be either referencing a binding or a built-in function. If you want to call a function, e.g. my_func(x)::Vector, you will have to interpolate the call: $(my_func(x))::Vector.

Algebraic evaluation

Type annotations may either:

  • Specify what type of geometric entity an input should be considered as, where components are then picked off with getcomponent.
  • Request the projection of an intermediate expression over one or multiple grades.
source
SymbolicGA.@pga2Macro
@pga2(T, ex)
+@ga <sig> <ex>

Generate Julia code which implements the computation of geometric elements from ex in an algebra defined by a signature sig (see SymbolicGA.Signature).

Supported syntax:

  • sig: Integer literal or tuple of 1, 2 or 3 integer literals corresponding to the number of positive, negative and degenerate basis vectors respectively, where unspecified integers default to zero. May also be a string literal of the form <+++--𝟎> where the number of +, - and 𝟎 correspond to the nmuber of positive, negative and degenerate basis vectors respectively.
  • T: Any arbitrary expression which evaluates to a type or to nothing.
  • ex: Any arbitrary expression that can be parsed algebraically.

See also: codegen_expression.

ex can be a single statement or a block, and uses a domain-specific language to facilitate the construction of algebraic expressions. ex is logically divided into two sections: a definition section, which defines bindings, and a final algebraic expression, which will be the object of the evaluation. It is processed in three phases:

  • A definition phase, in which bindings are defined with one or several statements for use in the subsequent phase;
  • An expansion phase, where identified bindings in the final algebraic expression are expanded. The defined bindings include the ones priorly defined and a set of default bindings.
  • An evaluation phase, in which the core algebraic expression is simplified and translated into a Julia expression.

Expression parsing

Binding definitions

All statements prior to the last can define new variables or functions with the following syntax and semantics:

  • Variables are either declared with <lhs::Symbol> = <rhs::Any> or with <lhs::Symbol>::<type>, the latter being expanded to <lhs> = <lhs>::<type>.
  • Functions are declared with a standard short or long form function definition <name>(<args...>) = <rhs> or function <name>(<args...>) <rhs> end, and are restricted to simple forms to encode simple semantics. The restrictions are as follows:
    • where clauses and output type annotations are not supported.
    • Function arguments must be untyped, e.g. f(x, y) is allowed but not f(x::Vector, y::Vector).
    • Function arguments must not be reassigned; it is assumed that any occurence of symbols declared as arguments will reference these arguments. For example, f(x, y) = x + y assumes that x + y actually means "perform + on the first and second function argument". Therefore, f(x, y) = (x = 2; x) + y will be likely to cause bugs. To alleviate this restriction, use codegen_expression with a suitable [SymbolicGA.Bindings] with function entries that contain specific calls to `:($(@arg <i>)).

Binding expansion

References and functions are expanded in a fairly straightforward copy-paste manner, where references are replaced with their right-hand side and function calls with their bodies with their arguments interpolated. Simple checks are put in place to allow for self-referencing bindings for references, such as x = x::T, leading to a single expansion of such a pattern in the corresponding expression subtree.

See SymbolicGA.Bindings for more information regarding the expansion of such variables and functions.

Function calls will be assumed to be either referencing a binding or a built-in function. If you want to call a function, e.g. my_func(x)::Vector, you will have to interpolate the call: $(my_func(x))::Vector.

Algebraic evaluation

Type annotations may either:

  • Specify what type of geometric entity an input should be considered as, where components are then picked off with getcomponent.
  • Request the projection of an intermediate expression over one or multiple grades.
source
SymbolicGA.@pga2Macro
@pga2(T, ex)
 @pga2(ex)

Macro generated via SymbolicGA.@geometric_space with signature (2, 0, 1) and the following definitions:

  • embed(x) = x[1]::e1 + x[2]::e2
  • magnitude2(x) = x ⦿ x
  • point(x) = embed(x) + 1.0::e3

No documentation found.

SymbolicGA.@pga2 is a macro.

# 2 methods for macro "@pga2" from SymbolicGA:
  [1] var"@pga2"(__source__::LineNumberNode, __module__::Module, ex)
      @ ~/work/SymbolicGA.jl/SymbolicGA.jl/src/spaces.jl:61
  [2] var"@pga2"(__source__::LineNumberNode, __module__::Module, T, ex)
-     @ ~/work/SymbolicGA.jl/SymbolicGA.jl/src/spaces.jl:57
source
SymbolicGA.@pga3Macro
@pga3(T, ex)
 @pga3(ex)

Macro generated via SymbolicGA.@geometric_space with signature (3, 0, 1) and the following definitions:

  • embed(x) = x[1]::e1 + x[2]::e2 + x[3]::e3
  • magnitude2(x) = x ⦿ x
  • point(x) = embed(x) + 1.0::e4

No documentation found.

SymbolicGA.@pga3 is a macro.

# 2 methods for macro "@pga3" from SymbolicGA:
  [1] var"@pga3"(__source__::LineNumberNode, __module__::Module, ex)
      @ ~/work/SymbolicGA.jl/SymbolicGA.jl/src/spaces.jl:61
  [2] var"@pga3"(__source__::LineNumberNode, __module__::Module, T, ex)
-     @ ~/work/SymbolicGA.jl/SymbolicGA.jl/src/spaces.jl:57
source
SymbolicGA.@cga3Macro
@cga3(T, ex)
-@cga3(ex)

Macro generated via SymbolicGA.@geometric_space with signature (4, 1) and the following definitions:

  • embed(x) = x[1]::e1 + x[2]::e2 + x[3]::e3
  • magnitude2(x) = x ⦿ x
  • point(x) = (embed(x) + (0.5::Scalar ⟑ magnitude2(embed(x))) ⟑ n + n̄)::Vector
  • weight(X) = -X ⋅ n
  • unitize(X) = X / weight(X)
  • radius2(X) = (magnitude2(X) / magnitude2(X ∧ n))::Scalar
  • center(X) = (X ⟑ n) ⟑ X
  • distance(S, X) = unitize(S) ⋅ unitize(X)

3D Conformal Geometric Algebra.

Warning

This functionality is experimental and will likely be subject to change in the future. It is not recommended for use beyond prototyping and playing around.

source
SymbolicGA.@cga3Macro
@cga3(T, ex)
+@cga3(ex)

Macro generated via SymbolicGA.@geometric_space with signature (4, 1) and the following definitions:

  • embed(x) = x[1]::e1 + x[2]::e2 + x[3]::e3
  • magnitude2(x) = x ⦿ x
  • point(x) = (embed(x) + (0.5::Scalar ⟑ magnitude2(embed(x))) ⟑ n + n̄)::Vector
  • weight(X) = -X ⋅ n
  • unitize(X) = X / weight(X)
  • radius2(X) = (magnitude2(X) / magnitude2(X ∧ n))::Scalar
  • center(X) = (X ⟑ n) ⟑ X
  • distance(S, X) = unitize(S) ⋅ unitize(X)

3D Conformal Geometric Algebra.

Warning

This functionality is experimental and will likely be subject to change in the future. It is not recommended for use beyond prototyping and playing around.

source
SymbolicGA.@geometric_spaceMacro
@geometric_space name sig quote
   n = 1.0::e4 + 1.0::e5
   n̄ = (-0.5)::e4 + 0.5::e5
   ... # other definitions
-end [warn_override = true]

Generate a macro @name which defines a geometric space with signature sig along with optional user-provided definitions.

The resulting macro will have two methods:

  • @name ex, which acts as a standard @ga sig ex (but with potential extra definitions).
  • @name T ex which wraps the result into type T, just like @ga sig T ex would (see @ga).

If definitions are provided as an Expr, they will be parsed into Bindings and added to the default bindings. If definitions already are Bindings, they will be used as is. warn_override can be set to false if you purposefully intend to purposefully override some of the default bindings.

source
SymbolicGA.KVectorType
KVector{K,T,D,N}

Geometric K-vector with eltype T with N elements in a geometric algebra of dimension D.

The constructors KVector{K,D}(elements...) and KVector{K,D}(elements::NTuple) will automatically infer T from the arguments and N from K and D.

Examples

julia> KVector{1,3}(1.0, 2.0, 3.0)
+end [warn_override = true]

Generate a macro @name which defines a geometric space with signature sig along with optional user-provided definitions.

The resulting macro will have two methods:

  • @name ex, which acts as a standard @ga sig ex (but with potential extra definitions).
  • @name T ex which wraps the result into type T, just like @ga sig T ex would (see @ga).

If definitions are provided as an Expr, they will be parsed into Bindings and added to the default bindings. If definitions already are Bindings, they will be used as is. warn_override can be set to false if you purposefully intend to purposefully override some of the default bindings.

source
SymbolicGA.KVectorType
KVector{K,T,D,N}

Geometric K-vector with eltype T with N elements in a geometric algebra of dimension D.

The constructors KVector{K,D}(elements...) and KVector{K,D}(elements::NTuple) will automatically infer T from the arguments and N from K and D.

Examples

julia> KVector{1,3}(1.0, 2.0, 3.0)
 KVector{1, Float64, 3, 3}(1.0, 2.0, 3.0)
 
 julia> KVector{2,3}(1.0, 2.0, 3.0)
 Bivector{Float64, 3, 3}(1.0, 2.0, 3.0)
 
 julia> KVector{4,4}(1.0)
-Quadvector{Float64, 4, 1}(1.0)
source

Expression generation

SymbolicGA.codegen_expressionFunction
codegen_expression(sig, ex; T = nothing, bindings::Optional{Bindings} = nothing)

Parse ex as an algebraic expression and generate a Julia expression which represents the corresponding computation. sig can be a SymbolicGA.Signature, a signature integer or a signature string, tuple or tuple expression adhering to semantics of @ga. See @ga for more information regarding the parsing and semantics applied to ex.

Parameters

  • T specifies what type to use when reconstructing geometric entities from tuple components with construct. If set to nothing and the result is in a non-flattened form (i.e. not annotated with an annotation of the type <ex>::(0 + 2)), then an appropriate KVector will be used depending on which type of geometric entity is returned; if multiple entities are present, a tuple of KVectors will be returned. If the result is in a flattened form, T will be set to :Tuple if unspecified.
  • bindings is a user-provided SymbolicGA.Bindings which controls what expansions are carried out on the raw Julia expression before conversion to an algebraic expression.
source
SymbolicGA.BindingsType
Bindings(; refs = Dict{Symbol,Any}(), funcs = Dict{Symbol,Any}(), warn_override = true)

Structure holding information about bindings which either act as references (simple substitutions) or as functions, which can be called with arguments. This allows a small domain-specific language to be used when constructing algebraic expressions.

References are lhs::Symbol => rhs pairs where the left-hand side simply expands to the right-hand side during parsing. Right-hand sides which include lhs are supported, such that references of the form x = x::Vector are allowed, but will be expanded only once. Functions are name::Symbol => body pairs where rhs must refer to their arguments with Expr(:argument, <literal::Int>) expressions. Recursion is not supported and will lead to a StackOverflowError. See @arg.

Most default functions and symbols are implemented using this mechanism. If warn_override is set to true, overrides of such default functions will trigger a warning.

source
SymbolicGA.SignatureType
Signature(positive::Int, negative::Int = 0, degenerate::Int = 0)
-Signature(str::AbstractString) # Signature("++-𝟎")

Signature of an Euclidean or pseudo-Euclidean space.

This signature encodes a space with a metric such that the first P basis vectors square to 1, the following N to -1 and the following D to 0. The metric evaluates to zero between two distinct basis vectors.

source

Interface methods

Expression generation

SymbolicGA.codegen_expressionFunction
codegen_expression(sig, ex; T = nothing, bindings::Optional{Bindings} = nothing)

Parse ex as an algebraic expression and generate a Julia expression which represents the corresponding computation. sig can be a SymbolicGA.Signature, a signature integer or a signature string, tuple or tuple expression adhering to semantics of @ga. See @ga for more information regarding the parsing and semantics applied to ex.

Parameters

  • T specifies what type to use when reconstructing geometric entities from tuple components with construct. If set to nothing and the result is in a non-flattened form (i.e. not annotated with an annotation of the type <ex>::(0 + 2)), then an appropriate KVector will be used depending on which type of geometric entity is returned; if multiple entities are present, a tuple of KVectors will be returned. If the result is in a flattened form, T will be set to :Tuple if unspecified.
  • bindings is a user-provided SymbolicGA.Bindings which controls what expansions are carried out on the raw Julia expression before conversion to an algebraic expression.
source
SymbolicGA.BindingsType
Bindings(; refs = Dict{Symbol,Any}(), funcs = Dict{Symbol,Any}(), warn_override = true)

Structure holding information about bindings which either act as references (simple substitutions) or as functions, which can be called with arguments. This allows a small domain-specific language to be used when constructing algebraic expressions.

References are lhs::Symbol => rhs pairs where the left-hand side simply expands to the right-hand side during parsing. Right-hand sides which include lhs are supported, such that references of the form x = x::Vector are allowed, but will be expanded only once. Functions are name::Symbol => body pairs where rhs must refer to their arguments with Expr(:argument, <literal::Int>) expressions. Recursion is not supported and will lead to a StackOverflowError. See @arg.

Most default functions and symbols are implemented using this mechanism. If warn_override is set to true, overrides of such default functions will trigger a warning.

source
SymbolicGA.SignatureType
Signature(positive::Int, negative::Int = 0, degenerate::Int = 0)
+Signature(str::AbstractString) # Signature("++-𝟎")

Signature of an Euclidean or pseudo-Euclidean space.

This signature encodes a space with a metric such that the first P basis vectors square to 1, the following N to -1 and the following D to 0. The metric evaluates to zero between two distinct basis vectors.

source

Interface methods

SymbolicGA.getcomponentFunction
getcomponent(collection)
 getcomponent(collection, i)
-getcomponent(collection, j, i)

Retrieve a number from a collection to be interpreted as the component of a geometric entity.

getcomponent(collection) which defaults to collection[] is used to extract the only component of a scalar or antiscalar.

getcomponent(collection, j, i) which defaults to collection[j][i] is used to extract the i-th component the j-th geometric entity for a collection of multiple geometric vectors.

getcomponent(collection, i) which defaults to collection[i] is used to extract the i-th component of a single geometric entity or a set of geometric entities backed by collection. In the case of a set of geometric entities, this is semantically equivalent to getcomponent(collection, j, i) where a single i is computed from the cumulated sum of past indices, i.e. as if components from consecutive entities were concatenated together. See @ga for more information regarding which mode is used depending on the syntax for grade extraction.

Most collections will not need to extend this method, but is exposed should the need arise for a tigher control over how input data is accessed.

source
SymbolicGA.constructFunction
construct(T, components::Tuple)

Construct an instance of T from a tuple of components.

Defaults to T(components).

source
+getcomponent(collection, j, i)

Retrieve a number from a collection to be interpreted as the component of a geometric entity.

getcomponent(collection) which defaults to collection[] is used to extract the only component of a scalar or antiscalar.

getcomponent(collection, j, i) which defaults to collection[j][i] is used to extract the i-th component the j-th geometric entity for a collection of multiple geometric vectors.

getcomponent(collection, i) which defaults to collection[i] is used to extract the i-th component of a single geometric entity or a set of geometric entities backed by collection. In the case of a set of geometric entities, this is semantically equivalent to getcomponent(collection, j, i) where a single i is computed from the cumulated sum of past indices, i.e. as if components from consecutive entities were concatenated together. See @ga for more information regarding which mode is used depending on the syntax for grade extraction.

Most collections will not need to extend this method, but is exposed should the need arise for a tigher control over how input data is accessed.

source
SymbolicGA.constructFunction
construct(T, components::Tuple)

Construct an instance of T from a tuple of components.

Defaults to T(components).

source
diff --git a/dev/tutorial/getting_started/index.html b/dev/tutorial/getting_started/index.html index 0ba8852..c961ed9 100644 --- a/dev/tutorial/getting_started/index.html +++ b/dev/tutorial/getting_started/index.html @@ -6,11 +6,11 @@ @ga 2 x::e1 + y::e2
KVector{1, Float64, 2, 2}(1.0, 2.0)

We simply constructed a simple vector within $\mathcal{G}(\mathbb{R}^2)$ by associating scalar components with basis vectors e1 and e2. Most of the time though, unless you desire to construct a geometric entity with sparse components, you will prefer providing vectors as annotated iterables, such as

@ga 2 (x, y)::Vector
KVector{1, Float64, 2, 2}(1.0, 2.0)

Note that this Vector annotation does not mean Base.Vector; it means a mathematical vector in the geometric space of interest. Now, let us take the geometric product ⟑ (\wedgedot) of two vectors:

a = (x, y)
 b = rand(2)
 
-@ga 2 a::Vector ⟑ b::Vector
(KVector{0, Float64, 2, 1}(1.0856585992955694), Bivector{Float64, 2, 1}(-1.6860227364510738))

Here, we obtained a mathematical object composed of both a 0-vector (scalar) and a 2-vector (bivector) part. In $\mathcal{G}(\mathbb{R}^2)$, a bivector has a single component, but with most other spaces bivectors have more; for any embedded space of dimension n, the number of elements for an entity with grade k is binomial(n, k).

Note

If you dislike the use of non-ASCII characters for major operators, you can use standard function names instead of operators, such as geometric_product(x, y) (equivalent to x ⟑ y) (see Table of symbols).

What if we wanted only the scalar part or the bivector part? We can project the result into either grade 0 or grade 2, respectively:

@ga 2 (a::Vector ⟑ b::Vector)::Scalar
KVector{0, Float64, 2, 1}(1.0856585992955694)
@ga 2 (a::Vector ⟑ b::Vector)::Bivector
Bivector{Float64, 2, 1}(-1.6860227364510738)

Since it may be a bit tedious to type in these names by hand, when all we really need is to express the grade in these annotations, we can directly use a number on the right-hand side of :: (see Type annotations).

@ga 2 (a::1 ⟑ b::1)::0
KVector{0, Float64, 2, 1}(1.0856585992955694)

In this particular case, getting the lowest and highest grade component of a geometric product is what defines the inner and outer products, (\cdot) and (\wedge). See Table of symbols for a complete list of symbols and operators.

@ga 2 a::1 ⋅ b::1
KVector{0, Float64, 2, 1}(1.0856585992955694)
@ga 2 a::1 ∧ b::1
Bivector{Float64, 2, 1}(-1.6860227364510738)

You can tweak the signature of the geometric space to your liking, if you want to use other spaces. For example, we can embed a 2D vector into Minkowski space (used to express flat spacetime, also called "Space-time algebra" or STA in works using geometric algebra):

c = rand(4)
4-element Vector{Float64}:
- 0.463730489644705
- 0.9799309128655369
- 0.726616177317508
- 0.05874003266816574
@ga (3, 1) c::1 ⋅ c::1
KVector{0, Float64, 4, 1}(1.6998312387172534)

If you are a bit lazy, you may annotate the c once before the expression:

@ga (3, 1) begin
+@ga 2 a::Vector ⟑ b::Vector
(KVector{0, Float64, 2, 1}(1.6647108718153987), Bivector{Float64, 2, 1}(-0.16434198225984098))

Here, we obtained a mathematical object composed of both a 0-vector (scalar) and a 2-vector (bivector) part. In $\mathcal{G}(\mathbb{R}^2)$, a bivector has a single component, but with most other spaces bivectors have more; for any embedded space of dimension n, the number of elements for an entity with grade k is binomial(n, k).

Note

If you dislike the use of non-ASCII characters for major operators, you can use standard function names instead of operators, such as geometric_product(x, y) (equivalent to x ⟑ y) (see Table of symbols).

What if we wanted only the scalar part or the bivector part? We can project the result into either grade 0 or grade 2, respectively:

@ga 2 (a::Vector ⟑ b::Vector)::Scalar
KVector{0, Float64, 2, 1}(1.6647108718153987)
@ga 2 (a::Vector ⟑ b::Vector)::Bivector
Bivector{Float64, 2, 1}(-0.16434198225984098)

Since it may be a bit tedious to type in these names by hand, when all we really need is to express the grade in these annotations, we can directly use a number on the right-hand side of :: (see Type annotations).

@ga 2 (a::1 ⟑ b::1)::0
KVector{0, Float64, 2, 1}(1.6647108718153987)

In this particular case, getting the lowest and highest grade component of a geometric product is what defines the inner and outer products, (\cdot) and (\wedge). See Table of symbols for a complete list of symbols and operators.

@ga 2 a::1 ⋅ b::1
KVector{0, Float64, 2, 1}(1.6647108718153987)
@ga 2 a::1 ∧ b::1
Bivector{Float64, 2, 1}(-0.16434198225984098)

You can tweak the signature of the geometric space to your liking, if you want to use other spaces. For example, we can embed a 2D vector into Minkowski space (used to express flat spacetime, also called "Space-time algebra" or STA in works using geometric algebra):

c = rand(4)
4-element Vector{Float64}:
+ 0.2720683096154568
+ 0.32647704445971115
+ 0.5056541210553631
+ 0.690187826665765
@ga (3, 1) c::1 ⋅ c::1
KVector{0, Float64, 4, 1}(-0.04006472028117991)

If you are a bit lazy, you may annotate the c once before the expression:

@ga (3, 1) begin
   c::1
   c ⋅ c
-end
KVector{0, Float64, 4, 1}(1.6998312387172534)

These are the very basics, now you know how to evaluate geometric algebra expressions in arbitrary geometric spaces. Feel free to look at other tutorials to learn about meaningful operations to perform!


This page was generated using Literate.jl.

+end
KVector{0, Float64, 4, 1}(-0.04006472028117991)

These are the very basics, now you know how to evaluate geometric algebra expressions in arbitrary geometric spaces. Feel free to look at other tutorials to learn about meaningful operations to perform!


This page was generated using Literate.jl.

diff --git a/dev/tutorial/integration/index.html b/dev/tutorial/integration/index.html index 7faaf89..7c4c9d8 100644 --- a/dev/tutorial/integration/index.html +++ b/dev/tutorial/integration/index.html @@ -12,4 +12,4 @@ y = MyType(Dict(:x => 1.2, :y => -1.4, :z => 0.1)) @ga 3 dual(x::1 ∧ y::1)
KVector{1, Float64, 3, 3}(4.3999999999999995, 3.4499999999999997, -4.5)

Note that we still got a KVector out by default; if you want, you may provide MyType as output, but you also need to define how to reconstruct a type given a tuple of components. By default, SymbolicGA.construct calls the provided type constructor on the tuple of components. You may therefore either:

SymbolicGA.construct(T::Type{<:MyType}, components::Tuple) = T(Dict((:x, :y, :z) .=> components))
 
-@ga 3 MyType dual(x::1 ∧ y::1)
Main.MyType{Float64}(Dict(:y => 3.4499999999999997, :z => -4.5, :x => 4.3999999999999995))

Of course, you can also omit the return type and operate with a KVector. In fact, that is recommended especially if you don't know what kind of object you'll end up with. For example, would you know what dual((x::1 ⟑ y::1) ⋅ y::1) + exp(x::1 ∧ y::1) returns? Well, let's see:

@ga 3 dual((x::1 ⟑ y::1) ⋅ y::1) + exp(x::1 ∧ y::1)
(KVector{0, Float64, 3, 1}(-0.3440881217009017), Bivector{Float64, 3, 3}(10.52536392668556, -4.934004959947116, 5.855062757428548))

Looks like we got a scalar and a bivector! We could manipulate this KVector around, which is a mere allocation-free wrapper over a tuple, but if you already know what type of data structure you want to put your data into, you may find it more convenient to specify it when calling the macro.


This page was generated using Literate.jl.

+@ga 3 MyType dual(x::1 ∧ y::1)
Main.MyType{Float64}(Dict(:y => 3.4499999999999997, :z => -4.5, :x => 4.3999999999999995))

Of course, you can also omit the return type and operate with a KVector. In fact, that is recommended especially if you don't know what kind of object you'll end up with. For example, would you know what dual((x::1 ⟑ y::1) ⋅ y::1) + exp(x::1 ∧ y::1) returns? Well, let's see:

@ga 3 dual((x::1 ⟑ y::1) ⋅ y::1) + exp(x::1 ∧ y::1)
(KVector{0, Float64, 3, 1}(-0.3440881217009017), Bivector{Float64, 3, 3}(10.52536392668556, -4.934004959947117, 5.855062757428548))

Looks like we got a scalar and a bivector! We could manipulate this KVector around, which is a mere allocation-free wrapper over a tuple, but if you already know what type of data structure you want to put your data into, you may find it more convenient to specify it when calling the macro.


This page was generated using Literate.jl.