top of page
Search

Balanced Work Assignment: An Optimization Model That Knows Its Operators, with Jev

Oct 17
13 min read

This article presents an approach that extends the previously discussed balanced work assignment optimization model with free-text information about the operators. Through an example, it shows in which situations the earlier model, which distributes work orders equally among pickers, fails to hold up on the warehouse floor. It then introduces Jev, a decision model developed by TypeSafe AI. Finally, it details, with code, how the shift supervisor’s notes are converted into model parameters with Jev and how these parameters are connected to the Python PuLP model.


Process Summary

The earlier article addressed the problem of distributing work orders generated for picking products inside a warehouse, that is, pick tours, evenly among pickers. The sample data contained 74 tours, in which 5,177 items were to be picked, and 8 pickers to carry out these tours. The model aimed to keep the total volume (desi) and the number of tours assigned to each picker close to the per-operator average.


The average volume per operator was calculated as Davg = 1,811 desi and the average number of tours as Tavg = 9.25.

When the model was solved, each picker was assigned roughly 1,800 desi and 9–10 tours, and the distribution looked balanced in terms of both volume and number of tours.


Problem Definition

The balanced distribution of the earlier model rests on the assumption that all pickers work under the same conditions and at the same speed. In warehouse operations, however, every day is different. At the start of a shift, the warehouse operations manager has notes about the pickers similar to the ones below.


Op. 2: “Started on Monday, still learning the locations.” Op. 4: “Doctor’s appointment in the afternoon, leaving at 13:00.” Op. 7: “Senior, fast and error-free.”

These notes change what an equal distribution means on the floor. When a picker who has just started is given the same amount of work as a senior picker, one finishes before the end of the shift while the other stays for overtime. When a picker who will leave at 13:00 is given a full day’s work, some of the tours remain unpicked at the end of the day. In other words, distributing equally does not always mean distributing fairly.


In this context, fair distribution needs to be redefined.


Fair distribution means that every picker can finish the work assigned to them within the time they are available that day, and at roughly the same time as the other pickers.


According to this definition, a fast picker should be assigned more work and a picker who has just started less. A picker who will work half a day should receive half a day’s work. But a difficulty arises here. The optimization model works with numbers, while the information about the pickers sits in the shift supervisor’s free-text notes. It is not possible to feed expressions such as “started on Monday” or “leaving at 13:00” directly into the model as input. These notes first need to be converted into parameters the model can understand.


A rule-based approach could be considered for this conversion. However, each note is written in a different style. One says “half day”, another “leaving at 13:00”, and yet another does not mention working hours at all. Rules based on keywords struggle to capture this variety. In this article, Jev, a model that reads text and produces typed decisions, is used to make this conversion.


This article uses Jev, a model that reads text and generates typographical decisions to perform this transformation

What is Jev?

Jev is an artificial intelligence model that reads text and makes a decision among predefined options. What distinguishes it from language models such as ChatGPT is that it does not write text as an answer. Jev is given a piece of text and a question about that text. It returns one of the question’s options, together with a probability value showing how confident it is in that option.


When Jev is asked “Will this picker work a full day or a half day today?”, the answer is not a paragraph but yarim_gun (half day) and 0.98.

This answer can be used directly inside software. It can go into an if condition, be written to a table, or be passed to an optimization model as a parameter.


Which problems is it used for?

The problems Jev is suited for share a common structure: the input is free text, but the decision to be made is choosing one of a few options. This structure repeats thousands of times a day in many industries.



Table 1. Decisions Jev can make across industries
Table 1. Decisions Jev can make across industries

In all of these examples, the decision is not an end result on its own. A process follows the decision: a routing, a prioritization, or, as in this article, an optimization model. Jev acts as a bridge between the text and this process.


Where does it provide an advantage?

Today, such decisions are usually made in one of two ways. The first is the rule-based approach: something like “if the note contains ‘half day’, count it as half a day”. However, notes are written with different expressions every time. The expression “leaving at 13:00” cannot pass this rule. Jev, on the other hand, reads the meaning of the expression.


The second is language models. A language model understands the text, but writes its answer as text, which then has to be parsed separately. In addition, each call takes seconds. For a decision repeated thousands of times a day, this is both slow and costly. Jev’s answer arrives in under half a second and is always one of the defined options.


