修改ScaledProcessingPattern倍乘策略为最小整数倍

This commit is contained in:
C-H716 2025-08-29 14:37:47 +08:00
parent 692ffb7396
commit 49574cb630
3 changed files with 31 additions and 70 deletions

View File

@ -39,8 +39,6 @@ public abstract class CraftingTreeProcessMixin {
CraftingTreeNodeAccessor parentAcc = (CraftingTreeNodeAccessor) craftingTreeNode;
AEKey parentTarget = parentAcc.extendedae_plus$getWhat();
long requested = RequestedAmountHolder.get();
// 记录所使用的请求数量和当前线程堆栈快照便于诊断 PatternScaler.scale 使用了哪个值以及何时清理
LOGGER.info("[extendedae_plus] 在 CraftingTreeProcess 构造中使用请求数量: {} ; stackDepth={} ; stackSnapshot={}", requested, RequestedAmountHolder.depth(), RequestedAmountHolder.snapshot());
// 使用当前线程栈顶的值进行缩放不在此处清理构造完成后应该由调用方的 pop 恢复状态
return PatternScaler.scale(proc, parentTarget, requested);
} catch (Exception e) {

View File

@ -23,56 +23,49 @@ public final class PatternScaler {
IInput[] baseInputs = base.getInputs();
GenericStack[] baseOutputs = base.getOutputs();
// 计算每个压缩输入槽位的总量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();
}
// 计算每个输出的数量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();
}
// 合并为一个数组并计算 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 中的索引
// 新逻辑不再对样板进行单位化处理
// 找到目标输出在 outputs 中的索引尝试匹配 target否则取第一个非空输出
int targetOutIndex = -1;
for (int i = 0; i < baseOutputs.length; i++) {
if (baseOutputs[i] != null) {
var out = baseOutputs[i];
if (out != null && target != null && out.what() != null && out.what().equals(target)) {
targetOutIndex = i;
break;
}
}
if (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;
long perOperationTarget = 1L;
if (targetOutIndex >= 0 && baseOutputs[targetOutIndex] != null) {
long amt = baseOutputs[targetOutIndex].amount();
if (amt > 0) perOperationTarget = amt;
}
// 单位数需要多少 "最简约单位" 才能满足 requestedAmount向上取整
long units = (requestedAmount + simplifiedTargetPerUnit - 1) / simplifiedTargetPerUnit;
// 使用最小整数倍ceil策略直接选择满足请求的最小倍数
long multiplier = 1L;
if (requestedAmount > 0) {
long needed = requestedAmount / perOperationTarget + ((requestedAmount % perOperationTarget) == 0 ? 0 : 1);
multiplier = needed <= 1L ? 1L : needed;
}
// 构建压缩输入ScaledInput模板数量为 simplifiedInputs, multiplier units
// 构建压缩输入将每个输入的 multiplier 翻倍保留每个模板的原始数量
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(), simplifiedInputAmount);
scaledTemplates[j] = new GenericStack(template[j].what(), template[j].amount());
}
scaledInputs[i] = new ScaledProcessingPattern.Input(scaledTemplates, units);
scaledInputs[i] = new ScaledProcessingPattern.Input(scaledTemplates, in.getMultiplier() * multiplier);
}
/* 4. 构建压缩输出 */
@ -80,26 +73,23 @@ public final class PatternScaler {
for (int i = 0; i < baseOutputs.length; i++) {
GenericStack out = baseOutputs[i];
if (out != null) {
long simplifiedOutAmount = simplified[inputsCounts.length + i];
scaledCondensedOutputs[i] = new GenericStack(out.what(), simplifiedOutAmount * units);
scaledCondensedOutputs[i] = new GenericStack(out.what(), out.amount() * multiplier);
}
}
// 构建并打印稀疏表示 unit * simplified / gcd 映射回原稀疏槽
// 构建并打印稀疏表示直接按 multiplier 放大
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);
scaledSparseInputs[i] = new GenericStack(in.what(), in.amount() * multiplier);
}
}
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);
scaledSparseOutputs[i] = new GenericStack(out.what(), out.amount() * multiplier);
}
}

View File

@ -2,7 +2,6 @@ package com.extendedae_plus.util;
import java.util.ArrayDeque;
import java.util.Deque;
import static com.extendedae_plus.util.ExtendedAELogger.LOGGER;
/**
* Thread-local stack holder for requested amounts to support nested requests.
@ -19,7 +18,6 @@ public final class RequestedAmountHolder {
public static void push(long v) {
Deque<Long> dq = HOLDER.get();
dq.push(v);
LOGGER.info("[extendedae_plus] 请求数量已推入堆栈: {} ; depth={}", v, dq.size());
}
/**
@ -28,11 +26,9 @@ public final class RequestedAmountHolder {
public static void pop() {
Deque<Long> dq = HOLDER.get();
if (dq.isEmpty()) {
LOGGER.info("[extendedae_plus] 请求数量堆栈为空,无法弹出");
return;
}
Long popped = dq.pop();
LOGGER.info("[extendedae_plus] 请求数量已弹出堆栈: {} ; depth={}", popped, dq.size());
dq.pop();
}
/**
@ -41,31 +37,8 @@ public final class RequestedAmountHolder {
public static long get() {
Deque<Long> dq = HOLDER.get();
Long v = dq.peek();
LOGGER.info("[extendedae_plus] 当前请求数量: {} ; depth={}", v, dq.size());
return v == null ? 0L : v;
}
/**
* Clear the entire stack for this thread.
*/
public static void clearAll() {
HOLDER.get().clear();
LOGGER.info("[extendedae_plus] 请求数量堆栈已清空");
}
/**
* 返回当前线程堆栈深度仅供日志/诊断使用
*/
public static int depth() {
return HOLDER.get().size();
}
/**
* 返回当前线程堆栈的字符串表示仅供日志/诊断使用
*/
public static String snapshot() {
return HOLDER.get().toString();
}
}