<jupyter_start><jupyter_text>input_data.py contains our sample data, including hull quantites and me values<jupyter_code>import input_data<jupyter_output><empty_output><jupyter_text>what mineral types do we need to build these hulls (and what are their prices)<jupyter_code>mineral_ids = sorted(list(set((sum([[m for m in input_data.ore_yield_dict[o].keys()] for o in input_data.ore_yield_dict.keys()], [])))))
mineral_names = [input_data.item_info_dict[m].get('name', '') for m in mineral_ids]
mineral_prices = [input_data.item_prices_dict[m] for m in mineral_ids]
dict(zip(mineral_names, mineral_prices))<jupyter_output><empty_output><jupyter_text>how many of those types to build what we want<jupyter_code>def calc_qty(count, quantity, me, fm):
    return round(max(float(count),
        math.ceil(round(float(count)*(float(quantity)*(1.0-float(me)/100.0)*float(fm)), 2))))


# add up the minerals for each ship order
total_minerals = dict(zip(mineral_ids, [0] * len(mineral_ids)))
for ship_id in input_data.ship_build_dict.keys():
    ship_qty = input_data.ship_build_dict.get(ship_id, 0)
    ship_me = input_data.ship_me_dict.get(ship_id, 0)
    ship_minerals = dict(zip(mineral_ids,
        [calc_qty(ship_qty, input_data.ship_requirements_dict[ship_id].get(m, 0), ship_me, 1.0) for m in sorted(list(mineral_ids))])
        )
    print("{:12s} x {:3} ({:2}) = {}".format(input_data.item_info_dict[ship_id]['name'], ship_qty, ship_me, ship_minerals))
    total_minerals = dict(zip(mineral_ids, 
        [total_minerals[x] + ship_minerals[x] for x in mineral_ids]
    ))

print("{:12s}            = {}".format('Total', total_minerals))

required_minerals = [total_minerals.get(m, 0) for m in mineral_ids]
print(required_minerals)<jupyter_output>[991163, 223347, 72793, 24913, 2611, 2801, 555]<jupyter_text>how much would it cost to just buy the minerals directly<jupyter_code>minerals_cost = int(sum([required_minerals[mi] * mineral_prices[mi] for mi in range(len(mineral_ids))]))
print("minerals_cost: {:n} ISK".format(minerals_cost))<jupyter_output>minerals_cost: 28,219,556 ISK<jupyter_text>refining efficiency - this is the variable that makes the most difference<jupyter_code>refining_efficiency = 0.50<jupyter_output><empty_output><jupyter_text>inputs (and their yield) - some experimentation here to reduce the number of inputs to make the optimization problem smaller (faster)<jupyter_code>ore_ids = sorted(list(filter(lambda x: input_data.item_info_dict[x].get('name', '').split()[0] == 'Compressed', list(input_data.ore_yield_dict.keys()))))

# cut back the list of ore so we only have the 'basic' compressed types. still works if you skip this next line, but larger data-set -> harder to verify manually.
ore_ids = sorted(list(filter(lambda x: len(input_data.item_info_dict[x].get('name', '').split()) == 2, ore_ids)))

ore_yields = dict(zip(ore_ids, [dict(zip(mineral_ids, [math.floor(refining_efficiency * input_data.ore_yield_dict[o].get(m, 0)) for m in mineral_ids])) for o in ore_ids]))
ore_names = [input_data.item_info_dict[o].get('name', '') for o in ore_ids]
ore_packaged_volume = [input_data.item_info_dict[o].get('packagedVolume', '') for o in ore_ids]
ore_prices = [input_data.item_prices_dict[o] for o in ore_ids]
dict(zip(ore_names, ore_prices))
ore_yields
import pymprog
def calc_optimal_ores(mineral_ids, ore_ids, required_minerals, ore_prices_list, ore_yield_list):
    p = pymprog.model('MineralExplOrer')
    p.verbose(False)
    x = p.var('x', len(ore_ids), kind=int)
    p.minimize(sum(x[oi] * ore_prices_list[oi] for oi in range(len(ore_ids))))
    [[sum(x[oi]*ore_yield_list[oi][mi] for oi in range(len(ore_ids))) >= required_minerals[mi]] for mi in range(len(mineral_ids))]
    p.solver(solver='simplex', msg_lev=pymprog.glpk.GLP_MSG_OFF)
    p.solve()
    results = [0.0 for oi in range(len(ore_ids))]
    if p.get_status() in [ pymprog.glpk.GLP_OPT , pymprog.glpk.GLP_FEAS ]:
        results = [int(x[oi].primal) for oi in range(len(ore_ids))]
    p.end()
    return results
print("mineral_ids: {}".format(mineral_ids))
print("ore_ids: {}".format(ore_ids))
print("required_minerals: {}".format(required_minerals))
print("ore_prices: {}".format(ore_prices))
ore_yield_list = [[ore_yields[o][i] for i in mineral_ids] for o in ore_ids]
print("ore_yield_list: {}".format(ore_yield_list))
rval = calc_optimal_ores(mineral_ids, ore_ids, required_minerals, ore_prices, ore_yield_list)
print(rval)
actual_ore_cost = int(sum([rval[oi] * ore_prices[oi] for oi in range(len(ore_ids))]))
actual_ore_packaged_volume = int(sum([rval[oi] * ore_packaged_volume[oi] for oi in range(len(ore_ids))]))
print("actual_ore: {}".format(dict(zip(ore_names, rval))))
print("actual_ore_cost: {:n} ISK".format(actual_ore_cost))
print("actual_ore_packaged_volume: {:n} m3".format(actual_ore_packaged_volume))
for oi in range(len(ore_ids)):
    if rval[oi] > 0:
        print("{},{}".format(ore_names[oi], rval[oi]))
actual_minerals = [sum([rval[oi] * ore_yields[ore_ids[oi]][m] for oi in range(len(ore_ids))]) for m in mineral_ids]
actual_minerals_cost = int(sum([actual_minerals[mi] * mineral_prices[mi] for mi in range(len(mineral_ids))]))
print("actual_minerals: {}".format(dict(zip(mineral_names, actual_minerals))))
print("actual_minerals_cost: {:n} ISK".format(actual_minerals_cost))
residual_minerals = [actual_minerals[mi] - required_minerals[mi] for mi in range(len(mineral_ids))]
minerals_slippage = int(sum([residual_minerals[mi] * mineral_prices[mi] for mi in range(len(mineral_ids))]))
print("residual_minerals: {}".format(dict(zip(mineral_names, residual_minerals))))
print("minerals_slippage: {:n} ISK".format(minerals_slippage))<jupyter_output>residual_minerals: {'Tritanium': 194, 'Pyerite': 23, 'Mexallon': 2, 'Isogen': 1, 'Nocxium': 189, 'Zydrine': 79, 'Megacyte': 45}
minerals_slippage: 354,707 ISK
{'fraction_non_alphanumeric': 0.14888507718696398, 'fraction_numerical': 0.015608919382504288, 'mean_word_length': 7.143854748603352, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '125979', 'license': 'Apache-2.0', 'n_tokens_mistral': 2340, 'n_tokens_neox': 2184, 'n_words': 434, 'path': 'LP.ipynb', 'repo_name': 'jayblunt/MineralExplOrer', 'size': '5830'}