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] Change @sym to a classdef. #590

Open
wants to merge 14 commits into
base: master
Choose a base branch
from

Conversation

genuinelucifer
Copy link
Contributor

Fixed issue #545

This is at very early stage. MOST of the tests fail with this change. This is here just for discussion.

@@ -65,7 +65,7 @@

% Note: symbolic sized matrices should return double, not sym/string.

n = x.size;
n = x.symsize;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was required. Because if I used size as property in the sym class then too (weirdly) octave called the size function and did not use the property..

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that because @sym/subsref explicitly forbids public access of x.size?

@genuinelucifer
Copy link
Contributor Author

I got some error about no class symfun so I thought of converting that to classdef too. Now many of the BIST tests are passing. :)
Hopefully we can have completely working classdefs within a few days...

@@ -62,7 +62,7 @@
'return sp.Matrix.hstack(*_proc),'
};

varargin = sym(varargin);
varargin = cell_array_to_sym(varargin);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change (and other similar ones) are required because after converting sym to classdef, octave is not allowing to call the constructor with a cell array!!!
That is, sym({1}) fails!!! I tried with some test classdef classes but the same error didn't appear. Something is different/weird with respect to sym only!

Copy link
Contributor

@latot latot Oct 1, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mm, this is weird, in my case works fine cells with sym, in my octave the classdeff can't access to the private functions....

octave:12> sym(2)
error: 'magic_double_str' undefined near line 230 column 19
error: called from
    sym at line 230 column 17

