Mentions légales du service
Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
faust
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
faust group
faust
Commits
cd73786a
Commit
cd73786a
authored
2 years ago
by
hhakim
Browse files
Options
Downloads
Patches
Plain Diff
Add pyfaust.LazyLinearOperator and aslazylinearoperator.
Update related unit tests to use those functions.
parent
013aae0d
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
wrapper/python/pyfaust/lazylinop.py
+99
-8
99 additions, 8 deletions
wrapper/python/pyfaust/lazylinop.py
wrapper/python/pyfaust/tests/TestLazyLinearOp2.py
+9
-8
9 additions, 8 deletions
wrapper/python/pyfaust/tests/TestLazyLinearOp2.py
with
108 additions
and
16 deletions
wrapper/python/pyfaust/lazylinop.py
+
99
−
8
View file @
cd73786a
...
@@ -716,7 +716,45 @@ def asLazyLinearOp(obj):
...
@@ -716,7 +716,45 @@ def asLazyLinearOp(obj):
<b>See also:</b> pyfaust.rand.
<b>See also:</b> pyfaust.rand.
"""
"""
return
LazyLinearOp
.
create
(
obj
)
return
LazyLinearOp2
.
create_from_op
(
obj
)
def
aslazylinearoperator
(
obj
):
"""
Creates a LazyLinearOp based on the object obj which must be of a linear operator compatible type.
NOTE: obj must support operations and attributes defined in the
LazyLinearOp class.
Any operation not supported would raise an exception at the evaluation
time.
Args:
obj: the root object on which the LazyLinearOp is based (it could
be a numpy array, a scipy matrix, a Faust object or almost any
object that supports the same kind of functions).
Returns:
a LazyLinearOp instance based on obj.
Example:
>>>
from
pyfaust.lazylinop
import
asLazyLinearOp
>>>
import
numpy
as
np
>>>
M
=
np
.
random
.
rand
(
10
,
12
)
>>>
lM
=
azlazylinearoperator
(
M
)
>>>
twolM
=
lM
+
lM
>>>
twolM
<
pyfaust
.
lazylinop
.
LazyLinearOp
at
0x7fcd7d7750f0
>
>>>
import
pyfaust
as
pf
>>>
F
=
pf
.
rand
(
10
,
12
)
>>>
lF
=
azlazylinearoperator
(
F
)
>>>
twolF
=
lF
+
lF
>>>
twolF
<
pyfaust
.
lazylinop
.
LazyLinearOp
at
0x7fcd7d774730
>
<b>See also:</b> pyfaust.rand.
"""
return
LazyLinearOp2
.
create_from_op
(
obj
)
def
hstack
(
tup
):
def
hstack
(
tup
):
"""
"""
...
@@ -912,7 +950,7 @@ class LazyLinearOp2(LinearOperator):
...
@@ -912,7 +950,7 @@ class LazyLinearOp2(LinearOperator):
Warning: This code is in a beta status.
Warning: This code is in a beta status.
"""
"""
def
__init__
(
self
,
lambdas
,
shape
,
root_obj
):
def
__init__
(
self
,
lambdas
,
shape
,
root_obj
,
dtype
=
None
):
"""
"""
Constructor. Not meant to be used directly.
Constructor. Not meant to be used directly.
...
@@ -936,7 +974,7 @@ class LazyLinearOp2(LinearOperator):
...
@@ -936,7 +974,7 @@ class LazyLinearOp2(LinearOperator):
self
.
shape
=
shape
self
.
shape
=
shape
self
.
_root_obj
=
root_obj
#TODO: delete because it can't always be
self
.
_root_obj
=
root_obj
#TODO: delete because it can't always be
# defined (create_from_funcs and hybrid operations)
# defined (create_from_funcs and hybrid operations)
self
.
dtype
=
Non
e
self
.
dtype
=
dtyp
e
super
(
LazyLinearOp2
,
self
).
__init__
(
self
.
dtype
,
self
.
shape
)
super
(
LazyLinearOp2
,
self
).
__init__
(
self
.
dtype
,
self
.
shape
)
def
_check_lambdas
(
self
):
def
_check_lambdas
(
self
):
...
@@ -987,10 +1025,10 @@ class LazyLinearOp2(LinearOperator):
...
@@ -987,10 +1025,10 @@ class LazyLinearOp2(LinearOperator):
l
[
'
T
'
]
=
None
l
[
'
T
'
]
=
None
l
[
'
H
'
]
=
None
l
[
'
H
'
]
=
None
l
[
'
slice
'
]
=
None
l
[
'
slice
'
]
=
None
lop
=
LazyLinearOp2
(
lambdas
,
obj
.
shape
,
obj
)
lop
=
LazyLinearOp2
(
lambdas
,
obj
.
shape
,
obj
,
dtype
=
obj
.
dtype
)
lopT
=
LazyLinearOp2
(
lambdasT
,
(
obj
.
shape
[
1
],
obj
.
shape
[
0
]),
obj
)
lopT
=
LazyLinearOp2
(
lambdasT
,
(
obj
.
shape
[
1
],
obj
.
shape
[
0
]),
obj
,
dtype
=
obj
.
dtype
)
lopH
=
LazyLinearOp2
(
lambdasH
,
(
obj
.
shape
[
1
],
obj
.
shape
[
0
]),
obj
)
lopH
=
LazyLinearOp2
(
lambdasH
,
(
obj
.
shape
[
1
],
obj
.
shape
[
0
]),
obj
,
dtype
=
obj
.
dtype
)
lopC
=
LazyLinearOp2
(
lambdasC
,
(
obj
.
shape
[
0
],
obj
.
shape
[
1
]),
obj
)
lopC
=
LazyLinearOp2
(
lambdasC
,
(
obj
.
shape
[
0
],
obj
.
shape
[
1
]),
obj
,
dtype
=
obj
.
dtype
)
# TODO: refactor with create_from_funcs (in ctor)
# TODO: refactor with create_from_funcs (in ctor)
lambdas
[
'
T
'
]
=
lambda
:
lopT
lambdas
[
'
T
'
]
=
lambda
:
lopT
...
@@ -1015,7 +1053,7 @@ class LazyLinearOp2(LinearOperator):
...
@@ -1015,7 +1053,7 @@ class LazyLinearOp2(LinearOperator):
return
create_from_op
(
a
)
return
create_from_op
(
a
)
@staticmethod
@staticmethod
def
create_from_funcs
(
matmat
,
rmatmat
,
shape
):
def
create_from_funcs
(
matmat
,
rmatmat
,
shape
,
dtype
=
None
):
from
scipy.sparse
import
eye
as
seye
from
scipy.sparse
import
eye
as
seye
#MX = lambda X: matmat(np.eye(shape[1])) @ X
#MX = lambda X: matmat(np.eye(shape[1])) @ X
...
@@ -1722,3 +1760,56 @@ class LazyLinearOp2(LinearOperator):
...
@@ -1722,3 +1760,56 @@ class LazyLinearOp2(LinearOperator):
if
not
all
(
issubclass
(
t
,
LazyLinearOp
)
for
t
in
types
):
if
not
all
(
issubclass
(
t
,
LazyLinearOp
)
for
t
in
types
):
return
NotImplemented
return
NotImplemented
return
HANDLED_FUNCTIONS
[
func
](
*
args
,
**
kwargs
)
return
HANDLED_FUNCTIONS
[
func
](
*
args
,
**
kwargs
)
def
LazyLinearOperator
(
shape
,
**
kwargs
):
"""
Returns a LazyLinearOp defined by shape and at least matvec.
NOTE: At least a matvec or a matmat function must be passed in kwargs.
Args:
shape: (tuple) dimensions (M, N).
matvec: (callable) returns A * v (v a vector).
rmatvec: (callable) returns A^H * v (v a vector of size N).
matmat: (callable) returns A * V (V a dense matrix of dimensions (N, K)).
rmatmat: (callable) returns A^H * V (V a dense matrix of dimensions (M, K)).
dtype: data type of the matrix (can be None).
"""
matvec
,
rmatvec
,
matmat
,
rmatmat
=
[
None
for
i
in
range
(
4
)]
def
callable_err
(
k
):
return
TypeError
(
k
+
'
in kwargs must be a callable/function
'
)
for
k
in
kwargs
.
keys
():
if
k
!=
'
dtype
'
and
not
callable
(
kwargs
[
k
]):
raise
callable_err
(
k
)
if
'
matvec
'
in
kwargs
.
keys
():
matvec
=
kwargs
[
'
matvec
'
]
if
'
rmatvec
'
in
kwargs
.
keys
():
rmatvec
=
kwargs
[
'
rmatvec
'
]
if
'
matmat
'
in
kwargs
.
keys
():
matmat
=
kwargs
[
'
matmat
'
]
if
'
rmatmat
'
in
kwargs
.
keys
():
rmatmat
=
kwargs
[
'
rmatmat
'
]
if
'
dtype
'
in
kwargs
.
keys
():
dtype
=
kwargs
[
'
dtype
'
]
else
:
dtype
=
None
if
matvec
is
None
and
matmat
is
None
:
raise
ValueError
(
'
At least a matvec or a matmat function must be
'
'
passed in kwargs.
'
)
def
_matmat
(
M
,
_matvec
):
out
=
np
.
empty
((
shape
[
0
],
M
.
shape
[
1
]),
dtype
=
dtype
if
dtype
is
not
None
else
M
.
dtype
)
for
i
in
range
(
M
.
shape
[
1
]):
out
[:,
i
]
=
_matvec
(
M
[:,
i
])
return
out
if
matmat
is
None
:
matmat
=
lambda
M
:
_matmat
(
M
,
matvec
)
if
rmatmat
is
None
and
rmatvec
is
not
None
:
rmatmat
=
lambda
M
:
_matmat
(
M
,
rmatvec
)
return
LazyLinearOp2
.
create_from_funcs
(
matmat
,
rmatmat
,
shape
,
dtype
=
dtype
)
This diff is collapsed.
Click to expand it.
wrapper/python/pyfaust/tests/TestLazyLinearOp2.py
+
9
−
8
View file @
cd73786a
import
unittest
import
unittest
import
pyfaust
as
pf
import
pyfaust
as
pf
from
pyfaust.lazylinop
import
LazyLinearOp2
,
vstack
,
hstack
,
LazyLinearOp2
from
pyfaust.lazylinop
import
(
LazyLinearOp2
,
vstack
,
hstack
,
LazyLinearOp2
,
LazyLinearOperator
,
aslazylinearoperator
)
import
numpy.linalg
as
LA
import
numpy.linalg
as
LA
import
numpy
as
np
import
numpy
as
np
class
TestLazyLinearOpFaust
(
unittest
.
TestCase
):
class
TestLazyLinearOpFaust
(
unittest
.
TestCase
):
def
setUp
(
self
):
def
setUp
(
self
):
self
.
lop
=
L
azy
L
inear
Op2
.
create_from_op
(
pf
.
rand
(
10
,
15
))
self
.
lop
=
asl
azy
l
inear
operator
(
pf
.
rand
(
10
,
15
))
self
.
lopA
=
self
.
lop
.
toarray
()
self
.
lopA
=
self
.
lop
.
toarray
()
self
.
lop2
=
L
azy
L
inear
Op2
.
create_from_op
(
pf
.
rand
(
self
.
lop
.
shape
[
0
],
self
.
lop
.
shape
[
1
]))
self
.
lop2
=
asl
azy
l
inear
operator
(
pf
.
rand
(
self
.
lop
.
shape
[
0
],
self
.
lop
.
shape
[
1
]))
self
.
lop2A
=
self
.
lop2
.
toarray
()
self
.
lop2A
=
self
.
lop2
.
toarray
()
self
.
lop3
=
L
azy
L
inear
Op2
.
create_from_op
(
pf
.
rand
(
self
.
lop
.
shape
[
1
],
self
.
lop
.
shape
[
0
]))
self
.
lop3
=
asl
azy
l
inear
operator
(
pf
.
rand
(
self
.
lop
.
shape
[
1
],
self
.
lop
.
shape
[
0
]))
self
.
lop3A
=
self
.
lop3
.
toarray
()
self
.
lop3A
=
self
.
lop3
.
toarray
()
def
test_shape
(
self
):
def
test_shape
(
self
):
...
@@ -234,12 +235,12 @@ class TestLazyLinearOpFFTFunc(TestLazyLinearOpFaust):
...
@@ -234,12 +235,12 @@ class TestLazyLinearOpFFTFunc(TestLazyLinearOpFaust):
from
scipy.fft
import
fft
,
ifft
from
scipy.fft
import
fft
,
ifft
# axis = 0 to be consistent with LazyLinearOp2.toarray() which applies
# axis = 0 to be consistent with LazyLinearOp2.toarray() which applies
# fft on columns of the matrix, not on the rows (axis=1)
# fft on columns of the matrix, not on the rows (axis=1)
self
.
lop
=
LazyLinearOp
2
.
create_from_funcs
(
lambda
x
:
fft
(
x
,
axis
=
0
),
self
.
lop
=
LazyLinearOp
erator
((
8
,
8
),
matmat
=
lambda
x
:
fft
(
x
,
axis
=
0
),
lambda
x
:
8
*
ifft
(
x
,
axis
=
0
)
,
(
8
,
8
)
)
rmatmat
=
lambda
x
:
8
*
ifft
(
x
,
axis
=
0
))
self
.
lopA
=
self
.
lop
.
toarray
()
self
.
lopA
=
self
.
lop
.
toarray
()
self
.
lop2
=
L
azy
L
inear
Op2
.
create_from_op
(
pf
.
rand
(
self
.
lop
.
shape
[
0
],
self
.
lop
.
shape
[
1
]))
self
.
lop2
=
asl
azy
l
inear
operator
(
pf
.
rand
(
self
.
lop
.
shape
[
0
],
self
.
lop
.
shape
[
1
]))
self
.
lop2A
=
self
.
lop2
.
toarray
()
self
.
lop2A
=
self
.
lop2
.
toarray
()
self
.
lop3
=
L
azy
L
inear
Op2
.
create_from_op
(
pf
.
rand
(
self
.
lop
.
shape
[
1
],
self
.
lop
.
shape
[
0
]))
self
.
lop3
=
asl
azy
l
inear
operator
(
pf
.
rand
(
self
.
lop
.
shape
[
1
],
self
.
lop
.
shape
[
0
]))
self
.
lop3A
=
self
.
lop3
.
toarray
()
self
.
lop3A
=
self
.
lop3
.
toarray
()
if
'
__main__
'
==
__name__
:
if
'
__main__
'
==
__name__
:
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment