Replies: 15 comments
-
I think it makes sense to keep the algebraic It would be great to be able to do enter
That would be a nice improvement. There is no special reason that it's not there :) |
Beta Was this translation helpful? Give feedback.
-
Well, that's exactly what I was proposing. In fact, I assumed that was already happening. I guess by analogy with javascript itself, which keeps the source code for functions even once they've been byte-compiled. I don't see why in mathjs if the parse tree is kept on an appropriately named property of the function it will cause much if any trouble. We must still reckon with the case that the user passes a non-mathjs-parsed function in through an external scope. For now I think derivative would punt unless/until we want to make an automatic differentiation package a dependency of mathjs. (One probably already exists, it is totally feasible.) |
Beta Was this translation helpful? Give feedback.
-
🤔 yeah, it's an interesting idea. To put a bit broader perspective on this idea: in general, it would be nice to be able to write expressions with symbolic computations as follows:
So, not writing with |
Beta Was this translation helpful? Give feedback.
-
Well, with just very tiny tweaks (see the demonstration PR #2470), all of the ingredients already exist in mathjs for a mode of evaluation in which all unspecified variables are interpreted as symbols, so that "evaluation" of an expression will result in either a concrete value (a number or BigNumber or Fraction or Matrix or Complex or etc.) or in an expression (Node) containing (only) the unspecified, free variables of the input expression (besides constants, operators, and functions). So with very little work, we could offer an alternative function The value of sometimes designating some variables as symbols and others as not is unclear to me... In other words, why should one have to do anything special to designate 'x' as a symbol when we just naturally write expressions with all kinds of symbols in them all the time, and mathjs naturally handles them symbolically? Or in still other words, it seems to me it just comes down to what happens when an undefined variable is encountered. Right now, we always throw an error. But we could (always, or just in a certain mode, indicated by a different function or a flag) just leave such a variable as a SymbolNode and continue on our merry way. (Of course, if there is truly a use case in marking just some variables as 'symbols' so that they will be allowed in the expression mode of evaluation results while those not designated will throw errors if encountered, that could be done, too -- it's just somewhat more work.) So from that perspective, the point of #2470 is to show that it's unnecessary to add mathematical operations on Node objects (in addition to the numbers, BigNumbers, Complex, etc. that they are already defined on) to accomplish this mode of evaluation -- mathjs has symbolic manipulation embedded in its core already. (The basic idea is that For your convenience, I'll post the output of the demonstration example file To sum up: let me know if you'd like mathjs to go in any directions suggested by #2470, and/or if there's anything else in particular you'd like me to try in terms of making |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
ahhh, that is really cool 😎 . So the "trick" you've implemented here is to introduce a flag I was thinking in a bit of a different direction: implementing first-class support for Nodes in all mathjs functions. That would be much more work to implement: we will have to extend each of the functions of mathjs with a new signature which allows handling // pseudo code...
export const createAdd(...) {
return typed('add', {
// ...
'Node, Node': (a, b) => {
return new OperatorNode('+', 'add', [a, b])
}
})
}
export const createSqrt(...) {
return typed('sqrt', {
// ...
'Node': (x) => {
return new FunctionNode('sqrt', [x])
}
})
}
// ... I have the feeling that from a practical point of view, both approaches would allow a user to do the same thing, it's only implemented in a different way. At this point I'm still a bit in search on what would be the use case. Having a clear use case could help to think though if there is added value in one or the other. I finally found the earlier discussions on this, see: #38, #218 (different I think), #1732, #1747 |
Beta Was this translation helpful? Give feedback.
-
Well, resolving and simplifying is the "on the cheap" approach, avoiding having to deal with arithmetic on expressions, since it didn't seem like it could possibly be worth it to modify every function's source file to add Node signatures to the typed-function. Plus the "proof of concept" you linked to having build problems suggesting an issue with circularity kind of scared me off. But this "cheap" approach is also not quite as powerful -- it doesn't allow any functions not built for handling symbolic expressions suddenly to do so. In particular, even if the source code for det only uses I guess what I am coming to is that the two approaches are not necessarily in opposition, but are rather complementary to each other. I don't currently have a goal in my other projects for which this style of symbolic computation is a must, so I am afraid I don't have a use case. I was offering this in the spirit of extending mathjs sphere of utility, and then it may attract use cases that we can employ as a guide to further development. So anyhow, let me know if there's a direction you want me to pursue in this arena. |
Beta Was this translation helpful? Give feedback.
-
Actually my last comment got me to thinking that the "symbolic" implementation of all of the standard functions is identical (except for the function name) and doesn't need any knowledge of the operation -- it just builds more tree structure. Thus, it can be implemented generically if typed-function allows a handler when no signature matches, without defining any new cases for any existing operators. I've followed up that idea with an alternate demo implementation of symbolic computation, #2475, for comparison purposes. For convenience, I will post the output of its version of the symbolic_computation example, so you can see the pros and cons. Personally, I think one approach or the other would make a natural extension to mathjs that would help it move further toward a bona fide CAS. On the other hand, I don't want to push a noodle here: I don't have an immediate practical need for for either approach, just a strong feeling that if we have symbolic operations like |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Thanks, that is a nifty idea to utilize a (new to be made) At this point I'm hesitant to spend a lot of effort if there isn't a very clear use case and overarching vision of where to go. Both demo PR's that you've worked out rely on implementing a small, simple "handler" in mathjs: a new option |
Beta Was this translation helpful? Give feedback.
-
I'm perfectly happy to go that dual route, starting by wrapping up josdejong/typed-function#125. But if we call the two methods the "simplifyConstant" method (#2470) and the "evaluate" method (#2475), note that the evaluate method does depend on removing the number -> string automatic conversion. Are you comfortable with that change? As I mentioned above, it breaks almost nothing in the unit tests. If so, then I will get a PR for just that change in here ASAP so it can be scheduled for v11. |
Beta Was this translation helpful? Give feedback.
-
🤔 yesss I understand it. The reason the What maybe could work is implement another hook too allow you to hijack Do you maybe have other ideas to both keep this |
Beta Was this translation helpful? Give feedback.
-
Slightly confused; sounds like you are talking about the string -> number auto conversion, which is not a problem. I would definitely not propose eliminating that! It's number -> string that causes issues for symbolic eval, and I am not so clear on the value of that. But if you think it's critical to keep number -> string I will try to find a workaround... |
Beta Was this translation helpful? Give feedback.
-
oh wow, yes I was confusing We can indeed remove the |
Beta Was this translation helpful? Give feedback.
-
OK, I will file a PR for just that ASAP so that you can schedule it into the v11 release at your discretion. |
Beta Was this translation helpful? Give feedback.
-
Currently (from the demo):
It would seem reasonable to extend
derivative
to apply to a "function" since it is not doing anything on such an argument now. Moreover, it would seem good when the argument is "function" for the return type to be "function" as well, so that one could do hypothetically:Additionally, do you see any problem with making
derivative
take rawArgs so that e.g.derivative(x^2+3x+2,x)
[Note: no quotes] would work as well? Are there cases when the user would want there to be evaluation in either argument thatderivative
couldn't figure out that it should do, or where the meaning would be ambiguous depending on whetherderivative
decided to do evaluation ?Finally, is there any reason why the second argument, giving the variable, shouldn't be optional, and default to the lexicographically first free variable that appears in the first argument? With all of these changes, we could write
derivative(x^2+3x+2)
and get back2*x+3
which would seem very reasonable.Beta Was this translation helpful? Give feedback.
All reactions