symexpress3 0.0.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- symexpress3/__init__.py +26 -0
- symexpress3/__main__.py +10 -0
- symexpress3/optFunctionBase.py +88 -0
- symexpress3/optSymAny/optSymAnyArrayPower.py +84 -0
- symexpress3/optSymAny/optSymAnyExpandArray.py +163 -0
- symexpress3/optSymAny/symRegisterOptSymAny.py +60 -0
- symexpress3/optSymFunction/__init__.py +5 -0
- symexpress3/optSymFunction/optSymFunctionCosAtanDiv3.py +139 -0
- symexpress3/optSymFunction/optSymFunctionCosAtanDivNToSinICos.py +124 -0
- symexpress3/optSymFunction/optSymFunctionCosToSum.py +84 -0
- symexpress3/optSymFunction/optSymFunctionCosXplusYtoSinCos.py +102 -0
- symexpress3/optSymFunction/optSymFunctionSinAtanDivNToSinICos.py +121 -0
- symexpress3/optSymFunction/optSymFunctionSinToSum.py +85 -0
- symexpress3/optSymFunction/optSymFunctionSinXplusYtoSinCos.py +103 -0
- symexpress3/optSymFunction/symRegisterOptSymFunction.py +83 -0
- symexpress3/optSymNumber/__init__.py +7 -0
- symexpress3/optSymNumber/optSymNumberNegRootToI.py +184 -0
- symexpress3/optSymNumber/optSymNumberPower.py +94 -0
- symexpress3/optSymNumber/optSymNumberRadicalDenominatorToCounter.py +98 -0
- symexpress3/optSymNumber/symRegisterOptSymNumber.py +68 -0
- symexpress3/optSymVariable/__init__.py +6 -0
- symexpress3/optSymVariable/optSymVariableI.py +224 -0
- symexpress3/optSymVariable/optSymVariableRootIToSinCos.py +162 -0
- symexpress3/optSymVariable/symRegisterOptSymVariable.py +60 -0
- symexpress3/optTypeBase.py +85 -0
- symexpress3/optimize/__init__.py +4 -0
- symexpress3/optimize/optimizeAdd.py +481 -0
- symexpress3/optimize/optimizeBase.py +86 -0
- symexpress3/optimize/optimizeExpandArrays.py +118 -0
- symexpress3/optimize/optimizeImaginairDenominator.py +214 -0
- symexpress3/optimize/optimizeMultiply.py +994 -0
- symexpress3/optimize/optimizeNestedRadicals.py +146 -0
- symexpress3/optimize/optimizeOnlyOneRoot.py +288 -0
- symexpress3/optimize/optimizePower.py +126 -0
- symexpress3/optimize/optimizePowerArrays.py +96 -0
- symexpress3/optimize/optimizeRootOfImagNumToCosISin.py +389 -0
- symexpress3/optimize/optimizeRootToPrincipalRoot.py +148 -0
- symexpress3/optimize/optimizeSinTwoCosTwo.py +185 -0
- symexpress3/optimize/optimizeSplitDenominator.py +117 -0
- symexpress3/optimize/optimizeUnnestingRadicals.py +378 -0
- symexpress3/optimize/symRegisterOptimize.py +94 -0
- symexpress3/primefactor.py +256 -0
- symexpress3/symexp3cmd.py +276 -0
- symexpress3/symexpress3.py +3622 -0
- symexpress3/symfunc/__init__.py +6 -0
- symexpress3/symfunc/symFuncAbs.py +185 -0
- symexpress3/symfunc/symFuncAtan.py +152 -0
- symexpress3/symfunc/symFuncAtan2.py +183 -0
- symexpress3/symfunc/symFuncBase.py +236 -0
- symexpress3/symfunc/symFuncBinomial.py +123 -0
- symexpress3/symfunc/symFuncCeilFloor.py +176 -0
- symexpress3/symfunc/symFuncCos.py +148 -0
- symexpress3/symfunc/symFuncExp.py +129 -0
- symexpress3/symfunc/symFuncFactorial.py +105 -0
- symexpress3/symfunc/symFuncSin.py +142 -0
- symexpress3/symfunc/symFuncSum.py +208 -0
- symexpress3/symfunc/symFuncTan.py +114 -0
- symexpress3/symfunc/symFuncTrigonoBase.py +578 -0
- symexpress3/symfunc/symRegisterFunctions.py +128 -0
- symexpress3/symfunc/symTrigonometricData.py +79 -0
- symexpress3/symtables.py +43 -0
- symexpress3/version.py +16 -0
- symexpress3-0.0.5.dist-info/METADATA +856 -0
- symexpress3-0.0.5.dist-info/RECORD +66 -0
- symexpress3-0.0.5.dist-info/WHEEL +4 -0
- symexpress3-0.0.5.dist-info/licenses/LICENSE +674 -0
symexpress3/__init__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Initilization of the functions and modules symexpress3
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .symexpress3 import *
|
|
6
|
+
from .version import __version__,__author__,__copyright__,__credits__,__license__,__maintainer__,__email__,__status__
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
from .symfunc.symRegisterFunctions import SymRegisterFunctions
|
|
10
|
+
from .optimize.symRegisterOptimize import SymRegisterOptimize
|
|
11
|
+
from .optSymNumber.symRegisterOptSymNumber import SymRegisterOptimize as SymRegisterOptSymNumber
|
|
12
|
+
from .optSymVariable.symRegisterOptSymVariable import SymRegisterOptimize as SymRegisterOptSymVariable
|
|
13
|
+
from .optSymFunction.symRegisterOptSymFunction import SymRegisterOptimize as SymRegisterOptSymFunction
|
|
14
|
+
from .optSymAny.symRegisterOptSymAny import SymRegisterOptimize as SymRegisterOptSymAny
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
SymRegisterFunctions()
|
|
18
|
+
SymRegisterOptimize()
|
|
19
|
+
SymRegisterOptSymNumber()
|
|
20
|
+
SymRegisterOptSymVariable()
|
|
21
|
+
SymRegisterOptSymFunction()
|
|
22
|
+
SymRegisterOptSymAny()
|
|
23
|
+
|
|
24
|
+
RegisterOptimzeActions()
|
|
25
|
+
|
|
26
|
+
# print( "Symexpress3.__init__ name: " + __name__ )
|
symexpress3/__main__.py
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Abstract class for optimze variable type` implementation symexpress3
|
|
6
|
+
|
|
7
|
+
Copyright (C) 2024 Gien van den Enden - swvandenenden@gmail.com
|
|
8
|
+
|
|
9
|
+
This program is free software: you can redistribute it and/or modify
|
|
10
|
+
it under the terms of the GNU General Public License as published by
|
|
11
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
(at your option) any later version.
|
|
13
|
+
|
|
14
|
+
This program is distributed in the hope that it will be useful,
|
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
GNU General Public License for more details.
|
|
18
|
+
|
|
19
|
+
You should have received a copy of the GNU General Public License
|
|
20
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from symexpress3 import symexpress3
|
|
27
|
+
from symexpress3 import optTypeBase
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# base class for a specific sym function type
|
|
31
|
+
#
|
|
32
|
+
class OptFunctionBase( optTypeBase.OptTypeBase ):
|
|
33
|
+
"""
|
|
34
|
+
Base class for type function optimization
|
|
35
|
+
"""
|
|
36
|
+
def __init__( self ):
|
|
37
|
+
super().__init__()
|
|
38
|
+
self._name = None # must be set by in the real class
|
|
39
|
+
self._symtype = symexpress3.SymFunction # symexpress type class, example symexpress3.SymNumber, symexpress3.SymVariable, symexpress3.SymFunction
|
|
40
|
+
self._desc = "" # description of the optimization
|
|
41
|
+
self._funcName = None # name of the function
|
|
42
|
+
self._minparams = 1 # minimum number of parameters
|
|
43
|
+
self._maxparams = 1 # maximum number of parameters
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def functionName(self):
|
|
48
|
+
"""
|
|
49
|
+
Name of the function
|
|
50
|
+
"""
|
|
51
|
+
return self._funcName
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def minimumNumberOfParameters(self):
|
|
55
|
+
"""
|
|
56
|
+
Minimum number of parameters
|
|
57
|
+
"""
|
|
58
|
+
return self._minparams
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def maximumNumberOfParameters(self):
|
|
62
|
+
"""
|
|
63
|
+
Maximum number of parameters
|
|
64
|
+
"""
|
|
65
|
+
return self._maxparams
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def checkType( self, elem, action ):
|
|
69
|
+
"""
|
|
70
|
+
Check if the given elem
|
|
71
|
+
"""
|
|
72
|
+
if super().checkType( elem, action ) != True:
|
|
73
|
+
# print("Name: " + self.name )
|
|
74
|
+
# print("Type: " + str( self._symtype ))
|
|
75
|
+
# print( "test 1")
|
|
76
|
+
return False
|
|
77
|
+
|
|
78
|
+
if elem.name != self.functionName:
|
|
79
|
+
return False
|
|
80
|
+
|
|
81
|
+
numElem = elem.numElements()
|
|
82
|
+
if numElem < self._minparams :
|
|
83
|
+
return False
|
|
84
|
+
|
|
85
|
+
if numElem > self._maxparams :
|
|
86
|
+
return False
|
|
87
|
+
|
|
88
|
+
return True
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Sym Express 3
|
|
6
|
+
|
|
7
|
+
Copyright (C) 2024 Gien van den Enden - swvandenenden@gmail.com
|
|
8
|
+
|
|
9
|
+
This program is free software: you can redistribute it and/or modify
|
|
10
|
+
it under the terms of the GNU General Public License as published by
|
|
11
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
(at your option) any later version.
|
|
13
|
+
|
|
14
|
+
This program is distributed in the hope that it will be useful,
|
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
GNU General Public License for more details.
|
|
18
|
+
|
|
19
|
+
You should have received a copy of the GNU General Public License
|
|
20
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from symexpress3 import symexpress3
|
|
26
|
+
from symexpress3 import optTypeBase
|
|
27
|
+
|
|
28
|
+
class OptSymAnyArrayPower( optTypeBase.OptTypeBase ):
|
|
29
|
+
"""
|
|
30
|
+
Put the power of an array into his elements
|
|
31
|
+
"""
|
|
32
|
+
def __init__( self ):
|
|
33
|
+
super().__init__()
|
|
34
|
+
self._name = "arrayPower"
|
|
35
|
+
self._desc = "Put the power of an array into his elements"
|
|
36
|
+
|
|
37
|
+
def optimize( self, elem, action ):
|
|
38
|
+
if self.checkType( elem, action ) != True:
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
if not isinstance( elem, symexpress3.SymArray) :
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
if elem.power == 1 and elem.onlyOneRoot == 1 :
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
newArray = symexpress3.SymArray()
|
|
48
|
+
|
|
49
|
+
for iCnt, elemsub in enumerate( elem.elements ):
|
|
50
|
+
symSub = symexpress3.SymExpress( '*' )
|
|
51
|
+
symSub.powerCounter = elem.powerCounter
|
|
52
|
+
symSub.powerDenominator = elem.powerDenominator
|
|
53
|
+
symSub.powerSign = elem.powerSign
|
|
54
|
+
symSub.onlyOneRoot = elem.onlyOneRoot
|
|
55
|
+
symSub.add( elemsub )
|
|
56
|
+
newArray.add( symSub )
|
|
57
|
+
|
|
58
|
+
return newArray
|
|
59
|
+
|
|
60
|
+
#
|
|
61
|
+
# Test routine (unit test), see testsymexpress3.py
|
|
62
|
+
#
|
|
63
|
+
def Test( display = False):
|
|
64
|
+
"""
|
|
65
|
+
Unit test
|
|
66
|
+
"""
|
|
67
|
+
symTest = symexpress3.SymFormulaParser( "[ 4 | 2 ]^^2" )
|
|
68
|
+
symTest.optimize()
|
|
69
|
+
symTest = symTest.elements[ 0 ]
|
|
70
|
+
testClass = OptSymAnyArrayPower()
|
|
71
|
+
symNew = testClass.optimize( symTest, "arrayPower" )
|
|
72
|
+
|
|
73
|
+
if display == True :
|
|
74
|
+
print( f"naam : {testClass.name}" )
|
|
75
|
+
print( f"orginal : {str( symTest )}" )
|
|
76
|
+
print( f"optimized : {str( symNew )}" )
|
|
77
|
+
|
|
78
|
+
if str( symNew ).strip() != "[ (4)^^2 | (2)^^2 ]":
|
|
79
|
+
print( f"Error unit test {testClass.name} function" )
|
|
80
|
+
raise NameError( f'SymAny optimze {testClass.name}, unit test error: {str( symTest )}, value: {symNew}' )
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
if __name__ == '__main__':
|
|
84
|
+
Test( True )
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Sym Express 3
|
|
6
|
+
|
|
7
|
+
Copyright (C) 2024 Gien van den Enden - swvandenenden@gmail.com
|
|
8
|
+
|
|
9
|
+
This program is free software: you can redistribute it and/or modify
|
|
10
|
+
it under the terms of the GNU General Public License as published by
|
|
11
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
(at your option) any later version.
|
|
13
|
+
|
|
14
|
+
This program is distributed in the hope that it will be useful,
|
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
GNU General Public License for more details.
|
|
18
|
+
|
|
19
|
+
You should have received a copy of the GNU General Public License
|
|
20
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from symexpress3 import symexpress3
|
|
26
|
+
from symexpress3 import optTypeBase
|
|
27
|
+
|
|
28
|
+
class OptSymAnyExpandArray( optTypeBase.OptTypeBase ):
|
|
29
|
+
"""
|
|
30
|
+
If the expression containts at least 1 array then make the hole expression an array element.
|
|
31
|
+
"""
|
|
32
|
+
def __init__( self ):
|
|
33
|
+
super().__init__()
|
|
34
|
+
self._name = "expandArrays"
|
|
35
|
+
self._desc = "If the expression containts at least 1 array then make the hole expression an array element."
|
|
36
|
+
|
|
37
|
+
def optimize( self, elem, action ):
|
|
38
|
+
|
|
39
|
+
def _subExpandSymArray( elem ):
|
|
40
|
+
if elem.power != 1 or elem.onlyOneRoot != 1 : # use arrayPower first
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
result = None
|
|
44
|
+
# for iCnt, elemsub in enumerate( elem.elements ):
|
|
45
|
+
for elemsub in elem.elements:
|
|
46
|
+
if isinstance( elemsub, symexpress3.SymArray ):
|
|
47
|
+
if elemsub.power != 1 or elemsub.onlyOneRoot != 1:
|
|
48
|
+
continue
|
|
49
|
+
result = symexpress3.SymArray()
|
|
50
|
+
break
|
|
51
|
+
if result != None:
|
|
52
|
+
# power is always 1 on this point
|
|
53
|
+
for iCnt, elemsub in enumerate( elem.elements ):
|
|
54
|
+
if isinstance( elemsub, symexpress3.SymArray ) and elemsub.power == 1 and elemsub.onlyOneRoot == 1:
|
|
55
|
+
# get the sub elements
|
|
56
|
+
for elemsub2 in elemsub.elements :
|
|
57
|
+
result.add( elemsub2 )
|
|
58
|
+
else:
|
|
59
|
+
result.add( elemsub )
|
|
60
|
+
|
|
61
|
+
return result
|
|
62
|
+
|
|
63
|
+
def _subExpandSymFunction( elem ):
|
|
64
|
+
result = None
|
|
65
|
+
iArrPos = -1
|
|
66
|
+
for iCnt, elemsub in enumerate( elem.elements ):
|
|
67
|
+
if isinstance( elemsub, symexpress3.SymArray ):
|
|
68
|
+
if elemsub.power != 1 or elemsub.onlyOneRoot != 1:
|
|
69
|
+
continue
|
|
70
|
+
iArrPos = iCnt
|
|
71
|
+
if iArrPos == -1:
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
result = symexpress3.SymArray()
|
|
75
|
+
arrElem = elem.elements[ iArrPos ].copy()
|
|
76
|
+
iNumArray = arrElem.numElements()
|
|
77
|
+
elem.elements[ iArrPos ] = symexpress3.SymNumber() # place holder
|
|
78
|
+
|
|
79
|
+
for iCnt in range( 0, iNumArray ):
|
|
80
|
+
elemSub = elem.copy()
|
|
81
|
+
elemSub.elements[ iArrPos ] = arrElem.elements[ iCnt ]
|
|
82
|
+
result.add( elemSub )
|
|
83
|
+
|
|
84
|
+
return result
|
|
85
|
+
|
|
86
|
+
def _subExpandSymSymExpress( elem ):
|
|
87
|
+
return _subExpandSymFunction( elem )
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
if self.checkType( elem, action ) != True:
|
|
91
|
+
return None
|
|
92
|
+
|
|
93
|
+
# if not isinstance( elem, ( symexpress3.SymArray, symexpress3.SymFunction, symexpress3.SymExpress)) :
|
|
94
|
+
if not isinstance( elem, ( symexpress3.SymArray, symexpress3.SymFunction)) :
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
result = None
|
|
98
|
+
if isinstance( elem, symexpress3.SymArray ):
|
|
99
|
+
result = _subExpandSymArray( elem )
|
|
100
|
+
elif isinstance( elem, symexpress3.SymFunction ):
|
|
101
|
+
result = _subExpandSymFunction( elem )
|
|
102
|
+
# elif isinstance( elem, symexpress3.SymExpress ):
|
|
103
|
+
# result = _subExpandSymSymExpress( elem )
|
|
104
|
+
return result
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
#
|
|
108
|
+
# Test routine (unit test), see testsymexpress3.py
|
|
109
|
+
#
|
|
110
|
+
def Test( display = False):
|
|
111
|
+
"""
|
|
112
|
+
Unit test
|
|
113
|
+
"""
|
|
114
|
+
symTest = symexpress3.SymFormulaParser( "[ 4 | [ a | b ] | 4 ]" )
|
|
115
|
+
symTest.optimize()
|
|
116
|
+
symTest = symTest.elements[ 0 ]
|
|
117
|
+
testClass = OptSymAnyExpandArray()
|
|
118
|
+
symNew = testClass.optimize( symTest, "expandArrays" )
|
|
119
|
+
|
|
120
|
+
if display == True :
|
|
121
|
+
print( f"naam : {testClass.name}" )
|
|
122
|
+
print( f"orginal : {str( symTest )}" )
|
|
123
|
+
print( f"optimized : {str( symNew )}" )
|
|
124
|
+
|
|
125
|
+
if str( symNew ).strip() != "[ 4 | a | b | 4 ]":
|
|
126
|
+
print( f"Error unit test {testClass.name} function" )
|
|
127
|
+
raise NameError( f'SymAny optimze {testClass.name}, unit test error: {str( symTest )}, value: {symNew}' )
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
symTest = symexpress3.SymFormulaParser( "cos( 1, [ 2 | 3 ], 4)" )
|
|
131
|
+
symTest.optimize()
|
|
132
|
+
symTest = symTest.elements[ 0 ]
|
|
133
|
+
testClass = OptSymAnyExpandArray()
|
|
134
|
+
symNew = testClass.optimize( symTest, "expandArrays" )
|
|
135
|
+
|
|
136
|
+
if display == True :
|
|
137
|
+
print( f"naam : {testClass.name}" )
|
|
138
|
+
print( f"orginal : {str( symTest )}" )
|
|
139
|
+
print( f"optimized : {str( symNew )}" )
|
|
140
|
+
|
|
141
|
+
if str( symNew ).strip() != "[ cos( 1,2,4 ) | cos( 1,3,4 ) ]":
|
|
142
|
+
print( f"Error unit test {testClass.name} function" )
|
|
143
|
+
raise NameError( f'SymAny optimze {testClass.name}, unit test error: {str( symTest )}, value: {symNew}' )
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# symTest = symexpress3.SymFormulaParser( "4 + [ 5 | 6 ]" )
|
|
147
|
+
# symTest.optimize()
|
|
148
|
+
# # symTest = symTest.elements[ 0 ]
|
|
149
|
+
# testClass = OptSymAnyExpandArray()
|
|
150
|
+
# symNew = testClass.optimize( symTest, "expandArrays" )
|
|
151
|
+
|
|
152
|
+
# if display == True :
|
|
153
|
+
# print( f"naam : {testClass.name}" )
|
|
154
|
+
# print( f"orginal : {str( symTest )}" )
|
|
155
|
+
# print( f"optimized : {str( symNew )}" )
|
|
156
|
+
|
|
157
|
+
# if str( symNew ).strip() != "[ 4 + 5 | 4 + 6 ]":
|
|
158
|
+
# print( f"Error unit test {testClass.name} function" )
|
|
159
|
+
# raise NameError( f'SymAny optimze {testClass.name}, unit test error: {str( symTest )}, value: {symNew}' )
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
if __name__ == '__main__':
|
|
163
|
+
Test( True )
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Registration any optimze for symexpress3
|
|
6
|
+
|
|
7
|
+
Copyright (C) 2024 Gien van den Enden - swvandenenden@gmail.com
|
|
8
|
+
|
|
9
|
+
This program is free software: you can redistribute it and/or modify
|
|
10
|
+
it under the terms of the GNU General Public License as published by
|
|
11
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
(at your option) any later version.
|
|
13
|
+
|
|
14
|
+
This program is distributed in the hope that it will be useful,
|
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
GNU General Public License for more details.
|
|
18
|
+
|
|
19
|
+
You should have received a copy of the GNU General Public License
|
|
20
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
Example documentenion:
|
|
24
|
+
pdoc3 --html symFuncCeilFloor.py
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from symexpress3 import symtables
|
|
29
|
+
from symexpress3.optSymAny import optSymAnyArrayPower
|
|
30
|
+
from symexpress3.optSymAny import optSymAnyExpandArray
|
|
31
|
+
|
|
32
|
+
#
|
|
33
|
+
# automatic called from symepxress3
|
|
34
|
+
#
|
|
35
|
+
def SymRegisterOptimize():
|
|
36
|
+
"""
|
|
37
|
+
Register all the any optimize classes
|
|
38
|
+
"""
|
|
39
|
+
symtables.RegisterTableEntry( 'optSymAny', optSymAnyArrayPower.OptSymAnyArrayPower() )
|
|
40
|
+
symtables.RegisterTableEntry( 'optSymAny', optSymAnyExpandArray.OptSymAnyExpandArray() )
|
|
41
|
+
|
|
42
|
+
#
|
|
43
|
+
# Get all the modules from the optSymVariable, used in testsymexpress3.py
|
|
44
|
+
#
|
|
45
|
+
def SymRegisterGetModuleNames():
|
|
46
|
+
"""
|
|
47
|
+
Get all the modules of the any optimizes
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
symModules = []
|
|
51
|
+
|
|
52
|
+
symModules.append( optSymAnyArrayPower )
|
|
53
|
+
symModules.append( optSymAnyExpandArray )
|
|
54
|
+
|
|
55
|
+
return symModules
|
|
56
|
+
|
|
57
|
+
if __name__ == '__main__':
|
|
58
|
+
SymRegisterOptimize()
|
|
59
|
+
print( "Modules: " + str( ( SymRegisterGetModuleNames() )))
|
|
60
|
+
# print( "globals: " + str( globals() ))
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Sym Express 3
|
|
6
|
+
|
|
7
|
+
Copyright (C) 2024 Gien van den Enden - swvandenenden@gmail.com
|
|
8
|
+
|
|
9
|
+
This program is free software: you can redistribute it and/or modify
|
|
10
|
+
it under the terms of the GNU General Public License as published by
|
|
11
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
(at your option) any later version.
|
|
13
|
+
|
|
14
|
+
This program is distributed in the hope that it will be useful,
|
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
GNU General Public License for more details.
|
|
18
|
+
|
|
19
|
+
You should have received a copy of the GNU General Public License
|
|
20
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from symexpress3 import symexpress3
|
|
27
|
+
from symexpress3 import optFunctionBase
|
|
28
|
+
|
|
29
|
+
class OptSymFunctionCosAtanDiv3( optFunctionBase.OptFunctionBase ):
|
|
30
|
+
"""
|
|
31
|
+
sin(atan(x)/n) to sin i cos
|
|
32
|
+
"""
|
|
33
|
+
def __init__( self ):
|
|
34
|
+
super().__init__()
|
|
35
|
+
self._name = "cosAtanDiv3"
|
|
36
|
+
self._desc = "Convert cos(atan(x)/3) to value"
|
|
37
|
+
self._funcName = "cos" # name of the function
|
|
38
|
+
self._minparams = 1 # minimum number of parameters
|
|
39
|
+
self._maxparams = 1 # maximum number of parameters
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def optimize( self, elem, action ):
|
|
43
|
+
# https://www.quora.com/Is-there-a-method-to-calculate-cos-%CF%80-7-and-sin-%CF%80-7
|
|
44
|
+
if self.checkType( elem, action ) != True:
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
elem1 = elem.elements[0]
|
|
48
|
+
if not isinstance( elem1, symexpress3.SymExpress ):
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
if elem1.symType != '*':
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
if elem1.numElements() != 2: # can be any number greater as 1 but for the moment only atan
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
elemA = elem1.elements[0]
|
|
58
|
+
elemB = elem1.elements[1]
|
|
59
|
+
# one must be a function, second must be number
|
|
60
|
+
|
|
61
|
+
if not isinstance( elemA, symexpress3.SymFunction):
|
|
62
|
+
elemB = elem1.elements[0]
|
|
63
|
+
elemA = elem1.elements[1]
|
|
64
|
+
|
|
65
|
+
if not isinstance( elemA, symexpress3.SymFunction):
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
if not isinstance( elemB, symexpress3.SymNumber):
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
if elemA.name != "atan": # can be anything but for the moment only atan
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
if elemB.power != 1:
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
if elemB.factSign != 1:
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
if elemB.factCounter != 1:
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
if elemB.factDenominator != 3:
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
# elemA = atan(x)
|
|
87
|
+
# elemB = 1/3
|
|
88
|
+
|
|
89
|
+
# "(( ((cos(x)^^2 - 1)^^(1/2) + cos(x))^^(1/3) + ( ((cos(x)^^2 - 1)^^(1/2) + cos(x))^^(1/3) )^^(-1))) * 1/2"
|
|
90
|
+
|
|
91
|
+
convertFrm = "(( ((cos(" + str( elemA ) + ")^^2 - 1)^^(1/2) + cos(" + str(elemA) + "))^^(1/3) + (( ((cos(" + str( elemA ) + ")^^2 - 1)^^(1/2) + cos(" + str(elemA) + "))^^(1/3) )^^(-1))) * 1/2"
|
|
92
|
+
|
|
93
|
+
exprResult = symexpress3.SymFormulaParser( convertFrm )
|
|
94
|
+
|
|
95
|
+
return exprResult
|
|
96
|
+
# https://www.quora.com/What-is-the-formula-for-sin-x-3-one-third-angle-formula
|
|
97
|
+
# sin(x/3) =
|
|
98
|
+
# (
|
|
99
|
+
# ( -1 * sin( x ) + (sin(x)^^2 - 1)^^(1/2) ) / 8
|
|
100
|
+
# )^^(1/3)
|
|
101
|
+
# +
|
|
102
|
+
# (
|
|
103
|
+
# ( -1 * sin( x ) - (sin(x)^^2 - 1)^^(1/2) ) / 8
|
|
104
|
+
# )^^(1/3)
|
|
105
|
+
#
|
|
106
|
+
# incorrecte antwoorden in de volgende situaties:
|
|
107
|
+
# x = pi / 2 - 1/10 -> fout antwoord, dezelfde als pi / 2 + 1/10
|
|
108
|
+
# x = pi / 2 + 1/10 -> goed antwoord
|
|
109
|
+
# x = pi / 2 -> goed antwoord -> dit lijkt een spiegel (mirror) te zijn,
|
|
110
|
+
# Alles hieronder is fout, alles hierboven is goed`
|
|
111
|
+
|
|
112
|
+
#
|
|
113
|
+
# Test routine (unit test), see testsymexpress3.py
|
|
114
|
+
#
|
|
115
|
+
def Test( display = False):
|
|
116
|
+
"""
|
|
117
|
+
Unit test
|
|
118
|
+
"""
|
|
119
|
+
symTest = symexpress3.SymFormulaParser( "cos(atan(x)/3)" )
|
|
120
|
+
symTest.optimize()
|
|
121
|
+
symTest = symTest.elements[ 0 ]
|
|
122
|
+
|
|
123
|
+
# print( "symTest: " + str( symTest ))
|
|
124
|
+
|
|
125
|
+
testClass = OptSymFunctionCosAtanDiv3()
|
|
126
|
+
symNew = testClass.optimize( symTest, "cosAtanDiv3" )
|
|
127
|
+
|
|
128
|
+
if display == True :
|
|
129
|
+
print( f"naam : {testClass.name}" )
|
|
130
|
+
print( f"orginal : {str( symTest )}" )
|
|
131
|
+
print( f"optimized : {str( symNew )}" )
|
|
132
|
+
|
|
133
|
+
if str( symNew ).strip() != "((( cos( atan( x ) )^^2 + (-1) * 1)^^(1/2) + cos( atan( x ) ))^^(1/3) + ((( cos( atan( x ) )^^2 + (-1) * 1)^^(1/2) + cos( atan( x ) ))^^(1/3))^^-1) * 1 * 2^^-1":
|
|
134
|
+
print( f"Error unit test {testClass.name} function" )
|
|
135
|
+
raise NameError( f'SymFunction optimze {testClass.name}, unit test error: {str( symTest )}, value: {str( symNew )}' )
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
if __name__ == '__main__':
|
|
139
|
+
Test( True )
|