maybe move the private files functions need sym to sym in private functions?
list of functions need sym:
*cell_array_to_sym
*numeric_array_to_sym
*magic_double_str
what version of octave are you using? (i'm using 4.2.0-rc2)
we probably need report this things.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I got that error message too. I just added the private dir to path... I had faced similar issues in past but could never figure out the cause. So i thought it was not related to classdef.
And, after classdef, did u try 'sym({1})'?? For me octave gave the error' cannot convert cell to object'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I am using 4.2-rc2, built from source downloaded from the gnu alpha website.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mm, seems i misinterpret a little why you change sym to cell_array_to_sym, yes it don't works, but we can call normally the classdef with cells but the private function for some reason can't be called:

octave:1> sym({'f'})
error: 'cell_array_to_sym' undefined near line 210 column 13
error: called from
    sym at line 210 column 11

i try adding the function as private in the classdef but seems don't is supported for octave...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know of anything off the top of my head, please continue to debug to find out why this is happening.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, it was pretty easy to debug this. Notice that the @sym/sym constructor is returning a cell array of sym objects. The error occurs after the @sym/sym constructor returns, if you set breakpoints and step through the code it's very easy to see this.

My guess is that Octave expects a classdef-based constructor to always return an instance of the object. What you have here is either a weird corner case or an abuse of the language, in the old-style constructor which returns a cell array instead of an object of type sym.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IOW, I think the current situation of

my_syms = sym ({'x', 'y', 'z'})

is neither good form nor does it seem to be legal under classdef-defined classes. A call to sym (anything) should always return an object of type sym.

Using classdef, it might be better to define a static method such as

my_syms = sym.symarray ({'x', 'y', 'z'})

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, it sounds better to be that way. But again, we have some odd conversions in place which might make it difficult (or rather would required many conditionals)....
Thanks for the debug.. I actually tried to debug it with breakpoints but the breakpoints could not be put on a classdef class.... I just read on the wiki that breakpoints via gui are not yet supported for classdef and have to be put via the cli....

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I filed #603 for this cell = sym(cell) thing.

inst/@sym/sym.m Outdated
s = sym(0);
return
classdef sym < handle
properties
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make some or all of these properties Access=Protected or Private? Some are used outside of the class but many are only used directly inside class methods.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, i try it but didn't works D: i get the message can't found the function...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, currently only symsize is used outside the class. I will check to make sure and then keep others as Protected (just to allow symfun to use them if needed, assuming that derived class can use protected members of the base class in the classdef style too)....

@genuinelucifer
Copy link
Contributor Author

Hi, it seems that there is no way to define private functions in separate files (even within the same folder). Also, I ended up copying some of the functions from private folder directly into the sym class. Do we really want our single classdef to be sooo large? Is there a better work-around? Or should we wait till upstream patches the private functions bug in classdefs? If so, I would be happy to contribute a patch to fix that if anyone could guide me to the file(s) that govern the classdef behaviour...
.
Weirdly, git push is unable to resolve github.com even though I can successfully ping github.com.. I will try to push the changes later...

@mtmiller
Copy link
Collaborator

mtmiller commented Oct 3, 2016

Did you try defining the function prototype inside the classdef block and defining the method in a function file inside the @sym directory (but not inside a private subdirectory)? This works for me with a test class.

Inside @foo/foo.m:

classdef foo < handle
...
  methods (Access = private)
    r = some_method (s);
  end

And inside @foo/some_method.m:

function r = some_method (s)
...

This is the "official" way of defining private methods in external files on Matlab's site, there is no mention of private subdirectories there.

Not saying the private subdir way shouldn't be supported or that it's wrong, but this technique seems to work in Octave today (just move all methods up a level from private, and tag them as Access = private in the class definition).

@genuinelucifer
Copy link
Contributor Author

Did you try defining the function prototype inside the classdef block and defining the method in a function file inside the @sym directory (but not inside a private subdirectory)?

I think yes. I actually copied all the files in private directory to the @sym directory. And then yes I included the prototype in the class. I played around with many different permutations of files in same directory or in private and different combinations of access of the methods.
Although I am not sure about protected/private access... I'll check back tomorrow and reply back..

@genuinelucifer
Copy link
Contributor Author

genuinelucifer commented Oct 4, 2016

Thanks @mtmiller . I finally found my mistake. I didn't know that to call functions within the same class too, I had to use classname 'dot' and then the function name! This behaviour is different from most of other OO languages... Altough it's fine for now, shouldn't it be allowed to call functions within the same class? Moreover to call a function by itself I have to use 'classname dot function_name'....
.
Almost all the @sym tests pass now. Currently failing tests include symfun tests (all) because I can't seem to figure out how to call 'subasgn' of symfun, because octave automatically calls 'subasgn' of sym (the base class)... Also the tests involving the == operator are failing, though I haven't looked much into them.
.
The test summary for now is:

PASS      1803
FAIL       112
XFAIL       34

.
Also, one more concern now. We can't test the private functions!! Is there a way to test private functions in BIST tests?

@mtmiller
Copy link
Collaborator

mtmiller commented Oct 4, 2016

You are referring to static methods only, right? Yes, that is the way the language works, whether inside or outside of the class, a static method is called with classname.methodname(). Normal instance methods of a class can be called either as method(obj, x, y, ...) or obj.method(x, y, ...)

There is no way to test private functions. A BIST test is just like something you would run at the command line, and the problem is that the private function is not visible outside of its scope. So we have to keep BIST tests on user-facing functions only.

@latot
Copy link
Contributor

latot commented Oct 4, 2016

mm, some way is make a new public function of the classdeff with the function of test private functionalities and send an assert if don't works.

end

idx.type = ".";
idx.subs = {"vars"};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ups remember here simples quotes .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops. These are my last second changes before pushing and moreover don't work as expected. I'll change this in the next commit. Thanks for pointing out.

@latot
Copy link
Contributor

latot commented Oct 4, 2016

This is seeing very nice! only a very very very little thing, its possible rename sym.symarray to sym.symcell?? (array normally do reference to matrix, while cell, you know, cells)

@genuinelucifer
Copy link
Contributor Author

You are referring to static methods only, right?

Yes.

we have to keep BIST tests on user-facing functions only.

Sure.

some way is make a new public function of the classdeff with the function of test private functionalities and send an assert if don't works

Sure it's a way. But adding a 'public test function' to a class... I donno. Thoughts @mtmiller @cbm755 ?

its possible rename sym.symarray to sym.symcell?? (array normally do reference to matrix, while cell, you know, cells)

Sure, I have no problem with the rename. I just picked out the name from one of Mike's comments. Also there is the function cell_"array"_to_sym which we are wrapping, so symarray seemed equally valid!
But, yes I too don't get the gist of 'array' here...

@latot
Copy link
Contributor

latot commented Oct 4, 2016

only as a note,actually is available to the user the function octsympy_tests, so don't think its too crazy add a test function.

@cbm755
Copy link
Collaborator

cbm755 commented Oct 4, 2016

Woo! Looking good! Why is it a subclass of handle?

Also re: BIST. In Pytave, I did a @pyobject/dummy.m to hold the BIST that otherwise get missed due to bugs in Octave (typically the BIST from the ctor). Whatever you do is probably not worse than that ;-)

re: octsympy_tests.m: that should go away soon: its a relic from Octave 3.6/3.8 and should be replaced by runtests or __run_test_suite__.

