{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [], "collapsed_sections": [ "J1U1zWCsziA0" ], "authorship_tag": "ABX9TyMR4vEIPbKGG/DDodHjpadk", "include_colab_link": true }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "view-in-github", "colab_type": "text" }, "source": [ "\"Open" ] }, { "cell_type": "code", "source": [ "%pip install binpacking" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "VCXPvVuBSG9C", "outputId": "202ad8bc-a2bd-4d22-b8e9-623daf6fbb38" }, "execution_count": null, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Collecting binpacking\n", " Downloading binpacking-1.5.2.tar.gz (8.7 kB)\n", " Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n", "Requirement already satisfied: future in /usr/local/lib/python3.10/dist-packages (from binpacking) (0.18.3)\n", "Building wheels for collected packages: binpacking\n", " Building wheel for binpacking (setup.py) ... \u001b[?25l\u001b[?25hdone\n", " Created wheel for binpacking: filename=binpacking-1.5.2-py3-none-any.whl size=10093 sha256=5a467383fc82014966c382597a99ab24e030377cddacf223de133b8f2c8fcc8a\n", " Stored in directory: /root/.cache/pip/wheels/4f/09/07/93d7c3a8acc3f39fc972dd12b8b8131fdd00f9e61ca09ed723\n", "Successfully built binpacking\n", "Installing collected packages: binpacking\n", "Successfully installed binpacking-1.5.2\n" ] } ] }, { "cell_type": "code", "source": [ "# Check the csv data\n", "import pandas as pd\n", "\n", "CSV_URL = 'https://raw.githubusercontent.com/inigmat/exupery/main/files/bbs.csv'\n", "data = pd.read_csv(CSV_URL)\n", "data.head(5)" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "dB6K9Vcyr3Uv", "outputId": "ea3b28e4-b780-42f1-e86a-99a564775b7c" }, "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ " index Unique Mark Dia Length Qty\n", "0 0 100 10 2350 96\n", "1 1 101 10 2800 24\n", "2 2 102 10 3030 336\n", "3 3 103 10 4230 144\n", "4 4 200 12 450 320" ], "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", " \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", "
indexUnique MarkDiaLengthQty
0010010235096
1110110280024
22102103030336
33103104230144
4420012450320
\n", "
\n", " \n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n", "\n", "\n", " \n", "\n", " \n", " \n", "\n", " \n", "
\n", "
\n" ] }, "metadata": {}, "execution_count": 2 } ] }, { "cell_type": "code", "source": [ "from binpacking import to_constant_volume\n", "\n", "# Constants\n", "BAR_LENGTH = 11700\n", "CSV_URL = CSV_URL\n", "\n", "\n", "def calculate_required_bars(bar_schedule: pd.DataFrame, bar_length: int) -> tuple:\n", " \"\"\"\n", " Calculates the cutting schemes based on input data (bar schedule)\n", " containing the length and quantity of bars and the length of the bars in stock.\n", " \"\"\"\n", " items = []\n", " # Extracting data from DataFrame\n", " for length, quantity in zip(bar_schedule['Length'], bar_schedule['Qty']):\n", " items.extend([length] * quantity)\n", " # Calculating the cutting schemes using bin packing algorithm\n", " cutting_scheme = to_constant_volume(items, bar_length)\n", " return cutting_scheme\n", "\n", "\n", "def generate_cutting_table(cutting_data: dict) -> pd.DataFrame:\n", " \"\"\"\n", " Generates a dataframe (cutting chart) with quantity,\n", " cuts, utilization, scrap, and diameter columns\n", " based on the cutting data (cutting schemes).\n", " \"\"\"\n", " cutting_chart = pd.DataFrame(columns=[\"Qty\", \"Cuts\", \"Utilization\", \"Scrap\", \"Dia\"])\n", " # Processing cutting data for each diameter\n", " for dia, cutting_schemes in cutting_data.items():\n", " df_temp = pd.DataFrame(zip(cutting_schemes), columns=[\"Cuts\"])\n", " # Calculate the quantity of each cutting scheme\n", " df_temp[\"Qty\"] = df_temp[\"Cuts\"].apply(lambda x: f\"{cutting_schemes.count(x)}x\")\n", " # Calculate the total length used by each cutting scheme\n", " df_temp[\"Utilization\"] = df_temp[\"Cuts\"].apply(sum)\n", " # Calculate the amount of scrap for each cutting scheme\n", " df_temp[\"Scrap\"] = BAR_LENGTH - df_temp[\"Utilization\"]\n", " # Add the diameter column\n", " df_temp[\"Dia\"] = dia\n", " # Change the type of values in the Cuts column to drop duplicates\n", " df_temp[\"Cuts\"] = df_temp[\"Cuts\"].astype(str)\n", " # Concatenate df_temp with cutting_scheme\n", " cutting_chart = pd.concat([cutting_chart, df_temp], ignore_index=True)\n", " # Drop duplicate rows\n", " cutting_chart = cutting_chart.drop_duplicates()\n", " # Reset the index\n", " cutting_chart = cutting_chart.reset_index(drop=True)\n", " return cutting_chart\n", "\n", "\n", "def main() -> pd.DataFrame:\n", " \"\"\"\n", " Executes the main workflow to calculate cutting schemes and generate a cutting chart.\n", " \"\"\"\n", " # Read the data from CSV\n", " data = pd.read_csv(CSV_URL)\n", " cutting_data = {}\n", " # Process data for each unique diameter\n", " for dia in data['Dia'].unique():\n", " data_dia = data[data['Dia'] == dia]\n", " # Calculate the cutting schemes and store them in a dictionary\n", " cutting_patterns = calculate_required_bars(data_dia, BAR_LENGTH)\n", " cutting_data[dia] = cutting_patterns\n", " # Print results\n", " print(f'Required number of reinforcement bars with diameter {dia} mm: {len(cutting_patterns)} pcs.')\n", " percent = ((data_dia['Qty'] * data_dia['Length']).sum()/(len(cutting_patterns) * BAR_LENGTH)) * 100\n", " print(f'Total scrap: {round(100 - percent, 2)}%')\n", " # Generate the cutting table\n", " cutting_chart = generate_cutting_table(cutting_data)\n", " return cutting_chart\n", "\n", "\n", "if __name__ == \"__main__\":\n", " # Execute the main function and store the resulting cutting table\n", " cutting_chart = main()\n" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "6QEDfJ6d0h3Q", "outputId": "8acc06d8-97f7-46ae-cc22-3e151fbb6875" }, "execution_count": null, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Required number of reinforcement bars with diameter 10 mm: 168 pcs.\n", "Total scrap: 2.32%\n", "Required number of reinforcement bars with diameter 12 mm: 138 pcs.\n", "Total scrap: 1.47%\n", "Required number of reinforcement bars with diameter 16 mm: 143 pcs.\n", "Total scrap: 3.76%\n", "Required number of reinforcement bars with diameter 20 mm: 759 pcs.\n", "Total scrap: 4.82%\n" ] } ] }, { "cell_type": "markdown", "source": [ "# Reviewing the results" ], "metadata": { "id": "J1U1zWCsziA0" } }, { "cell_type": "code", "source": [ "cutting_chart" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "id": "AvnVW_pfxaGB", "outputId": "d9ea5bbf-27e6-46ec-e853-5a6ec1970e95" }, "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ " Qty Cuts Utilization Scrap \\\n", "0 72x [4230, 4230, 3030] 11490 210 \n", "1 88x [3030, 3030, 3030, 2350] 11440 260 \n", "2 6x [2800, 2800, 2800, 2800] 11200 500 \n", "3 2x [2350, 2350, 2350, 2350] 9400 2300 \n", "4 32x [5280, 5280, 870] 11430 270 \n", "5 42x [3720, 3720, 3720, 450] 11610 90 \n", "6 1x [3720, 3720, 2300, 870, 870] 11480 220 \n", "7 15x [2300, 2300, 2300, 2300, 2300] 11500 200 \n", "8 1x [2300, 2300, 2300, 2300, 870, 870, 450] 11390 310 \n", "9 3x [870, 870, 870, 870, 870, 870, 870, 870, 870, ... 11310 390 \n", "10 1x [870, 870, 870, 870, 870, 840, 840, 840, 840, ... 11520 180 \n", "11 11x [840, 840, 840, 840, 840, 840, 840, 840, 840, ... 11685 15 \n", "12 1x [840, 840, 840, 840, 840, 840, 840, 840, 840, ... 11385 315 \n", "13 20x [765, 765, 765, 765, 765, 765, 765, 765, 765, ... 11475 225 \n", "14 1x [765, 765, 765, 765, 450, 450, 450, 450, 450, ... 11610 90 \n", "15 9x [450, 450, 450, 450, 450, 450, 450, 450, 450, ... 11700 0 \n", "16 1x [450, 450, 450, 450, 450, 450, 450, 450, 450, ... 10350 1350 \n", "17 8x [10340, 870] 11210 490 \n", "18 8x [9120, 870, 870] 10860 840 \n", "19 8x [7320, 870, 870, 870, 870, 870] 11670 30 \n", "20 8x [6235, 5240] 11475 225 \n", "21 24x [4840, 4840, 870, 870] 11420 280 \n", "22 86x [870, 870, 870, 870, 870, 870, 870, 870, 870, ... 11310 390 \n", "23 1x [870, 870] 1740 9960 \n", "24 192x [9085, 1900] 10985 715 \n", "25 60x [8885, 2800] 11685 15 \n", "26 68x [8885, 1900] 10785 915 \n", "27 24x [4000, 4000, 3585] 11585 115 \n", "28 68x [3985, 3985, 3585] 11555 145 \n", "29 50x [3885, 3885, 3885] 11655 45 \n", "30 1x [3885, 3885, 3785] 11555 145 \n", "31 14x [3785, 3785, 3785] 11355 345 \n", "32 1x [3785, 3585, 3585] 10955 745 \n", "33 115x [3585, 3585, 3585] 10755 945 \n", "34 1x [3585, 3385, 3385] 10355 1345 \n", "35 15x [3385, 3385, 3385] 10155 1545 \n", "36 1x [3385, 3185, 3185, 1900] 11655 45 \n", "37 78x [3185, 3185, 3185, 2100] 11655 45 \n", "38 9x [3185, 3185, 3185, 1900] 11455 245 \n", "39 1x [3185, 1900, 1900, 1900, 1900] 10785 915 \n", "40 10x [1900, 1900, 1900, 1900, 1900, 1900] 11400 300 \n", "41 1x [1900, 1900, 1740, 1740, 1740, 1740] 10760 940 \n", "42 50x [1740, 1740, 1740, 1740, 1740, 1740] 10440 1260 \n", "\n", " Dia \n", "0 10 \n", "1 10 \n", "2 10 \n", "3 10 \n", "4 12 \n", "5 12 \n", "6 12 \n", "7 12 \n", "8 12 \n", "9 12 \n", "10 12 \n", "11 12 \n", "12 12 \n", "13 12 \n", "14 12 \n", "15 12 \n", "16 12 \n", "17 16 \n", "18 16 \n", "19 16 \n", "20 16 \n", "21 16 \n", "22 16 \n", "23 16 \n", "24 20 \n", "25 20 \n", "26 20 \n", "27 20 \n", "28 20 \n", "29 20 \n", "30 20 \n", "31 20 \n", "32 20 \n", "33 20 \n", "34 20 \n", "35 20 \n", "36 20 \n", "37 20 \n", "38 20 \n", "39 20 \n", "40 20 \n", "41 20 \n", "42 20 " ], "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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
QtyCutsUtilizationScrapDia
072x[4230, 4230, 3030]1149021010
188x[3030, 3030, 3030, 2350]1144026010
26x[2800, 2800, 2800, 2800]1120050010
32x[2350, 2350, 2350, 2350]9400230010
432x[5280, 5280, 870]1143027012
542x[3720, 3720, 3720, 450]116109012
61x[3720, 3720, 2300, 870, 870]1148022012
715x[2300, 2300, 2300, 2300, 2300]1150020012
81x[2300, 2300, 2300, 2300, 870, 870, 450]1139031012
93x[870, 870, 870, 870, 870, 870, 870, 870, 870, ...1131039012
101x[870, 870, 870, 870, 870, 840, 840, 840, 840, ...1152018012
1111x[840, 840, 840, 840, 840, 840, 840, 840, 840, ...116851512
121x[840, 840, 840, 840, 840, 840, 840, 840, 840, ...1138531512
1320x[765, 765, 765, 765, 765, 765, 765, 765, 765, ...1147522512
141x[765, 765, 765, 765, 450, 450, 450, 450, 450, ...116109012
159x[450, 450, 450, 450, 450, 450, 450, 450, 450, ...11700012
161x[450, 450, 450, 450, 450, 450, 450, 450, 450, ...10350135012
178x[10340, 870]1121049016
188x[9120, 870, 870]1086084016
198x[7320, 870, 870, 870, 870, 870]116703016
208x[6235, 5240]1147522516
2124x[4840, 4840, 870, 870]1142028016
2286x[870, 870, 870, 870, 870, 870, 870, 870, 870, ...1131039016
231x[870, 870]1740996016
24192x[9085, 1900]1098571520
2560x[8885, 2800]116851520
2668x[8885, 1900]1078591520
2724x[4000, 4000, 3585]1158511520
2868x[3985, 3985, 3585]1155514520
2950x[3885, 3885, 3885]116554520
301x[3885, 3885, 3785]1155514520
3114x[3785, 3785, 3785]1135534520
321x[3785, 3585, 3585]1095574520
33115x[3585, 3585, 3585]1075594520
341x[3585, 3385, 3385]10355134520
3515x[3385, 3385, 3385]10155154520
361x[3385, 3185, 3185, 1900]116554520
3778x[3185, 3185, 3185, 2100]116554520
389x[3185, 3185, 3185, 1900]1145524520
391x[3185, 1900, 1900, 1900, 1900]1078591520
4010x[1900, 1900, 1900, 1900, 1900, 1900]1140030020
411x[1900, 1900, 1740, 1740, 1740, 1740]1076094020
4250x[1740, 1740, 1740, 1740, 1740, 1740]10440126020
\n", "
\n", " \n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n", "\n", "\n", " \n", "\n", " \n", " \n", "\n", " \n", "
\n", "
\n" ] }, "metadata": {}, "execution_count": 4 } ] }, { "cell_type": "markdown", "source": [ "# Downloading the results" ], "metadata": { "id": "Oe0sivwZzXg5" } }, { "cell_type": "code", "source": [ "from google.colab import files\n", "\n", "# determining the name of the file\n", "file_name = 'cutting_chart.xlsx'\n", "\n", "# saving the excel\n", "cutting_chart.to_excel(file_name)\n", "\n", "# downloading the file\n", "files.download('cutting_chart.xlsx')\n", "print('DataFrame is written to Excel File successfully. Save the file')" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 34 }, "id": "2NNrdvwlyPI7", "outputId": "13ed0d6b-bed4-4d56-b819-754686028db0" }, "execution_count": null, "outputs": [ { "output_type": "display_data", "data": { "text/plain": [ "" ], "application/javascript": [ "\n", " async function download(id, filename, size) {\n", " if (!google.colab.kernel.accessAllowed) {\n", " return;\n", " }\n", " const div = document.createElement('div');\n", " const label = document.createElement('label');\n", " label.textContent = `Downloading \"${filename}\": `;\n", " div.appendChild(label);\n", " const progress = document.createElement('progress');\n", " progress.max = size;\n", " div.appendChild(progress);\n", " document.body.appendChild(div);\n", "\n", " const buffers = [];\n", " let downloaded = 0;\n", "\n", " const channel = await google.colab.kernel.comms.open(id);\n", " // Send a message to notify the kernel that we're ready.\n", " channel.send({})\n", "\n", " for await (const message of channel.messages) {\n", " // Send a message to notify the kernel that we're ready.\n", " channel.send({})\n", " if (message.buffers) {\n", " for (const buffer of message.buffers) {\n", " buffers.push(buffer);\n", " downloaded += buffer.byteLength;\n", " progress.value = downloaded;\n", " }\n", " }\n", " }\n", " const blob = new Blob(buffers, {type: 'application/binary'});\n", " const a = document.createElement('a');\n", " a.href = window.URL.createObjectURL(blob);\n", " a.download = filename;\n", " div.appendChild(a);\n", " a.click();\n", " div.remove();\n", " }\n", " " ] }, "metadata": {} }, { "output_type": "display_data", "data": { "text/plain": [ "" ], "application/javascript": [ "download(\"download_040e1944-164e-4462-86f5-bb44f6f8d530\", \"cutting_chart.xlsx\", 6557)" ] }, "metadata": {} }, { "output_type": "stream", "name": "stdout", "text": [ "DataFrame is written to Excel File successfully. Save the file\n" ] } ] } ] }