Hoffmann Montaj Hattı DengelemeHoffmann Assembly Line Balancing

SALBP-1 için Hoffmann'ın (1963) öncelik matrisi yöntemi: saf Python çekirdek, komut satırı aracı ve beş dilli Streamlit arayüzü. Ders ödevi olarak başladı; inceleme, kodun aslında Hoffmann olmadığını gösterince sıfırdan yazıldı.Hoffmann's (1963) precedence-matrix method for SALBP-1: a pure-Python core, a command-line tool and a five-language Streamlit UI. It started as coursework; when a review showed the code was not actually Hoffmann's method, it was rewritten from scratch.

Python 3.11+Streamlithypothesismypy --strictGitHub ActionsApache-2.0
TestTests
127
Arayüz diliUI languages
EN · TR · DE · ES · FR
DoğrulamaVerification
brute-force + bitmask-DP
SürümRelease
v1.1.0
Streamlit arayüzü: iş tablosu, çevrim süresi, istasyon sonuçları
Streamlit arayüzü: iş tablosu (süre + ardıllar), çevrim süresi, eşitlik kuralı, sonuç kartları; kenar çubuğundan dil seçimi.Streamlit UI: task table (duration + successors), cycle time, tie-break rule, result cards; language selector in the sidebar.

ProblemProblem

Montaj hattı dengeleme (SALBP-1): verilen çevrim süresi C için işleri öncelik kısıtlarını bozmadan en az sayıda istasyona dağıtmak. Projenin ilk sürümü bir ders ödeviydi: MATLAB'dan Python'a taşınmış, üstüne Tkinter arayüzü konmuştu ve "sonuç" üretiyordu.

Kod incelemesi, uygulanan döngünün Hoffmann yöntemi değil first-fit sezgiseli olduğunu gösterdi ("kodu sıfır olan ilk uygun işi al"). Alt küme sayımı olmadığı için optimumdan sapıyordu: [4, 4, 3, 3, 3, 3], C = 10 örneğinde 3 istasyon buluyordu, Hoffmann 2 bulur. Ayrıca öncelik döngüsünde sonsuz döngüye giriyor, ondalık süreleri reddediyor ve geçersiz girdiyi sessizce yutuyordu.

Assembly line balancing (SALBP-1): for a given cycle time C, assign tasks to the fewest stations without violating precedence. The first version was coursework: a MATLAB script ported to Python with a Tkinter GUI on top, and it did produce "results".

A code review showed the implemented loop was a first-fit heuristic, not Hoffmann's method ("take the first available task whose code is zero"). Without subset enumeration it deviated from the optimum: on [4, 4, 3, 3, 3, 3] with C = 10 it found 3 stations where Hoffmann finds 2. It also looped forever on precedence cycles, rejected fractional durations and silently dropped invalid input.

YaklaşımApproach

  • Gerçek Hoffmann. Her istasyon için öncelik kısıtını sağlayan tüm iş alt kümeleri sayılır, boş süreyi en aza indiren seçilir. Eşitlik kuralı seçilebilir: ORIGINAL, MOST_TASKS, MOST_FOLLOWERS.
  • Eski davranış korundu. First-fit döngüsü greedy_first_fit olarak duruyor; arayüzde "eski yöntemle karşılaştır" iki çözümü yan yana gösterir.
  • Ölçütler. Verimlilik, denge kaybı, teorik alt sınır ⌈Σt/C⌉, düzgünlük indeksi (Moodie & Young).
  • Gerçek girdiler. Türkçe Excel CSV'si (; ayracı, ondalık virgül), Türkçe sütun başlıkları; hatalar BalancingError altında ve sorunlu iş kimliklerini söyler.
  • Üç arayüz, tek çekirdek. Python API, komut satırı (metin/JSON/CSV çıktı) ve Streamlit (tablo editörü, çevrim süresi taraması, CSV/JSON indirme). Çekirdeğin zorunlu bağımlılığı yok.
  • Beş dil. Arayüz ve komut satırı EN/TR/DE/ES/FR; i18n bütünlüğü testle kilitli.
  • Real Hoffmann. For every station, every task subset that satisfies precedence is enumerated and the one with minimum idle time is chosen. The tie-break rule is selectable: ORIGINAL, MOST_TASKS, MOST_FOLLOWERS.
  • The old behaviour is preserved. The first-fit loop lives on as greedy_first_fit; "compare with legacy method" shows both solutions side by side.
  • Metrics. Efficiency, balance delay, theoretical lower bound ⌈Σt/C⌉, smoothness index (Moodie & Young).
  • Real inputs. Turkish Excel CSV (; delimiter, decimal comma), Turkish column headers; errors derive from BalancingError and name the offending task ids.
  • Three interfaces, one core. Python API, CLI (text/JSON/CSV output) and Streamlit (table editor, cycle-time sweep, CSV/JSON download). The core has no mandatory dependency.
  • Five languages. UI and CLI in EN/TR/DE/ES/FR; i18n completeness is locked by a test.

