修复ScaledProcessingPattern构建过程中产出比的计算问题
This commit is contained in:
parent
1d55920af9
commit
ac522c7751
78
src/main/java/com/extendedae_plus/util/ArraySimplifier.java
Normal file
78
src/main/java/com/extendedae_plus/util/ArraySimplifier.java
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,35 +21,56 @@ public final class PatternScaler {
|
||||||
IInput[] baseInputs = base.getInputs();
|
IInput[] baseInputs = base.getInputs();
|
||||||
GenericStack[] baseOutputs = base.getOutputs();
|
GenericStack[] baseOutputs = base.getOutputs();
|
||||||
|
|
||||||
/* 1. 构建缩放后的 sparseInputs */
|
// 计算每个压缩输入槽位的总量(per operation): multiplier * template.amount
|
||||||
GenericStack[] scaledSparseInputs = new GenericStack[baseSparseInputs.length];
|
long[] inputsCounts = new long[baseInputs.length];
|
||||||
for (int i = 0; i < baseSparseInputs.length; i++) {
|
for (int i = 0; i < baseInputs.length; i++) {
|
||||||
GenericStack in = baseSparseInputs[i];
|
var in = baseInputs[i];
|
||||||
if (in != null) {
|
var first = in.getPossibleInputs()[0];
|
||||||
scaledSparseInputs[i] = new GenericStack(in.what(), requestedAmount);
|
inputsCounts[i] = in.getMultiplier() * first.amount();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. 构建缩放后的 sparseOutputs */
|
// 计算每个输出的数量(per operation)
|
||||||
GenericStack[] scaledSparseOutputs = new GenericStack[baseSparseOutputs.length];
|
long[] outputsCounts = new long[baseOutputs.length];
|
||||||
for (int i = 0; i < baseSparseOutputs.length; i++) {
|
for (int i = 0; i < baseOutputs.length; i++) {
|
||||||
GenericStack out = baseSparseOutputs[i];
|
var out = baseOutputs[i];
|
||||||
if (out != null) {
|
outputsCounts[i] = out == null ? 0L : out.amount();
|
||||||
scaledSparseOutputs[i] = new GenericStack(out.what(), requestedAmount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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];
|
IInput[] scaledInputs = new IInput[baseInputs.length];
|
||||||
for (int i = 0; i < baseInputs.length; i++) {
|
for (int i = 0; i < baseInputs.length; i++) {
|
||||||
var in = baseInputs[i];
|
var in = baseInputs[i];
|
||||||
var template = in.getPossibleInputs();
|
var template = in.getPossibleInputs();
|
||||||
|
|
||||||
GenericStack[] scaledTemplates = new GenericStack[template.length];
|
GenericStack[] scaledTemplates = new GenericStack[template.length];
|
||||||
|
long simplifiedInputAmount = simplified[i];
|
||||||
for (int j = 0; j < template.length; j++) {
|
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. 构建压缩输出 */
|
/* 4. 构建压缩输出 */
|
||||||
|
|
@ -57,10 +78,30 @@ public final class PatternScaler {
|
||||||
for (int i = 0; i < baseOutputs.length; i++) {
|
for (int i = 0; i < baseOutputs.length; i++) {
|
||||||
GenericStack out = baseOutputs[i];
|
GenericStack out = baseOutputs[i];
|
||||||
if (out != null) {
|
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 输出 */
|
/* Debug 输出 */
|
||||||
System.out.println("[extendedae_plus] 正在缩放样板:");
|
System.out.println("[extendedae_plus] 正在缩放样板:");
|
||||||
System.out.println(" 原始样板: " + base);
|
System.out.println(" 原始样板: " + base);
|
||||||
|
|
@ -79,10 +120,4 @@ public final class PatternScaler {
|
||||||
scaledInputs,
|
scaledInputs,
|
||||||
scaledCondensedOutputs);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user