मुख्य सामग्री पर जाएं

Gurobi: जटिल समस्याओं के लिए गणितीय ऑप्टिमाइज़ेशन

सेटअप से लेकर वास्तविक अनुप्रयोगों तक Gurobi ऑप्टिमाइज़ेशन में महारत हासिल करें। मॉडल बनाएँ, सॉल्वर कॉन्फ़िगर करें, और लीनियर, इंटीजर, तथा नॉनलिनियर प्रोग्रामिंग समस्याएँ कुशलता से सुलझाएँ।
अपडेट किया गया 2 अक्टू॰ 2026  · 14 मि॰ पढ़ें

AI के साथ खोजें

ChatGPTClaudePerplexity

जब वेरिएबल्स बहुत बढ़ जाते हैं, तो बेसिक सॉल्वर और ट्रायल‑एंड‑एरर तरीके लड़खड़ाने लगते हैं। Gurobi इन जटिलताओं को गति और सटीकता के साथ संभालता है—ऐसी समस्याएँ सेकंडों में हल कर देता है जिन्हें वरना घंटों लग सकते थे। यही फर्क है एक संभव योजना की उम्मीद करने और गणितीय रूप से यह सिद्ध करने के बीच कि आपके पास सबसे उत्तम योजना है।

यह ट्यूटोरियल आपको शक्तिशाली कमर्शियल सॉल्वर Gurobi से परिचित कराता है। मैं आपको Python लाइब्रेरी इंस्टॉल करना, अपना पहला मॉडल बनाना, और मिक्स्ड‑इंटीजर प्रोग्रामिंग जैसे उन्नत समस्याओं तक स्केल करना दिखाऊँगा।

गणितीय ऑप्टिमाइज़ेशन और Gurobi की भूमिका समझना

कोड लिखने से पहले, यह समझना उपयोगी है कि ऑप्टिमाइज़ेशन वास्तव में होता क्या है। यह संदर्भ बताता है कि मानक प्रोग्रामिंग तरीकों की बजाय कब Gurobi का उपयोग करें।

गणितीय ऑप्टिमाइज़ेशन क्या है?

गणितीय ऑप्टिमाइज़ेशन सभी संभावित समाधानों में से सर्वश्रेष्ठ समाधान ढूँढता है। आप तय करते हैं कि "सर्वश्रेष्ठ" का मतलब क्या है (लागत न्यूनतम, लाभ अधिकतम, समय न्यूनतम), आपके नियंत्रण में क्या है (डिसीज़न वेरिएबल्स), और आपकी सीमाएँ क्या हैं (कंस्ट्रेंट्स)। ऑप्टिमाइज़र संभव समाधानों में खोज कर के ऑप्टिमल समाधान ढूँढता है।

यह पारंपरिक प्रोग्रामिंग से अलग है, जहाँ आप सटीक स्टेप्स बताते हैं। ऑप्टिमाइज़ेशन में, आप समस्या को गणितीय रूप से वर्णित करते हैं और सॉल्वर को उसे हल करने का तरीका खोजने देते हैं। आप "यदि यह तो वह" जैसी लॉजिक नहीं लिखते, आप संबंधों को परिभाषित करते हैं और एल्गोरिद्म्स को सर्वश्रेष्ठ मान खोजने देते हैं।

ऑप्टिमाइज़ेशन में Gurobi का महत्व

Gurobi क्यों अलग दिखता है

Gurobi लगातार सबसे तेज़ कमर्शियल ऑप्टिमाइज़र्स में गिना जाता है। बेंचमार्क अक्सर दिखाते हैं कि बड़े पैमाने की समस्याओं पर यह ओपन‑सोर्स विकल्पों से काफी आगे निकल जाता है। यह स्पीड तब अहम हो जाती है जब आप हर घंटे ऑप्टिमाइज़ेशन चलाते हैं या सख्त समय सीमा में नतीजे चाहिए।

उद्योग में अपनाया जाना

लॉजिस्टिक्स, फाइनेंस, ऊर्जा और हेल्थकेयर जैसी इंडस्ट्रीज़ प्रोडक्शन सिस्टम्स के लिए Gurobi का उपयोग करती हैं। FedEx डिलीवरी रूट्स को ऑप्टिमाइज़ करता है, जबकि वित्तीय फर्में अरबों का पोर्टफोलियो आवंटित करती हैं। ऊर्जा कंपनियाँ पावर जनरेशन शेड्यूल करती हैं। ये अकादमिक अभ्यास नहीं, बल्कि असल धन और वास्तविक बाधाओं वाले सिस्टम हैं।

सॉल्वर की क्षमताएँ

Gurobi लीनियर प्रोग्रामिंग (LP), मिक्स्ड‑इंटीजर प्रोग्रामिंग (MIP), क्वाड्रैटिक प्रोग्रामिंग (QP) आदि संभालता है। इसमें अत्याधुनिक एल्गोरिद्म्स होते हैं जैसे कन्करेंट ऑप्टिमाइज़ेशन, जहाँ कई तरीकों को समानांतर चलाया जाता है और जो सबसे तेज़ हो, वही चुना जाता है। आपको एल्गोरिद्म चुनने की ज़रूरत नहीं—विश्वसनीयता और स्पीड साथ‑साथ मिलती है।

Gurobi सेटअप करना

Gurobi इंस्टॉल करना कुछ ही स्टेप्स में हो जाता है। एक बार कॉन्फ़िगर होने पर, यह Python के साथ सहजता से काम करता है।

इंस्टॉलेशन और सेटअप

डाउनलोड और इंस्टॉल

Gurobi की वेबसाइट पर जाएँ और अपने OS के लिए इंस्टॉलर लें। इसमें ऑप्टिमाइज़र, gurobipy इंटरफ़ेस और डॉक्यूमेंटेशन शामिल हैं। यदि कस्टम पाथ की ज़रूरत न हो तो इंस्टॉलर को डिफ़ॉल्ट सेटिंग्स के साथ चलाएँ।

इंस्टॉलेशन के बाद, यह जाँच लें कि सब ठीक से हुआ है:

import gurobipy as gp
print(f"Gurobi version: {gp.__version__}")

यहाँ हम संस्करण संख्या प्रिंट करके इंस्टॉलेशन सत्यापित करते हैं। सफल प्रिंट दिखाता है कि आपका एनवायरनमेंट तैयार है।

Jupyter Notebook cell showing Python code to import gurobipy and print the installed version, outputting Gurobi version 13.0.0.

