{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7fb27b941602401d91542211134fc71a",
   "metadata": {},
   "source": [
    "# 玩具示例\n",
    "\n",
    "**类别：** 装箱\n",
    "\n",
    "使用 OptAgent 的 Python 接口描述变量、约束与目标。\n",
    "\n",
    "问题与原始示例来源：[Hexaly Code Templates](https://www.hexaly.com/templates/toy)。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "acae54e37e7d407bbb7b55eff062a284",
   "metadata": {},
   "source": [
    "## 问题描述\n",
    "\n",
    "我们描述**背包问题的一个玩具示例**。我们考虑 8 件物品，其重量分别为 10、60、30、40、30、20、20、2，价值分别为 1、10、15、40、60、90、100、15。目标是确定一个物品子集，使其总重量不超过 102，并且总价值尽可能大。\n",
    "\n",
    "### 学习要点\n",
    "\n",
    "- 使用 OptAgent 区分决策变量与由决策推导出的中间表达式\n",
    "- 使用布尔决策变量表示物品是否被选中\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a63283cbaf04dbcab1f6479b197f3a8",
   "metadata": {},
   "source": [
    "## 建模思路\n",
    "\n",
    "对每件物品定义一个布尔决策变量，若该物品被选中则为真。所选物品的总重量和总价值均为由决策变量推导出的中间表达式，而不是额外的决策变量。模型约束总重量不超过 102，并最大化总价值。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8dd0d8092fe74a7c96281538738b07e2",
   "metadata": {},
   "source": [
    "## Python 实现\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "72eea5119410473aa328ad9291626812",
   "metadata": {},
   "outputs": [],
   "source": [
    "from optagent import OptModel, solve\n",
    "\n",
    "\n",
    "def main(time_limit=10):\n",
    "    weights = [10, 60, 30, 40, 30, 20, 20, 2]\n",
    "    values = [1, 10, 15, 40, 60, 90, 100, 15]\n",
    "    knapsack_bound = 102\n",
    "\n",
    "    model = OptModel()\n",
    "\n",
    "    # x[item] is true when the item is selected.\n",
    "    x = [model.bool() for item in range(len(weights))]\n",
    "\n",
    "    knapsack_weight = model.sum(weights[item] * x[item] for item in range(len(weights)))\n",
    "    model.constraint(knapsack_weight <= knapsack_bound)\n",
    "\n",
    "    knapsack_value = model.sum(values[item] * x[item] for item in range(len(values)))\n",
    "    model.maximize(knapsack_value)\n",
    "\n",
    "    solution = solve(model, time_limit_s=float(time_limit))\n",
    "    if not solution.feasible:\n",
    "        print(f\"No feasible selection found; Status = {solution.status}\")\n",
    "        return solution\n",
    "\n",
    "    selected_items = [item for item, selected in enumerate(x) if selected.value]\n",
    "    print(\n",
    "        f\"Selected items = {selected_items}; Weight = {knapsack_weight.value}; \"\n",
    "        f\"Value = {knapsack_value.value}; Status = {solution.status}\"\n",
    "    )\n",
    "    return solution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8edb47106e1a46a883d545849b8ab81b",
   "metadata": {},
   "outputs": [],
   "source": [
    "solution = main(time_limit=1)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