Jev’s most important advantage, however, is the probability value it returns with its answer. This value makes it possible to decide when a decision is applied automatically and when a person is asked.

If Jev is 95% sure of a decision, the decision is applied. If it is 60% sure, the shift supervisor is asked.

Where should it not be used?

Jev does not perform calculations, does not solve optimization problems and does not produce text. For this reason, the division of labor in this study is clear.

Jev reads, code calculates, PuLP decides.

Jev’s Place in the Balanced Work Assignment Problem

In the earlier model, the process consisted of two steps: the tour data was prepared, and then the PuLP model assigned the tours to the pickers. The only thing the model knew about the pickers was their number. In this study, a new layer is added between the two steps.


Shift notes → Jev → working time and speed → picker-specific targets → PuLP → assignment

In this process, Jev does only one thing: it reads each picker’s note and answers two questions. It does not interfere directly with the assignment decision.

Which questions are asked to Jev?

The definition of fair distribution made in the problem definition requires two pieces of information: how long the picker will work that day and how fast the picker works. Two separate questions are defined for these two pieces of information.


The second question concerns the picker’s speed. Since speed is expressed on an ordered scale from slow to fast, the question is of the Score type. The scale consists of five levels:

İkinci soru toplayıcının hızına ilişkindir. Hız, yavaştan hızlıya sıralı bir ölçekte ifade edildiği için soru Score tipindedir. Ölçek beş seviyeden oluşur:

0 — Very slow: just started, still learning the location 1 — Below average: new but learning fast 2 — Average: normal pace, or no speed information in the note 3 — Above average: experienced, senior 4 — Very fast: top performance, senior and error-free

The reason the two pieces of information are asked in separate questions rather than in a single one is that the same picker can both work half a day and be fast. Jev answers both questions in a single call.

What did Jev answer?

When the notes of the 8 pickers were sent to Jev, the following answers were obtained. The notes were written in Turkish and are translated here.

Table 2. Shift notes and Jev’s answers
Table 2. Shift notes and Jev’s answers

Two answers in the table are particularly noteworthy. Although the expression “half day” does not appear in picker 4’s note, Jev determined that leaving at 13:00 means working half a day. Picker 6’s note, on the other hand, contained two different pieces of information together. Jev placed the half-day leave in working time and the “new but learning fast” information in level 1 of the speed scale.


Who defines the scale?

The speed score of picker 1 is a result that deserves careful examination. Although the note contains the expression “the most senior in the warehouse”, Jev placed this picker not at the top level but at level 3. The reason for this is the definition of the scale. Seniority sits at level 3, while level 4 requires top performance in addition to seniority. Since the note contains no information about performance, Jev applied the scale exactly as it was defined.


Jev’s decision is determined as much by the person who defines the scale as by the notes.

This shows that, when using Jev, the options and scale definitions are business decisions. The answer to the question “Does eight years of seniority alone correspond to the highest speed level?” is given not by Jev but by the warehouse operations manager.

What happens when Jev is not sure?

Jev returns a confidence value with each answer. In this study, a rule was defined that the picker in question is referred to the shift supervisor when the confidence value is below 0.7 for working time and below 0.5 for speed. Since the confidence values of all 8 pickers were above 0.88, this rule was not triggered. However, in cases where notes are written more vaguely, this rule prevents decisions Jev is not sure about from being passed to the model automatically.

Extending the Model

The answers coming from Jev are labels and scores. For the optimization model to use these answers, they first need to be converted into numerical coefficients. This conversion is done not by Jev but in Python code, according to business rules.


The working-time coefficient is determined relative to a full-day shift: 1.0 for a full day, 0.5 for a half day and 0.0 for not working. The speed coefficient is determined by assigning each level of the speed scale a value that expresses productivity relative to an average picker: 0.60 for level 0, 0.80 for level 1, 1.00 for level 2, 1.15 for level 3 and 1.30 for level 4.


When Jev’s score takes a value between two levels, the speed coefficient is calculated linearly between the coefficients of the two levels. For example, for a score of 2.91 the coefficient is 1.00 + 0.91 × 0.15 = 1.14.

These coefficients were set for illustration purposes. In a real application, they should be derived from historical picking data in the warehouse management system.

The new parameters added to the model are shown below.


In the earlier model, the average volume and the number of tours per operator were the same for all operators. In the extended model, these two parameters are calculated according to each operator’s share of the total effective capacity.