लाइसेंसिंग विकल्प

छोटे टेस्ट प्रॉब्लम्स से आगे के लिए Gurobi को लाइसेंस चाहिए। आपके विकल्प:

  • फ्री ट्रायल लाइसेंस: 30‑दिन का मूल्यांकन। अपने वर्क ईमेल के साथ Gurobi की वेबसाइट से अनुरोध करें।
  • अकादमिक लाइसेंस: फैकल्टी और छात्रों के लिए निःशुल्क। असीमित एक्सेस के लिए अपना अकादमिक ईमेल वेरिफ़ाई करें—सीखने के लिए बिल्कुल उपयुक्त।
  • कमर्शियल लाइसेंस: व्यवसाय के लिए आवश्यक। कीमत स्केल पर निर्भर है। नामित‑उपयोगकर्ता लाइसेंस व्यक्तिगत डेटा वैज्ञानिकों के लिए, जबकि फ़्लोटिंग लाइसेंस टीमों को क्षमता साझा करने देते हैं।
  • क्लाउड लाइसेंस: पे‑ऐज़‑यू‑गो। कोई अग्रिम लागत नहीं, जितना उपयोग करें उतना ही भुगतान करें। कभी‑कभार के ऑप्टिमाइज़ेशन कार्यों के लिए उपयोगी।

मैं सीखने के लिए अकादमिक लाइसेंस और प्रोडक्शन के लिए कमर्शियल लाइसेंस का उपयोग करता/करती हूँ। ट्रायल आपको कमिट करने से पहले पर्याप्त समय देता है।

एनवायरनमेंट कॉन्फ़िगरेशन

Python सेटअप

Gurobi Python 3.7+ के साथ काम करता है। कॉन्फ़्लिक्ट से बचने के लिए वर्चुअल एनवायरनमेंट उपयोग करने की सलाह है:

python -m venv gurobi_env
gurobi_env\Scripts\activate
source gurobi_env/bin/activate
pip install gurobipy

ये कमांड्स एक साफ़ वर्कस्पेस बनाते हैं और लाइब्रेरी इंस्टॉल करते हैं।

Jupyter Notebook इंटीग्रेशन

इंटरैक्टिव डेवलपमेंट के लिए नोटबुक्स Gurobi के साथ बेहतरीन काम करती हैं:

pip install jupyter
jupyter notebook
import gurobipy as gp
print("Gurobi ready!")

यह स्निपेट Jupyter इंस्टॉल करता है, सर्वर चालू करता है, और जल्दी से जाँचता है कि नोटबुक के भीतर Gurobi सही से लोड हो रहा है।

कब Gurobi का उपयोग नहीं करना चाहिए

Gurobi शक्तिशाली है, लेकिन हर बार सही विकल्प नहीं।

  • सरल समस्याएँ: यदि आपके पास 50 वेरिएबल्स और बुनियादी रैखिक कंस्ट्रेंट्स हैं, तो scipy.optimize.linprog या Excel Solver अच्छी तरह काम करेंगे।

  • लागत: कमर्शियल लाइसेंस महँगे हैं। गैर‑आवश्यक आंतरिक टूल्स के लिए CBC या GLPK (PuLP के जरिए) जैसे ओपन‑सोर्स विकल्प पर्याप्त हो सकते हैं।

  • ह्यूरिस्टिक्स: यदि किसी रियल‑टाइम गेम के लिए मिलीसेकंड्स में "काफ़ी अच्छा" उत्तर चाहिए, तो जेनेटिक एल्गोरिद्म जैसे ह्यूरिस्टिक्स अक्सर एक्ज़ैक्ट सॉल्वर से बेहतर होते हैं।

Gurobi का उपयोग तब करें जब समस्याएँ बड़ी हों (10k+ वेरिएबल्स) या आपको क्वाड्रैटिक कंस्ट्रेंट्स जैसी उन्नत सुविधाएँ चाहिए।

प्लेटफ़ॉर्म संगतता

Gurobi Windows, macOS, और Linux पर चलता है। AWS, Azure और Google Cloud जैसे क्लाउड एनवायरनमेंट उनके मार्केटप्लेस के माध्यम से Gurobi सपोर्ट करते हैं। मैंने तीनों प्रमुख क्लाउड्स पर बिना प्लेटफ़ॉर्म‑विशिष्ट समस्याओं के Gurobi मॉडल डिप्लॉय किए हैं।

ऑप्टिमाइज़ेशन मॉडल बनाना

Gurobi इंस्टॉल हो चुका है, अब अपना पहला मॉडल बनाते हैं। ये मूलभूत कॉन्सेप्ट हर समस्या पर लागू होंगे।

एक ऑप्टिमाइज़ेशन मॉडल के प्रमुख घटक

हर मॉडल में तीन अनिवार्य हिस्से होते हैं:

डिसीज़न वेरिएबल्स

ये वे चुनाव हैं जो ऑप्टिमाइज़र करता है। प्रोडक्शन प्लानिंग में यह "प्रोडक्ट A की यूनिट्स" और "प्रोडक्ट B की यूनिट्स" हो सकता है। आप वेरिएबल्स परिभाषित करते हैं; Gurobi उन्हें मान असाइन करता है।

ऑब्जेक्टिव फ़ंक्शन

यह आपका लक्ष्य है—जिसे आप अधिकतम या न्यूनतम करना चाहते हैं। लाभ अधिकतम करें (3*product_a + 5*product_b) या लागत न्यूनतम करें। एक मॉडल में एक ही ऑब्जेक्टिव होता है।

कंस्ट्रेंट्स

ये आपकी सीमाएँ हैं। आप फ़ैक्टरी क्षमता से ज़्यादा नहीं बना सकते या अपने बजट से अधिक खर्च नहीं कर सकते। कंस्ट्रेंट्स यह तय करते हैं कि कौन‑से समाधान वास्तव में संभव हैं।

फॉर्म्युलेशन के सर्वोत्तम अभ्यास

स्पष्ट वेरिएबल नाम रखें। x[1] की जगह produce_product_a जैसा नाम दें। यह आपको आगे चलकर डिबगिंग में घंटों बचाएगा—जैसा मैं ट्रबलशूटिंग सेक्शन में बताऊँगा/बताऊँगी।

कंस्ट्रेंट्स को सरल रखें। जटिल लॉजिक को छोटे‑छोटे, सरल कंस्ट्रेंट्स में बाँटने से आपका मॉडल पढ़ने और डिबग करने में आसान हो जाता है।

