Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add 2D sym functions and use them. #1235

Open
wants to merge 43 commits into
base: Array_not_Matrix
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
a7c44c0
Use a SymPy Array not a Matrix for non-Expr
cbm755 Oct 18, 2021
b618e5f
Python header: Add new function 'make_matrix_or_array'.
Aug 28, 2022
53059ac
@sym/private/mat_rclist_access.m: Test Array-compatible code.
Aug 22, 2022
54c8271
@sym/private/mat_rclist_asgn.m: Test Array-compatible code.
Aug 24, 2022
5385713
Merge branch 'test-array-in-mat_rclist_' into Array_not_Matrix
Aug 30, 2022
f1b210f
@sym/{horzcat,vertcat}: Fix typo.
Aug 30, 2022
d3b1547
@sym/vertcat: Make function Array-compatible.
Aug 29, 2022
136184d
@sym/transpose: Make function Array-compatible.
Aug 30, 2022
0d93602
@sym/horzcat: Make function Array-compatible by simplifying it.
Aug 30, 2022
fb044e3
@sym/private/mat_rclist_{access,asgn}: Remove unused variables.
Aug 31, 2022
9a3b3f0
Merge branch 'make-cats-array-compat' into Array_not_Matrix
Aug 31, 2022
65da8ab
@sym/repmat: Re-implement function without using 'pycall_sympy__'.
Sep 1, 2022
e895cc7
Merge branch 'repmat-without-pycall' into Array_not_Matrix
Sep 2, 2022
56bd719
elementwise_op: use 2d loop for Array
cbm755 Sep 2, 2022
30af4ef
uniop_bool_helper: Array support in "bool" case
cbm755 Sep 2, 2022
8b10a44
logical: remove 1-d indexing for Array support
cbm755 Sep 4, 2022
53fbee2
Minor fix to test: ctranspose of logical is tested elsewhere
cbm755 Sep 4, 2022
d36285c
Oops MatrixBase
cbm755 Sep 4, 2022
1381757
isAlways: avoid 1-d matrix/Array indexing
cbm755 Sep 4, 2022
37724d6
private/python_ipc_native: Disable 'dbg_no_array' to keep in sync...
Sep 4, 2022
a82cbd8
Merge branch '2dloop' into Array_not_Matrix
Sep 4, 2022
a1d3608
levels=1 sufficient with tolist() from 2dArray/Matrix
cbm755 Sep 6, 2022
269022d
Merge pull request #1224 from cbm755/uniop
cbm755 Sep 6, 2022
79d0526
subs: use make_matrix_or_array and use 2-d indexing
cbm755 Sep 3, 2022
ef9744d
Use S.Zero not integer 0
cbm755 Sep 5, 2022
551081b
Array: fix a failing test in subasgn
cbm755 Sep 5, 2022
526fe23
Merge branch 'subs' into Array_not_Matrix
Sep 6, 2022
b24005e
isconstant: fix behaviour with Array and add tests for errors
cbm755 Sep 6, 2022
693e055
find: work with Array
cbm755 Sep 6, 2022
9ce0a26
Fix some unused code
cbm755 Sep 6, 2022
bd795e8
@sym/vertcat: Use sympy function 'flatten'.
Sep 6, 2022
1f8163e
@sym/private/mat_rclist_asgn: Use sympy function 'flatten'.
Sep 6, 2022
c9f6f0f
@sym/transpose: Use sympy function 'transpose'.
Sep 6, 2022
321ee17
@sym/private/mat_replace: Make matrix mutable before modifying.
Sep 6, 2022
05fbad6
Merge branch 'use-sympy-funcs' into use-sympy-funcs-and-generalise
Sep 6, 2022
59176a2
make_matrix_or_array: Generalise to accept an iterable of iterables.
Sep 6, 2022
0327827
Merge branch 'use-sympy-funcs-and-generalise' into Array_not_Matrix
Sep 6, 2022
5ea9b30
elementwise_op: call make_array_or_matrix
cbm755 Sep 7, 2022
3c0e95c
Rough gating of Array on older SymPy
cbm755 Sep 7, 2022
7ee32e5
Merge pull request #1229 from cbm755/more_ndim
cbm755 Sep 13, 2022
48ddaaf
Merge pull request #1233 from cbm755/central
cbm755 Sep 13, 2022
e74ce50
Python header: Rename 'make_matrix_or_array' -> 'make_2d_sym'.
Aug 31, 2022
d4f5427
Python header: Add more 2D sym functions.
Aug 31, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions inst/@sym/find.m
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@
' return r'
'#'
'x, = _ins'
'if x is not None and x.is_Matrix:'
' x = [a for a in x.T]' % note transpose
'if isinstance(x, (MatrixBase, NDimArray)):'
' x = [a for a in flatten(transpose(x).tolist(), levels=1)]' % note transpose
'else:'
' x = [x,]'
'return [scalar2tf(a) for a in x],' };
Expand Down
24 changes: 4 additions & 20 deletions inst/@sym/horzcat.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
%% Copyright (C) 2014-2017, 2019 Colin B. Macdonald
%% Copyright (C) 2022 Alex Vong
%%
%% This file is part of OctSymPy.
%%
Expand All @@ -21,7 +22,7 @@
%% @defop Method @@sym {horzcat} {(@var{x}, @var{y}, @dots{})}
%% @defopx Operator @@sym {[@var{x}, @var{y}, @dots{}]} {}
%% @defopx Operator @@sym {[@var{x} @var{y} @dots{}]} {}
%% Horizontally concatentate symbolic arrays.
%% Horizontally concatenate symbolic arrays.
%%
%% Example:
%% @example
Expand All @@ -45,25 +46,8 @@

