From ac522c7751f8ec6d2537de2044b465ff7c76f829 Mon Sep 17 00:00:00 2001 From: C-H716 <1536152356@qq.com> Date: Thu, 28 Aug 2025 15:23:06 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DScaledProcessingPattern?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E8=BF=87=E7=A8=8B=E4=B8=AD=E4=BA=A7=E5=87=BA?= =?UTF-8?q?=E6=AF=94=E7=9A=84=E8=AE=A1=E7=AE=97=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../extendedae_plus/util/ArraySimplifier.java | 78 +++++++++++++++++ .../extendedae_plus/util/PatternScaler.java | 85 +++++++++++++------ 2 files changed, 138 insertions(+), 25 deletions(-) create mode 100644 src/main/java/com/extendedae_plus/util/ArraySimplifier.java diff --git a/src/main/java/com/extendedae_plus/util/ArraySimplifier.java b/src/main/java/com/extendedae_plus/util/ArraySimplifier.java new file mode 100644 index 0000000..076eb31 --- /dev/null +++ b/src/main/java/com/extendedae_plus/util/ArraySimplifier.java @@ -0,0 +1,78 @@ +package com.extendedae_plus.util; + +import java.util.Arrays; + +public class ArraySimplifier { + + // 计算两个数的GCD using Euclidean algorithm (long版本) + public static long gcd(long a, long b) { + while (b != 0) { + long temp = b; + b = a % b; + a = temp; + } + return a; + } + + // 计算整个数组的GCD + public static long findGCD(long[] arr) { + if (arr.length == 0) { + return 0; + } + long result = arr[0]; + for (int i = 1; i < arr.length; i++) { + result = gcd(result, arr[i]); + // 如果已经找到GCD为1,可以提前终止 + if (result == 1) { + break; + } + } + return result; + } + + // 简化数组:每个元素除以数组的GCD + public static long[] simplifyFraction(long[] arr) { + if (arr.length == 0) { + return new long[0]; + } + long gcd = findGCD(arr); + if (gcd == 0) { + // 如果GCD为0(所有元素为0),返回原数组的副本 + return Arrays.copyOf(arr, arr.length); + } + long[] simplified = new long[arr.length]; + for (int i = 0; i < arr.length; i++) { + simplified[i] = arr[i] / gcd; + } + return simplified; + } + + // 将两个数组合并为一个新数组(先放 a 后放 b) + public static long[] combine(long[] a, long[] b) { + long[] out = new long[a.length + b.length]; + System.arraycopy(a, 0, out, 0, a.length); + System.arraycopy(b, 0, out, a.length, b.length); + return out; + } + + // 寻找数组的 GCD,遇到 1 则立即返回 1(早期退出优化) + public static long findGCDWithEarlyExit(long[] arr) { + if (arr.length == 0) return 0; + long result = 0; + for (long v : arr) { + if (v == 1) return 1; // already irreducible + if (v == 0) continue; + if (result == 0) result = v; else result = gcd(result, v); + if (result == 1) return 1; + } + return result == 0 ? 0 : Math.abs(result); + } + + // 根据给定的 gcd 返回一个已除以 gcd 的新数组;如果 gcd==1 返回原数组(避免不必要的分配) + public static long[] simplifyByGcd(long[] arr, long gcd) { + if (gcd <= 1) return arr; + long[] out = new long[arr.length]; + for (int i = 0; i < arr.length; i++) out[i] = arr[i] / gcd; + return out; + } +} \ No newline at end of file diff --git a/src/main/java/com/extendedae_plus/util/PatternScaler.java b/src/main/java/com/extendedae_plus/util/PatternScaler.java index f57f620..13712e9 100644 --- a/src/main/java/com/extendedae_plus/util/PatternScaler.java +++ b/src/main/java/com/extendedae_plus/util/PatternScaler.java @@ -21,35 +21,56 @@ public final class PatternScaler { IInput[] baseInputs = base.getInputs(); GenericStack[] baseOutputs = base.getOutputs(); - /* 1. 构建缩放后的 sparseInputs */ - GenericStack[] scaledSparseInputs = new GenericStack[baseSparseInputs.length]; - for (int i = 0; i < baseSparseInputs.length; i++) { - GenericStack in = baseSparseInputs[i]; - if (in != null) { - scaledSparseInputs[i] = new GenericStack(in.what(), requestedAmount); - } + // 计算每个压缩输入槽位的总量(per operation): multiplier * template.amount + long[] inputsCounts = new long[baseInputs.length]; + for (int i = 0; i < baseInputs.length; i++) { + var in = baseInputs[i]; + var first = in.getPossibleInputs()[0]; + inputsCounts[i] = in.getMultiplier() * first.amount(); } - /* 2. 构建缩放后的 sparseOutputs */ - GenericStack[] scaledSparseOutputs = new GenericStack[baseSparseOutputs.length]; - for (int i = 0; i < baseSparseOutputs.length; i++) { - GenericStack out = baseSparseOutputs[i]; - if (out != null) { - scaledSparseOutputs[i] = new GenericStack(out.what(), requestedAmount); - } + // 计算每个输出的数量(per operation) + long[] outputsCounts = new long[baseOutputs.length]; + for (int i = 0; i < baseOutputs.length; i++) { + var out = baseOutputs[i]; + outputsCounts[i] = out == null ? 0L : out.amount(); } - /* 3. 构建压缩输入(ScaledInput) */ + // 合并为一个数组并计算 gcd(使用早期退出优化) + long[] combined = ArraySimplifier.combine(inputsCounts, outputsCounts); + long gcd = ArraySimplifier.findGCDWithEarlyExit(combined); + if (gcd <= 0) gcd = 1; + + // 如果 gcd == 1,则无需分配新的数组,直接使用 combined 作为 simplified 视图 + long[] simplified = ArraySimplifier.simplifyByGcd(combined, gcd); + + // 找到目标输出在 outputs 中的索引 + int targetOutIndex = -1; + for (int i = 0; i < baseOutputs.length; i++) { + if (baseOutputs[i] != null) { + targetOutIndex = i; + break; + } + } + if (targetOutIndex == -1 && baseOutputs.length > 0) targetOutIndex = 0; + + long simplifiedTargetPerUnit = simplified[inputsCounts.length + Math.max(0, targetOutIndex)]; + if (simplifiedTargetPerUnit <= 0) simplifiedTargetPerUnit = 1; + + // 单位数:需要多少 "最简约单位" 才能满足 requestedAmount(向上取整) + long units = (requestedAmount + simplifiedTargetPerUnit - 1) / simplifiedTargetPerUnit; + + // 构建压缩输入(ScaledInput)——模板数量为 simplifiedInputs, multiplier 为 units IInput[] scaledInputs = new IInput[baseInputs.length]; for (int i = 0; i < baseInputs.length; i++) { var in = baseInputs[i]; var template = in.getPossibleInputs(); - GenericStack[] scaledTemplates = new GenericStack[template.length]; + long simplifiedInputAmount = simplified[i]; for (int j = 0; j < template.length; j++) { - scaledTemplates[j] = new GenericStack(template[j].what(), 1); + scaledTemplates[j] = new GenericStack(template[j].what(), simplifiedInputAmount); } - scaledInputs[i] = new ScaledProcessingPattern.Input(scaledTemplates, requestedAmount); + scaledInputs[i] = new ScaledProcessingPattern.Input(scaledTemplates, units); } /* 4. 构建压缩输出 */ @@ -57,10 +78,30 @@ public final class PatternScaler { for (int i = 0; i < baseOutputs.length; i++) { GenericStack out = baseOutputs[i]; if (out != null) { - scaledCondensedOutputs[i] = new GenericStack(out.what(), requestedAmount); + long simplifiedOutAmount = simplified[inputsCounts.length + i]; + scaledCondensedOutputs[i] = new GenericStack(out.what(), simplifiedOutAmount * units); } } + // 构建并打印稀疏表示(按 unit * simplified / gcd 映射回原稀疏槽) + GenericStack[] scaledSparseInputs = new GenericStack[baseSparseInputs.length]; + for (int i = 0; i < baseSparseInputs.length; i++) { + var in = baseSparseInputs[i]; + if (in != null) { + long scaledAmount = in.amount() * units / gcd; + scaledSparseInputs[i] = new GenericStack(in.what(), scaledAmount); + } + } + GenericStack[] scaledSparseOutputs = new GenericStack[baseSparseOutputs.length]; + for (int i = 0; i < baseSparseOutputs.length; i++) { + var out = baseSparseOutputs[i]; + if (out != null) { + long scaledAmount = out.amount() * units / gcd; + scaledSparseOutputs[i] = new GenericStack(out.what(), scaledAmount); + } + } + + /* Debug 输出 */ System.out.println("[extendedae_plus] 正在缩放样板:"); System.out.println(" 原始样板: " + base); @@ -79,10 +120,4 @@ public final class PatternScaler { scaledInputs, scaledCondensedOutputs); } - - private static long safeMul(long a, long b) { - if (a == 0 || b == 0) return 0; - if (a > Long.MAX_VALUE / b) return Long.MAX_VALUE; - return a * b; - } }