आधुनिक Gurobi: मैट्रिक्स API

यदि आप डेटा साइंस बैकग्राउंड से आते हैं, तो लूप‑आधारित मॉडलिंग धीमी लग सकती है। Gurobi 13.0+ में मैट्रिक्स API है जो NumPy ऐरेज़ का उपयोग करता है, और मॉडल बिल्डिंग को 10–50 गुना तेज़ बनाता है।

वेक्टर का उपयोग करते हुए बेकरी मॉडल कुछ यूँ दिखता है:

import gurobipy as gp
import numpy as np

# Data
prices = np.array([2.0, 5.0])
resources = np.array([[0.5, 2.0], [1.0, 1.0]])
limits = np.array([100.0, 80.0])

model = gp.Model("bakery_matrix")
x = model.addMVar(shape=2, name="x")

model.setObjective(prices @ x, gp.GRB.MAXIMIZE)
model.addConstr(resources @ x <= limits, name="constraints")

model.optimize()

यह A @ x <= b सिंटैक्स क्लीन है और प्रोडक्शन सिस्टम्स में मानक है।

एक सरल लीनियर प्रोग्रामिंग मॉडल बनाना

एक व्यावहारिक समस्या हल करते हैं: एक बेकरी तय करती है कि लाभ अधिकतम करने के लिए कितनी ब्रेड और केक बेक करने हैं।

समस्या सेटअप:

- ब्रेड लाभ: $2 | आटा: 0.5 किग्रा

- केक लाभ: $5 | आटा: 2 किग्रा

- उपलब्ध आटा: 100 किग्रा

- ओवन क्षमता: 80 आइटम्स

मॉडल इस प्रकार है:

import gurobipy as gp
from gurobipy import GRB

model = gp.Model("bakery_optimization")

bread = model.addVar(name="bread", vtype=GRB.CONTINUOUS, lb=0)
cake = model.addVar(name="cake", vtype=GRB.CONTINUOUS, lb=0)

model.setObjective(2 * bread + 5 * cake, GRB.MAXIMIZE)

model.addConstr(0.5 * bread + 2 * cake <= 100, name="flour_limit")
model.addConstr(bread + cake <= 80, name="oven_capacity")

model.optimize()

if model.status == GRB.OPTIMAL:
    print(f"Optimal profit: ${model.objVal:.2f}")
    print(f"Bake {bread.X:.2f} loaves of bread")
    print(f"Bake {cake.X:.2f} cakes")
else:
    print("No optimal solution found")

यह कोड मॉडल इनिशियलाइज़ करता है, वेरिएबल्स परिभाषित करता है और लाभ का ऑब्जेक्टिव सेट करता है। यह ऊपर परिभाषित कंस्ट्रेंट्स लागू करता है और ऑप्टिमल योजना निकालता है।

सॉल्वर लॉग्स को समझना

जब आप model.optimize() चलाते हैं, तो Gurobi एक लॉग प्रिंट करता है। इसे ऐसे पढ़ें:

Gurobi Optimizer version 13.0.0...
Presolve removed 0 rows and 0 columns
...
Explored 0 nodes (2 simplex iterations) in 0.01 seconds
Optimal objective  2.800000000e+02
  • Presolve: Gurobi हल से पहले आपकी समस्या को सरल बनाता है। "Removed rows" का मतलब है कि उसे अनावश्यक कंस्ट्रेंट्स मिले।
  • Simplex iterations: एल्गोरिद्म ने कितने स्टेप्स लिए। छोटी समस्या पर उच्च संख्या फॉर्म्युलेशन इश्यू दिखा सकती है।
  • Optimal objective: आपका अंतिम परिणाम (उदा., $280 लाभ)।
  • Gap: इंटीजर समस्याओं में, यह अब तक मिले सर्वोत्तम समाधान और सैद्धांतिक सर्वश्रेष्ठ के बीच का अंतर दिखाता है।

लॉग पर नज़र रखने से आप समझ पाते हैं कि मॉडल "अटक" गया है या बस मेहनत कर रहा है।

यहाँ के कॉन्सेप्ट सीधे स्केल होते हैं। चाहे 10 वेरिएबल्स हों या 10,000—पैटर्न वही रहता है।

Gurobi द्वारा समर्थित उन्नत समस्या प्रकार

लीनियर प्रोग्रामिंग बस शुरुआत है। Gurobi वास्तविक दुनिया की बारीकियों को पकड़ने वाले जटिल प्रकारों को संभालता है, जिनमें संस्करण 13.0 की नई Non‑Convex MINLP क्षमताएँ भी शामिल हैं।

मिक्स्ड‑इंटीजर लीनियर प्रोग्रामिंग

यह अलग क्यों है

मिक्स्ड‑इंटीजर प्रोग्रामिंग (MIP) वेरिएबल्स को इंटीजर होने देता है। आप 0.7 फ़ैक्ट्रियाँ नहीं बना सकते, इसलिए इंटीजर समाधानों की ज़रूरत होती है।

वास्तविक उपयोग

फैसिलिटी लोकेशन: सिटी A में वेयरहाउस खोलें? हाँ (1) या नहीं (0)।

प्रोडक्शन शेड्यूलिंग: बैच साइज़ अक्सर पूर्णांक होने चाहिए।

नेटवर्क डिज़ाइन: रूटिंग निर्णय आमतौर पर बाइनरी होते हैं—ट्रैफ़िक लिंक से गुजरता है या नहीं।

उदाहरण: फैसिलिटी लोकेशन

import gurobipy as gp
from gurobipy import GRB

model = gp.Model("facility_location")

cities = ['CityA', 'CityB', 'CityC']
fixed_costs = {'CityA': 10000, 'CityB': 8000, 'CityC': 12000}

open_warehouse = model.addVars(cities, vtype=GRB.BINARY, name="open")

model.setObjective(
    gp.quicksum(fixed_costs[city] * open_warehouse[city] for city in cities),
    GRB.MINIMIZE
)

model.addConstr(gp.quicksum(open_warehouse[city] for city in cities) >= 2)

model.optimize()

print("Open warehouses in:")
for city in cities:
    if open_warehouse[city].X > 0.5:
        print(f"  {city}")

यहाँ हम वेयरहाउस खोलने का निर्णय लेने के लिए बाइनरी वेरिएबल्स का उपयोग करते हैं। मॉडल फिक्स्ड कॉस्ट्स को न्यूनतम करता है, साथ ही कम से कम दो सुविधाएँ खुली रखने को सुनिश्चित करता है।