With this definition, the sum of the operators’ targets is again equal to the total volume and the total number of tours. Thus, no tour is left out of the distribution. The values calculated for the 8 operators are shown in the table below.


Table 3. Picker-specific targets
Table 3. Picker-specific targets


The sets, decision variables and objective function of the model remain the same as in the earlier article. Only constraints (2) and (3), which concern the volume and number of tours per operator, change. In these constraints, operator-specific Davg_i and Tavg_i are used instead of the Davg and Tavg shared by all operators.




In other words, Jev does not change the structure of the model. What it changes is what the model knows about the operators.

Coding and Solving with Python

All the code for this study is available in the GitHub repository. The code is split into three files reflecting the division of labor: veri.py, which contains the tour data and the shift supervisor's notes; jev_katmani.py, where the questions are sent to Jev and the answers are converted into coefficients; and model.py, which contains the extended balanced tour assignment model. This section covers only the parts where Jev joins the process and where the model changes. The variable names follow the repository, which is written in Turkish: SORULAR means questions, calisma_suresi working time, hiz speed and cevaplar answers.

First, the questions to be asked to Jev are defined. A Choice question is created for working time and a Score question for speed.


SORULAR = {
    "calisma_suresi": {
        "type": "choice",
        "instructions": "Operatör bugün ne kadar süre çalışacak?",
        "criteria": {
            "tam_gun": "Tam vardiya çalışacak. Notta süreyi kısaltan bir bilgi yoksa bu seçilir.",
            "yarim_gun": "Vardiyanın yaklaşık yarısında çalışacak: yarım gün izin, erken çıkış, randevu gibi.",
            "calismiyor": "Bugün hiç çalışmayacak: tam gün izin, raporlu gibi.",
        },
    },
    "hiz": {
        "type": "score",
        "instructions": "Operatörün toplama hızı ve verimi ortalama bir toplayıcıya göre nasıl?",
        "criteria": [
            "Çok yavaş: işe yeni başlamış, lokasyonları henüz öğreniyor",
            "Ortalamanın altında: yeni ama öğrenmesi hızlı",
            "Ortalama: normal tempo veya notta hız bilgisi yok",
            "Ortalamanın üstünde: deneyimli, kıdemli",
            "Çok hızlı: en yüksek performans, kıdemli ve hatasız",
        ],
    },
}

The questions are written in Turkish because the notes are in Turkish. Their English meaning is the same as the scale given in the previous section.


Then each operator’s note is sent to Jev and the answers are received.

for i, metin in operator_notlari.items():
    r = requests.post(
        "https://api.typesafe.ai/v1/systemone",
        headers={"Authorization": f"Bearer {os.environ['TYPESAFE_API_KEY']}"},
        json={
            "model": "jev-latest",
            "state": {"operator_id": i, "vardiya_amiri_notu": metin},
            "questions": SORULAR,
        },
    )
    a = r.json()["answers"]
    cevaplar[i] = {
        "calisma_suresi": a["calisma_suresi"]["choice"],
        "sure_conf": a["calisma_suresi"]["confidence"],
        "hiz": a["hiz"]["score"],
        "hiz_conf": a["hiz"]["confidence"],
    }

Jev’s answers are converted into coefficients and the operator-specific targets are calculated.

SURE_K = {"tam_gun": 1.0, "yarim_gun": 0.5, "calismiyor": 0.0}
HIZ_K = [0.60, 0.80, 1.00, 1.15, 1.30]

def hiz_katsayisi(skor):
    alt = min(int(skor), 3)
    return HIZ_K[alt] + (skor - alt) * (HIZ_K[alt + 1] - HIZ_K[alt])

etkin = {i: SURE_K[c["calisma_suresi"]] * hiz_katsayisi(c["hiz"]) for i, c in cevaplar.items()}
toplam = sum(etkin.values())

Davg = {i: sum(tur_desi) * etkin[i] / toplam for i in operator_list}
Tavg = {i: len(tur_list) * etkin[i] / toplam for i in operator_list}

In the model, only constraints (2) and (3) change. The Davg and Tavg parameters of the earlier article are replaced by the operator-specific Davg[i] and Tavg[i].

for i in operator_list:
    model += lpSum(x[(i, j)] for j in tur_list) >= Tavg[i] * z
    model += lpSum(x[(i, j)] * desi[j] for j in tur_list) >= Davg[i] * y

