Pull to refresh

Теория вероятностей в действии 2.0 (суть алгоритма корректировки прогнозов разработчиков)

Level of difficultyMedium
Reading time5 min
Views3.8K

Раз в несколько лет возвращаюсь к задаче создания алгоритма для наиболее вероятного прогноза какого-либо события на основании ошибок предыдущих прогнозов. В этот раз попробую обойтись минимумом текста (ссылка на демо в конце).

Ссылка на оригинал статьи с объяснением принципа Доказательного Планирования (в оригинале Evidence Based Scheduling) - советую ознакомиться, чтоб быть в контексте: Joel Spolsky Evidence Based Scheduling / Перевод на русский

Для меня лично эта задача имеет небольшую историю:

  • Версия 1.0 - При желании, можно ознакомиться с первым вариантом увлекательного процесса поиска истины

  • Версия 2.0 [Вы здесь]

😠 Версия 1.0: Первый блин в коме (2019)

Как я видел решение этой задачи 5 лет назад (здесь очевидная ошибка): Берем самый худший вариант из предыдущего опыта и проецируем на текущую задачу - это и будет мой прогноз для Продукт Менеджера как наиболее худший сценарий.

🚀 Версия 2.0: Кажется, это успех (2024)

К примеру, у разработчика (исполнителя) есть несколько решенных задач с параметрами:

  1. Дата начала выполнения задачи (start)

  2. Дата его оценки финиша (estimation)

  3. Дата реального финиша (finish)

Итак, добавлена новая задача, получен estimation от разраба. Теперь вопрос - насколько он ошибся в этот раз?

🧐 Теперь поговорим про алгоритм определения наиболее вероятного сценария: Думаю, всем очевидно, что брать скорость "среднюю по больнице" - это неточно. Поэтому я предлагаю следующую логику: Человек работает, как правило (плюс-минус), с одной комфортной для него скоростью - алгоритм должен ее "ощутить". Как именно: Если по имеющимся результатам для анализа среди возможных вариантов скоростей его работы встречаются два с минимальным отклонением (Δ) - это повод искать ещё варианты с примерно таким же отклонением (но чуть больше на константу погрешности). В итоге, найденные варианты образуют "скопления", среднее (или медианное - это уже детали) значение которых можно учитывать как наиболее вероятное. Поправьте в комментариях, если я неправ.

// Код чисто для понимания,
// на императивщину не смотрите,
// вариант на ООП более многословен, а здесь нужна краткость

// NOTE: 1. Отсортированный список скоростей выполнения задач
const sortedSpeeds: {
  v: number;
}[] = speeds.sort((e1, e2) => e1.v - e2.v)

// NOTE: 2. Список отклонений между этими скоростями
const deltas: {
  speed: number | null;
  delta: number | null;
  prev: number | null;
  next: number | null;
  isSensed: boolean; // Это тот самый показатель "чувствительности"
}[] = []
let minDelta = 1000000
let maxDelta = 0
  
for (let i = 0, max = sortedSpeeds.length; i < max; i++) {
  const prevValue = !!sortedSpeeds[i - 1]
    ? sortedSpeeds[i - 1]
    : null
  const nextValue = !!sortedSpeeds[i + 1]
    ? sortedSpeeds[i + 1]
    : null
  const currentValue = sortedSpeeds[i]
  const delta = typeof prevValue?.v === 'number'
    ? currentValue.v - (prevValue.v)
    : null
  deltas.push({
    speed: sortedSpeeds[i].v,
    delta,
    next: nextValue?.v || null,
    prev: prevValue?.v || null,
    isSensed: false, // By default
  })

  if (typeof delta === 'number') {
    if (minDelta >= delta) minDelta = delta
    if (maxDelta <= delta) maxDelta = delta
  }
}

// NOTE: 3. Оставим только скорости с минимальным отклонением друг от друга
// Коэфф sensibility нужен для большего охвата задач, когда их немного (я беру 4)
// По мере роста задач коэфф. sensibility можно уменьшать до значения 1.5-2
const sensed: {
  counter: number;
  speedValues: number[];
  averageSpeed: number;
} = {
  counter: 0,
  speedValues: [],
  averageSpeed: 0,
}
for (let i = 0, max = deltas.length; i< max; i++) {
  if ((deltas[i].delta as number) <= sensibility * minDelta) {
    deltas[i].isSensed = true
    if (typeof deltas[i].speed === 'number') {
      sensed.counter += 1
      sensed.speedValues.push((deltas[i].speed as number))
    }
  }
  else
    deltas[i].isSensed = false
}