@genuinelucifer
Copy link
Contributor Author

genuinelucifer commented Oct 4, 2016

Woo! Looking good! Why is it a subclass of handle?

No particular reason. Probably passing by reference can help some memory and probably improve performance.. (assuming octave also treats handle subclasses like matlab)
Should I make it a value class?

@mtmiller
Copy link
Collaborator

mtmiller commented Oct 4, 2016

If I'm reading the code right, sym objects are immutable, right? So making it a value class would incur unnecessary copies of the internal properties for no added benefit. I think handle makes sense, unless I missed a spot where a sym can be modified in place.

@latot
Copy link
Contributor

latot commented Oct 18, 2016

Hi, only to be sure, Matlab have this behavior?, i refer to call subsasgn of the parent class instead of self (in a class of class context).

@cbm755
Copy link
Collaborator

cbm755 commented Oct 18, 2016

yes, I think Matlab has the same subsasgn behaviour.

@latot
Copy link
Contributor

latot commented Oct 18, 2016

maybe ask in their forums to know a what do here?

@genuinelucifer why symfun need their own subsasgn if the original don't need it?

a way to use is add subsref and subsasgn as static methods and call it with symfun.subsref.

Thx. Cya.

@genuinelucifer
Copy link
Contributor Author

why symfun need their own subsasgn if the original don't need it?

We because in the constructor of symfun if we try to assign value to a property then the subsasgn of 'sym' is being called which simply breaks on a assert statement. I didn't want to change behavior of sym class so though to implement it for symfun too.
.
P.S. - - about the delay, my laptop has stopped working (again) due to hardware issues, i wil resume work on this as soon as possible.

@latot
Copy link
Contributor

latot commented Oct 21, 2016

Hi: genuinelucifer#5
i send to you this pr to fix subsasgn, but still symfun don't works, always get 0, but the assignment its right, so something else is failing, anyway, step by step.

i had move properties of symfun to sym because octave can't set properties of a subclass...

error: subsasgn: unknown property: vars
error: called from
    subsasgn at line 60 column 7
    symfun at line 200 column 9
    syms at line 176 column 10

subsasgn and subsref need be static to can be called correctly from symfun.

Thx. Cya.

@genuinelucifer
Copy link
Contributor Author

i had move properties of symfun to sym because octave can't set properties of a subclass...

Are you sure? Is it documented anywhere?
As I can't test it as of now, I will wait for someone else (or until I find it documented) to confirm this before merging your changes.
Or could you do a little test with some barebone classdefs to confirm this?

@latot
Copy link
Contributor

latot commented Oct 21, 2016

Hi, sadly when i try reproduce it with a simplified version i can't do it works (i don't know to much about classdef), so for now to confirm it, someone else can change this line in symfun:

f.subsasgn (f, idx, vars);

to

f = builtin('subsasgn' f, idx, vars);

and you should have the error i post above.

Thx. Cya.

@latot
Copy link
Contributor

latot commented Oct 21, 2016

the next commit its a simplified way to do this, remove the subsasgn of symfun and handle it from sym, you can choose what you like, or check both ways if can help.

@latot
Copy link
Contributor

latot commented Oct 22, 2016

Hi all, well with the last commit symfun is fixed!
now, should we overload isa to fix symfun? or just move all isa(a, 'symfun') to isa(a, sym')`?

octave:9> syms f(x)
octave:10> isa(f, 'symfun')
ans = 0
octave:11> diff(f)
ans = (sym)

  d       
  ──(f(x))
  dx     

Thx. Cya.

@genuinelucifer
Copy link
Contributor Author

with the last commit symfun is fixed!

Great :)

