修改ScaledProcessingPattern倍乘策略为最小整数倍
This commit is contained in:
parent
692ffb7396
commit
49574cb630
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user