|
import gradio as gr |
|
import numpy as np |
|
import pulp |
|
|
|
|
|
def bounded_knapsack_problem_solver(target, df): |
|
|
|
name_ls = [] |
|
for index, item in enumerate(df["name"]): |
|
if item: |
|
name_ls.append(item) |
|
else: |
|
name_ls.append(f"📦{str(index+1)}") |
|
|
|
if len(name_ls) != len(set(name_ls)): |
|
return "Please check for duplicate item names and try again." |
|
|
|
items = np.array(name_ls) |
|
prices = np.array([int(p) if p else 0 for p in df["value"]]) |
|
stocks = np.array([int(c) if c else 0 for c in df["count"]]) |
|
|
|
|
|
prob = pulp.LpProblem("Maximize_Value", pulp.LpMaximize) |
|
|
|
|
|
x = pulp.LpVariable.dicts("x", range(len(prices)), lowBound=0, cat="Integer") |
|
|
|
|
|
for i in range(len(stocks)): |
|
x[i].upBound = stocks[i] |
|
|
|
|
|
prob += pulp.lpSum([prices[i] * x[i] for i in range(len(stocks))]) |
|
|
|
|
|
prob += pulp.lpSum([prices[i] * x[i] for i in range(len(stocks))]) <= target |
|
|
|
|
|
|
|
solver = pulp.getSolver("PULP_CBC_CMD") |
|
prob.solve(solver=solver) |
|
|
|
if pulp.LpStatus[prob.status] == "Optimal": |
|
|
|
value = 0 |
|
solution = [] |
|
for i, v in x.items(): |
|
if v.varValue: |
|
if v.varValue > 0: |
|
solution.append(f"{items[i]}(${prices[i]}): {int(v.varValue)}\n") |
|
value += int(v.varValue) * prices[i] |
|
if value == target: |
|
return f"Optimal solution found:\n\n{''.join(solution)}\nTotal value: {value}\nGreat! Found a combination of items with a total value equal to the target value(${target}).😃" |
|
|
|
else: |
|
return f"Optimal solution found:\n\n{''.join(solution)}\nTotal value: {value}\n${target - value} short of the target value(${target}).😂" |
|
|
|
|
|
|
|
with gr.Blocks(theme=gr.themes.Soft()) as demo: |
|
gr.Markdown( |
|
""" |
|
<center><font size=8>📦Easy Bounded Knapsack Problem Solver📦</center> |
|
|
|
### Given |
|
|
|
- A set of items, each with: |
|
- Value ( v_i ) |
|
- Maximum quantity ( q_i ) |
|
- A target value ( T ) |
|
|
|
### Objective |
|
|
|
Find a combination of items such that the sum of the selected items' values equals ( T ) |
|
or maximizes the total value without exceeding ( T ). |
|
Each item ( i ) can be selected up to ( q_i ) times. |
|
""" |
|
) |
|
|
|
with gr.Column(): |
|
|
|
target = gr.Number( |
|
label="Target", |
|
info="number less than 50,000", |
|
value=0, |
|
precision=0, |
|
minimum=0, |
|
maximum=50000, |
|
step=100, |
|
) |
|
|
|
df = gr.Dataframe( |
|
headers=["name", "value", "count"], |
|
datatype=["str", "number", "number"], |
|
row_count=3, |
|
col_count=(3, "fixed"), |
|
label="Items", |
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with gr.Row(): |
|
clear_btn = gr.ClearButton(df, size="sm", value="❌Clear") |
|
|
|
|
|
submit_btn = gr.Button(value="🛠Calculate") |
|
|
|
|
|
with gr.Row(): |
|
result = gr.Textbox(label="Output") |
|
|
|
examples = gr.Examples( |
|
examples=[ |
|
[150, [["", 12, 10], ["", 9, 5], ["", 8, 10]]], |
|
[ |
|
500, |
|
[ |
|
["pencil", 129, 1], |
|
["magic keyboard", 349, 1], |
|
["homepod", 299, 1], |
|
["airpods max", 549, 1], |
|
], |
|
], |
|
], |
|
inputs=[target, df], |
|
) |
|
|
|
|
|
submit_btn.click( |
|
bounded_knapsack_problem_solver, |
|
inputs=[target, df], |
|
outputs=[result], |
|
) |
|
|
|
|
|
demo.queue(api_open=False) |
|
demo.launch(max_threads=5, share=False) |
|
|
|
if __name__ == "__main__": |
|
demo.launch() |
|
|