should we overload isa to fix symfun? or just move all isa(a, 'symfun') to isa(a, `sym')?

I would say we should have an overload. That seems more correct to me.

@latot
Copy link
Contributor

latot commented Oct 22, 2016

Hi, @genuinelucifer its necessary expose symsize?

and @cbm755 can we drop the first and last asserts of subsasgn?

      assert( isa(rhs, 'sym'))
      assert( ~isa(idx.subs, 'sym'))
      assert( ~isa(val, 'sym'))
      val.(idx.subs) = rhs;
      out = val;

How now we are working with classdef i think we can use the properties more free, and how the prop are privates if the user try change someone octave will send the error, and if try set a non existent property octave will send an error too.

Thx. Cya.

@genuinelucifer
Copy link
Contributor Author

its necessary expose symsize?

Yes. It's actually used in 'size' overload of sym to get the size! :P
We can definitely calculate it at every instant via python but that would just be a waste of resources.

@latot
Copy link
Contributor

latot commented Oct 22, 2016

Hi, the private properties can be acceded from other functions, test it, seems works if is private:

octave:57> a=sym([1 2;3 4])
a = (sym 2×2 matrix)

  ⎡1  2⎤
  ⎢    ⎥
  ⎣3  4⎦

octave:58> size(a)
ans =

   2   2

Thx. Cya.

@genuinelucifer
Copy link
Contributor Author

genuinelucifer commented Jan 18, 2017

With my latest commit, almost all tests in @symfun dir are now passing! 💃
There are just problems with a few tests which I will comment inline as I don't understand why they should pass!

Copy link
Contributor Author

@genuinelucifer genuinelucifer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the tests are working now. If I can understand things in these tests then I will fix them and then look at the tests that I left in @sym unattended... Hopefully this PR will be complete soon :D

%! h = f ^ x; assert(isa(h, 'symfun') && isequal(h.symbol, g ^ x))
%! h = f .* x; assert(isa(h, 'symfun') && isequal(h.symbol, g .* x))
%! h = f ./ x; assert(isa(h, 'symfun') && isequal(h.symbol, g ./ x))
%! h = f .^ x; assert(isa(h, 'symfun') && isequal(h.symbol, g .^ x))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since earlier it was sym - symfun so minus of sym was being called, so I changed it to symfun - sym to allow for proper call of out function. I don't know how the conversion/calling worked without classdef. If required, we can add an if statement in sym to convert results of sym - symfun to symfun too.

Copy link
Collaborator

@cbm755 cbm755 Jan 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests should stay sym - symfun: the whole point of this test is the Octave bug #42735. You can mark it xtest if you can't make it work rather than changing it.

I notice the older workaround gives infinite recursion so we may need a new workaround! In the workaround in @sym/plus, I tried plus@symfun(x, y) but that gave an error message than symfun is not a subclass of sym (which is true enough).

In some cases, such as ``@sym/minus.m` we could do:

  % Dear hacker from the distant future... maybe you can delete this?
  if (isa(y, 'symfun'))
    warning('OctSymPy:sym:arithmetic:workaround42735', ...
            'worked around octave bug #42735')
    z = plus(-y, x);
    return
  end

(but I don't know we can do that for every case).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, in minus atleast, we are calling minus on the symbol of symfun and the sym and then converting the result to symfun. If it's ok I can add conditions in minus of sym so that it converts the result to symfun if either of the operands is symfun.. Is that ok? Or should I mark it as xtest?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moreover it seems that superiorto can not be called in a classdef! So, I don't know if we can fix this with superiorto even if upstream is fixed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its not called "superiorto" in classdef: I've posted at the [upstream bug] (https://savannah.gnu.org/bugs/?42735).

@genuinelucifer Maybe you're the right person, at the right time, at the right place to try to fix this upstream bug? I'm sure @mtmiller would be very willing to review a patch for such thing!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's ok I can add conditions in ...

Dunno, try I guess. My impression was if we cannot call the subclass method than all the subclass code will have to be duplicated in @sym... ick! Fix upstream would be best of all of course!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you're the right person, at the right time, at the right place to try to fix this upstream bug?

Sure. After finishing this PR, I will try to submit a patch upstream...

@@ -58,7 +58,8 @@

function h = mtimes(f, g)
[vars, s1, s2] = helper_symfun_binops(f, g);
h = symfun(s1 * s2, vars);
res = s1 * s2;
h = symfun(res, symvar(res));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, this is most confusing part for me... When we are doing any arithmetic operator. The result will definitely have variables from both the symbols involved in that operation. In helper_symfun_binops, it's not allowed to do operations on 2 symfuns if they dont' have exactly same variables!! Also, the variables of the symfun are only considered as final variables in any operation!! This definitely looks wrong to me. I was tempted to change helper_symfun_binops to take a union of the sets of variables in each of the operands involved but I currently did this only for mtimes.
Am I missing something? Why isn't operations for symfuns with different variables allowed? Why are variables only from the symfun operand considered as variables in final expression?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find a reference but IIRC, SMT did this too. I agree it does seem reasonable to take the union of the inputs as the vars of the result. But anyway this has little to do with this PR right?

The result will definitely have variables from both the symbols involved in that operation

Hmm, but this may not be the correct result. Consider:

octave:9> f(x,y) = 2*x
f(x, y) = (symfun) 2⋅x
octave:10> g(x,y) = 1
g(x, y) = (symfun) 1
octave:11> f*g
ans(x) = (symfun) 2⋅x

(Previous to this PR, that would be ans(x,y).)

Also, the variables of the symfun are only considered as final variables in any operation!!

Not sure what you mean.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But anyway this has little to do with this PR right?

Well, partly yes. But some tests are failing because they are not getting correct vars in result. Such tests are very less in number so I can leave them now and fix them in next PR.

Hmm, but this may not be the correct result. Consider

Well, in the example you gave, the previous approach would work because both are symfun and both have the same variables.

Not sure what you mean

If we consider a symfun f(x) = x^2 and a sym y then f(x)*y should have both x and y in its vars. But since the code of helper_symfun_binops considers only the variables of the symfun involved in such cases,the result will have only x and not y included in the vars.

I see that my current approach of symvar is wrong too. I can change it to take union of the variables from both the operands involved. I think that would definitely work.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can change it to take union of the variables from both the operands involved.

Let's take this conversation to #738. I don't see it being relevant to this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

@@ -78,7 +78,7 @@

function z = diff(f, varargin)

z = diff(f.sym, varargin{:});
z = diff(f.symbol, varargin{:});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I could not find any direct way of converting a classdef to its parent class, I had to store expr in a symbol property. Also, If I name it sym then it doesn't work! So I named it symbol...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe in this case you could call diff@sym(f, varargin{:}). That is supposed to be the proper OO syntax for dispatching to a base class method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh thanks! Will do.

@genuinelucifer
Copy link
Contributor Author

Also, @mtmiller , I think I found a bug with classdefs. The files in a @class folder are not properly updated even after doing rehash or clear classes!! To reproduce do:

  • Open octave and cd to inst directory of octsympy
  • In linux terminal do: mv @symfun/isequal.m ../../
  • Then use isequal on 2 symfun objects. Octave will try to call @symfun/isequal.m and since it doesn't exist, there will be error! I tried doing rehash clear all clear classes but nothing worked. I had to close octave and reopen it for this to work...

@mtmiller
Copy link
Collaborator

There are quite a few bugs with classdef and @class scoped function files. I'm not quite following what you think the bug is, obviously if you mv the file out of the directory it won't exist anymore. Do you want it to revert to the builtin isequal function in this case? If so, then that looks like https://savannah.gnu.org/bugs/?36230, there's a workaround posted there.

@genuinelucifer
Copy link
Contributor Author

Do you want it to revert to the builtin isequal function in this case?

Yes. As it would if there was no such file to begin with.

If so, then that looks like https://savannah.gnu.org/bugs/?36230, there's a workaround posted there.

Oh. Thanks. That worked for me too.

@genuinelucifer
Copy link
Contributor Author

Finally now most of the tests in symfun are working! I have made a few tests in minus and symvar as xtest since as per me they ought to fail. I can't understand why they aren't failing without classdef.

Also the test in findsymbols is fixed automatically.

But more problems have arrised..... Now dsolve has 14 fails and solve has 10 fails. Both are failing because the equations are automatically evaluated and not being solved as equations and hence they cannot be solved!

Moreover, it seems that, for classdef, callling a(x) where x is the object of sym and a is a normal vector/integer variable is NOT allowed at all. As in such cases the call gives error without going to subsref at all... So there are now failing tests in @sym/inNone and @sym/subsref...

Lastly, there are 2 failing tests in @sym/sym!! One is because, apparently, save cannot be called on a classdef object!! And the other one is some error in assumptions. I marked both of them as xtests. I will look into them later. Currently I am just amazed at how many more errors there are to debug!!! :(

@mtmiller
Copy link
Collaborator

apparently, save cannot be called on a classdef object

https://savannah.gnu.org/bugs/?45833

@cbm755
Copy link
Collaborator

cbm755 commented Jan 19, 2017

One cause of some of the failing tests is because evaluating a symfun at a variable should give a sym:

>> syms x
>> f(x) = 2*x
f(x) = (symfun) 2⋅x
>> f(x)
ans = (sym) 2⋅x

But this PR currently gives a symfun ans(x) = (sym) 2⋅x.

@@ -43,19 +43,20 @@

switch idx.type
case '()'
out = subs(f, f.vars, idx.subs);
out = subs (f.symbol, f.vars, idx.subs);
out = symfun (out, symvar (out));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this out = symfun (out, ...) is incorrect.

cbm755 and others added 6 commits January 19, 2017 19:07
I'm not sure how to do this properly, but symfun should support
casting to sym.  Make "formula" use this new casting.
I'm not even sure this cast was correct for old-style class but
its certainly not for classdef.  Anyway, "formula" is semantically
correct in these cases.
@genuinelucifer
Copy link
Contributor Author

Thanks to @cbm755 , all the tests are passing now! :D
This PR is hence complete and ready for final review, in my opinion. So, please test it and review it once more.

I have just a couple of questions left now:

  • What would be the best way to resolve the conflicts without having to rewrite all the changes of this PR on top of master? Till now, to resolve conflicts, I have simply been deleting my branch and creating a new branch from master and rewriting all the required changes. Since this PR spans so many files with little changes in each one, it doesn't look feasible to me.
  • Should I squash some of the starting comments? The ones like Fix almost all symfun tests! and Fix more symfun problems?

@cbm755
Copy link
Collaborator

cbm755 commented Jan 20, 2017

I would git merge origin/master into this branch, then fix the conflicts.

Before doing that, maybe you could review #731? If we merge that to master, that should make a bunch of the sym.symarray stuff unneeded.

(this classdef change is not going to be merged before 2.5.0 anyway).

@genuinelucifer
Copy link
Contributor Author

I would git merge origin/master into this branch, then fix the conflicts.

Thanks I tried this with meld as mergetool and looks so easy. Good to know this.

this classdef change is not going to be merged before 2.5.0 anyway

Oh ok. Then I would wait for that as the new master will have to be merged again anyway.

Also, Currently we have following 3 outstanding errors due to use of classdef (just to sum it up):

  • Define symfun as superior to sym so as to call its functions like that in case of minus
  • Allow saveing of sym and symfun
  • Indexing of constants with classdef is not supported in octave. Either get rid of those tests or leave them as xtests till octave supports it.

I am assuming we will translate to classdef hoping that all these will soon be supported by octave and we will get rid of all the xtests. In the mean time, I will try to provide patches for fixing some/all of these points in octave. But, this will still bump the minumum required version of octave for the next release of symbolic to atleast 4.4. I am assuming that it's not a problem...

@cbm755
Copy link
Collaborator

cbm755 commented Jan 20, 2017

Re: your points:

  1. please at least make our class have the inferior classes thing (classdef {SOMETHING ABOUT sym GOES HERE} symfun < sym)
  2. saving: seems we cannot merge this until this is fixed.
  3. "Indexing of constants with classdef is not supported in octave": citation needed, do you have an upstream bug report? Definitely leave them as xtests for now. If there is no upstream report, we'll need to make a minimal example and file it.

final review

Wishful thinking ;-) It seems quite likely we will not merge this until 4.4 is released :(

@cbm755
Copy link
Collaborator

cbm755 commented Mar 1, 2017

I think master is reasonably stable; would be good to merge to here. We also need a clear idea of what needs fixed in upstream octave to get this merged.

@genuinelucifer
Copy link
Contributor Author

Well, the 3 things that I mentioned in my last comment seem to be the bottleneck currently.

  • defining a classdef superiorto some other classdef
  • saving and loading classdef objects
  • indexing constants with a classdef object

@cbm755
Copy link
Collaborator

cbm755 commented Mar 1, 2017

Do those all have upstream issue numbers?

@mtmiller
Copy link
Collaborator

mtmiller commented Mar 1, 2017

I am not sure what is meant by "indexing constants with a classdef object". Does this mean using a classdef object as the index of a subsref on a builtin matrix? Is there some builtin conversion rules that are supposed to be used? Do we have a Matlab doc describing this?

I thought there were some other bugs. Are there other classdef issues that you were able to find workarounds for, but it would still be better to not have to use a workaround? For example method name resolution problems, problems with private methods, etc?

@cbm755
Copy link
Collaborator

cbm755 commented Mar 7, 2017

"indexing constants with a classdef object"

@genuinelucifer do you mean this?

>> a = [1.2 3.4]
a =

         1.2         3.4

>> a(sym(3)) = 42.42
a =

         1.2         3.4       42.42

@genuinelucifer
Copy link
Contributor Author

@genuinelucifer do you mean this?

Yes, exactly.

Sorry, I've been busy with my exams and couldn't reply.

@cbm755 cbm755 mentioned this pull request Jul 24, 2017
@cbm755 cbm755 mentioned this pull request Mar 24, 2019
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants