Feature: Polynomials and rational functions #469
No reviewers
Labels
No Label
bug
dependencies
discussion
documentation
duplicate
feature
good first issue
misc
performance
question
test
use case
wontfix
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: kscience/kmath#469
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "feature/polynomials"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This is implementation of different kinds of polynomials and rational functions.
It should close issues #462, #336
See also: #39, #446,
Comment: files systematisation
Util
suffix.Constructors
suffix.Polynomial.kt
andRationalFunction.kt
.Problems and questions
Is it worth to change
Map<Symbol, UInt>
toandroid.util.ArrayMap<Symbo, UInt>
or something similar?This class is designed to be more memory efficient for small numbers of entries which is exactly our use case.
What is better way to implement interoperability with integers?
As fact, additive (abelian) groups has natural product operation with integers: product of element
c
and integern
is just:n
copies ofc
ifn
is positive,-n
copies of-c
ifn
is negative (or negate of sum of-n
copies ofc
, which is the same),n
is zero.The same goes for multiplicative groups and power. (As a matter of fact, rings do not provide multiplicative (abelian) groups, but multiplicative (abelian) monoids, so the power can be defined not for integers, but for non-negative integers.) In context of rings we also have addition of ring members and integers: for real, sum of element
c
and integern
is justc + n * one
(whereone
is unit of the ring). And multiplication and exponentiation are very helpful and frequently used.For example, when you calculate derivative of polynomial you multiply coefficients of terms to corresponding degrees (which are positive integers), so to implement derivative you have to implement multiplication yourself (see
algebraicStub.kt
) or require ability to convert integer to ring member (seePolynomial<C>.derivative
that preserves former logic). Both variants are bad: manual multiplication usually slower then multiplication that could be provided by corresponding ring, and requiring convertibility (byScaleOperations
or evenNumericAlgebra
because there are no alternatives) makes it impossible to use it in common rings (say hi to rational numbers again).In my opinion, the best way is to declare the interactions in
GroupOps
/Group
(for multiplication) andRing
(for exponentiation that is already declared and addition) interfaces and implement them in all current algebraic structures. (It's very easy, even is a bit of boilerplate.) It's even inconsistent in some way that exponentiation is declared inRing
, but multiplication byInt
/UInt
(which is the same operation not in multiplicative group/monoid, but in additive group/monoid) is not.So the trivial question here: what should I do here?
Maybe, it is better to move first argument
ring
of utility functions (substitute
,derivative
, etc.) to context (when context receivers will be available), isn't it?Is there need in other functionality?
For example, string representation: it is already implemented in my other repositories, it remains only to copy it with minimal modification.
Should RFs spaces be implemented as field?
If yes, then what division operations should be implemented? (For example, what should
c / c
return? And when field overC
is provided?) And how to implement currentNumber
-oriented functions ofField
?Should cases for
A
(the type of provided ring of constants) beingField
be considered as well?I mean that function
operator fun Polynomial<C>.div(other: C): Polynomial<C>
makes sense only in context of of field overC
. And it looks helpful. So should I implement something like this? (But of course, I'll be able to implement something like this when context receivers will be released. For now I can sketch it, comment it and add TODO mark to it.)TODO list
So now the main feature is finally ready. It only remains to add tests and write optimized algorithms for substitutions (with tests and benchmarks). (Maybe I should move algorithm optimization to another pull request and/or another branch.)
I also have questions about some details which I formulated in "Problems and questions" section in the pull request description message.
This is a large PR, so review will take some time. In order for this to be accepted, you need to add some examples in the example directory making it obvious how to use it. Tests are also necessary. I think that we will require a design note (in
docs
directory) on all new feature PRs in order to make sure different features play well together. You can probably use your very thorough (👍 ) PR text for that.OK. I am going to be busy for now. So I think I'll write examples and design notes some time later (about 1 to 2 weeks later). And after that will deal with tests and rest stuff.
I added examples and design notes. (Although, I am not sure if they came out good.) Also decided to move optimizations to new refactoring branch (because I found out that there a lot of algorithms to refactor).
Now I am going to gradually add tests...
Please review necessity of test modules. Otherwise, we will merge the module and then refine the API post-merge
Done.
@CommanderTvis waiting for your review
My first comment would be - it's a huge module without README.md in the directory...
Seems to be failing on Native. @lounres, have you done the full build locally?
Maybe better to remove native plugin from polynomials for now. We can always add it later.
@altavir Just cleanly rebuilt it (
:clean
+:build
as-is and with kover disabled). Everything has been built successfully (and without any problems nor warnings inkmath-functions
andkmath-polynomial
). You can see logs here. It's Windows 10 x64.By the way, a lot of on-push GitHub builds in this PR failed. Most of them failed due to bug in kover (seems like this issue) and some of them failed due to disappearance of daemon.
It seems like it requires to much resources to run in the github container. I will try to fix it post-merge. Waiting for @CommanderTvis review now.
The first problem is that
Polynomial
interface is duplicated in two modules:kmath-functions: https://github.com/lounres/kmath/blob/feature/polynomials/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt#L22
kmath-polynomial: https://github.com/lounres/kmath/blob/feature/polynomials/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt#L17
Another doubt is about the type parameter in
interface Polynomial
in kmath-polynomial. It can be just removed without any changes in semantics.Also, about type parameters, many classes in this PR can have
out
orin
declaration site variances e.g., ListPolynomial<out C>.Some implementations of operators in the contexts can be shortened:
OK. Will be removed.
If "many" means "just
ListPolynomial
,NumberedPolynomial
,LabeledPolynomial
", then I agree. Because I don't see any other possible variance cases. This three will be provided with variance.Watching discussion in telegram. Waiting for a final verdict.
Yes, it's true. Although, I don't like it in some way because I don't fully control the
minus
operation's logic but delegate it to another operation. (It was driven by principal that I should control number of the ring's used operations because there can be algebraic contexts with very slow operations, soa + (-b)
would be twice slower thana - b
. Fortunately, it's not the case in the example.)But, yeah, I'll fix it.
Yes, actually I meant them.
I removed
Polynomial
and fixed variance (and everything seems OK there). But I am currently struggling with code "shortening" (see neighbour branch for current progress). I suspect KT-31420. So it seems to me that some changes should be applied a bit later (when the issue will be fixed, which is planned on 1.8.0).