diff --git a/.github/workflows/generate-docs.yml b/.github/workflows/generate-docs.yml new file mode 100644 index 0000000..4c260ae --- /dev/null +++ b/.github/workflows/generate-docs.yml @@ -0,0 +1,25 @@ +name: generate-docs +on: + push: + branches: + - master + - main +permissions: + contents: write +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV + - uses: actions/cache@v3 + with: + key: mkdocs-material-${{ env.cache_id }} + path: .cache + restore-keys: | + mkdocs-material- + - run: pip install mkdocs-material + - run: mkdocs gh-deploy --force diff --git a/.gitignore b/.gitignore index 41ce531..6b987e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ # Prototyping Notebooks notebooks/ -*.ipynb # vscode settings .vscode/ diff --git a/docs/example.ipynb b/docs/example.ipynb new file mode 100644 index 0000000..2fd1baf --- /dev/null +++ b/docs/example.ipynb @@ -0,0 +1,155 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from planbee import Task, Resource, Scheduler" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "r1 = Resource(id=1, available_windows=[(0, 10), (20, 30)])\n", + "r2 = Resource(id=2, available_windows=[(0, 10), (20, 30)])\n", + "\n", + "t1 = Task(id=1, duration=5, resources=[r1], priority=1)\n", + "t2 = Task(id=2, duration=5, resources=[r2], priority=1, predecessors=[t1])\n", + "tasks = [t1,t2]" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scheduled 2 of 2 tasks.\n" + ] + } + ], + "source": [ + "result = Scheduler(tasks=tasks).schedule()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
task_uidassigned_resource_idstask_starttask_endresource_intervals
01[1]0.05.0([(0.0, 5.0)])
12[2]5.010.0([(5.0, 10.0)])
\n", + "
" + ], + "text/plain": [ + " task_uid assigned_resource_ids task_start task_end resource_intervals\n", + "0 1 [1] 0.0 5.0 ([(0.0, 5.0)])\n", + "1 2 [2] 5.0 10.0 ([(5.0, 10.0)])" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result.to_dataframe()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABKUAAAJOCAYAAABm7rQwAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAwHklEQVR4nO3de5TVdaH//9fMIBcFjyWkiXFJhVARCIT0iLcyyZTUo5acNG/hNS2zRD15w0IhRMkUyUgtE83UVaZlVFr9UiwNxF8iAiaYiqChiMhlZr5/+HXW4YvXcXhvZ/N4rMVa7s+ePfMaWZ+1xqef/ZmaxsbGxgAAAABAQbWVHgAAAADAhkeUAgAAAKA4UQoAAACA4kQpAAAAAIoTpQAAAAAoTpQCAAAAoDhRCgAAAIDiRCkAAAAAihOlAAAAACiuTaUHAAC8W0cccUQeeOCBtY7V1NRk4403To8ePfKlL30pn/vc5yq07v3lqaeeyic/+cm1jtXU1KRDhw7p2bNnRowYkUMOOSRJMn369Bx55JG5/vrrM2TIkErMBQA2IKIUANAqbb/99jnvvPOaHtfX1+fZZ5/Ntddem29+85vZbLPNsscee1Rw4fvLiSeemD333DNJ0tjYmOXLl+dnP/tZzjnnnKxZsyZf+MIXKjsQANjgiFIAQKvUsWPH9O/ff53ju+++e3bZZZfceuutotT/0q1bt3X+fe26666ZPXt2rr32WlEKACjOPaUAgKrSrl27tG3bNjU1NU3HGhoaMnny5Oyzzz7Zcccds+++++bHP/7xWq9bsGBBTjjhhAwZMiT9+vXL5z//+dx7771rfcysWbNy7LHHZsiQIfn4xz+eE044IY8//njT87feemt69+6dp556aq3X7b333hk1alTT4969e+eKK67IwQcfnJ122ilXXHFFkmT+/Pk55ZRTMnjw4Oy88845/vjjM2/evKbXrVy5MmPHjs0ee+yRHXfcMQcccEDuvPPOZv+7qq2tTZ8+ffL000+/6cdMmzYtI0aMyIABA7Ljjjtm2LBhueGGG5qenz59enr37p377rsvxxxzTPr165f//M//zLhx41JfX9/sbQBA9ROlAIBWqbGxMWvWrGn6s3LlysyfPz9nnXVWli9fvtY9pc4///xMnDgxw4cPz6RJkzJs2LB85zvfyfe///0kr0Wr448/PitWrMjYsWNz5ZVXZrPNNsuJJ56YJ598Mkly//335/DDD0+SfOc738lFF12UZ555Jl/4whfWCkfv1KRJk3LAAQdk4sSJ2XfffbNo0aJ8/vOfzz//+c+cf/75GTduXJYsWZIvfelLWbp0aRobG3PyySdn6tSpOfroo3PVVVdlwIAB+drXvpbbb7+92f8en3jiiXTr1u0Nn7vnnnty8sknZ4cddsiVV16Z733ve/nIRz6SCy+8MDNnzlzrY88444wMHDgwkyZNyv77759rrrkmP/vZz5q9CwCoft6+BwC0Sn/961+zww47rHWspqYmvXr1yuWXX5699toryWvR5eabb87pp5+ekSNHJkl222231NTU5Oqrr86IESOyZs2azJ8/PyeddFLTW/5ev4Jp1apVSZLx48ene/fumTx5curq6po+zz777JOJEyfm8ssvf1f7Bw0alKOPPrrp8SWXXJJVq1blRz/6Ubp06ZIk+djHPpbDDz88M2fOTJs2bfKnP/0pEyZMyH777ZckGTp0aFasWJHvfve72X///dOmzZv/aNfQ0JA1a9Y0/fOiRYvy4x//OLNnz87555//hq+ZO3duDjrooJxzzjlNxwYMGJAhQ4Zk+vTp6devX9PxQw89NCeffHKSZJdddsm0adNyzz33eFsgAPCmRCkAoFXaYYcdcsEFFyRJnnvuuVx22WVZvXp1Lrvssnz0ox9t+rj7778/jY2N2XvvvZuiTPLaW+quuuqqPPjgg/nkJz+ZbbfdNt/61rfy5z//Obvttlt23333nHXWWUmSV155JbNmzcopp5zSFKSSZNNNN81ee+21ztv83ok+ffqs9fjBBx9M//79m4JUkmy55Zb5wx/+kCT57ne/m5qamuyxxx7rfB+/+MUv8vjjj6/zOf+3c845Z624lCSdOnXKiSeemM9//vNv+JrjjjsuSbJ8+fI88cQTWbBgQWbNmpUkTbHudQMGDFjr8ZZbbplXXnnlTfcAAIhSAECrtMkmm6Rv375Nj/v165fhw4fnmGOOya233poPfvCDSZKlS5cmST772c++4edZtGhRampqMmXKlFx11VX57W9/m9tvvz0bbbRRPvWpT+WCCy7Iq6++msbGxnTu3Hmd13fu3DnLli171/s33njjtR4vXbo0W2+99Zt+/Otv4fv4xz/+hs8/99xzbxmlTjnllKbfvldbW5tOnTpl6623Tm3tm9/N4YUXXsh5552XadOmpaamJt27d8+gQYOSvPb2yf+tffv2az2ura1d52MAAP43UQoAqAqdO3fOueeem9NOOy3f/va3M378+CSvXc2UJNddd1022WSTdV631VZbJUm22GKLnH/++TnvvPMye/bs/PrXv84PfvCDfOADH8g3vvGN1NTUZMmSJeu8fvHixdlss82SpOnm6g0NDWt9zPLly992f6dOnfLCCy+sc/y+++7L1ltvnU6dOmXjjTfO9ddf/4av7969+1t+/q5du64V8d6JM844I/Pnz8+1116bAQMGpG3btlmxYkVuvvnmd/V5AADeiBudAwBVY9iwYRk6dGjuuOOOPPDAA0nSdGXPv//97/Tt27fpzwsvvJDLL788S5cuzd///vfsuuuuefjhh1NTU5M+ffrka1/7Wnr16pWnn346G2+8cXbcccfcdddda/1GuWXLluWee+7JwIEDkyQdO3ZMkjz77LNNHzNv3rymq7XeyqBBgzJz5sy1wtTzzz+f4447Lvfee28GDx6cV155JY2NjWt9H3PmzMn3v//9td7S11IefPDBfPrTn86QIUPStm3bJMkf//jHJOuGNwCAd8uVUgBAVTn77LMzfPjwXHTRRbntttvSu3fvDB8+PN/61rfyr3/9KzvuuGOeeOKJTJgwIVtvvXV69OiRNWvWpH379vnmN7+Zr3zlK+ncuXP+8pe/5NFHH82RRx6ZJPn617+eY489NiNHjsyIESOyevXqTJ48OatWrWq6wfeQIUPSvn37XHzxxTnttNOyfPnyTJw4selKqrdy1FFH5fbbb89xxx2X448/PhtttFGuuuqqbLnlljnggAPSqVOn7LzzzjnppJNy0kknZZtttsnDDz+ciRMnZujQoU1vV2xJO+20U375y19mhx12yJZbbpmHHnookydPTk1NTVasWNHiXw8A2LCIUgBAVfnoRz+aI444IlOmTMmNN96YL37xixkzZkyuvvrqTJ06Nc8++2w233zz7LfffvnqV7+aurq61NXVZcqUKRk/fny+/e1v56WXXkqPHj1y4YUX5uCDD07y2m+U+9GPfpSJEyfm9NNPT9u2bTNo0KBccskl2W677ZK89lbB733vexk/fnxOPvnkdO3aNaecckpuv/32t9394Q9/OD/96U8zbty4jBo1Km3bts2QIUMyYcKE/Md//EeS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krq6uvTs2TOjRo3K5Zdf3hKfEgAAAIAq1iJR6nXPP/98XnrppZb8lAAAAABUoWa9fe+ss85a59jy5cvzl7/8JcOGDXvPowAAAACobs2KUm9ks802y5lnnpnPfe5zLfUpAQAAAKhSzYpSY8aMaekdAAAAAGxAmn2l1LRp03LNNddk/vz5qa+vT8+ePfPFL34xBx54YAvOAwAAAKAaNStKTZ06NZdcckm++MUvZuTIkWloaMhDDz2UCy64IKtXr86hhx7a0jsBAAAAqCLNilLXXHNNzjvvvLWuivrUpz6V7bbbLpMmTRKlAAAAAHhLtc150fPPP5/+/fuvc3zAgAF55pln3usmAAAAAKpcs6JUnz59cvvtt69z/Lbbbsu22277XjcBAAAAUOWa9fa9b3zjGznqqKMyffr09OvXL0kyY8aMzJ49O5MmTWrRgQAAAABUn2ZdKTVgwIDceuut6devX+bNm5ennnoqO++8c+6666584hOfaOmNAAAAAFSZZl0plSTbbLNNRo0alSR59dVXM2fOnHTs2LHFhgEAAABQvZp1pdTcuXNz2GGH5aGHHspLL72Ugw46KIcddlh233333H///S29EQAAAIAq06wodcEFF+QjH/lIevTokVtuuSXLli3Ln//855xwwgm55JJLWnojAAAAAFWmWVHq4Ycfzle/+tV88IMfzLRp07LPPvukc+fO2X///TN//vyW3ggAAABAlWlWlOrUqVOWLFmSZ555JjNmzMiee+6ZJHn00Uez+eabt+Q+AAAAAKpQs250fvDBB+fEE09M27Zts/XWW2e33XbLjTfemLFjx+a0005r6Y0AAAAAVJlmRanTTz89ffv2zb/+9a/sv//+qaury1ZbbZVLL700e+21V0tvBAAAAKDKNCtKJck+++yTl19+OQsWLMimm26agQMHpmPHji25DQAAAIAq1ax7Sq1cuTL/8z//k8GDB+eQQw7JokWLMmrUqBx77LF58cUXW3ojAAAAAFWmWVFq3LhxmTt3bm677ba0a9cuSfKVr3wl//73v3PRRRe16EAAAAAAqk+zotTdd9+dc845J71792461rt374wePTp//OMfW2wcAAAAANWpWVFq+fLl6dChwzrHGxoaUl9f/55HAQAAAFDdmhWl9t5770yYMCEvv/xy07GFCxfmoosuyh577NFi4wAAAACoTs2K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s88+O4MGDcpuu+2WKVOmVHoSVIVFixbl1FNPzeDBgzN06NCMGTMmK1eurPQsqDojR47MqFGjKj0DqsaqVatywQUXZOedd86uu+6aSy+9NI2NjZWeBVXhmWeeyfHHH5+Pf/zj2XvvvXPttddWehK0eqtWrcr++++f6dOnNx1buHBhjjrqqPTv3z/77bdf/vznP1dwYTltKj2gOcaOHZtHHnkk1113XZ5++umceeaZ2WqrrTJs2LBKT4NWq7GxMaeeemo23XTT3HDDDXnxxRdz9tlnp7a2NmeeeWal50HV+NWvfpV77703Bx10UKWnQNW46KKLMn369Pzwhz/M8uXL87WvfS1bbbVVvvCFL1R6GrR6X/3qV7PVVlvl1ltvzdy5c3PGGWeka9eu2WeffSo9DVqllStX5utf/3oef/zxpmONjY05+eST06tXr/z85z/PtGnTcsopp+TOO+/MVlttVcG161+ru1LqlVdeyc9+9rOcc8452WGHHbLPPvvkuOOOyw033FDpadCqzZ8/PzNmzMiYMWOy3XbbZdCgQTn11FNzxx13VHoaVI2lS5dm7Nix6du3b6WnQNVYunRpfv7zn2f06NHZaaedsssuu+SYY47JzJkzKz0NWr0XX3wxM2bMyIknnpgePXrkU5/6VIYOHZr77ruv0tOgVZo7d24OO+ywLFiwYK3j999/fxYuXJgLL7ww22yzTY4//vj0798/P//5zyu0tJxWF6Vmz56dNWvWZMCAAU3HBg4cmJkzZ6ahoaGCy6B169KlS6655pp07tx5reMvv/xyhRZB9bnkkkvyuc99Lttuu22lp0DVePDBB9OxY8cMHjy46djIkSMzZsyYCq6C6tC+fft06NAht956a1avXp358+fnoYceSp8+fSo9DVqlBx54IEOGDMlNN9201vGZM2dm++23z8Ybb9x0bODAgZkxY0bhheW1uii1ePHifOADH0jbtm2bjnXu3DkrV67M0qVLKzcMWrlNN900Q4cObXrc0NCQn/zkJ/nEJz5RwVVQPe6777787W9/y0knnVTpKVBVFi5cmK5du+b222/PsGHD8slPfjLf//73/c9KaAHt2rXLueeem5tuuin9+vXLZz7zmey+++459NBDKz0NWqURI0bk7LPPTocOHdY6vnjx4nzoQx9a69jmm2+eZ599tuS8imh195RasWLFWkEqSdPjVatWVWISVKVx48blH//4R2655ZZKT4FWb+XKlTnvvPNy7rnnpn379pWeA1XllVdeyZNPPpmpU6dmzJgxWbx4cc4999x06NAhxxxzTKXnQas3b9687LXXXjn66KPz+OOPZ/To0dlll10yfPjwSk+DqvFmnWNDaBytLkq1a9dunb+Y1x/7QR9axrhx43LddddlwoQJ6dWrV6XnQKt3xRVXZMcdd1zrakSgZbRp0yYvv/xyxo8fn65duyZJnn766dx4442iFLxH9913X2655Zbce++9ad++ffr27ZtFixblqquuEqWgBbVr126dd36tWrVqg2gcrS5KbbHFFvn3v/+dNWvWpE2b1+YvXrw47du3z6abblrhddD6jR49OjfeeGPGjRuXfffdt9JzoCr86le/ypIlS5ruh/j6/0z5zW9+k7///e+VnAatXpcuXdKuXbumIJUkPXv2zDPPPFPBVVAdHnnkkXTv3n2t/zDefvvtM2nSpAquguqzxRZbZO7cuWsdW7JkyTpv6atGrS5K9enTJ23atMmMGTMyaNCgJK/d4LJv376prW11t8iC95UrrrgiU6dOzaWXXpphw4ZVeg5UjR//+MdZs2ZN0+Pvfve7SZIzzjijUpOgavTr1y8rV67ME088kZ49eyZ57TfK/u9IBTTPhz70oTz55JNZtWpV01uL5s+fn6233rrCy6C69OvXL5MnT86rr77aFIEffPDBDBw4sMLL1r9WV3E6dOiQAw88MOeff34efvjhTJs2LVOmTMmRRx5Z6WnQqs2bNy9XXnllvvzlL2fgwIFZvHhx0x/gvenatWu6d+/e9GeTTTbJJptsku7du1d6GrR6H/3oR7PnnnvmrLPOyuzZs/OnP/0pkydPzuGHH17padDq7b333tloo43yP//zP3niiSfy+9//PpMmTcoRRxxR6WlQVQYPHpwPf/jDOeuss/L4449n8uTJefjhh3PIIYdUetp6V9PY2NhY6RHv1ooVK3L++efn7rvvTseOHXPsscfmqKOOqvQsaNUmT56c8ePHv+Fzjz32WOE1UN1GjRqVJLn44osrvASqw7JlyzJ69Oj89re/TYcOHTJixIicfPLJqampqfQ0aPXmzp2bb3/723n44YfzwQ9+MP/93/+dL33pS84veI969+6d66+/PkOGDEmSPPnkkznnnHMyc+bMdO/ePWeffXZ23XXXCq9c/1pllAIAAACgdWt1b98DAAAAoPUTpQAAAAAoTpQCAAAAoDhRCgAAAIDiRCkAAAAAihOlAAAAAChOlAIAAACgOFEKAAAAgOLaVHoAAEA1GTVqVG677ba3/Jjf/e532XrrrQstAgB4f6ppbGxsrPQIAIBqsWzZsrz66qtJkjvvvDNTpkzJLbfckiRpaGhIfX19tthii9TV1VVyJgBAxblSCgCgBXXq1CmdOnVq+ue6urp06dKlwqsAAN5/3FMKAKCQp556Kr17985TTz2VJOndu3fuuuuufOYzn0m/fv1y+umnZ+HChTnyyCPTr1+/jBgxIosWLWp6/W9/+9vst99+6devXw455JA88MADlfpWAADeM1EKAKCCJk6cmIsvvjhXX3117r777hx++OE5/PDDM3Xq1CxevDg/+MEPkiSzZ8/OmWeemRNPPDG/+MUvMnz48Hz5y1/Ok08+WeHvAACgebx9DwCggo466qj069cvSdKnT5/07Nkzn/nMZ5Ikn/70pzN79uwkyQ9/+MMcdthhOeCAA5IkRx55ZP7617/mxhtvzKhRoyozHgDgPRClAAAq6CMf+UjTP7dv3z5du3Zd6/GqVauSJPPmzctdd92Vm266qen51atXZ7fddis3FgCgBYlSAAAV9P/+Fr7a2je+u0J9fX2+/OUv58ADD1zrePv27dfXNACA9co9pQAAWoGePXvmqaeeSvfu3Zv+3HTTTfnjH/9Y6WkAAM0iSgEAtAJHHXVU7rzzzlx//fVZsGBBrr322lx77bXp0aNHpacBADSLKAUA0Ar0798/Y8eOzU9/+tPst99+ufnmmzN+/PjsvPPOlZ4GANAsNY2NjY2VHgEAAADAhsWVUgAAAAAUJ0oBAAAAUJwoBQAAAEBxohQAAAAAxYlSAAAAABQnSgEAAABQnCgFAAAAQHGiFAAAAADFiVIAAAAAFCdKAQAAAFCcKAUAAABAcaIUAAAAAMX9H4NMjKvTjUZ3AAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "result.plot_resource_plan()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.10" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..167c52f --- /dev/null +++ b/docs/index.md @@ -0,0 +1,36 @@ +# factryengine + +`factryengine` is a Python package designed to simplify task scheduling by considering task priorities, resources, and predecessors. It allows you to easily create tasks and resources, define dependencies between tasks, and schedule them efficiently. With `factryengine`, you can ensure that tasks are executed in the correct order, taking into account their dependencies and resource availability, while also adhering to their priorities. + +## Installation + +Installing `factryengine` is straightforward and can be done using `pip`. Run the following command in your terminal: + +```bash +pip install factryengine +``` + +This command fetches the latest version of `factryengine` from the Python Package Index (PyPI) and installs it on your system. + +After installation, you can import and use `Resource`, `Task`, and `Scheduler` classes from `factryengine` in your Python scripts to model and solve your scheduling problems. + +## Quick Start + +Below is a basic example to get you started with `factryengine`: + +```python +from factryengine import Task, Resource, Scheduler + +# Creating a Resource object +resource = Resource(id=1, available_windows=[(0,10)]) + +# Creating Task objects +task1 = Task(id=1, duration=3, priority=2, resources=[[resource]]) +task2 = Task(id=2, duration=5, priority=1, resources=[[resource]], predecessors=[task1]) + +# Creating a Scheduler object and scheduling the tasks +scheduler = Scheduler(tasks=[task1, task2]) +scheduler_result = scheduler.schedule() +``` + +In this example, `task1` is scheduled before `task2` despite its lower priority, as `task2` is dependent on `task1`. diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..52196fb --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,105 @@ +# Usage + +The `factryengine` package contains three main components: `Resource`, `Task`, and `Scheduler`. Below is the documentation for using each of these components. + +## Resource + +The `Resource` class is used to represent a resource in the scheduling problem. Below is an example of how to create a `Resource` object. + +```python +from factryengine import Resource + +# Creating a Resource object +resource = Resource( + id=1, + available_windows=[(0, 5), (10, 15)], +) +``` + +**Attributes:** + +- `id` (`int`): Unique identifier for the resource. +- `available_windows` (`list[tuple[int, int]]`): List of available windows for the resource represented as tuples of start and end times. + +## Task + +The `Task` class is used to represent a task in the scheduling problem. Below is an example of how to create a `Task` object, reusing the `resource` object created above. + +```python +from factryengine import Task + +# Creating a Task object +task = Task( + id=1, + duration=5, + priority=1, + resources=[[resource]], + resource_count=1, + predecessors=[], + predecessor_delay=0, +) +``` + +**Attributes:** + +- `id` (`int | str`): Unique identifier for the task. +- `duration` (`int`): Duration of the task with a constraint of being greater than 0. +- `priority` (`int`): Priority of the task with a constraint of being greater than 0. +- `resources` (`list[set[Resource]]`): List of sets of resources required by the task. +- `resource_count` (`int | str`): Number of resources required by the task. +- `predecessors` (`list["Task"]`): List of predecessor tasks. +- `predecessor_delay` (`int`): Buffer time after the completion of predecessor tasks before the current task can commence, must be greater than 0. + +!!! tip + Resource count allows you to specifiy to use all resources specified: + ```python + resource_count = "all" + ``` + +## Scheduler + +The `Scheduler` class is used to schedule tasks based on their priorities, durations, and resources. Below is an example of how to use the `Scheduler` class, reusing the `task` object created above. + +```python +from factryengine import Scheduler + +# Creating a Scheduler object +scheduler = Scheduler(tasks=[task]) + +# Scheduling the tasks +scheduler_result = scheduler.schedule() +``` + +**Methods:** + +- `schedule()`: This method schedules the tasks and returns a `SchedulerResult` object. + +## SchedulerResult + +The `SchedulerResult` class contains the results of the scheduling. + +**Methods:** + +- `to_dict()`: Converts the scheduling result to a dictionary. +- `to_dataframe()`: Converts the scheduling result to a pandas DataFrame. +- `summary()`: Provides a summary of the scheduling result. +- `plot_resource_plan()`: Plots the resource plan. +- `get_resource_intervals_df()`: Returns a DataFrame of resource intervals. + +## Task Priority + +In `factryengine`, task priority helps decide the order tasks are scheduled. Lower priority numbers are scheduled first. But, if a task depends on another (called a predecessor), the predecessor will be scheduled first, no matter its priority. + +Here's a simple example: + +```python +from factryengine import Task, Resource + +# Task with lower priority +task1 = Task(id=1, duration=3, priority=2, resources=[[resource]]) + +# Task with higher priority, but depends on task1 +task2 = Task(id=2, duration=5, priority=1, resources=[[resource]], predecessors=[task1]) +``` + +In this case, even though `task2` has higher priority, `task1` will be scheduled first because `task2` depends on it. diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..7008525 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,47 @@ +site_name: factryengine +# site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production + +theme: + name: material + palette: + - media: '(prefers-color-scheme: light)' + scheme: default + toggle: + icon: material/lightbulb + name: Switch to dark mode + - media: '(prefers-color-scheme: dark)' + scheme: slate + toggle: + icon: material/lightbulb-outline + name: Switch to light mode + features: + - search.suggest + - search.highlight + - content.tabs.link + - navigation.indexes + - content.tooltips + - navigation.path + - content.code.annotate + - content.code.copy + - content.code.select + icon: + repo: fontawesome/brands/github-alt + language: en + +repo_url: https://github.com/Yacobolo/factryengine +repo_name: factryengine + +nav: + - Home: index.md + - Usage: usage.md + - Example: example.ipynb + + +plugins: + - mkdocs-jupyter + + +markdown_extensions: + - admonition + - pymdownx.details + - pymdownx.superfences