क्वाड्रैटिक और नॉनलिनियर प्रोग्रामिंग

क्वाड्रैटिक प्रोग्रामिंग (QP)

जब आपके ऑब्जेक्टिव में स्क्वायर्ड टर्म्स या वेरिएबल प्रोडक्ट्स हों, तो वह QP होता है। पोर्टफोलियो ऑप्टिमाइज़ेशन इसका क्लासिक उदाहरण है क्योंकि जोखिम (वेरिएंस) क्वाड्रैटिक होता है।

क्वाड्रैटिकली कंस्ट्रेन्ड प्रोग्रामिंग (QCP)

कंस्ट्रेंट्स भी क्वाड्रैटिक हो सकते हैं—जैसे सर्कल्स या घुमावदार सीमाएँ शामिल समस्याएँ।

उदाहरण: पोर्टफोलियो ऑप्टिमाइज़ेशन

import gurobipy as gp
from gurobipy import GRB
import numpy as np

model = gp.Model("portfolio")

assets = ['StockA', 'StockB', 'StockC']
expected_returns = [0.12, 0.18, 0.10]

covariance = np.array([
    [0.04, 0.01, 0.02],
    [0.01, 0.09, 0.03],
    [0.02, 0.03, 0.05]
])

weights = model.addVars(len(assets), name="weight", lb=0, ub=1)

model.setObjective(
    gp.quicksum(expected_returns[i] * weights[i] for i in range(len(assets))),
    GRB.MAXIMIZE
)

model.addConstr(gp.quicksum(weights[i] for i in range(len(assets))) == 1)

risk_expr = gp.quicksum(
    covariance[i][j] * weights[i] * weights[j]
    for i in range(len(assets))
    for j in range(len(assets))
)
model.addConstr(risk_expr <= 0.05, name="risk_limit")

model.optimize()

print("Optimal portfolio allocation:")
for i, asset in enumerate(assets):
    print(f"{asset}: {weights[i].X * 100:.1f}%")

यह सेटअप पोर्टफोलियो ऑप्टिमाइज़ेशन को संबोधित करता है—यह रिटर्न अधिकतम करता है और क्वाड्रैटिक कंस्ट्रेंट्स का उपयोग कर कुल जोखिम (वेरिएंस) पर सख्त सीमा लगाता है।

अतिरिक्त समर्थित समस्या प्रकार

सेकंड‑ऑर्डर कोन प्रोग्रामिंग (SOCP)

ज्यामितीय कंस्ट्रेंट्स—जैसे कोन या वृत्ताकार सीमा—वाली समस्याएँ इस श्रेणी में आती हैं। मज़बूत ऑप्टिमाइज़ेशन और इंजीनियरिंग डिज़ाइन में आम।

मिक्स्ड‑इंटीजर क्वाड्रैटिक प्रोग्रामिंग (MIQP)

इंटीजर वेरिएबल्स को क्वाड्रैटिक ऑब्जेक्टिव या कंस्ट्रेंट्स के साथ जोड़ता है। नॉनलिनियर संबंधों वाली डिस्क्रीट ऑप्टिमाइज़ेशन में उपयोगी।

Gurobi ये सभी प्रकार मूल रूप से सपोर्ट करता है। आपको किसी खास सॉल्वर में फिट करने के लिए समस्याएँ दोबारा फॉर्म्युलेट नहीं करनी पड़तीं—Gurobi स्वतः प्रकार पहचानकर उपयुक्त एल्गोरिद्म लागू करता है।

Flowchart of Gurobi optimization types: Linear (LP), Integer (MIP), and Non-Linear (QP, MINLP).

Gurobi द्वारा समर्थित ऑप्टिमाइज़ेशन समस्या प्रकार। चित्र: लेखक।

Gurobi एल्गोरिद्म और उनके उपयोग

एल्गोरिद्म चयन

Gurobi स्वतः एल्गोरिद्म चुनता है, लेकिन विकल्प जानना धीमे सॉल्व की ट्रबलशूटिंग में मदद करता है।

Method मान:

  • -1 (डिफ़ॉल्ट): Gurobi को तय करने दें

  • 0: प्राइमल सिम्प्लेक्स (ज़्यादातर LPs के लिए ठीक)

  • 1: डुअल सिम्प्लेक्स (इनफ़िज़िबल से शुरू होने पर अच्छा)

  • 2: बैरियर (बहुत बड़े मॉडल या QP के लिए श्रेष्ठ)

  • 3: कन्करेंट (कई तरीके साथ चलें, सबसे तेज़ चुने)

  • 4: डिटरमिनिस्टिक कन्करेंट

  • 5: डिटरमिनिस्टिक कन्करेंट सिम्प्लेक्स

  • PDHG (फ़र्स्ट‑ऑर्डर मेथड): Gurobi 13.0 में PDHG भी शामिल है—GPU पर फिट होने वाला ग्रेडिएंट‑आधारित तरीका, जो विशाल LPs के लिए आदर्श है।

कौन‑सा चला, यह सॉल्वर लॉग में देखें (उदा., "Barrier solved model...").

कब ओवरराइड करें: यदि डिफ़ॉल्ट घंटों ले रहा है, बहुत बड़े मॉडलों के लिए Barrier आज़माएँ या अप्रत्याशित समस्याओं के लिए Concurrent।

model.Params.Method = 2
model.Params.BarConvTol = 1e-8

यह स्पष्ट रूप से बैरियर मेथड चुनता है और टॉलरेंस कड़ी करता है—विशाल या संवेदनशील डेटा सेट्स पर मददगार।

Gurobi की उन्नत सुविधाओं का उपयोग

बेसिक्स पर पकड़ होने के बाद, एंटरप्राइज़‑स्केल समस्याओं के लिए Gurobi शक्तिशाली टूल्स देता है।

डिस्ट्रिब्यूटेड ऑप्टिमाइज़ेशन

बहुत बड़े मॉडल जिन्हें एक मशीन पर सुलझाने में बहुत समय लगता है, उनमें आप काम बाँट सकते हैं। Gurobi का डिस्ट्रिब्यूटेड ऑप्टिमाइज़ेशन एक ही समस्या को तेज़ी से हल करने के लिए कई कंप्यूटर्स का उपयोग करता है।