// NOTE: 4. Все! Теперь наиболее вероятная дата финиша
// может быть расчитана в соответствии с наиболее вероятной скоростью:
sensed.averageSpeed = getArithmeticalMean(sensed.speedValues)
// Этот момент AI предложила заменить на расчет медианы
// этих скоростей - на проде так и работает сейчас

👉 Попробовать живьем

Примерно так выглядит прогресс текущей задачи: прогрессбары трёх сценариев - анонсированный, ощущаемый и худший
Примерно так выглядит прогресс текущей задачи: прогрессбары трёх сценариев - анонсированный, ощущаемый и худший

Где тут Теория вероятностей? [спросите Вы]

Существует понятие Функция распределения вероятностей. Закон распределения вероятностей получил свое название из-за его способности разбросать вероятность между значениями случайной величины чтобы в итоге она составила единицу.

Используя библиотеку react-google-charts, я получил (в грубом виде) кривую (в данном случае она прямая, но это не важно) распределения вероятностей, основанную на данных предыдущих опытов:

Три задачи были завершены - на графике возможные сценарии для активной задачи (ось x - это время, чуть позже заменю фото)...
Три задачи были завершены - на графике возможные сценарии для активной задачи (ось x - это время, чуть позже заменю фото)...
...две из них (синие на графике) имеют наименьшую разницу в скорости продвижения к финишу - а значит, их значения ближе к комфортной.
...две из них (синие на графике) имеют наименьшую разницу в скорости продвижения к финишу - а значит, их значения ближе к комфортной.
Задачи, выполненные со скоростью, которую я называю комфортной для конкретного исполнителя будут стремиться к позиции X - эта позиция в которой вероятность завершения любой задачи ровно 50% с комфортной скоростью, а разница между скоростями близкими к комфортной будет стремиться к нулю.
Задачи, выполненные со скоростью, которую я называю комфортной для конкретного исполнителя будут стремиться к позиции X - эта позиция в которой вероятность завершения любой задачи ровно 50% с комфортной скоростью, а разница между скоростями близкими к комфортной будет стремиться к нулю.

Итак, мой вывод в двух тезисах:

  1. Скорость с которой обычно работает конкретный человек с задачами, сложность которых он может для себя определить - можно считать наиболее вероятной (она же идеально комфортная для данного исполнителя)

  2. Приблизиться к ней можно, сделав N опытов, уменьшая погрешность с каждым новым опытом (этот тезис учитывает личный прогресс разработчика)

Надо заметить, комфортная скорость конкретного человека может разниться в зависимости от сложности задачи - простые планировать легко, средние чуть сложнее и т.д. - именно по этой причине нужно не забывать уточнять грейд задачи на старте и на финише (в процессе возможна переоценка с соответствующим пересчетом вероятностей).

В споре рождается истина. Спорьте со мной в комментах ) Здесь периодически пишу про обновления и новые фичи.

Есть пачка обновлений 2025.03

  • Теперь задачам можно присвоить "родителя". Таким образом любая задача может стать проектом и делать суммарный расчет потраченного времени по "задачам-детям";

  • Резюме по выполненной задаче;

  • Теперь "ощущаемый" прогноз по задаче может быть пересчитан в экспериментальном режиме как "Если бы она перешла на следующий грейд сложности..." (см. кликабельные морды в открывшемся сайдбаре); Лично мне эта функция нужна чтоб прикинуть дату релиза сложных задач в рамках телефонного разговора (при достаточном количестве решённых задач аналогичной сложности);

  • Business Time - можно извлечь только рабочее время (планирую добавить json-редактор для настроек конфигурации пользовательского рабочего времени);

Можно прикинуть, сколько бизнес-часов будет эквивалентно скорректированному запланированному календарному промежутку времени (по "ощущениям алгоритма"). "5WD" - это пятидневка с часовым перерывом на обед, остальные варианты - пока экспериментальные
Можно прикинуть, сколько бизнес-часов будет эквивалентно скорректированному запланированному календарному промежутку времени (по "ощущениям алгоритма"). "5WD" - это пятидневка с часовым перерывом на обед, остальные варианты - пока экспериментальные
Резюме по выполненной задаче: Сколько официального времени заявлено и потрачено
Резюме по выполненной задаче: Сколько официального времени заявлено и потрачено
Тот случай, когда планировал закончить в 21-00, а скорее всего получится в час ночи )
Тот случай, когда планировал закончить в 21-00, а скорее всего получится в час ночи )
Only registered users can participate in poll. Log in, please.
Этот подход правильный?
0% Да0
100% Нет (аргументирую в комментарии)1
1 user voted. 3 users abstained.
Tags:
Hubs:
Total votes 5: ↑3 and ↓2+3
Comments5

Articles