function h = horzcat(varargin)

% special case for 0x0 but other empties should be checked for
% compatibilty
cmd = {
'_proc = []'
'for i in _ins:'
' if i is None or not i.is_Matrix:'
' _proc.append(sp.Matrix([[i]]))'
' else:'
' if i.shape == (0, 0):'
' pass'
' else:'
' _proc.append(i)'
'return sp.MatrixBase.hstack(*_proc),'
};

for i = 1:nargin
varargin{i} = sym(varargin{i});
end
h = pycall_sympy__ (cmd, varargin{:});
args = cellfun (@transpose, varargin, 'UniformOutput', false);
h = vertcat (args{:}).';

end

Expand Down
4 changes: 2 additions & 2 deletions inst/@sym/isAlways.m
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@

cmd = vertcat(cmd, {
'(x, unknown) = _ins'
'if x is not None and x.is_Matrix:'
' r = [a for a in x.T]' % note transpose
'if isinstance(x, (MatrixBase, NDimArray)):'
' r = [a for a in flatten(transpose(x).tolist(), levels=1)]' % note tranpose
'else:'
' r = [x,]'
'r = [simplify_tfn(a) for a in r]'
Expand Down
13 changes: 12 additions & 1 deletion inst/@sym/isconstant.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
function z = isconstant(x)

cmd = { '(x,) = _ins'
'if x is not None and x.is_Matrix:'
'if isinstance(x, (MatrixBase, NDimArray)):'
' return x.applyfunc(lambda a: a.is_constant()),'
'return x.is_constant(),' };
z = pycall_sympy__ (cmd, sym(x));
Expand All @@ -68,3 +68,14 @@
%! A = [x 2; 3 x];
%! B = [false true; true false];
%! assert (isequal (isconstant (A), B))

%!error
%! % semantically not an error, but is using SymPy's Array
%! t = sym(true);
%! A = [t t];
%! isconstant (A);

%!error
%! syms x
%! A = [x == 10; x <= 10];
%! isconstant (A);
8 changes: 4 additions & 4 deletions inst/@sym/logical.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
%% Copyright (C) 2014-2016, 2019 Colin B. Macdonald
%% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald
%%
%% This file is part of OctSymPy.
%%
Expand Down Expand Up @@ -100,8 +100,8 @@

cmd = vertcat(cmd, {
'(x, unknown) = _ins'
'if x is not None and x.is_Matrix:'
' r = [a for a in x.T]' % note transpose
'if isinstance(x, (MatrixBase, NDimArray)):'
' r = [a for a in flatten(transpose(x).tolist(), levels=1)]' % note tranpose
'else:'
' r = [x,]'
'r = [scalar2tfn(a) for a in r]'
Expand Down Expand Up @@ -178,7 +178,7 @@
%! w = logical(e);
%! assert (islogical (w))
%! assert (isequal (w, [true false true]))
%! e = e';
%! e = e.';
%! w = logical(e);
%! assert (islogical (w))
%! assert (isequal (w, [true; false; true]))
Expand Down
15 changes: 9 additions & 6 deletions inst/@sym/private/elementwise_op.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
%% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald
%% Copyright (C) 2014, 2016, 2018-2019, 2021-2022 Colin B. Macdonald
%% Copyright (C) 2016 Lagu
%%
%% This file is part of OctSymPy.
Expand Down Expand Up @@ -84,7 +84,7 @@
% Make sure all matrices in the input are the same size, and set q to one of them
'q = None'
'for A in _ins:'
' if isinstance(A, MatrixBase):'
' if isinstance(A, (MatrixBase, NDimArray)):'
' if q is None:'
' q = A'
' else:'
Expand All @@ -94,10 +94,13 @@
' return _op(*_ins)'
% at least one input was a matrix:
'# dbout(f"at least one matrix param, shape={q.shape}")'
'elements = []'
'for i in range(0, len(q)):'
' elements.append(_op(*[k[i] if isinstance(k, MatrixBase) else k for k in _ins]))'
'return Matrix(*q.shape, elements)' ];
'assert len(q.shape) == 2, "non-2D arrays/tensors not yet supported"'
'm, n = q.shape'
'g = [[0]*n for i in range(m)]'
'for i in range(m):'
' for j in range(n):'
' g[i][j] = _op(*[k[i, j] if isinstance(k, (MatrixBase, NDimArray)) else k for k in _ins])'
'return make_2d_sym(g)' ];

z = pycall_sympy__ (cmd, varargin{:});

Expand Down
15 changes: 6 additions & 9 deletions inst/@sym/private/mat_rclist_access.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
%% Copyright (C) 2014, 2016, 2019, 2022 Colin B. Macdonald
%% Copyright (C) 2022 Alex Vong
%%
%% This file is part of OctSymPy.
%%
Expand Down Expand Up @@ -32,15 +33,11 @@
error('this routine is for a list of rows and cols');
end

cmd = { '(A, rr, cc) = _ins'
'if A is None or not A.is_Matrix:'
' A = sp.Matrix([A])'
'n = len(rr)'
'M = [[0] for i in range(n)]'
'for i in range(0, n):'
' M[i][0] = A[rr[i],cc[i]]'
'M = sp.Matrix(M)'
'return M,' };
cmd = {'(A, rr, cc) = _ins'
'AA = list_from_2d_sym(A) if is_2d_sym(A) else [[A]]'
'MM = [[AA[i][j]] for i, j in zip(rr, cc)]'
'M = make_2d_sym(MM)'
'return M,'};

rr = num2cell(int32(r-1));
cc = num2cell(int32(c-1));
Expand Down
59 changes: 28 additions & 31 deletions inst/@sym/private/mat_rclist_asgn.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
%% Copyright (C) 2014, 2016-2017, 2019, 2022 Colin B. Macdonald
%% Copyright (C) 2020 Mike Miller
%% Copyright (C) 2020 Fernando Alvarruiz
%% Copyright (C) 2022 Alex Vong
%%
%% This file is part of OctSymPy.
%%
Expand Down Expand Up @@ -59,40 +60,36 @@
% AA[0, 0] = A
% Also usefil: .copyin_matrix

cmd = { '(A, r, c, B) = _ins'
'# B linear access fix, transpose for sympy row-based'
'if B is None or not B.is_Matrix:'
' B = sp.Matrix([[B]])'
'BT = B.T'
'# make a resized copy of A, and copy existing stuff in'
'if isinstance(A, list):'
' assert len(A) == 0, "unexpectedly non-empty list: report bug!"'
' n = max(max(r) + 1, 1)'
' m = max(max(c) + 1, 1)'
' AA = [[0]*m for i in range(n)]'
'elif A is None or not isinstance(A, MatrixBase):'
' # we have non-matrix, put in top-left'
' n = max(max(r) + 1, 1)'
' m = max(max(c) + 1, 1)'
' AA = [[0]*m for i in range(n)]'
' AA[0][0] = A'
'else:'
' # build bigger matrix'
' n = max(max(r) + 1, A.rows)'
' m = max(max(c) + 1, A.cols)'
' AA = [[0]*m for i in range(n)]'
' # copy current matrix in'
' for i in range(A.rows):'
' for j in range(A.cols):'
' AA[i][j] = A[i, j]'
'# now insert the new bits from B'
'for i, (r, c) in enumerate(zip(r, c)):'
' AA[r][c] = BT[i]'
'return sp.Matrix(AA),' };
cmd = {'(A, rr, cc, b) = _ins'
'assert A == [] or not isinstance(A, list), "unexpectedly non-empty list: report bug!"'
'if A == []:'
' AA = []'
' (nrows_A, ncols_A) = (0, 0)'
'elif is_2d_sym(A):'
' AA = list_from_2d_sym(A)'
' (nrows_A, ncols_A) = shape_of_2d_sym(A)'
'else:'
' AA = [[A]]'
' (nrows_A, ncols_A) = (1, 1)'
'bb = list_from_2d_sym(b) if is_2d_sym(b) else [[b]]'
'entries = dict(zip(zip(rr, cc), flatten(bb, levels=1)))'
'def entry(i, j):'
' if (i, j) in entries:'
' return entries[i, j]'
' elif i < nrows_A and j < ncols_A:'
' return AA[i][j]'
' else:'
' return S.Zero'
'n = max(max(rr) + 1, nrows_A)'
'm = max(max(cc) + 1, ncols_A)'
'MM = [[entry(i, j) for j in range(m)] for i in range(n)]'
'M = make_2d_sym(MM)'
'return M,'};

rr = num2cell(int32(r-1));
cc = num2cell(int32(c-1));
z = pycall_sympy__ (cmd, A, rr, cc, B);
b = vec (B); # B is accessed with linear indexing, as a column vector
z = pycall_sympy__ (cmd, A, rr, cc, b);

% a simpler earlier version, but only for scalar r,c
%cmd = { '(A, r, c, b) = _ins'
Expand Down
7 changes: 5 additions & 2 deletions inst/@sym/private/mat_replace.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
%% Copyright (C) 2016 Lagu
%% Copyright (C) 2016 Abhinav Tripathi
%% Copyright (C) 2020 Fernando Alvarruiz
%% Copyright (C) 2022 Alex Vong
%%
%% This file is part of OctSymPy.
%%
Expand Down Expand Up @@ -154,7 +155,8 @@
if isscalar (A)
z = sym(zeros (1, 0));
else
cmd = { 'A, subs = _ins'
cmd = { 'AA, subs = _ins'
'A = AA.as_mutable()'
'if isinstance(subs, Integer):'
' A.col_del(subs - 1)'
' return A,'
Expand All @@ -171,7 +173,8 @@
% no test coverage: not sure how to hit this
z = sym(zeros (0, 1));
else
cmd = { 'A, subs = _ins'
cmd = { 'AA, subs = _ins'
'A = AA.as_mutable()'
'if isinstance(subs, Integer):'
' A.row_del(subs - 1)'
' return A,'
Expand Down
9 changes: 5 additions & 4 deletions inst/@sym/private/uniop_bool_helper.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
%% Copyright (C) 2016, 2019 Colin B. Macdonald
%% Copyright (C) 2016, 2019, 2022 Colin B. Macdonald
%%
%% This file is part of OctSymPy.
%%
Expand Down Expand Up @@ -51,9 +51,9 @@
cmd = [ cmd
'x = _ins[0]'
'pp = _ins[1:]'
'if x is not None and x.is_Matrix:'
'if isinstance(x, (MatrixBase, NDimArray)):'
' # bool will map None to False'
' return [bool(sf(a, *pp)) for a in x.T],'
' return [bool(sf(a, *pp)) for a in flatten(transpose(x).tolist(), levels=1)],'
'return bool(sf(x, *pp))' ];

r = pycall_sympy__ (cmd, x, varargin{:});
Expand All @@ -65,10 +65,11 @@
case 'sym'
warning('FIXME: not working for scalars')

% currently unused, and certainly not tested
cmd = [ cmd
'x = _ins[0]'
'pp = _ins[1:]'
'if x if not None and x.is_Matrix:'
'if isinstance(x, (MatrixBase, NDimArray)):'
' return x.applyfunc(sf, *pp)'
'return sf(x, *pp)' ];

Expand Down
34 changes: 23 additions & 11 deletions inst/@sym/repmat.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
%% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald
%% Copyright (C) 2022 Alex Vong
%%
%% This file is part of OctSymPy.
%%
Expand Down Expand Up @@ -51,18 +52,21 @@
print_usage ();
end

cmd = { '(A, n, m) = _ins'
'if n == 0 or m == 0:'
' return sp.Matrix(n, m, [])'
'if A is None or not A.is_Matrix:'
' A = sp.Matrix([A])'
'L = [A]*m'
'B = sp.Matrix.hstack(*L)'
'L = [B]*n'
'B = sp.Matrix.vstack(*L)'
'return B' };
if n == 0 || m == 0
[nrows_A, ncols_A] = size (A);
B = sym (zeros (n * nrows_A, m * ncols_A));
return
end

%% duplicate A horizontally m times
MM = cellfun (@(varargin) A, cell (1, m), 'UniformOutput', false);
M = horzcat (MM{:});

%% now duplicate that result vertically n times
NN = cellfun (@(varargin) M, cell (1, n), 'UniformOutput', false);
N = vertcat (NN{:});

B = pycall_sympy__ (cmd, sym(A), int32(n), int32(m));
B = N;

end

Expand Down Expand Up @@ -95,3 +99,11 @@
%! assert (isequal (size(A), [0 3]))
%! A = repmat(sym(pi), [2 0]);
%! assert (isequal (size(A), [2 0]))

%!test
%! % even more empties, see also https://github.com/cbm755/octsympy/issues/1218
%! A = randi (16, 5, 7);
%! assert (isa (repmat (sym (A), [0 3]), 'sym'));
%! assert (isa (repmat (sym (A), [2 0]), 'sym'));
%! assert (isequal (sym (repmat (A, [0 3])), (repmat (sym (A), [0 3]))));
%! assert (isequal (sym (repmat (A, [2 0])), (repmat (sym (A), [2 0]))));
9 changes: 5 additions & 4 deletions inst/@sym/reshape.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
%% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald
%% Copyright (C) 2014, 2016, 2019, 2022 Colin B. Macdonald
%%
%% This file is part of OctSymPy.
%%
Expand Down Expand Up @@ -75,9 +75,10 @@

cmd = {
'(A, n, m) = _ins'
'if A is not None and A.is_Matrix:'
' #sympy is row-based'
' return A.T.reshape(m,n).T'
'if isinstance(A, (MatrixBase, NDimArray)):'
' #sympy is row-based, but Array does not have .T'
' #return A.T.reshape(m,n).T'
' return transpose(transpose(A).reshape(m, n))'
'else:'
' if n != 1 or m != 1:'
' raise ValueError("cannot reshape scalar to non-1x1 size")'
Expand Down
Loading