आप एक मशीन को "मैनेजर" और बाकी को "वर्कर्स" नामित करते हैं। मैनेजर सर्च ट्री के हिस्से वर्कर्स को भेजता है, जो उन्हें समानांतर हल करते हैं। छोटे मॉडलों के लिए यह ओवरकिल है, पर वैश्विक सप्लाई चेन या एयरलाइन शेड्यूलिंग जैसी समस्याओं में अनिवार्य।

मल्टी‑ऑब्जेक्टिव ऑप्टिमाइज़ेशन

वास्तविक जीवन में शायद ही कभी एक ही लक्ष्य होता है। आप लाभ अधिकतम और पर्यावरणीय प्रभाव न्यूनतम—दोनों चाह सकते हैं।

Gurobi आपको प्राथमिकताएँ सेट करने देता है। आप कह सकते हैं, "पहले लाभ अधिकतम करो, फिर कचरा न्यूनतम—पर लाभ 10% से अधिक कम न हो।" वैकल्पिक रूप से आप वेट भी दे सकते हैं: Objective = 0.7 * Profit - 0.3 * Waste।

# Multi-objective example
model.setObjectiveN(profit_expr, index=0, priority=2, name="Profit")
model.setObjectiveN(waste_expr, index=1, priority=1, name="Waste")

रीयल‑टाइम इंटरैक्शन और कॉलबैक्स

कभी‑कभी आप चाहते हैं कि Gurobi के सॉल्व करते समय बीच में हस्तक्षेप कर सकें। कॉलबैक्स आपको विशिष्ट बिंदुओं पर कस्टम कोड चलाने देते हैं—जैसे हर बार नया समाधान मिलने पर।

मैं कॉलबैक्स का उपयोग तब करता/करती हूँ जब समाधान "काफ़ी अच्छा" हो तो जल्दी रोकने के लिए, या अपने डेटा के अनुरूप कस्टम ह्यूरिस्टिक्स इंजेक्ट करने के लिए।

क्लाउड क्षमताएँ

डेवलपमेंट के लिए लैपटॉप पर ऑप्टिमाइज़ेशन चलाना ठीक है, पर प्रोडक्शन में अक्सर अधिक शक्ति चाहिए। Gurobi Cloud आपको भारी गणना AWS, Azure या Gurobi के अपने Instant Cloud पर ऑफ़लोड करने देता है। आप केवल सॉल्व समय का भुगतान करते हैं—छिटपुट, भारी वर्कलोड्स के लिए यह उत्तम है।

व्यावहारिक मॉडलिंग सर्वोत्तम अभ्यास

कुशल मॉडल लिखने के लिए रणनीति चाहिए। यहाँ कुछ टिप्स हैं ताकि आपका कोड साफ़ और तेज़ रहे।

मॉडल फॉर्म्युलेशन रणनीतियाँ

सरल से शुरू करें, धीरे‑धीरे जटिलता जोड़ें

पहले दिन ही 50 कंस्ट्रेंट्स वाला मॉडल न बनाएं। कोर लॉजिक से शुरुआत करें, उसे सत्यापित करें, फिर परिष्कृत करें। मैंने जटिल मॉडल्स डिबग करने में बहुत समय गंवाया है, और गलती बुनियादी हिस्से में निकली।

मतलबपूर्ण वेरिएबल और कंस्ट्रेंट नाम दें

x1 = model.addVar(name="x1")
model.addConstr(x1 + x2 <= 100, name="c1")

units_produced = model.addVar(name="units_produced")
model.addConstr(
    units_produced + units_stored <= warehouse_capacity,
    name="warehouse_capacity_limit"
)

फ़र्क नोट करें: दूसरा ब्लॉक बिज़नेस लॉजिक को स्पष्ट करता है। जैसा पहले कहा, यह डिबगिंग सिरदर्द से बचाता है।

डेटा का प्रीप्रोसेस करें

मॉडलिंग से पहले डेटा वैलिडेट करें—मिसिंग वैल्यूज़ या असंभव कंस्ट्रेंट्स जाँचें। 3 घंटे के सॉल्व के बाद डेटा एरर मिलना तकलीफ़देह है।

डेटा को उपयुक्त रूप से स्केल करें

Gurobi संख्यात्मक प्रिसीजन ठीक से संभालता है, पर अत्यधिक मान दिक्कत दे सकते हैं। यदि कॉस्ट मिलियन्स में हैं और क्वांटिटी हज़ारवें हिस्सों में, तो उन्हें समान परिमाणों में स्केल करें:

# Instead of cost = 10000000 and quantity = 0.0001
# Scale to cost = 10 (in millions) and quantity = 100 (in 1/1000 units)

अच्छे से स्केल किए गए मॉडलों में न्यूमेरिकल इश्यू दुर्लभ होते हैं; खराब स्केलिंग में आम।

न्यूमेरिकल स्थिरता पर विचार

Gurobi फ़्लोटिंग‑पॉइंट एरिथमेटिक उपयोग करता है, जो अनंत नहीं है। यदि आपका कंस्ट्रेंट x <= 1000000000 कहता है और टॉलरेंस 1e-6 है, तो अजीब परिणाम मिल सकते हैं।

"बिग M" कंस्ट्रेंट्स जैसे if y=0 then x <= 1,000,000,000 से बचें। इसके बजाय, सबसे छोटा वैध अपर बाउंड चुनें (उदा., कुल मार्केट साइज़)। टाइटर बाउंड्स का मतलब तेज़ और अधिक स्थिर सॉल्व है।

वॉर्म स्टार्ट्स और मॉडल संशोधन

आप शायद ही कोई समस्या सिर्फ़ एक बार हल करते हैं—आमतौर पर नया डेटा आता रहता है (उदा., डिमांड अपडेट)।

मॉडल दोबारा बनाने की बजाय वॉर्म स्टार्ट का उपयोग करें। आप पिछला समाधान स्टार्टिंग पॉइंट के रूप में देते हैं। क्योंकि बीते कल की ऑप्टिमल योजना आज के काफ़ी करीब होती है, Gurobi खोज का बहुत‑सा काम छोड़ सकता है।

# Warm start example
bread.Start = 40  # Start search assuming we bake 40 loaves

प्रोग्रामिंग इंटरफ़ेस और इंटीग्रेशन

Gurobi का Python API

हमने gurobipy का उपयोग किया क्योंकि यह पाइथनिक है। यह ऑपरेटर ओवरलोडिंग सपोर्ट करता है (x + y <= 5) और pandas तथा NumPy के साथ सीधे इंटीग्रेट होता है। डेटा साइंस में Gurobi उपयोग करने का यह सबसे लोकप्रिय तरीका है।

