新型コロナウイルス感染症対策のため、各社、苦労されているでしょう。 人との接触を8割減らすように、との目標が示されました。とはいえ、仕事を8割減するわけにはいかないと思います。 できるだけ人と会わず、今までと同じ生産性を保つにはどうすればいいか考えてみます。
ナップサック問題
今回、そのために使うのが、ナップサック問題です。ナップサック問題とは「限られた大きさのナップサックに、できるだけ自分にとって価値の高いものを詰めたい」といった問題です。ここでは、
- 生産性を減らすことなく
- できるだけ人と会う人数を減らしたい
という問題にしてみます。けれど、あまり人と会わずにできる仕事を詰め込みすぎると過労になってしまうので、あくまで生産性については「今までと同じくらい働くことを目指す」とします。このようにすることで過労を防げるだけでなく、量子アニーリングで問題を解く場合に厄介な「不等式制約」をなくすことができ、計算が安定します。
今までの仕事
従来の働き方をピックアップしてみます。
(仕事内容(文字列), 接触人数(数字), 生産性(数字))
の形で書き出してみましょう。
works = [
('定例ミーティング', 6, 4),
('xxプロジェクトの打ち合わせ', 7, 4),
('打ち合わせのための出張', 25, 6),
('勉強会の開催', 50, 10),
('普段の開発', 4, 10),
('お客さん訪問', 8, 6),
]
上に書いたものが、とある1日の仕事の流れとしましょう。普段は、一体、何人と接触し、どれくらいの生産性を上げているでしょうか。
productivity = sum(map(lambda w: w[2], works))
persons = sum(map(lambda w: w[1], works))
print('接触人数:', persons)
print(('👦👧🧑👨'*persons)[:persons])
print('生産性:', productivity)
print(('📧💰📈📝'*productivity)[:productivity])
接触人数: 100 👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨👦👧🧑👨
生産性: 40 📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝
さて、ここから、人と触れ合わない働き方に、どのようなものがあるか考えてみます。
works += [
('zoomを使ったオンラインミーティング', 0, 3),
('WebExを使ったオンラインミーティング', 0, 3),
('Google Hangoutを使ったオンラインミーティング', 0, 3),
('Skypeを使ったオンラインミーティング', 0, 3),
('Slack等を活用した社内情報共有', 0, 4),
('YouTubeを使ったオンライン勉強会の開催', 1, 9),
('普段は後回しになっていた業務効率化や戦略の検討をする', 0, 2),
('在宅勤務を一部取り入れる', 2, 6),
('ネットやメールでの営業', 0, 5),
]
さて、最適化をしていきます。
生産性を保ったまま、できるだけ人と会わないような働き方を作っていきます。
from pyqubo import Array, Constraint, solve_qubo
q = Array.create('q', shape=len(works), vartype='BINARY')
Hconstraint = Constraint((sum(w[2] * q_ for w, q_ in zip(works, q)) - productivity)**2, 'productivity')
Hobjective = sum(w[1] * q_ for w, q_ in zip(works, q))
H = (Hobjective + 2*Hconstraint)*0.1
model = H.compile()
qubo, offset = model.to_qubo()
import dimod
from dwave.system.samplers import LeapHybridSampler
bqm = dimod.BQM.from_qubo(qubo)
#solution = solve_qubo(qubo)
import re
token = "token here"
while 1:
sampler = LeapHybridSampler(token=token)
result = sampler.sample(bqm)
solution = result.first.sample
solution = dict(sorted(solution.items(), key=lambda kv: int(re.search('[0-9]+', kv[0])[0])))
new_works = [w for v, w in zip(solution.values(), works) if v]
new_productivity = sum(map(lambda w: w[2], new_works))
new_persons = sum(map(lambda w: w[1], new_works))
if productivity <= new_productivity < productivity + 5 and new_persons <= persons * 0.2:
break
new_works
[('普段の開発', 4, 10),
('zoomを使ったオンラインミーティング', 0, 3),
('WebExを使ったオンラインミーティング', 0, 3),
('Google Hangoutを使ったオンラインミーティング', 0, 3),
('Skypeを使ったオンラインミーティング', 0, 3),
('Slack等を活用した社内情報共有', 0, 4),
('YouTubeを使ったオンライン勉強会の開催', 1, 9),
('ネットやメールでの営業', 0, 5)]
print('接触人数:', new_persons)
print(('👦👧🧑👨'*new_persons)[:new_persons])
print('生産性:', new_productivity)
print(('📧💰📈📝'*new_productivity)[:new_productivity])
接触人数: 5
👦👧🧑👨👦
生産性: 40
📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝📧💰📈📝
生産性そのままに、接触人数を大きく減らすことができました。
blueqatでは、元々リモートワークは取り入れていましたが、それでも、実際に人と会ってのミーティングなどはありました。最近ではオンラインミーティングがほとんどになりました。 業種によってはリモートワークが難しい場合もありますが、労働も、不要不急の他人との接触を避けつつ生産性を保っていければと思います。