Finally, we solve.

model.solve(HiGHS(msg=False, timeLimit=60))

Evaluating the Results

To see the effect of the extended model, both models were run on the same data. The original model was solved as in the earlier article, that is, with the same target for all operators. The extended model was solved with the operator-specific targets coming from Jev. The results of both models were compared on three measures: total volume per operator, number of tours, and the time required to complete the assigned work.

First, the total volume per operator is examined.



In the original model, each operator is assigned between 1,802 and 1,869 desi. The distribution is quite balanced, as intended in the earlier article. In the extended model, on the other hand, the volume assigned to operators varies between 807 and 2,585 desi. Operator 7 received more than three times the work of operator 6. At first glance, one might think that the original model made a fairer distribution.

A similar picture is seen in the number of tours.



While the original model assigns 9 or 10 tours to the operators, the number of tours in the extended model ranges from 4 to 13. Evaluated on their own, these two charts give the impression that the extended model disrupted the balance.

However, this impression changes when one looks at the time required to complete the assigned work. The time each operator needs to finish their work was calculated by dividing the assigned volume by the operator’s speed.



The dashed lines in the chart show the time each operator is available that day. In the original model, a significant share of the orange bars is far from these lines.

Operator 2, who has just started, needs 12 hours to complete the work assigned to them. Operators 4 and 6, who will leave at 13:00, were assigned 7.2 and 8.9 hours of work respectively.

In contrast, operators 1, 3 and 7, who are senior and fast, complete their work in around 6 hours and stay idle for the rest of the shift. In the original plan, a total of 12.1 hours of work exceeds the operators’ available time, while a total of 7.9 hours of capacity remains unused on the same day. In other words, the warehouse experiences both overtime and idle capacity on the same day. The work that exceeds the available time is either completed with overtime or carried over to the next day.


In the extended model, the blue bars almost coincide with the dashed lines. Full-day operators complete their work in 7.9 to 8.2 hours, and half-day operators in 4.0 to 4.1 hours. No operator significantly exceeds their available time, and no operator stays idle.


When the three charts are evaluated together, it can be seen that the imbalance in the amount of work actually creates a balance in the time spent. What makes the difference between the two models is not the solution method. Both models use the same objective function, the same constraint structure and the same solver. The difference comes from what the extended model knows about the operators.

Distributing equally does not always mean distributing fairly.

Conclusion

In this study, I extended the balanced work assignment optimization model I had previously discussed so that it takes into account the operators’ working hours and relative speeds. My starting point was that an equal distribution of work does not always mean a fair one.


Using Jev, the model developed by TypeSafe AI, I converted the shift supervisor’s free-text notes into working-time and speed information. On the Python side, this information was mapped to numerical coefficients and passed to the mathematical optimization model. This made it possible to create operator-specific workload targets without changing the core structure of the model.


The results showed that although the original model distributed volume (desi) and the number of tours evenly, the operators’ different capacities could still lead to imbalances in completion times. In the Jev-supported model, workloads were distributed according to the operators’ effective capacities, which brought completion times closer to the available working hours.


Since the speed coefficients used here were set for illustration purposes, the results should be read as an experiment demonstrating the feasibility of the proposed approach, not as evidence of a real operational performance gain. In real-world use, these coefficients need to be validated with historical operational data, and Jev’s decisions need to be monitored.


In this study, my aim was not for Jev to replace mathematical optimization but to complement it. The division of labor is quite simple:

Jev reads the text, code calculates, and the optimization model decides.

In my view, the real value of this approach is that information which usually stays buried in operational notes and descriptions can now be carried into mathematical models. A similar structure can be used in a range of resource assignment problems, from call centers to field team planning.


In conclusion, the opportunity in combining AI with optimization may not always be about producing solutions faster. Sometimes the real gain is enabling existing optimization models to make decisions with more accurate and richer information.


I hope this approach will serve as a source of inspiration for work assignment and planning problems across different industries.


Dr. Şükrü İmre


Note: The Python code in this article was written together with Claude, the AI assistant developed by Anthropic. The framing of the problem, the design of the model and the interpretation of the results belong to the author. All the code was run and verified by the author.

 
 
© 2026 Şükrü Orcun İmre. All rights reserved.
bottom of page