अन्य भाषाओं के साथ इंटीग्रेशन

प्रोडक्शन सिस्टम्स अक्सर स्पीड के लिए C++, Java या .NET पर चलते हैं। Gurobi इन सभी को सपोर्ट करता है। कॉन्सेप्ट (वेरिएबल्स, कंस्ट्रेंट्स, ऑब्जेक्टिव्स) समान होते हैं—सिर्फ़ सिंटैक्स बदलता है।

क्रॉस‑लैंग्वेज वर्कफ़्लो के लिए, मैं अक्सर Python में प्रोटोटाइप (तेज़ कोडिंग) करता/करती हूँ और C++ में डिप्लॉय (तेज़ निष्पादन) करता/करती हूँ, मॉडल्स को ले जाने के लिए Gurobi के फ़ाइल फ़ॉर्मैट्स (.mps या .lp) का उपयोग करता/करती हूँ।

मॉडलिंग लैंग्वेज सपोर्ट

Gurobi समर्पित मॉडलिंग लैंग्वेजेस जैसे AMPL और GAMS, या यहाँ तक कि Excel से भी प्लग‑इन होता है।

- AMPL/GAMS: शुद्ध गणितीय शोधकर्ताओं के लिए बढ़िया जो सॉफ्टवेयर कोड नहीं लिखना चाहते।

- Excel: त्वरित प्रोटोटाइप्स या बिज़नेस स्टेकहोल्डर्स को ऐसा मॉडल दिखाने के लिए उपयोगी जिसे वे बिना Python इंस्टॉल किए छू सकें।

परफॉर्मेंस ऑप्टिमाइज़ेशन और ट्यूनिंग

ट्यूनिंग वर्कफ़्लो

बेतरतीब ट्यून न करें। यह प्रक्रिया अपनाएँ:

  1. बेसलाइन नापें: डिफ़ॉल्ट्स के साथ चलाएँ, सॉल्व समय नोट करें।

  2. पहले कड़े लिमिट सेट करें: प्रोडक्शन सिस्टम्स में TimeLimit जरूरी है।

  3. गति के लिए सटीकता का सौदा: केवल तभी MIPGap ढीला करें जब बिज़नेस स्वीकार करे।

  4. थ्रेड स्केलिंग जाँचें: अधिक थ्रेड्स ≠ हमेशा तेज़ (4–8 के बाद लाभ घटते हैं)।

# Example: Production deployment
model.Params.TimeLimit = 300  # Hard 5-min cutoff for API response
baseline_time = model.Runtime

if baseline_time > 240:  # If cutting it close
    model.Params.MIPGap = 0.02  # Accept 2% suboptimality
    # Business rationale: 2% cost increase < late delivery penalty

परफॉर्मेंस बेंचमार्क्स

बेंचमार्क्स दिखाते हैं कि कठिन MIP समस्याओं पर Gurobi ओपन‑सोर्स सॉल्वर्स की तुलना में कई गुना बेहतर प्रदर्शन करता है। जबकि scipy छोटी LPs को ठीक से संभालता है, जटिलता बढ़ने पर Gurobi चमकता है। तुलनात्मक बेंचमार्क्स Hans Mittelmann वेबसाइट पर मिलते हैं, जो स्वतंत्र रूप से सॉल्वर परफॉर्मेंस ट्रैक करती है।

डिबगिंग और ट्रबलशूटिंग

मॉडल इनफ़िज़िबिलिटी

जब Gurobi "Model is infeasible" रिपोर्ट करता है, तो आपके कंस्ट्रेंट्स आपस में टकरा रहे हैं—कोई भी समाधान सभी को एक साथ संतुष्ट नहीं करता।

कंफ़्लिक्टिंग कंस्ट्रेंट्स खोजें:

model.computeIIS()
model.write("infeasible.ilp")

print("Conflicting constraints:")
for c in model.getConstrs():
    if c.IISConstr:
        print(f"  {c.ConstrName}: {c.ConstrExpr}")

यह Irreducible Inconsistent Subsystem (IIS) निकालता है और ठीक‑ठीक बताता है कि कौन‑से कंस्ट्रेंट्स आपस में भिड़ रहे हैं।

अनबाउंडेड मॉडल्स

अनबाउंडेड मॉडल का मतलब है ऑब्जेक्टिव अनंत तक बेहतर हो सकता है—आमतौर पर मिसिंग कंस्ट्रेंट्स का संकेत।

जाँचें:

- क्या आपने सभी वेरिएबल्स को बाउंड किया है? addVar(lb=0, ub=1000)

- क्या कंस्ट्रेंट्स सही तरह फॉर्म्युलेट हुए हैं?

- क्या ऑब्जेक्टिव फ़ंक्शन सही है?

सॉल्वर लॉग्स का उपयोग

विस्तृत लॉगिंग सक्षम करें ताकि देखें Gurobi क्या कर रहा है:

model.Params.OutputFlag = 1
model.Params.LogToConsole = 1
model.Params.LogFile = "gurobi.log"

यह कंसोल में विस्तृत आउटपुट सक्षम करता है और एक लोकल फ़ाइल में कॉपी सेव करता है—सॉल्व प्रक्रिया का विस्तृत इतिहास उपलब्ध कराता है।

डेटा हैंडलिंग

वास्तविक ऐप्स में डेटा फाइलों से आता है, हार्डकोडेड लिस्ट्स से नहीं।

import pandas as pd

# Load data
df = pd.read_csv("facility_costs.csv")
fixed_costs = dict(zip(df['city'], df['fixed_cost']))

# Validate BEFORE modeling
if any(c < 0 for c in fixed_costs.values()):
    raise ValueError("Costs cannot be negative")

यह पैटर्न—लोड, वैलिडेट, मॉडल—छुपी त्रुटियों से बचाता है।

Gurobi के वास्तविक‑दुनिया के उपयोग

सिद्धांत अच्छा है, लेकिन देखें उद्योग इसे वास्तव में कैसे उपयोग करते हैं।

सप्लाई चेन ऑप्टिमाइज़ेशन

डिस्ट्रिब्यूशन नेटवर्क डिज़ाइन

FedEx, UPS, और Amazon Supply Chain Analytics in Python कोर्स की अवधारणाओं का उपयोग लागत कम रखते हुए डिलीवरी गारंटी पूरी करने में करते हैं।

