Skip to content

Commit

Permalink
Add producers of last resort, when necessary.
Browse files Browse the repository at this point in the history
  • Loading branch information
KirkMcDonald committed Oct 21, 2024
1 parent 9cc8533 commit 3174c45
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 4 deletions.
54 changes: 52 additions & 2 deletions solve.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,30 @@ export function solve(spec, fullOutputs) {
spec.lastMetadata = null
spec.lastSolution = null
solution.set(new OutputRecipe(outputs), one)
return new Totals(spec, outputs, solution, new Map())
return new Totals(spec, outputs, solution, new Map(), new Map())
}

recipes = spec.getRecipeGraph(partialSolution.remaining)

// If an item
// 1) Is used as a link internal to a recipe cycle.
// and
// 2) Is not produced by a recipe outside of the cycle.
// unless
// 2a) It is a product of a factory target.
// then include that item's disableRecipe in the tableau, at the maximum
// possible priority level, as a producer of last resort. It is possible
// for such items to be involved in a net-negative production loop, and
// doing so will avoid infeasible solutions.

// Map of build target items to recipes, if they are recipe-targets.
let targetItemMap = new Map()
for (let target of spec.buildTargets) {
if (target.changedBuilding && target.recipe) {
targetItemMap.set(target.item, target.recipe)
}
}

let products = new Set()
//let ingredients = new Set()

Expand All @@ -153,6 +172,34 @@ export function solve(spec, fullOutputs) {
let recipeArray = []
let recipeRows = new Map()

let maxPriorityRecipes = new Map()

for (let recipe of recipes) {
if (cyclic.has(recipe)) {
for (let {item} of recipe.getIngredients()) {
if (recipes.has(item.disableRecipe)) {
continue
}
let candidate = false
let outside = false
for (let subrecipe of item.recipes) {
if (cyclic.has(subrecipe)) {
candidate = true
} else {
if (recipes.has(subrecipe)) {
outside = true
}
}
}
if (candidate && (targetItemMap.has(item) || !outside)) {
maxPriorityRecipes.set(item, item.disableRecipe)
}
}
}
}
for (let [item, recipe] of maxPriorityRecipes) {
recipes.add(recipe)
}
for (let recipe of recipes) {
recipeRows.set(recipe, recipeArray.length)
recipeArray.push(recipe)
Expand Down Expand Up @@ -273,6 +320,9 @@ export function solve(spec, fullOutputs) {
P = P.mul(cost_ratio).mul(N)
}
}
for (let [item, recipe] of maxPriorityRecipes) {
A.setIndex(recipeRows.get(recipe), columns - 1, P)
}

spec.lastTableau = A.copy()
spec.lastMetadata = {
Expand Down Expand Up @@ -309,6 +359,6 @@ export function solve(spec, fullOutputs) {
if (surplus.size > 0) {
solution.set(new SurplusRecipe(surplus), one)
}
return new Totals(spec, outputs, solution, surplus)
return new Totals(spec, outputs, solution, surplus, maxPriorityRecipes)
//return {"solution": solution, "surplus": surplus}
}
8 changes: 6 additions & 2 deletions totals.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function set(map, key1, key2, value) {
}

export class Totals {
constructor(spec, products, rates, surplus) {
constructor(spec, products, rates, surplus, extraRecipes) {
this.products = products
this.rates = rates
this.surplus = surplus
Expand Down Expand Up @@ -76,7 +76,11 @@ export class Totals {
let rate = recipeRate.mul(ing.amount)
let ratio = rate.div(totalRate)
let fuel = i >= recipe.ingredients.length
for (let subRecipe of spec.getRecipes(ing.item)) {
let subRecipes = spec.getRecipes(ing.item)
if (extraRecipes.has(ing.item)) {
subRecipes.push(extraRecipes.get(ing.item))
}
for (let subRecipe of subRecipes) {
if (!rates.has(subRecipe)) {
continue
}
Expand Down

0 comments on commit 3174c45

Please sign in to comment.