Sonuç ve doğrulamaResult and verification

Ders örneği (12 iş, C = 18) komut satırından:

The course example (12 tasks, C = 18) from the command line:

$ python -m hoffmann_lb examples/course_example.csv --cycle 18

Method: hoffmann   Cycle time: 18

Station  1: 1, 2            load      18   idle       0
Station  2: 3, 4, 5, 7, 9   load      18   idle       0
Station  3: 6, 8            load      17   idle       1
Station  4: 10, 11, 12      load      17   idle       1

Stations          : 4 (equals lower bound)
Efficiency (E)    : 97.22 %
Balance delay (D) : 2.78 %
Smoothness (SI)   : 1.4142

127 test: birim, uçtan uca CLI, Streamlit AppTest, i18n bütünlüğü ve rastgele DAG'lar üzerinde hypothesis özellik testleri. Ders örneğinin beklenen değerleri bağımsız bir brute-force oracle ve kesin bir bitmask-DP çözücü ile hesaplandı; Hoffmann test edilen her C için tam optimuma ulaşıyor. ORIGINAL kuralıyla 8 işe kadar rastgele graflarda oracle ile birebir aynı istasyon kümelerini veriyor. ruff, mypy --strict, CI (Python 3.11 / 3.12).

Sürümler: v0.1.0 çekirdek → v0.2.0 CSV/JSON + CLI → v1.0.0 Streamlit → v1.1.0 çok dilli arayüz. v1.0.0'a kadar MIT, sonrası Apache-2.0 (NOTICE dosyasında belirtildi).

127 tests: unit, end-to-end CLI, Streamlit AppTest, i18n completeness and hypothesis property tests on random DAGs. Expected values for the course example were computed with an independent brute-force oracle and an exact bitmask-DP solver; Hoffmann reaches the exact optimum for every tested C. With the ORIGINAL rule it yields exactly the same station sets as the oracle on random graphs up to 8 tasks. ruff, mypy --strict, CI on Python 3.11 / 3.12.

Releases: v0.1.0 core → v0.2.0 CSV/JSON + CLI → v1.0.0 Streamlit → v1.1.0 multilingual UI. MIT up to v1.0.0, Apache-2.0 afterwards (recorded in NOTICE).

ÖğrendiklerimWhat I learned

Çalışan kod ile doğru kod arasındaki fark ancak bağımsız bir doğrulayıcıyla görünür. Ödev sürümü de her girdide bir "sonuç" üretiyordu; brute-force oracle olmadan first-fit olduğu hiç anlaşılmayacaktı. Bir yöntemin adını taşıyan kodun o yöntemi gerçekten uyguladığını kanıtlamak, kodu yazmaktan daha değerli.

The difference between working code and correct code only shows up with an independent verifier. The coursework version produced a "result" for every input; without the brute-force oracle nobody would have noticed it was first-fit. Proving that code named after a method actually implements that method is worth more than writing the code.