इस उदाहरण के लिए हम स्केल को कुशलता से संभालने हेतु मैट्रिक्स API का उपयोग करेंगे।

import gurobipy as gp
from gurobipy import GRB
import numpy as np

# 1. Data Generation
factories = ["F1", "F2"]
warehouses = ["W1", "W2", "W3"]
customers = ["C1", "C2", "C3", "C4"]

# Cost matrices (Factory->Warehouse, Warehouse->Customer)
transport_fw = np.array([[2.0, 4.0, 5.0], [3.0, 1.0, 6.0]])
transport_wc = np.array([
    [1.5, 2.0, 3.0, 4.0],
    [3.0, 1.0, 2.0, 2.5],
    [5.0, 4.0, 1.0, 1.5]
])

# Capacity and Demand
factory_cap = np.array([1000, 1000])
demand = np.array([300, 500, 400, 600])

try:
    with gp.Model("SupplyChain_Matrix") as model:
        # 2. Variables (Matrix Form)
        # Flow F->W and W->C
        flow_fw = model.addMVar((len(factories), len(warehouses)), name="fw")
        flow_wc = model.addMVar((len(warehouses), len(customers)), name="wc")
        
        # Binary decision: Open warehouse?
        open_w = model.addMVar(len(warehouses), vtype=GRB.BINARY, name="open")

        # 3. Objective: Minimize Transport + Fixed Costs
        fixed_cost = 5000
        obj = (transport_fw * flow_fw).sum() + \
              (transport_wc * flow_wc).sum() + \
              (fixed_cost * open_w).sum()
        model.setObjective(obj, GRB.MINIMIZE)

        # 4. Constraints
        # Factory capacity (sum rows of flow_fw <= cap)
        model.addConstr(flow_fw.sum(axis=1) <= factory_cap, name="Cap")

        # Customer demand (sum cols of flow_wc >= demand)
        model.addConstr(flow_wc.sum(axis=0) >= demand, name="Demand")

        # Flow balance: Inflow to W == Outflow from W
        model.addConstr(flow_fw.sum(axis=0) == flow_wc.sum(axis=1), name="Balance")

        # Warehouse capacity linking: Flow out <= BigM * OpenBinary
        model.addConstr(flow_wc.sum(axis=1) <= 2000 * open_w, name="Link")

        model.optimize()

        if model.Status == GRB.OPTIMAL:
            print(f"Optimal Cost: ${model.ObjVal:,.2f}")
            print(f"Open Warehouses: {open_w.X}")

except gp.GurobiError as e:
    print(f"Error: {e}")

यह वेक्टराइज़्ड अप्रोच (addMVar, sum(axis=1)) हज़ारों वेरिएबल्स को फटाफट संभाल लेता है—धीमे Python लूप्स से बचाता है।

Network graph showing a supply chain optimization model with flows connecting Factories (red) to Distribution Centers (blue) and finally to Customers (green).

सप्लाई चेन नेटवर्क ग्राफ़। चित्र: लेखक।

इन्वेंटरी ऑप्टिमाइज़ेशन

ऑर्डरिंग, होल्डिंग और शॉर्टेज कॉस्ट्स को संतुलित करना पेचीदा है। अनिश्चित डिमांड के साथ, यह स्टोकेस्टिक ऑप्टिमाइज़ेशन बन जाता है—जिसे Gurobi परिदृश्य मॉडलिंग के जरिए संभालता है।

वर्कफ़ोर्स शेड्यूलिंग

शिफ्ट प्लानिंग

अस्पतालों और कॉल सेंटर्स को स्टाफ़िंग आवश्यकताओं, श्रम नियमों और प्राथमिकताओं का सम्मान करते हुए कर्मियों का शेड्यूल बनाना होता है।

यह शुद्ध मिक्स्ड‑इंटीजर प्रोग्रामिंग है। हर असाइनमेंट बाइनरी विकल्प है। 100 नर्स और 50 शिफ्ट वाले अस्पताल के पास 5,000 वेरिएबल्स होते हैं।

उदाहरण: नर्स शेड्यूलिंग

import gurobipy as gp
from gurobipy import GRB

model = gp.Model("nurse_scheduling")

nurses = ['Alice', 'Bob', 'Carol', 'Dave']
shifts = ['Mon_Day', 'Mon_Night', 'Tue_Day', 'Tue_Night']
min_required = {'Mon_Day': 2, 'Mon_Night': 1, 'Tue_Day': 2, 'Tue_Night': 1}

schedule = model.addVars(nurses, shifts, vtype=GRB.BINARY, name="schedule")

model.setObjective(
    gp.quicksum(schedule[n, s] for n in nurses for s in shifts),
    GRB.MINIMIZE
)

for shift in shifts:
    model.addConstr(
        gp.quicksum(schedule[n, shift] for n in nurses) >= min_required[shift],
        name=f"min_staff_{shift}"
    )

for nurse in nurses:
    model.addConstr(
        gp.quicksum(schedule[nurse, s] for s in shifts) <= 3,
        name=f"max_shifts_{nurse}"
    )

for nurse in nurses:
    # Labor rule: 8-hour rest required between shifts
    model.addConstr(
        schedule[nurse, 'Mon_Day'] + schedule[nurse, 'Mon_Night'] <= 1,
        name=f"no_double_{nurse}_Mon"
    )
    model.addConstr(
        schedule[nurse, 'Tue_Day'] + schedule[nurse, 'Tue_Night'] <= 1,
        name=f"no_double_{nurse}_Tue"
    )

model.optimize()

print("Optimal schedule:")
for nurse in nurses:
    assigned = [s for s in shifts if schedule[nurse, s].X > 0.5]
    print(f"{nurse}: {', '.join(assigned)}")

यह बाइनरी वेरिएबल्स से शेड्यूलिंग समस्या मॉडल करता है—यह कुल शिफ्ट्स को न्यूनतम करता है, साथ ही स्टाफ़िंग ज़रूरतें, अधिकतम घंटे और अनिवार्य विश्राम अवधि का पालन करता है।

वित्तीय पोर्टफोलियो ऑप्टिमाइज़ेशन

जोखिम‑रिटर्न संतुलन

पोर्टफोलियो ऑप्टिमाइज़ेशन प्रत्याशित रिटर्न को जोखिम के विरुद्ध संतुलित करता है। क्लासिक Markowitz मॉडल:

  • अधिकतम करें: प्रत्याशित रिटर्न
  • शर्त: जोखिम (वेरिएंस) सीमा से नीचे
  • कंस्ट्रेंट्स: बजट, डाइवर्सिफ़िकेशन आवश्यकताएँ, रेगुलेटरी लिमिट्स

