From 7fe0bc4ad1a24dfbfc0b43f488b24dcf2afb9448 Mon Sep 17 00:00:00 2001 From: meatball <69751659+meatball133@users.noreply.github.com> Date: Fri, 9 Feb 2024 13:34:09 +0000 Subject: [PATCH 1/3] First draft for proposal --- text/0005-Combinatoric math proposal.md | 142 ++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 text/0005-Combinatoric math proposal.md diff --git a/text/0005-Combinatoric math proposal.md b/text/0005-Combinatoric math proposal.md new file mode 100644 index 0000000..fc9bf2b --- /dev/null +++ b/text/0005-Combinatoric math proposal.md @@ -0,0 +1,142 @@ +- Feature Name: `math-combinatoric-library` +- Start Date: 2024-02-09 +- RFC PR: [crystal-lang/rfcs#0005](https://github.com/crystal-lang/rfcs/pull/0005) +- Issue: - + +# Summary + +Add combinatoric and permutations methods to the standard library which works on integers. + +# Motivation + +Crystal has an already exsisting methods for doing combinations and permutations but those work on some form of collection which for larger sizes makes them very computanional heavy and high memory usage. +In the scientific world is there many uses of getting to know the size of combinations or permutations but not the individual combinations or permutations. +These methods could also have an `Int` implementation which doesnt use any form of collections to reduce on the calculations and memory usage required. +There are already exsisting libraries which impliments this logic but most of them are unmaintained. + +The expected outcome out of this is that Crystal will have a stronger standard library for working with scientific purposes. +But also when working with just sizes of permutations and combinations will have drasticly faster executions. + +# Guide-level explanation + +When you just want the size of a combination or permutations so are the `BigInt#combination` or `BigInt#permutation` methods way more efficent when working on arrays. +They work using a mathematical formula based on factorial of numbers. + +To use the methods will you have to include the `BigInt` libaries using `require "big"`. +Deffine a number then you can use the method on that number with how many combinations you want to use. + +```crystal +require "big" + +number : BigInt = 5 +number.combinations(3) +# => 10 + +number.combinations(2) +# => 10 +``` + +In the examples above can the number be reasoned about having 5 items and wanting to know how many ways those 5 items can be put in groups of 3 or 2. +The reason why those 2 examples becomes the same can be reasoned out of 2 perspectives: + +- Say you would want to add 5 new features to Crystal but you are only allowed to add 3. +- That would be the same as resoning that you would want to get groups of 2 features that doesnt get added. + +Intrested in learning more: https://en.wikipedia.org/wiki/Combination + +Another example: + +```crystal +require "big" + +number : BigInt = 20 +number.combinations(2) +# => 190 + +number_2 : BigInt = 10 +number_2.combinations(2) +# => 45 +``` + +Error handeling examples: + +```crystal +require "big" + +number : BigInt = 5 +number.combinations(-4) +# ArgummentError: combinations can't be done on negativ integers + +number2 : BigInt = -5 +number2.combinations(2) +# ArgummentError: combinations can't be done on negativ integers +``` + +As for permutations does that work simiralliy with the use `BigInt` libaries using `require "big"`. + +```Crystal +require "big" + +number : BigInt = 5 +number.permutations(4) +# => 120 +``` + +Combinations and permutations share a lot with each other. +The key difference between combinations and permutations is that permutations care about the order. +Take the last example with new features, say instead you have to make a list of the 3 features you would like to see in the language and the first feature is the one you want to see the most to be implemented. +Then the order matters you put them in the list. + +Permutations doesnt have the same pattern as combinations with `5.combinations(3)` is the same as `5.combinations(2)`. +Instead for permutations so are `n.combinations(n)` always equal `n.combinations(n - 1)` (as long as n is a posstive number and not zero). + +```crystal +require "big" + +number : BigInt = 5 +number.combinations(5) +# => 120 + +number.combinations(4) +# => 120 +``` + +This is because say you have a list of the 4 features in order you most want to see in the languages. +Adding one more feature to the list would not add another combinations since there is only 1 feature left of choosing. + +# Reference-level explanation + +Since both of these methods quickly reach large numbers so do they both have to be implemented under `BigInt`. +They could either be written manualy using the mathematical formula togehter with `BigInt#factorial` or using a more optimzied version. +The mathematical formula for combinations: C(n,k) = (n!) / (k! * (n - k)!) +The mathematical formula for permutations: P(n,k) = n! / k! +The `!` is factorial. + +Another alternative is to use: https://www.gnu.org/software/gsl/ + +# Drawbacks + +Dependent on which apparoch is used so would the mathematical formula mostly add more maintaince burden. +The gsl library would add another library which has to be activly made sure to keep combatible to and in that way also add maintaince burden. + +# Rationale and alternatives + +The impact of not doing this would mostly mean that these features remains library exclusive, it could have certain benefits to that since the standard library would likely not be able to store all possible methods. +Although currently there is no real math library which has everything you have to combine a set of libraries if you would like to get a large amount of mathematical methods in various areas. +Alternativly is that users implements this logic by themselves which could mean unoptimized methods or repatativ method implementation. +In worst case a user could implement this using arrays (together with the built-in methods), which for large models would be very slow. + +# Prior art + +In quite a few languages does these methods comes in form of libraries, there could be many reasons to this including the fact that some languages wants to keep the standard library smal. + +Although, python added a `math.comb` and `math.perm` method in 3.8. +This could be due to the fact being more math "focused" then others, but the methods have been appricated for users which have had to use those types of methods. + +# Unresolved questions + +Should Crystal lang add these combinatoric methods or should they remain to be gatherd through libraries? + +# Future possibilities + +I cant think of anything. From 785a4166b6d810a41e0561c57e2b13b0a523a2e7 Mon Sep 17 00:00:00 2001 From: meatball <69751659+meatball133@users.noreply.github.com> Date: Fri, 9 Feb 2024 16:02:28 +0000 Subject: [PATCH 2/3] Various fixes and improvements --- text/0005-Combinatoric math proposal.md | 98 +++++++++++++------------ 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/text/0005-Combinatoric math proposal.md b/text/0005-Combinatoric math proposal.md index fc9bf2b..a916947 100644 --- a/text/0005-Combinatoric math proposal.md +++ b/text/0005-Combinatoric math proposal.md @@ -5,30 +5,30 @@ # Summary -Add combinatoric and permutations methods to the standard library which works on integers. +Add combinatorics and permutation methods to the standard library which works on integers. # Motivation -Crystal has an already exsisting methods for doing combinations and permutations but those work on some form of collection which for larger sizes makes them very computanional heavy and high memory usage. -In the scientific world is there many uses of getting to know the size of combinations or permutations but not the individual combinations or permutations. -These methods could also have an `Int` implementation which doesnt use any form of collections to reduce on the calculations and memory usage required. -There are already exsisting libraries which impliments this logic but most of them are unmaintained. +Crystal has already existing methods for doing combinations and permutations but those work on some form of collection which for larger sizes makes them very computational heavy and high memory usage. +In the scientific world is there many uses for getting to know the size of combinations or permutations but not the individual combinations or permutations. +These methods could also have an `Int` implementation which doesn't use any form of collections to reduce the calculations and memory usage required. +There are already existing libraries that implement this logic but most of them are unmaintained. -The expected outcome out of this is that Crystal will have a stronger standard library for working with scientific purposes. -But also when working with just sizes of permutations and combinations will have drasticly faster executions. +The expected outcome of this is that Crystal will have a stronger standard library for working with scientific purposes. +But also when working with just sizes of permutations and combinations will have drastically faster executions. # Guide-level explanation -When you just want the size of a combination or permutations so are the `BigInt#combination` or `BigInt#permutation` methods way more efficent when working on arrays. -They work using a mathematical formula based on factorial of numbers. +When you just want the size of a combination or permutations, the `BigInt#combination` or `BigInt#permutation` methods are way more efficient when working on arrays. +They work using a mathematical formula based on the factorial of numbers. -To use the methods will you have to include the `BigInt` libaries using `require "big"`. -Deffine a number then you can use the method on that number with how many combinations you want to use. +To use the methods will you have to include the `BigInt` libraries using `require "big"`. +Define a number then you can use the method on that number with how many combinations you want to use. ```crystal require "big" -number : BigInt = 5 +number = BigInt.new(5) number.combinations(3) # => 10 @@ -36,78 +36,79 @@ number.combinations(2) # => 10 ``` -In the examples above can the number be reasoned about having 5 items and wanting to know how many ways those 5 items can be put in groups of 3 or 2. -The reason why those 2 examples becomes the same can be reasoned out of 2 perspectives: +In the examples above can the number be reasoned about having 5 items and wanting to know how many ways those 5 items can be put in groups of 3 or 2. +The reason why those 2 examples become the same can be reasoned out from 2 perspectives: - Say you would want to add 5 new features to Crystal but you are only allowed to add 3. -- That would be the same as resoning that you would want to get groups of 2 features that doesnt get added. +- That would be the same as reasoning that you would want to get groups of 2 features that don't get added. -Intrested in learning more: https://en.wikipedia.org/wiki/Combination +Interested in learning more: https://en.wikipedia.org/wiki/Combination Another example: ```crystal require "big" -number : BigInt = 20 +number = BigInt.new(20) number.combinations(2) # => 190 -number_2 : BigInt = 10 +number_2 = BigInt.new(10) number_2.combinations(2) # => 45 ``` -Error handeling examples: +Error handling examples: ```crystal require "big" -number : BigInt = 5 +number = BigInt.new(5) number.combinations(-4) -# ArgummentError: combinations can't be done on negativ integers +# ArgumentError: combinations can't be done on negative integers -number2 : BigInt = -5 -number2.combinations(2) -# ArgummentError: combinations can't be done on negativ integers +number_2 BigInt.new(-5) +number_2.combinations(2) +# ArgumentError: combinations can't be done on negative integers ``` -As for permutations does that work simiralliy with the use `BigInt` libaries using `require "big"`. +As for permutations does that work similarly with the use `BigInt` libraries using `require "big"`. ```Crystal require "big" -number : BigInt = 5 +number = BigInt.new(5) number.permutations(4) # => 120 ``` -Combinations and permutations share a lot with each other. +Combinations and permutations share a lot. The key difference between combinations and permutations is that permutations care about the order. -Take the last example with new features, say instead you have to make a list of the 3 features you would like to see in the language and the first feature is the one you want to see the most to be implemented. +Take the last example with new features, say instead you have to list the 3 features you would like to see in the language and the first feature is the one you want to see the most to be implemented. Then the order matters you put them in the list. -Permutations doesnt have the same pattern as combinations with `5.combinations(3)` is the same as `5.combinations(2)`. -Instead for permutations so are `n.combinations(n)` always equal `n.combinations(n - 1)` (as long as n is a posstive number and not zero). +Permutations don't have the same pattern as combinations with `5.permutations(3)` is the same as `5.permutations(2)`. +Instead for permutations so are `n.permutations(n)` always equal `n.permutations(n - 1)` (as long as n is a positive number and not zero). + ```crystal require "big" -number : BigInt = 5 -number.combinations(5) +number = BigInt.new(5) +number.permutations(5) # => 120 -number.combinations(4) +number.permutations(4) # => 120 ``` -This is because say you have a list of the 4 features in order you most want to see in the languages. -Adding one more feature to the list would not add another combinations since there is only 1 feature left of choosing. +This is because say you have a list of the 4 features in order you most want to see in the language. +Adding one more feature to the list would not add another permutation since there is only 1 feature left to choose. # Reference-level explanation -Since both of these methods quickly reach large numbers so do they both have to be implemented under `BigInt`. -They could either be written manualy using the mathematical formula togehter with `BigInt#factorial` or using a more optimzied version. +Since both of these methods quickly reach large numbers, they both have to be implemented under `BigInt`. +They could either be written manually using the mathematical formula together with `BigInt#factorial` or using a more optimized version. The mathematical formula for combinations: C(n,k) = (n!) / (k! * (n - k)!) The mathematical formula for permutations: P(n,k) = n! / k! The `!` is factorial. @@ -116,27 +117,30 @@ Another alternative is to use: https://www.gnu.org/software/gsl/ # Drawbacks -Dependent on which apparoch is used so would the mathematical formula mostly add more maintaince burden. -The gsl library would add another library which has to be activly made sure to keep combatible to and in that way also add maintaince burden. +Depending on which approach is used so would the mathematical formula mostly adds more maintenance burden. +The gsl library would add another library which has to be actively made sure to remain compatible and in that way also add maintenance burden. + # Rationale and alternatives -The impact of not doing this would mostly mean that these features remains library exclusive, it could have certain benefits to that since the standard library would likely not be able to store all possible methods. -Although currently there is no real math library which has everything you have to combine a set of libraries if you would like to get a large amount of mathematical methods in various areas. -Alternativly is that users implements this logic by themselves which could mean unoptimized methods or repatativ method implementation. -In worst case a user could implement this using arrays (together with the built-in methods), which for large models would be very slow. +The impact of not doing this would mostly mean that these features remain library exclusive, it could have certain benefits to that since the standard library would likely not be able to store all possible methods. +Currently, there is no real math library that has everything you have to combine a set of libraries if you would like to get a large amount of mathematical methods in various areas. +Alternatively, users implement this logic by themselves which could mean unoptimized methods or repetitive method implementation. +In the worst case, a user could implement this using arrays (together with the built-in methods), which for large models would be very slow. # Prior art -In quite a few languages does these methods comes in form of libraries, there could be many reasons to this including the fact that some languages wants to keep the standard library smal. +In quite a few languages these methods come in the form of libraries, there could be many reasons for this including the fact that some languages want to keep the standard library small. Although, python added a `math.comb` and `math.perm` method in 3.8. -This could be due to the fact being more math "focused" then others, but the methods have been appricated for users which have had to use those types of methods. +This could be because it is more math "focused" than others, but the methods have been appreciated by users who have had to use those types of methods. + +There are also a couple of libraries in Crystal which implements these methods like: https://github.com/ruivieira/crystal-gsl, https://github.com/ouracademy/statistical-analysis # Unresolved questions -Should Crystal lang add these combinatoric methods or should they remain to be gatherd through libraries? +Should Crystal-lang add these combinatoric methods or should they remain to be gathered through libraries? # Future possibilities -I cant think of anything. +I can't think of anything. From 7e9ab28a4dd43a68dc50ba73d48e76071e23f9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Wed, 26 Feb 2025 00:08:57 +0100 Subject: [PATCH 3/3] Convert metadata into YAML frontmatter (see #3) --- text/0005-Combinatoric math proposal.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/text/0005-Combinatoric math proposal.md b/text/0005-Combinatoric math proposal.md index a916947..a2602c2 100644 --- a/text/0005-Combinatoric math proposal.md +++ b/text/0005-Combinatoric math proposal.md @@ -1,7 +1,9 @@ -- Feature Name: `math-combinatoric-library` -- Start Date: 2024-02-09 -- RFC PR: [crystal-lang/rfcs#0005](https://github.com/crystal-lang/rfcs/pull/0005) -- Issue: - +--- +Feature Name: math-combinatoric-library +Start Date: 2024-02-09 +RFC PR: "https://github.com/crystal-lang/rfcs/pull/0005" +Issue: +--- # Summary