1
- export Variable, @polyvar , @ncpolyvar
1
+ export Variable, @polyvar , @ncpolyvar , @complex_polyvar
2
2
3
- function polyarrayvar (variable_order, monomial_order, prefix, indices... )
3
+ function polyarrayvar (
4
+ variable_order,
5
+ monomial_order,
6
+ complex_kind,
7
+ prefix,
8
+ indices... ,
9
+ )
4
10
return map (
5
11
i -> Variable (
6
12
" $(prefix) [$(join (i, " ," )) ]" ,
7
13
variable_order,
8
14
monomial_order,
15
+ complex_kind,
9
16
),
10
17
Iterators. product (indices... ),
11
18
)
12
19
end
13
20
14
- function buildpolyvar (var, variable_order, monomial_order)
21
+ function buildpolyvar (var, variable_order, monomial_order, complex_kind )
15
22
if isa (var, Symbol)
16
23
var,
17
- :($ (esc (var)) = $ Variable ($ " $var " , $ variable_order, $ monomial_order))
24
+ :(
25
+ $ (esc (var)) = $ Variable (
26
+ $ " $var " ,
27
+ $ variable_order,
28
+ $ monomial_order,
29
+ $ complex_kind,
30
+ )
31
+ )
18
32
else
19
33
isa (var, Expr) || error (" Expected $var to be a variable name" )
20
34
Base. Meta. isexpr (var, :ref ) ||
@@ -28,26 +42,28 @@ function buildpolyvar(var, variable_order, monomial_order)
28
42
$ (esc (varname)) = polyarrayvar (
29
43
$ (variable_order),
30
44
$ (monomial_order),
45
+ $ (complex_kind),
31
46
$ prefix,
32
47
$ (esc .(var. args[2 : end ])... ),
33
48
)
34
49
)
35
50
end
36
51
end
37
52
38
- function buildpolyvars (args, variable_order, monomial_order)
53
+ function buildpolyvars (args, variable_order, monomial_order, complex_kind )
39
54
vars = Symbol[]
40
55
exprs = []
41
56
for arg in args
42
- var, expr = buildpolyvar (arg, variable_order, monomial_order)
57
+ var, expr =
58
+ buildpolyvar (arg, variable_order, monomial_order, complex_kind)
43
59
push! (vars, var)
44
60
push! (exprs, expr)
45
61
end
46
62
return vars, exprs
47
63
end
48
64
49
65
# Inspired from `JuMP.Containers._extract_kw_args`
50
- function _extract_kw_args (args, variable_order)
66
+ function _extract_kw_args (args, variable_order, complex_kind )
51
67
positional_args = Any[]
52
68
monomial_order = :($ (MP. Graded{MP. LexOrder}))
53
69
for arg in args
@@ -56,29 +72,42 @@ function _extract_kw_args(args, variable_order)
56
72
variable_order = esc (arg. args[2 ])
57
73
elseif arg. args[1 ] == :monomial_order
58
74
monomial_order = esc (arg. args[2 ])
75
+ elseif arg. args[1 ] == :complex
76
+ complex_kind = arg. args[2 ] == :true ? COMPLEX : REAL
59
77
else
60
78
error (" Unrecognized keyword argument `$(arg. args[1 ]) `" )
61
79
end
62
80
else
63
81
push! (positional_args, arg)
64
82
end
65
83
end
66
- return positional_args, variable_order, monomial_order
84
+ return positional_args, variable_order, monomial_order, complex_kind
67
85
end
68
86
69
87
# Variable vector x returned garanteed to be sorted so that if p is built with x then vars(p) == x
70
88
macro polyvar (args... )
71
- pos_args, variable_order, monomial_order =
72
- _extract_kw_args (args, :($ (Commutative{CreationOrder})))
73
- vars, exprs = buildpolyvars (pos_args, variable_order, monomial_order)
89
+ pos_args, variable_order, monomial_order, complex_kind =
90
+ _extract_kw_args (args, :($ (Commutative{CreationOrder})), REAL)
91
+ vars, exprs =
92
+ buildpolyvars (pos_args, variable_order, monomial_order, complex_kind)
74
93
return :($ (foldl ((x, y) -> :($ x; $ y), exprs, init = :()));
75
94
$ (Expr (:tuple , esc .(vars)... )))
76
95
end
77
96
78
97
macro ncpolyvar (args... )
79
- pos_args, variable_order, monomial_order =
80
- _extract_kw_args (args, :($ (NonCommutative{CreationOrder})))
81
- vars, exprs = buildpolyvars (pos_args, variable_order, monomial_order)
98
+ pos_args, variable_order, monomial_order, complex_kind =
99
+ _extract_kw_args (args, :($ (NonCommutative{CreationOrder})), REAL)
100
+ vars, exprs =
101
+ buildpolyvars (pos_args, variable_order, monomial_order, complex_kind)
102
+ return :($ (foldl ((x, y) -> :($ x; $ y), exprs, init = :()));
103
+ $ (Expr (:tuple , esc .(vars)... )))
104
+ end
105
+
106
+ macro complex_polyvar (args... )
107
+ pos_args, variable_order, monomial_order, complex_kind =
108
+ _extract_kw_args (args, :($ (Commutative{CreationOrder})), COMPLEX)
109
+ vars, exprs =
110
+ buildpolyvars (pos_args, variable_order, monomial_order, complex_kind)
82
111
return :($ (foldl ((x, y) -> :($ x; $ y), exprs, init = :()));
83
112
$ (Expr (:tuple , esc .(vars)... )))
84
113
end
@@ -114,19 +143,54 @@ function instantiate(::Type{NonCommutative{O}}) where {O}
114
143
return NonCommutative (instantiate (O))
115
144
end
116
145
146
+ """
147
+ ComplexKind
148
+
149
+ The type used to identify whether a variable is complex-valued. It has the following instances:
150
+ - `REAL`: the variable is real-valued, [`conj`](@ref) and [`real`](@ref) are identities, [`imag`](@ref) is zero.
151
+ - `COMPLEX`: the variable is a declared complex-valued variable with distinct conjugate, real, and imaginary part.
152
+ [`ordinary_variable`](@ref) is an identity.
153
+ - `CONJ`: the variable is the conjugate of a declared complex-valued variable. [`ordinary_variable`](@ref) is equal to
154
+ [`conj`](@ref). It will print with an over-bar.
155
+ - `REAL_PART`: the variable is the real part of a complex-valued variable. It is real-valued itself: [`conj`](@ref) and
156
+ [`real`](@ref) are identities, [`imag`](@ref) is zero. [`ordinary_variable`](@ref) will give back the original complex-valued
157
+ _declared_ variable from which the real part was extracted. It will print with an `ᵣ` subscript.
158
+ - `IMAG_PART`: the variable is the imaginary part of a declared complex-valued variable (or the negative imaginary part of the
159
+ conjugate of a declared complex-valued variable). It is real-valued itself: [`conj`](@ref) and [`real`](@ref) are identities,
160
+ [`imag`](@ref) is zero. [`ordinary_variable`](@ref) will give back the original complex-valued _declared_ variable from which
161
+ the imaginary part was extracted. It will print with an `ᵢ` subscript.
162
+ """
163
+ @enum ComplexKind REAL COMPLEX CONJ REAL_PART IMAG_PART
164
+
117
165
struct Variable{V,M} <: AbstractVariable
118
166
name:: String
167
+ kind:: ComplexKind
119
168
variable_order:: V
120
169
121
- function Variable {V,M} (name:: AbstractString ) where {V<: AbstractVariableOrdering ,M<: MP.AbstractMonomialOrdering }
122
- return new {V,M} (convert (String, name), instantiate (V))
170
+ function Variable {V,M} (
171
+ name:: AbstractString ,
172
+ kind:: ComplexKind = REAL,
173
+ ) where {V<: AbstractVariableOrdering ,M<: MP.AbstractMonomialOrdering }
174
+ return new {V,M} (convert (String, name), kind, instantiate (V))
123
175
end
176
+
124
177
function Variable (
125
178
name:: AbstractString ,
126
179
:: Type{V} ,
127
180
:: Type{M} ,
181
+ kind:: ComplexKind = REAL,
128
182
) where {V<: AbstractVariableOrdering ,M<: MP.AbstractMonomialOrdering }
129
- return new {V,M} (convert (String, name), instantiate (V))
183
+ return new {V,M} (convert (String, name), kind, instantiate (V))
184
+ end
185
+
186
+ function Variable (
187
+ from:: Variable{V,M} ,
188
+ kind:: ComplexKind ,
189
+ ) where {V<: AbstractVariableOrdering ,M<: MP.AbstractMonomialOrdering }
190
+ (from. kind == REAL && kind == REAL) ||
191
+ (from. kind != REAL && kind != REAL) ||
192
+ error (" Cannot change the complex type of an existing variable" )
193
+ return new {V,M} (from. name, kind, from. variable_order)
130
194
end
131
195
end
132
196
@@ -150,6 +214,41 @@ MP.ordering(::Type{Variable{V,M}}) where {V,M} = M
150
214
151
215
iscomm (:: Type{Variable{C}} ) where {C} = C
152
216
217
+ Base. isreal (x:: Variable{C} ) where {C} = x. kind != COMPLEX && x. kind != CONJ
218
+ MP. isrealpart (x:: Variable{C} ) where {C} = x. kind == REAL_PART
219
+ MP. isimagpart (x:: Variable{C} ) where {C} = x. kind == IMAG_PART
220
+ MP. isconj (x:: Variable{C} ) where {C} = x. kind == CONJ
221
+ function MP. ordinary_variable (x:: Variable )
222
+ return x. kind == REAL || x. kind == COMPLEX ? x : Variable (x, COMPLEX)
223
+ end
224
+
225
+ function Base. conj (x:: Variable )
226
+ if x. kind == COMPLEX
227
+ return Variable (x, CONJ)
228
+ elseif x. kind == CONJ
229
+ return Variable (x, COMPLEX)
230
+ else
231
+ return x
232
+ end
233
+ end
234
+
235
+ function Base. real (x:: Variable )
236
+ if x. kind == COMPLEX || x. kind == CONJ
237
+ return Variable (x, REAL_PART)
238
+ else
239
+ return x
240
+ end
241
+ end
242
+ function Base. imag (x:: Variable{V,M} ) where {V,M}
243
+ if x. kind == COMPLEX
244
+ return Variable (x, IMAG_PART)
245
+ elseif x. kind == CONJ
246
+ return _Term {V,M,Int} (- 1 , Monomial (Variable (x, IMAG_PART)))
247
+ else
248
+ return MA. Zero ()
249
+ end
250
+ end
251
+
153
252
function mergevars_to! (
154
253
vars:: Vector{PV} ,
155
254
varsvec:: Vector{Vector{PV}} ,
0 commit comments