यह क्वाड्रैटिक प्रोग्रामिंग है—रिटर्न वेट्स में लीनियर है, पर वेरिएंस क्वाड्रैटिक (वेट्स के गुणन शामिल) होता है।

व्यावहारिक विचार

वास्तविक पोर्टफोलियो ऑप्टिमाइज़ेशन में शामिल होते हैं:

  • ट्रांज़ैक्शन कॉस्ट्स (खरीद/बिक्री पर फ़ीस)
  • इंटीजर कंस्ट्रेंट्स (कुछ एसेट्स के अंश शेयर नहीं खरीद सकते)
  • रेगुलेटरी आवश्यकताएँ (एक ही सिक्योरिटी में 10% से अधिक नहीं)
  • रीबैलेंसिंग कंस्ट्रेंट्स (मौजूदा पोर्टफोलियो को बहुत ज़्यादा न बदलें)

एसेट मैनेजर्स ये ऑप्टिमाइज़ेशन रोज़ चलाते हैं—अरबों की पूँजी मैनेज करते हुए। मॉडल का सॉल्व समय सीधे ट्रेडिंग स्ट्रैटेजी एक्ज़ीक्यूशन को प्रभावित करता है।

निष्कर्ष

हमने बहुत कुछ कवर किया—Gurobi इंस्टॉल करने से लेकर जटिल सप्लाई चेन मॉडल बनाने तक।

अब मीटिंग रूम में रायों पर बहस करने की बजाय आप स्क्रीन पर कोड रख सकते हैं—"यह है गणितीय रूप से उत्तम योजना।" बातचीत बदल जाती है—अटकलबाज़ी बंद, प्रमाण शुरू।

आगे बढ़ें और इसे अपनी अगली उलझी समस्या—वह शेड्यूलिंग कन्फ़्लिक्ट या बजट दबाव—पर आज़माएँ जिसे आप टाल रहे थे। मुमकिन है कि पूर्ण उत्तर आपके डेटा में ही छिपा हो।

और यदि आप अपनी ऑप्टिमाइज़ेशन स्किल्स और निखारना चाहते हैं, तो हमारा Introduction to Linear Programming ट्यूटोरियल और Introduction to Optimization in Python कोर्स देखें और सीखते रहें।


Khalid Abdelaty's photo
Author
Khalid Abdelaty
LinkedIn

मैं एक डेटा इंजीनियर और कम्युनिटी बिल्डर हूँ, जो डेटा पाइपलाइनों, क्लाउड, और AI टूलिंग के साथ काम करता/करती हूँ, साथ ही DataCamp और उभरते डेवलपर्स के लिए व्यावहारिक, असरदार ट्यूटोरियल लिखता/लिखती हूँ।

Gurobi FAQs

Gurobi Optimizer और gurobipy में क्या अंतर है?

Gurobi Optimizer वह कंप्यूटेशनल इंजन है जो गणितीय समस्याएँ हल करता है। gurobipy वह Python लाइब्रेरी है जिसका उपयोग आप मॉडल बनाने और उसी इंजन से संवाद करने के लिए करते हैं। आप gurobipy में कोड लिखते हैं, और यह समस्या Optimizer को भेज देता है ताकि समाधान मिल सके।

क्या Gurobi का प्रभावी उपयोग करने के लिए उन्नत गणित चाहिए?

ज्यादा नहीं। यदि आपको बुनियादी बीजगणित (जैसे 2x + y <= 10) समझ में आता है, तो अधिकांश समस्याओं के लिए आप तैयार हैं। जटिल एल्गोरिद्म टूल संभाल लेता है—आपको बस अपनी समस्या को तार्किक रूप से वर्णित करने में सक्षम होना चाहिए।

क्या मैं Python के अलावा अन्य भाषाओं के साथ Gurobi उपयोग कर सकता/सकती हूँ?

हाँ! जबकि डेटा साइंस के लिए Python सबसे लोकप्रिय विकल्प है, Gurobi के C++, Java, .NET और MATLAB के लिए भी सशक्त APIs हैं। यह सांख्यिकीय विश्लेषण वर्कफ़्लोज़ के लिए R के साथ भी इंटीग्रेट होता है।

अगर मेरा मॉडल हल होने में बहुत समय ले रहा हो तो क्या करें?

हमेशा "परफेक्ट" उत्तर की ज़रूरत नहीं होती। आप "MIPGap" सेट कर सकते हैं ताकि सॉल्वर ऑप्टिमल से 1% या 5% के भीतर समाधान मिलते ही रुक जाए। वास्तविक निर्णयों में, आज अच्छा उत्तर कल के परफेक्ट उत्तर से बेहतर होता है।

क्या प्रोडक्शन में Gurobi मेंटेन करना मुश्किल है?

असल में यह काफ़ी स्थिर है। मुख्य चुनौती सॉफ़्टवेयर नहीं, डेटा है। यदि आपका इनपुट डेटा फ़ॉर्मैट बदलता है या उसमें त्रुटियाँ हैं, तो आपका मॉडल टूट सकता है। अच्छे डेटा वैलिडेशन पाइपलाइन्स Gurobi कोड से अधिक अहम होते हैं।

क्या मैं नतीजों को आसानी से विज़ुअलाइज़ कर सकता/सकती हूँ?

Gurobi संख्याएँ आउटपुट करता है, लेकिन क्योंकि यह Python से अच्छी तरह जुड़ता है, आप उन नतीजों को सीधे Matplotlib, Seaborn, या Plotly जैसी लाइब्रेरीज़ में भेज सकते हैं। कुछ ही लाइनों के कोड में आप अपने ऑप्टिमाइज़ेशन नतीजों को गैंट चार्ट्स या नेटवर्क मैप्स में बदल सकते हैं।

विषय
डेटा विश्लेषण
Python

DataCamp के साथ सीखें

कोर्स

Python में Optimization परिचय

4 घंटा
5.6K
Python के SciPy और PuLP से वास्तविक-विश्व अनुकूलन समस्याएँ हल करना सीखें, बुनियादी से लेकर बाधित और जटिल अनुकूलन तक।
विवरण देखेंRight Arrow
पाठ्यक्रम शुरू करें
और देखेंRight Arrow