|
| 1 | +/* |
| 2 | + * java-math-library is a Java library focused on number theory, but not necessarily limited to it. It is based on the PSIQS 4.0 factoring project. |
| 3 | + * Copyright (C) 2018-2024 Tilman Neumann - [email protected] |
| 4 | + * |
| 5 | + * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License |
| 6 | + * as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. |
| 7 | + * |
| 8 | + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied |
| 9 | + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
| 10 | + * |
| 11 | + * You should have received a copy of the GNU General Public License along with this program; |
| 12 | + * if not, see <http://www.gnu.org/licenses/>. |
| 13 | + */ |
| 14 | +package de.tilman_neumann.jml.partitions; |
| 15 | + |
| 16 | +import static org.junit.Assert.assertEquals; |
| 17 | + |
| 18 | +import java.math.BigInteger; |
| 19 | +import java.util.ArrayList; |
| 20 | + |
| 21 | +import org.apache.logging.log4j.Logger; |
| 22 | +import org.junit.BeforeClass; |
| 23 | +import org.junit.Test; |
| 24 | +import org.apache.logging.log4j.LogManager; |
| 25 | + |
| 26 | +import de.tilman_neumann.jml.combinatorics.Factorial; |
| 27 | +import de.tilman_neumann.util.ConfigUtil; |
| 28 | + |
| 29 | +public class MpiPartitionGeneratorTest { |
| 30 | + |
| 31 | + private static final Logger LOG = LogManager.getLogger(MpiPartitionGeneratorTest.class); |
| 32 | + |
| 33 | + private static final boolean DEBUG = false; |
| 34 | + |
| 35 | + @BeforeClass |
| 36 | + public static void setup() { |
| 37 | + ConfigUtil.initProject(); |
| 38 | + } |
| 39 | + |
| 40 | + /** |
| 41 | + * Test the number of essentially different factorizations of n= 1, 2, 3, ... |
| 42 | + * A001055 (n=1...) = 1, 1, 1, 2, 1, 2, 1, 3, 2, 2, 1, 4, 1, 2, 2, 5, 1, 4, 1, 4, 2, 2, 1, 7, 2, 2, 3, 4, 1, ... |
| 43 | + */ |
| 44 | + @Test |
| 45 | + public void testNumberOfFactorizations() { |
| 46 | + int maxListSize = 30; |
| 47 | + ArrayList<Long> list = new ArrayList<>(); |
| 48 | + for (int n=1; n<=10000; n++) { |
| 49 | + long numberOfFactorizations = MpiPartitionGenerator.numberOfFactorizationsOf(BigInteger.valueOf(n)); |
| 50 | + if (DEBUG) LOG.debug(n + " can be factored in " + numberOfFactorizations + " different ways"); |
| 51 | + if (list.size() < maxListSize) list.add(numberOfFactorizations); |
| 52 | + } |
| 53 | + if (DEBUG) LOG.debug("First 30 sequence elements = " + list); |
| 54 | + assertEquals("[1, 1, 1, 2, 1, 2, 1, 3, 2, 2, 1, 4, 1, 2, 2, 5, 1, 4, 1, 4, 2, 2, 1, 7, 2, 2, 3, 4, 1, 5]", list.toString()); |
| 55 | + } |
| 56 | + |
| 57 | + /** |
| 58 | + * Test record numbers of essentially different factorizations of n = 1, 2, 3, ... |
| 59 | + * A033833 = 1, 4, 8, 12, 16, 24, 36, 48, 72, 96, 120, 144, 192, 216, 240, 288, 360, 432, 480, 576, 720, 960, 1080, 1152, 1440, 2160, 2880, 4320, 5040, 5760, 7200, 8640, 10080, 11520, ... |
| 60 | + */ |
| 61 | + @Test |
| 62 | + public void testNumberOfFactorizationsRecords() { |
| 63 | + int maxListSize = 30; |
| 64 | + ArrayList<Integer> list = new ArrayList<>(); |
| 65 | + long record = 0; |
| 66 | + for (int n=1; n<=10000; n++) { |
| 67 | + long numberOfFactorizations = MpiPartitionGenerator.numberOfFactorizationsOf(BigInteger.valueOf(n)); |
| 68 | + if (numberOfFactorizations > record) { // same value does not count as new record |
| 69 | + LOG.info(n + " can be factored in " + numberOfFactorizations + " different ways"); |
| 70 | + record = numberOfFactorizations; |
| 71 | + if (list.size() < maxListSize) list.add(n); |
| 72 | + } |
| 73 | + } |
| 74 | + if (DEBUG) LOG.debug("First 30 sequence elements = " + list); |
| 75 | + assertEquals("[1, 4, 8, 12, 16, 24, 36, 48, 72, 96, 120, 144, 192, 216, 240, 288, 360, 432, 480, 576, 720, 960, 1080, 1152, 1440, 2160, 2880, 4320, 5040, 5760]", list.toString()); |
| 76 | + } |
| 77 | + |
| 78 | + /** |
| 79 | + * Test record numbers of essentially different factorizations of n per bit. |
| 80 | + * This sequence S(n) = 1, 12, 16, 24, 36, 48, 72, 96, 120, 144, 240, 288, 360, 432, 480, 576, 720, 960, 1080, 1152, ... is not in OEIS. |
| 81 | + */ |
| 82 | + @Test |
| 83 | + public void testNumberOfFactorizationsRecordsPerBit() { |
| 84 | + int maxListSize = 30; |
| 85 | + ArrayList<Integer> list = new ArrayList<>(); |
| 86 | + double recordRatio = 0; |
| 87 | + for (int n=1; n<=10000; n++) { |
| 88 | + long numberOfFactorizations = MpiPartitionGenerator.numberOfFactorizationsOf(BigInteger.valueOf(n)); |
| 89 | + double bits = n==1 ? 1.0 : Math.log(n)/Math.log(2.0); // ld(n) |
| 90 | + double ratio = numberOfFactorizations/bits; |
| 91 | + if (ratio > recordRatio) { // same value does not count as new record |
| 92 | + LOG.info(n + " (" + bits + " bit) can be factored in " + numberOfFactorizations + " different ways -> ratio = " + ratio); |
| 93 | + recordRatio = ratio; |
| 94 | + if (list.size() < maxListSize) list.add(n); |
| 95 | + } |
| 96 | + } |
| 97 | + if (DEBUG) LOG.debug("First 30 sequence elements = " + list); |
| 98 | + assertEquals("[1, 12, 16, 24, 36, 48, 72, 96, 120, 144, 240, 288, 360, 432, 480, 576, 720, 960, 1080, 1152, 1440, 2160, 2880, 4320, 5040, 5760, 7200, 8640]", list.toString()); |
| 99 | + } |
| 100 | + |
| 101 | + /** |
| 102 | + * Test the number of essentially different factorizations of n!. |
| 103 | + * This is A076716(n=2, 3, ...) = 1, 2, 7, 21, 98, 392, 2116, 11830, 70520, 425240, ... |
| 104 | + */ |
| 105 | + @Test |
| 106 | + public void testNumberOfFactorialFactorizations() { |
| 107 | + ArrayList<Long> list = new ArrayList<>(); |
| 108 | + for (int n=2; n<=11; n++) { |
| 109 | + long start = System.currentTimeMillis(); |
| 110 | + BigInteger factorial = Factorial.factorial(n); |
| 111 | + long numberOfFactorizations = MpiPartitionGenerator.numberOfFactorizationsOf(factorial); |
| 112 | + LOG.info(n + "! = " + factorial + " can be factored in " + numberOfFactorizations + " different ways (computed in " + (System.currentTimeMillis()-start) + " ms)"); |
| 113 | + list.add(numberOfFactorizations); |
| 114 | + } |
| 115 | + if (DEBUG) LOG.debug("list = " + list); |
| 116 | + assertEquals("[1, 2, 7, 21, 98, 392, 2116, 11830, 70520, 425240]", list.toString()); |
| 117 | + } |
| 118 | + |
| 119 | + /** |
| 120 | + * Test the number of partitions of partitions. |
| 121 | + * A001970 = 1, 1, 3, 6, 14, 27, 58, 111, 223, 424, 817, 1527, 2870, 5279, 9710, 17622, 31877, 57100, 101887, 180406, 318106, 557453, 972796, 1688797, 2920123, ... |
| 122 | + */ |
| 123 | + @Test |
| 124 | + public void testPartitionsOfPartitions() { |
| 125 | + ArrayList<Long> list = new ArrayList<>(); |
| 126 | + for (int n=0; n<=20; n++) { |
| 127 | + long start = System.currentTimeMillis(); |
| 128 | + long totalNumberOfPartitions = MpiPartitionGenerator.numberOfPartitionsOfPartitions(n); |
| 129 | + LOG.info(n + " has " + totalNumberOfPartitions + " partitions of partitions (computed in " + (System.currentTimeMillis()-start) + " ms)"); |
| 130 | + list.add(totalNumberOfPartitions); |
| 131 | + } |
| 132 | + if (DEBUG) LOG.debug("list = " + list); |
| 133 | + assertEquals("[1, 1, 3, 6, 14, 27, 58, 111, 223, 424, 817, 1527, 2870, 5279, 9710, 17622, 31877, 57100, 101887, 180406, 318106]", list.toString()); |
| 134 | + } |
| 135 | + |
| 136 | + /** |
| 137 | + * Test the number of partitions of strong multisets. |
| 138 | + * This is A035310 = "Ways of partitioning an n-multiset with multiplicities some partition of n." |
| 139 | + * = 1, 4, 12, 47, 170, 750, 3255, 16010, 81199, 448156, 2579626, 15913058, 102488024, 698976419, 4976098729, 37195337408, 289517846210, 2352125666883, 19841666995265, 173888579505200, 1577888354510786, 14820132616197925, 143746389756336173, 1438846957477988926, ... |
| 140 | + */ |
| 141 | + @Test |
| 142 | + public void testMultisetPartitions() { |
| 143 | + ArrayList<Long> list = new ArrayList<>(); |
| 144 | + for (int n=1; n<=10; n++) { |
| 145 | + long start = System.currentTimeMillis(); |
| 146 | + long totalNumberOfPartitions = MpiPartitionGenerator.numberOfMultisetPartitions(n); |
| 147 | + LOG.info(n + " has " + totalNumberOfPartitions + " multiset partitions (computed in " + (System.currentTimeMillis()-start) + " ms)"); |
| 148 | + list.add(totalNumberOfPartitions); |
| 149 | + } |
| 150 | + if (DEBUG) LOG.debug("list = " + list); |
| 151 | + assertEquals("[1, 4, 12, 47, 170, 750, 3255, 16010, 81199, 448156]", list.toString()); |
| 152 | + } |
| 153 | +} |
0 commit comments