আর্জেন্টিনা বনাম

আর্জেন্টিনা জাতীয় ফুটবল দল

Meta AI Open-Sources Rebalancer: A C++ Assignment Solver That Runs About 40 Million Placement Problems a Day

Meta AI Open-Sources Rebalancer: A C++ Assignment Solver That Runs About 40 Million Placement Problems a Day


Meta has open-sourced Rebalancer, a C++ library with a Python interface for solving assignment problems. It decides which objects go into which bins under constraints and objectives. According to the Engineering at Meta’s post, Rebalancer has handled resource allocation across Meta for over 9 years. The release ships under Apache 2.0 with documentation, a PyPI package and a debugging UI called Rebalancer Explorer.

Is it deployable? Yes. pip install rebalancer installs v1.0.4 for Python 3.12+, with prebuilt wheels for Linux x86-64 and macOS 14+ ARM64. .deb, .rpm and Homebrew packages also exist. PyPI still classifies the project as Alpha.

What Problem Does Rebalancer Solve?

Assignment problems show up across Meta’s stack. Racks go into datacenters, servers go to services, tasks go to servers, and user traffic goes to datacenters. Meta names 2 blockers: usability and scalability. Engineers struggle to turn policies into precise formulas, and many problems are NP-hard and too large for commercial solvers.

Rebalancer’s answer is to separate how a problem is specified from how it is solved. The design is detailed in the OSDI 2024 paper, Optimizing Resource Allocation in Hyperscale Datacenters.

How the Specification Layer Works

The spec language has 3 layers:

  • Modeling constructs: dimensions (attributes such as CPU or storage), partitions (groups of objects), scopes (groups of bins) and utilization.
  • Expression API: aggregate utilization with SUM or MAX, or transform it with operations such as SQUARE.
  • Spec API: dozens of predefined objectives and constraints, listed in the docs.

Meta’s example models tasks as objects, servers as bins and racks as a scope. A CapacitySpec caps CPU and storage per server. A GroupCountSpec keeps 1 job type per rack. A BalanceSpec balances each server’s utilization across both dimensions.

One Expression Graph, Two Solvers

Rebalancer compiles the spec into a directed acyclic expression graph. Leaf nodes hold utilization values; aggregation and transformation nodes sit above them. Users supply an initial assignment and a stopping condition. Constraints that the initial assignment already violates become high-priority goals.

Optimal solver: The graph is translated into a mixed integer program for FICO Xpress, Gurobi or HiGHS. Variable aggregation and symmetry breaking shrink models. The worst-case model size is still O(objects × bins). Meta’s largest problems are too big for any MIP solver.

Local search: This solver works directly on the expression graph. It explores moves of objects to other bins, with a worst-case neighborhood of O(objects + bins). It then applies the best candidate that breaks no constraint. Evaluation is parallelized, reaching millions of evaluations per second, and the search space is pruned.

Meta uses local search for almost all large problems and MIP for small to mid-size ones, often prototyping with MIP first.

Production Numbers at Meta

  • About 40 million assignment problems solved per day, across 30+ unique formulations.
  • P99 solve time of 12 seconds on 265k objects and 3.2k bins.
  • Problems above 1 million objects and 5k bins average 171 seconds, across 3.4k+ runs.

Best Use Cases for Rebalancer

  1. Placing shards, tasks or containers on a cluster: Assign work to servers under CPU and memory caps while spreading replicas across racks. Meta’s Shard Manager and RAS run this pattern.
  2. Balancing traffic and workloads across regions: Route user traffic or jobs to datacenters, trading latency against load. Taiji does this for edge traffic, and Meta balances ML training by priority.
  3. Operational assignment outside infrastructure: Map support tickets to engineers, meetings to rooms or desks to people under capacity rules. Meta has done all 3.

Debugging With Rebalancer Explorer

Modelers at Meta spent most of their time debugging solver behavior. Rebalancer Explorer is a Dockerized web UI built for this. It shows binding constraints, relaxation effects, and why an object landed in a bin.

Interactive Explainer

<iframe id="mtp-rebal-frame" title="Meta Rebalancer interactive explainer" loading="lazy" style="width:100%;height:600px;border:0;display:block;background:transparent;" scrolling="no" srcdoc="<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<style>
html,body{margin:0!important;padding:0!important;background:transparent!important;}
#mtp-rebal{–blue:#0866FF;–blue2:#4C9BFF;–cyan:#38D6FF;–bg:#070D1A;–panel:#0E1729;–line:#1E2B45;–text:#E8EEF9;–muted:#93A3BF;–red:#FF5A6E;–ok:#2BD99F;
max-width:880px;margin:0 auto;background:var(–bg)!important;color:var(–text)!important;border:1px solid var(–line)!important;border-radius:16px;font-family:Inter,system-ui,-apple-system,Segoe UI,Roboto,sans-serif;overflow:hidden;box-sizing:border-box;}
#mtp-rebal *{box-sizing:border-box;}
#mtp-rebal .hd{padding:18px 20px 10px;background:linear-gradient(135deg,rgba(8,102,255,.28),rgba(8,102,255,0) 60%)!important;border-bottom:1px solid var(–line);}
#mtp-rebal .eyebrow{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(–blue2)!important;font-weight:700;}
#mtp-rebal h3{margin:4px 0 4px;font-size:20px;line-height:1.25;color:#fff!important;font-weight:800;}
#mtp-rebal .sub{margin:0;color:var(–muted)!important;font-size:13px;line-height:1.5;}
#mtp-rebal .tabs{display:flex;gap:6px;padding:10px 14px;border-bottom:1px solid var(–line);overflow-x:auto;}
#mtp-rebal .tab{flex:0 0 auto;background:transparent!important;color:var(–muted)!important;border:1px solid var(–line)!important;border-radius:999px;padding:7px 13px;font-size:12.5px;font-weight:600;cursor:pointer;transition:all .2s;}
#mtp-rebal .tab:hover{color:#fff!important;border-color:var(–blue2)!important;}
#mtp-rebal .tab.on{background:var(–blue)!important;color:#fff!important;border-color:var(–blue)!important;box-shadow:0 0 18px rgba(8,102,255,.45);}
#mtp-rebal .pane{display:none;padding:16px 18px 18px;animation:mtpfade .35s ease;}
#mtp-rebal .pane.on{display:block;}
@keyframes mtpfade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
#mtp-rebal .note{font-size:12.5px;color:var(–muted)!important;line-height:1.55;margin:0 0 12px;}
#mtp-rebal .note b{color:var(–text)!important;}
#mtp-rebal .btns{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 12px;}
#mtp-rebal button.b{background:var(–panel)!important;color:var(–text)!important;border:1px solid var(–line)!important;border-radius:9px;padding:8px 13px;font-size:12.5px;font-weight:600;cursor:pointer;transition:all .15s;}
#mtp-rebal button.b:hover{border-color:var(–blue2)!important;}
#mtp-rebal button.b.pri{background:var(–blue)!important;border-color:var(–blue)!important;color:#fff!important;}
#mtp-rebal button.b:disabled{opacity:.45;cursor:not-allowed;}
#mtp-rebal .stats{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:12px;}
#mtp-rebal .st{background:var(–panel)!important;border:1px solid var(–line)!important;border-radius:10px;padding:8px 10px;}
#mtp-rebal .st .k{font-size:10.5px;color:var(–muted)!important;text-transform:uppercase;letter-spacing:.08em;}
#mtp-rebal .st .v{font-size:18px;font-weight:800;font-variant-numeric:tabular-nums;color:#fff!important;transition:color .3s;}
#mtp-rebal .st .v.bad{color:var(–red)!important;}
#mtp-rebal .st .v.good{color:var(–ok)!important;}
#mtp-rebal .racks{display:grid;grid-template-columns:1fr 1fr;gap:10px;}
#mtp-rebal .rack{border:1px dashed #2A3B5E!important;border-radius:12px;padding:8px;}
#mtp-rebal .rack .rl{font-size:10.5px;color:var(–muted)!important;letter-spacing:.1em;text-transform:uppercase;margin:0 0 6px 2px;}
#mtp-rebal .srvs{display:grid;grid-template-columns:1fr 1fr;gap:8px;}
#mtp-rebal .srv{background:var(–panel)!important;border:1px solid var(–line)!important;border-radius:10px;padding:8px;min-height:118px;display:flex;flex-direction:column;transition:border-color .3s,box-shadow .3s;}
#mtp-rebal .srv.over{border-color:var(–red)!important;box-shadow:0 0 14px rgba(255,90,110,.35);}
#mtp-rebal .srv .sn{display:flex;justify-content:space-between;font-size:12px;font-weight:700;margin-bottom:6px;color:var(–text)!important;}
#mtp-rebal .srv .sn span{color:var(–muted)!important;font-weight:600;font-variant-numeric:tabular-nums;}
#mtp-rebal .bar{position:relative;height:7px;background:#16223A!important;border-radius:6px;margin-bottom:8px;overflow:visible;}
#mtp-rebal .bar i{position:absolute;left:0;top:0;bottom:0;border-radius:6px;background:linear-gradient(90deg,var(–blue),var(–cyan))!important;transition:width .45s ease;}
#mtp-rebal .srv.over .bar i{background:linear-gradient(90deg,#FF8A5A,var(–red))!important;}
#mtp-rebal .bar u{position:absolute;top:-3px;bottom:-3px;width:2px;background:#fff!important;opacity:.7;text-decoration:none;}
#mtp-rebal .chips{display:flex;flex-wrap:wrap;gap:5px;align-content:flex-start;}
#mtp-rebal .chip{display:inline-flex;align-items:center;justify-content:center;height:26px;border-radius:7px;font-size:11px;font-weight:700;color:#fff!important;background:#1B3D7A!important;border:1px solid #2F5FB8!important;font-variant-numeric:tabular-nums;will-change:transform;}
#mtp-rebal .chip.hot{background:var(–blue)!important;border-color:var(–cyan)!important;box-shadow:0 0 14px rgba(56,214,255,.7);}
#mtp-rebal .spark{margin-top:12px;background:var(–panel)!important;border:1px solid var(–line)!important;border-radius:10px;padding:8px 10px;}
#mtp-rebal .spark .k{font-size:10.5px;color:var(–muted)!important;text-transform:uppercase;letter-spacing:.08em;}
#mtp-rebal .log{font-size:12px;color:var(–cyan)!important;min-height:18px;margin:8px 0 0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;}
#mtp-rebal svg text{font-family:Inter,system-ui,sans-serif;}
#mtp-rebal .gwrap{background:var(–panel)!important;border:1px solid var(–line)!important;border-radius:12px;padding:6px;}
#mtp-rebal .edge{fill:none;stroke:#24365A;stroke-width:2;transition:stroke .3s;}
#mtp-rebal .edge.live{stroke:var(–cyan);stroke-dasharray:6 6;animation:mtpflow .6s linear infinite;}
@keyframes mtpflow{to{stroke-dashoffset:-24}}
#mtp-rebal .node rect{fill:#122039;stroke:#2A3B5E;stroke-width:1.5;transition:all .3s;}
#mtp-rebal .node.live rect{fill:#0B3B8F;stroke:var(–cyan);filter:drop-shadow(0 0 6px rgba(56,214,255,.8));}
#mtp-rebal .node text{fill:#E8EEF9;font-size:12px;font-weight:700;text-anchor:middle;}
#mtp-rebal .node text.val{fill:#93A3BF;font-size:11px;font-weight:600;}
#mtp-rebal .node.live text.val{fill:#38D6FF;}
#mtp-rebal .sl{margin:0 0 12px;}
#mtp-rebal .sl label{display:flex;justify-content:space-between;font-size:12.5px;color:var(–muted)!important;margin-bottom:4px;}
#mtp-rebal .sl label b{color:#fff!important;font-variant-numeric:tabular-nums;}
#mtp-rebal input[type=range]{width:100%;accent-color:#0866FF;}
#mtp-rebal .cmp{display:grid;gap:10px;margin:6px 0 12px;}
#mtp-rebal .cmp .row .t{display:flex;justify-content:space-between;font-size:12px;margin-bottom:4px;color:var(–text)!important;}
#mtp-rebal .cmp .row .t span{color:var(–muted)!important;font-variant-numeric:tabular-nums;}
#mtp-rebal .track{height:12px;border-radius:7px;background:#16223A!important;overflow:hidden;}
#mtp-rebal .track i{display:block;height:100%;border-radius:7px;transition:width .5s cubic-bezier(.2,.8,.2,1);}
#mtp-rebal .verdict{border-radius:12px;padding:12px 14px;border:1px solid var(–blue)!important;background:rgba(8,102,255,.12)!important;font-size:13.5px;line-height:1.5;transition:all .3s;}
#mtp-rebal .verdict b{color:#fff!important;}
#mtp-rebal .grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;}
#mtp-rebal .card{background:var(–panel)!important;border:1px solid var(–line)!important;border-radius:12px;padding:12px;opacity:0;transform:translateY(10px);transition:all .5s ease;}
#mtp-rebal .card.in{opacity:1;transform:none;}
#mtp-rebal .card .n{font-size:26px;font-weight:800;color:#fff!important;font-variant-numeric:tabular-nums;}
#mtp-rebal .card .n em{font-style:normal;color:var(–blue2)!important;}
#mtp-rebal .card .d{font-size:12px;color:var(–muted)!important;line-height:1.45;margin-top:2px;}
#mtp-rebal .pills{display:flex;flex-wrap:wrap;gap:6px;margin-top:12px;}
#mtp-rebal .pill{font-size:11.5px;padding:5px 10px;border-radius:999px;border:1px solid #2A3B5E!important;color:var(–text)!important;background:#0F1C33!important;}
#mtp-rebal .ft{display:flex;justify-content:space-between;flex-wrap:wrap;gap:6px;padding:10px 18px;border-top:1px solid var(–line);font-size:11px;color:var(–muted)!important;}
#mtp-rebal .ft a{color:var(–blue2)!important;text-decoration:none;}
#mtp-rebal .ft .brand{color:#76B900!important;font-weight:700;}
@media (max-width:640px){
#mtp-rebal .stats{grid-template-columns:repeat(2,1fr);}
#mtp-rebal .racks{grid-template-columns:1fr;}
#mtp-rebal .grid{grid-template-columns:1fr 1fr;}
#mtp-rebal h3{font-size:17px;}
#mtp-rebal .pane{padding:14px 12px;}
#mtp-rebal .srv{min-height:100px;}
}
</style></head><body>

<div id="mtp-rebal">
<div class="hd">
<div class="eyebrow">Interactive explainer · Meta Rebalancer</div>
<h3>How Rebalancer puts objects into bins</h3>
<p class="sub">Play with a small task-placement problem, watch the expression graph update, and see when Meta picks local search over MIP.</p>
</div>
<div class="tabs" role="tablist">
<button class="tab on" data-p="0">1 · Local search</button>
<button class="tab" data-p="1">2 · Expression graph</button>
<button class="tab" data-p="2">3 · Which solver?</button>
<button class="tab" data-p="3">4 · At Meta scale</button>
</div>

<!– PANE 1 –>
<div class="pane on" id="mtpP0">
<p class="note">12 <b>tasks</b> (objects, number = CPU units) go onto 4 <b>servers</b> (bins) in 2 <b>racks</b> (scopes). Each server has a <b>CapacitySpec</b> of 16 CPU. The goal is a <b>BalanceSpec</b>: minimize the sum of squared utilization. Each step evaluates every single move and swap, then applies the best one.</p>
<div class="btns">
<button class="b pri" id="mtpRun">Meta AI Open-Sources Rebalancer: A C++ Assignment Solver That Runs About 40 Million Placement Problems a Day Run local search</button>
<button class="b" id="mtpStep">Step once</button>
<button class="b" id="mtpShuf">Random bad start</button>
<button class="b" id="mtpReset">Reset</button>
</div>
<div class="stats">
<div class="st"><div class="k">Step</div><div class="v" id="mtpS">0</div></div>
<div class="st"><div class="k">Moves evaluated</div><div class="v" id="mtpE">0</div></div>
<div class="st"><div class="k">Capacity overflow</div><div class="v" id="mtpV">0</div></div>
<div class="st"><div class="k">Balance objective</div><div class="v" id="mtpO">0</div></div>
</div>
<div class="racks" id="mtpRacks"></div>
<div class="spark"><div class="k">Objective over steps (lower is better, ideal = 324)</div>
<svg id="mtpSpark" viewBox="0 0 800 70" width="100%" height="70" preserveAspectRatio="none"></svg>
</div>
<div class="log" id="mtpLog">Server S1 starts 4 CPU over capacity. Press Run.</div>
</div>

<!– PANE 2 –>
<div class="pane" id="mtpP1">
<p class="note">Rebalancer compiles specs into a <b>directed acyclic expression graph</b>. Leaves hold each server’s utilization; SQUARE, SUM and MAX nodes sit above them. When one task moves, only the leaves it touches and their ancestors need new values. The graph uses the same live state as tab 1.</p>
<div class="btns">
<button class="b pri" id="mtpGMove">Move a random task</button>
<button class="b" id="mtpGBest">Apply best local-search move</button>
</div>
<div class="gwrap"><svg id="mtpGraph" viewBox="0 0 820 300" width="100%"></svg></div>
<div class="log" id="mtpGLog">Press a button to move a task.</div>
</div>

<!– PANE 3 –>
<div class="pane" id="mtpP2">
<p class="note">The MIP model needs about one binary variable per object per bin, so it grows as <b>O(objects × bins)</b>. A local-search neighborhood grows as <b>O(objects + bins)</b>. Drag the sliders or load Meta’s published sizes.</p>
<div class="btns">
<button class="b" data-o="500" data-bn="20">Small: 500 × 20</button>
<button class="b" data-o="265000" data-bn="3200">Meta P99: 265k × 3.2k</button>
<button class="b" data-o="1000000" data-bn="5000">Meta XL: 1M × 5k</button>
</div>
<div class="sl"><label>Objects <b id="mtpOv"></b></label><input type="range" id="mtpOs" min="1" max="6.3" step="0.01" value="2.7"></div>
<div class="sl"><label>Bins <b id="mtpBv"></b></label><input type="range" id="mtpBs" min="0.3" max="4" step="0.01" value="1.3"></div>
<div class="cmp">
<div class="row"><div class="t">MIP binary variables, worst case <span id="mtpMv"></span></div><div class="track"><i id="mtpMb" style="background:linear-gradient(90deg,#FF8A5A,#FF5A6E)"></i></div></div>
<div class="row"><div class="t">Local-search neighborhood, worst case <span id="mtpLv"></span></div><div class="track"><i id="mtpLb" style="background:linear-gradient(90deg,#0866FF,#38D6FF)"></i></div></div>
</div>
<div class="verdict" id="mtpVerdict"></div>
<p class="note" style="margin-top:10px">Bars use a log scale. Size bands in the verdict are illustrative; Meta’s stated rule is local search for almost all large problems and MIP for small to mid-size ones.</p>
</div>

<!– PANE 4 –>
<div class="pane" id="mtpP3">
<p class="note">Production figures published by Meta for Rebalancer (Engineering at Meta, Sep 21 2026).</p>
<div class="grid" id="mtpCards">
<div class="card"><div class="n"><span data-c="40">0</span><em>M</em></div><div class="d">assignment problems solved per day</div></div>
<div class="card"><div class="n"><span data-c="30">0</span><em>+</em></div><div class="d">unique problem formulations</div></div>
<div class="card"><div class="n"><span data-c="12">0</span><em>s</em></div><div class="d">P99 solve time on 265k objects and 3.2k bins</div></div>
<div class="card"><div class="n"><span data-c="171">0</span><em>s</em></div><div class="d">average solve for 1M+ objects and 5k bins</div></div>
<div class="card"><div class="n"><span data-c="3.4" data-d="1">0</span><em>k+</em></div><div class="d">runs at that 1M+ object scale</div></div>
<div class="card"><div class="n"><span data-c="9">0</span><em>+ yrs</em></div><div class="d">in use across Meta before open-sourcing</div></div>
</div>
<div class="pills">
<span class="pill">Shard Manager: shards → servers</span>
<span class="pill">RAS: servers → services</span>
<span class="pill">Taiji: edge traffic → datacenters</span>
<span class="pill">Serverless function grouping</span>
<span class="pill">ML training balancing</span>
<span class="pill">Meetings → rooms</span>
</div>
</div>

<div class="ft">
<span>Sources: <a href=" target="_blank" rel="noopener">Engineering at Meta</a> · <a href=" target="_blank" rel="noopener">GitHub</a> · Tabs 1 to 3 are simplified simulations</span>
<span class="brand">Built by Marktechpost</span>
</div>
</div>

<script>
(function(){
var R=document.getElementById(‘mtp-rebal’);
function postH(){try{parent.postMessage({mtpRebalH:R.offsetHeight+40},’*’);}catch(e){}}
var SIZES=[6,5,4,4,3,3,3,2,2,2,1,1], CAP=16, NS=4;
var START=[0,0,0,0,1,1,1,2,2,2,0,1];
var asg=START.slice(), step=0, evals=0, hist=[], timer=null, hot=-1;

function util(a){var u=[0,0,0,0];for(var i=0;i<a.length;i++)u[a[i]]+=SIZES[i];return u;}
function score(a){var u=util(a),v=0,o=0;for(var s=0;s<NS;s++){v+=Math.max(0,u[s]-CAP);o+=u[s]*u[s];}return [v,o];}
function better(x,y){return x[0]<y[0]||(x[0]===y[0]&&x[1]<y[1]);}

function bestMove(){
var cur=score(asg),best=null,bs=cur,n=0;
for(var i=0;i<asg.length;i++){for(var s=0;s<NS;s++){if(s===asg[i])continue;var b=asg.slice();b[i]=s;n++;var sc=score(b);if(better(sc,bs)){bs=sc;best={a:b,txt:’move t’+(i+1)+’ S’+(asg[i]+1)+’ → S’+(s+1),ids:[i]};}}}
for(var i2=0;i2<asg.length;i2++)for(var j=i2+1;j<asg.length;j++){if(asg[i2]===asg[j])continue;var c=asg.slice();c[i2]=asg[j];c[j]=asg[i2];n++;var sc2=score(c);if(better(sc2,bs)){bs=sc2;best={a:c,txt:’swap t’+(i2+1)+’ ↔ t’+(j+1),ids:[i2,j]};}}
return {best:best,n:n,sc:bs};
}

var racksEl=document.getElementById(‘mtpRacks’);
function rects(){var m={};racksEl.querySelectorAll(‘.chip’).forEach(function(c){m[c.dataset.id]=c.getBoundingClientRect();});return m;}
function render(ids){
var before=rects(),u=util(asg),h=””;
for(var r=0;r<2;r++){h+='<div class="rack"><div class="rl">Rack ‘+(r?’B’:’A’)+’ (scope)</div><div class="srvs">’;
for(var s=r*2;s<r*2+2;s++){var over=u[s]>CAP;
h+='<div class="srv’+(over?’ over’:”)+’"><div class="sn">S’+(s+1)+'<span>’+u[s]+’ / ‘+CAP+’ CPU</span></div><div class="bar"><i style="width:’+Math.min(100,u[s]/24*100)+’%"></i><u style="left:’+(CAP/24*100)+’%"></u></div><div class="chips">’;
for(var i=0;i<asg.length;i++)if(asg[i]===s){h+='<div class="chip’+(ids&&ids.indexOf(i)>-1?’ hot’:”)+’" data-id="’+i+’" style="width:’+(30+SIZES[i]*8)+’px">t’+(i+1)+’·’+SIZES[i]+'</div>’;}
h+='</div></div>’;}
h+='</div></div>’;}
racksEl.innerHTML=h;
racksEl.querySelectorAll(‘.chip’).forEach(function(c){var b=before[c.dataset.id];if(!b)return;var a=c.getBoundingClientRect(),dx=b.left-a.left,dy=b.top-a.top;if(dx||dy){c.style.transition=’none’;c.style.transform=’translate(‘+dx+’px,’+dy+’px)’;requestAnimationFrame(function(){requestAnimationFrame(function(){c.style.transition=’transform .55s cubic-bezier(.2,.8,.2,1)’;c.style.transform=”;});});}});
var sc=score(asg);
document.getElementById(‘mtpS’).textContent=step;
document.getElementById(‘mtpE’).textContent=evals;
var V=document.getElementById(‘mtpV’);V.textContent=sc[0];V.className=”v “+(sc[0]?’bad’:’good’);
var O=document.getElementById(‘mtpO’);O.textContent=sc[1];O.className=”v”+(sc[1]===324?’ good’:”);
spark();drawGraph(null);postH();
}
function spark(){
var s=document.getElementById(‘mtpSpark’),pts=hist.length?hist:[score(asg)[1]];
var mx=Math.max.apply(null,pts.concat([600])),mn=300,n=Math.max(pts.length-1,12);
var p=pts.map(function(v,i){return (i/n*790+5)+’,’+(65-(v-mn)/(mx-mn)*58);}).join(‘ ‘);
var ideal=65-(324-mn)/(mx-mn)*58;
s.innerHTML='<line x1="0" x2="800" y1="’+ideal+’" y2="’+ideal+’" stroke="#2BD99F" stroke-dasharray="4 4" opacity=".6"/><polyline points="’+p+’" fill="none" stroke="#38D6FF" stroke-width="2.5"/>’+pts.map(function(v,i){return ‘<circle cx="’+(i/n*790+5)+’" cy="’+(65-(v-mn)/(mx-mn)*58)+’" r="3.5" fill="#0866FF" stroke="#fff" stroke-width="1"/>’;}).join(”);
}
var logEl=document.getElementById(‘mtpLog’);
function doStep(){
var r=bestMove();evals+=r.n;
if(!r.best){stop();logEl.textContent=”Local optimum: no move or swap improves the score (“+evals+’ evaluations).’;render();return false;}
var old=asg;asg=r.best.a;step++;hist.push(score(asg)[1]);
var moved=r.best.ids;logEl.textContent=”Step “+step+’: ‘+r.best.txt+’ (checked ‘+r.n+’ candidates)’;
render(moved);drawGraph(diff(old,asg));return true;
}
function diff(a,b){var s={};for(var i=0;i<a.length;i++)if(a[i]!==b[i]){s[a[i]]=1;s[b[i]]=1;}return Object.keys(s).map(Number);}
function stop(){if(timer){clearInterval(timer);timer=null;}document.getElementById(‘mtpRun’).textContent=”Meta AI Open-Sources Rebalancer: A C++ Assignment Solver That Runs About 40 Million Placement Problems a Day Run local search”;}
document.getElementById(‘mtpRun’).onclick=function(){if(timer){stop();return;}this.textContent=”❚❚ Pause”;if(!doStep())return;timer=setInterval(function(){if(!doStep())stop();},900);};
document.getElementById(‘mtpStep’).onclick=function(){stop();doStep();};
function resetTo(a,msg){stop();asg=a;step=0;evals=0;hist=[score(asg)[1]];logEl.textContent=msg;render();}
document.getElementById(‘mtpReset’).onclick=function(){resetTo(START.slice(),’Server S1 starts 4 CPU over capacity. Press Run.’);};
document.getElementById(‘mtpShuf’).onclick=function(){var a=[];for(var i=0;i<12;i++)a.push(Math.random()<.55?Math.floor(Math.random()*2):Math.floor(Math.random()*4));resetTo(a,’New random start. Press Run.’);};

/* expression graph */
var G=document.getElementById(‘mtpGraph’),gLog=document.getElementById(‘mtpGLog’);
var LX=[110,300,490,680];
function drawGraph(live){
live=live||[];var u=util(asg),sc=score(asg),h=””;
function on(s){return live.indexOf(s)>-1;}
var any=live.length>0;
for(var s=0;s<4;s++){
h+='<path class="edge’+(on(s)?’ live’:”)+’" d="M’+LX[s]+’,232 L’+LX[s]+’,172"/>’;
h+='<path class="edge’+(on(s)?’ live’:”)+’" d="M’+LX[s]+’,138 C’+LX[s]+’,100 300,110 300,78"/>’;
h+='<path class="edge’+(on(s)?’ live’:”)+’" d="M’+(LX[s]+40)+’,233 C’+(LX[s]+60)+’,200 650,130 650,78"/>’;
}
h+='<path class="edge’+(any?’ live’:”)+’" d="M300,44 L300,22"/><path class="edge’+(any?’ live’:”)+’" d="M650,44 L650,22"/>’;
function node(x,y,w,label,val,l){return ‘<g class="node’+(l?’ live’:”)+’"><rect x="’+(x-w/2)+’" y="’+(y-17)+’" width="’+w+’" height="34" rx="8"/><text x="’+x+’" y="’+(y-2)+’">’+label+'</text><text class="val" x="’+x+’" y="’+(y+11)+’">’+val+'</text></g>’;}
for(var k=0;k<4;k++){h+=node(LX[k],250,96,’U(S’+(k+1)+’)’,’= ‘+u[k],on(k));h+=node(LX[k],155,96,’SQUARE’,’= ‘+u[k]*u[k],on(k));}
h+=node(300,61,120,’SUM’,’= ‘+sc[1],any);h+=node(650,61,120,’MAX’,’= ‘+Math.max.apply(null,u),any);
h+='<text x="300" y="14" fill="#4C9BFF" font-size="11" font-weight="700" text-anchor="middle">BalanceSpec objective</text>’;
h+='<text x="650" y="14" fill="’+(Math.max.apply(null,u)>CAP?’#FF5A6E’:’#2BD99F’)+’" font-size="11" font-weight="700" text-anchor="middle">CapacitySpec: MAX ≤ ‘+CAP+(Math.max.apply(null,u)>CAP?’ (violated)’:’ (ok)’)+'</text>’;
h+='<text x="410" y="292" fill="#93A3BF" font-size="11" text-anchor="middle">Leaves: utilization per server · nodes recomputed this move: ‘+(any?(live.length*2+2):0)+’ of 10</text>’;
G.innerHTML=h;
}
document.getElementById(‘mtpGMove’).onclick=function(){stop();var i=Math.floor(Math.random()*12),s;do{s=Math.floor(Math.random()*4);}while(s===asg[i]);var old=asg;asg=asg.slice();asg[i]=s;evals++;step++;hist.push(score(asg)[1]);render([i]);var d=diff(old,asg);drawGraph(d);gLog.textContent=”Moved t”+(i+1)+’ S’+(old[i]+1)+’ → S’+(s+1)+’. Only ‘+(d.length*2+2)+’ of 10 nodes needed new values.’;};
document.getElementById(‘mtpGBest’).onclick=function(){stop();var r=bestMove();evals+=r.n;if(!r.best){gLog.textContent=”Local optimum reached. Try a random move first.”;render();return;}var old=asg;asg=r.best.a;step++;hist.push(score(asg)[1]);render(r.best.ids);var d=diff(old,asg);drawGraph(d);gLog.textContent=”Best of “+r.n+’ candidates: ‘+r.best.txt+’. Recomputed ‘+(d.length*2+2)+’ of 10 nodes.’;};

/* solver picker */
var Os=document.getElementById(‘mtpOs’),Bs=document.getElementById(‘mtpBs’);
function fmt(n){if(n>=1e9)return (n/1e9).toFixed(n>=1e10?0:1)+’B’;if(n>=1e6)return (n/1e6).toFixed(n>=1e7?0:1)+’M’;if(n>=1e3)return (n/1e3).toFixed(n>=1e4?0:1)+’k’;return Math.round(n)+”;}
function pick(){
var o=exactO||Math.round(Math.pow(10,+Os.value)),b=exactB||Math.round(Math.pow(10,+Bs.value)),m=o*b,l=o+b;exactO=exactB=0;
document.getElementById(‘mtpOv’).textContent=fmt(o);document.getElementById(‘mtpBv’).textContent=fmt(b);
document.getElementById(‘mtpMv’).textContent=”≈ “+fmt(m);document.getElementById(‘mtpLv’).textContent=”≈ “+fmt(l);
document.getElementById(‘mtpMb’).style.width=Math.min(100,Math.log10(m)/11*100)+’%’;
document.getElementById(‘mtpLb’).style.width=Math.min(100,Math.log10(l)/11*100)+’%’;
var v=document.getElementById(‘mtpVerdict’),t;
if(m<=1e6){t=”<b>Optimal (MIP) solver is a good start.</b> Small model: hand it to HiGHS, Gurobi or FICO Xpress and get a provably optimal assignment.”;v.style.borderColor=”#2BD99F”;}
else if(m<=1e8){t=”<b>Prototype with MIP, then move to local search.</b> Meta says this is a common path: find a strong baseline with the optimal solver, then migrate.”;v.style.borderColor=”#4C9BFF”;}
else{t=”<b>Local search.</b> The MIP would need ≈ “+fmt(m)+’ binary variables in the worst case, while each local-search neighborhood stays near ‘+fmt(l)+’. Meta runs almost all large problems this way.’;v.style.borderColor=”#38D6FF”;}
v.innerHTML=t;postH();
}
var exactO=0,exactB=0;Os.oninput=pick;Bs.oninput=pick;
document.querySelectorAll(‘#mtpP2 button[data-o]’).forEach(function(btn){btn.onclick=function(){exactO=+btn.dataset.o;exactB=+btn.dataset.bn;Os.value=Math.log10(+btn.dataset.o);Bs.value=Math.log10(+btn.dataset.bn);pick();};});

/* stats */
var counted=false;
function count(){
var cards=document.querySelectorAll(‘#mtpCards .card’);
cards.forEach(function(c,i){c.classList.remove(‘in’);setTimeout(function(){c.classList.add(‘in’);},90*i);});
document.querySelectorAll(‘#mtpCards [data-c]’).forEach(function(el){var tgt=+el.dataset.c,dp=+(el.dataset.d||0),t0=null;
function f(ts){if(!t0)t0=ts;var p=Math.min(1,(ts-t0)/1100),e=1-Math.pow(1-p,3);el.textContent=(tgt*e).toFixed(dp);if(p<1)requestAnimationFrame(f);}requestAnimationFrame(f);});
}

/* tabs */
var tabs=R.querySelectorAll(‘.tab’);
tabs.forEach(function
R.querySelectorAll(‘.pane’).forEach(function(p){p.classList.remove(‘on’);});document.getElementById(‘mtpP’+t.dataset.p).classList.add(‘on’);
if(t.dataset.p===’3′)count();if(t.dataset.p===’1′)drawGraph(null);setTimeout(postH,60);setTimeout(postH,450);};});

hist=[score(asg)[1]];render();pick();
window.addEventListener(‘load’,postH);window.addEventListener(‘resize’,postH);setTimeout(postH,300);
})();
</script>
</body></html>”>

(function(){var f=document.getElementById(‘mtp-rebal-frame’);window.addEventListener(‘message’,function(e){if(e.data&&e.data.mtpRebalH&&f&&e.source===f.contentWindow){f.style.height=e.data.mtpRebalH+’px’;}});})();

Rebalancer vs Closest Open Source Alternatives

Feature Meta Rebalancer Google OR-Tools Timefold Solver (Community)
License Apache 2.0 Apache 2.0 Apache 2.0 (Enterprise edition is commercial)
Core language C++ C++ Java
APIs C++, Python C++, Python, Java, C# Java, Kotlin
Focus Generic assignment (objects to bins) Broad suite: CP-SAT, LP, MIP wrappers, routing, packing, assignment Planning: routing, rostering, scheduling, task assignment
Local search Yes, parallel, on expression graph Yes, in routing solver (guided local search, simulated annealing, tabu) Yes, core engine (tabu, simulated annealing, late acceptance)
MIP backends FICO Xpress, Gurobi, HiGHS Wrappers for commercial and open source MIP solvers Not used
Debugging UI Rebalancer Explorer (Docker) Not listed in README Benchmarker; score analysis in commercial editions
Install pip install rebalancer pip install ortools Maven, JDK 21+

OR-Tools covers more problem classes, and Timefold targets JVM scheduling and routing. Rebalancer’s edge is one assignment spec that runs on both local search and MIP.

Key Takeaways

  • Rebalancer models any assignment problem as objects, bins, constraints and objectives.
  • Specs compile into an expression graph solved by local search or a MIP solver.
  • MIP backends include FICO Xpress, Gurobi and open source HiGHS.
  • Meta runs about 40M problems a day; P99 is 12s on 265k objects and 3.2k bins.
  • Apache 2.0, C++ and Python APIs, installable from PyPI today.


Check out the Paper, GitHub Repo and Technical details. All credit goes to the researcher of this project. Also, feel free to follow us on Twitter and don’t forget to join our 150k+ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.

[Sponsored] The web is the one API most agents are missing. Databases, calendars and repos have APIs. The open web mostly doesn’t. The TinyFish MCP server gives any MCP client four tools: TinySearch, TinyFetch (full pages as markdown, JavaScript included), TinyBrowser for logins and forms, and TinyAgent for multi-step jobs. Search and Fetch are free.

The post Meta AI Open-Sources Rebalancer: A C++ Assignment Solver That Runs About 40 Million Placement Problems a Day appeared first on MarkTechPost.



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *

阿根廷对阵布基纳法索 阿根廷 - 布基纳法索 阿根廷对阵 阿根廷 阿根廷国家足球队 布基纳法索国家足球队 阿根廷国家足球队对阵布基纳法索国家足球队阵容 阿根廷比赛 哪里观看阿根廷国家足球队对阵布基纳法索国家足球队的比赛 阿根廷对阵布基纳法索 俄亥俄州立大学对阵爱荷华大学 爱荷华大学对阵俄亥俄州立大学 爱荷华大学橄榄球 杰里迈亚·史密斯 (Jeremiah Smith) 杰里迈亚·史密斯数据 爱荷华大学 俄亥俄州立大学 OSU对阵爱荷华大学 朱利安·萨因 (Julian Sayin) 爱荷华大学比赛 俄亥俄州立大学 爱荷华大学 俄亥俄州立大学七叶树队 (Buckeyes) 橄榄球 俄亥俄州立大学比分 爱荷华大学比分 俄亥俄州立大学七叶树队对阵爱荷华大学鹰眼队 (Hawkeyes) 比赛球员数据 俄亥俄州立大学七叶树队 七叶树队橄榄球 鹰眼队橄榄球 柯克·费伦茨 (Kirk Ferentz) 汉克·布朗 (Hank Brown) 俄亥俄州立大学橄榄球赛程 贾科比·杰克逊 (Ja'Kobi Jackson) 爱荷华大学鹰眼队 俄亥俄州立大学比赛在哪个频道播出 哪里观看俄亥俄州立大学七叶树队对阵爱荷华大学鹰眼队的橄榄球比赛 今天俄亥俄州立大学比赛在哪个频道播出 教士队 (Padres) 对阵酿酒人队 (Brewers) 酿酒人队 酿酒人队比赛 密尔沃基酿酒人队 酿酒人队对阵教士队 酿酒人队比分 教士队 教士队比赛 教士队今日比赛 酿酒人队今日比赛 圣地亚哥教士队 泰·弗朗斯 (Ty France) 曼尼·马查多 (Manny Machado) 威廉·孔特雷拉斯 (William Contreras) 密尔沃基 教士队 - 酿酒人队 教士队比分 特雷弗·梅吉尔 (Trevor Megill) 酿酒人队赛程 教士队 酿酒人队 梅吉尔 酿酒人队 酿酒人队比赛 酿酒人队 教士队 孔特雷拉斯 酿酒人队 教士队对阵密尔沃基酿酒人队 今日MLB比赛 Baseball Savant Lucki Lucki被刺伤 Lucki被刺伤了吗 说唱歌手Lucki Lucki遇刺事件 美国 - 墨西哥 墨西哥对阵美国 墨西哥国家队 美国对阵墨西哥 迭戈·坎皮略 (Diego Campillo) 墨西哥国家足球队 劳尔·兰赫尔 (Raúl Rangel) 友谊赛 路易斯·罗莫 (Luis Romo) 墨西哥何时比赛 墨西哥对阵美国 美国美国对墨西哥 墨西哥对阵 奥尔贝林·皮内达 迈阿密(佛罗里达州)对克莱姆森 迈阿密橄榄球 克莱姆森对迈阿密 迈阿密对克莱姆森 迈阿密飓风队 迈阿密飓风队橄榄球 达里安·门萨 迈阿密 迈阿密-克莱姆森 迈阿密大学橄榄球 克莱姆森-迈阿密 库珀·巴卡特 迈阿密对克莱姆森预测 麦克尼斯州立大学对LSU LSU对麦克尼斯 麦克尼斯橄榄球 LSU今日比赛 麦克尼斯 勇士队对道奇队 道奇队今日比赛 塔里克·斯库巴尔 道奇队赛程 勇士队今日比赛 斯库巴尔 亚特兰大勇士队对道奇队 扬基队对光芒队 德鲁·拉斯穆森 扬基队 扬基队今日比赛 坦帕湾光芒队 光芒队 扬基队比赛 纽约扬基队 扬基队今日比赛 光芒队比赛 扬基队比赛 光芒队今日比赛 NYY 扬基队-光芒队 奥斯汀·威尔斯 纽约扬基队 扬基队 阿肯色大学对德州农工大学 德州农工大学橄榄球 德州理工大学对科罗拉多大学 德州理工大学橄榄球 迪昂·桑德斯 科罗拉多大学橄榄球 德州理工大学 科罗拉多大学对德州理工大学 科罗拉多大学水牛队橄榄球 아르헨티나 대 부르키나파소 아르헨티나 - 부르키나파소 아르헨티나 대 아르헨티나 아르헨티나 축구 국가대표팀 부르키나파소 축구 국가대표팀 아르헨티나 대 부르키나파소 축구 국가대표팀 선발 명단 아르헨티나 경기 아르헨티나 대 부르키나파소 축구 국가대표팀 경기 중계 정보 아르헨티나 대 부르키나파소 오하이오 주립대 대 아이오와대 아이오와대 대 오하이오 주립대 아이오와대 미식축구 제레미아 스미스 제레미아 스미스 기록 아이오와대 오하이오 주립대 OSU 대 아이오와대 줄리안 세이인 아이오와대 경기 오하이오 주립대 아이오와대 오하이오 주립대 버키스 미식축구 오하이오 주립대 점수 아이오와대 점수 오하이오 주립대 버키스 대 아이오와대 호키스 미식축구 경기 선수 기록 오하이오 주립대 버키스 버키스 미식축구 호키스 미식축구 커크 페렌츠 행크 브라운 오하이오 주립대 미식축구 일정 자코비 잭슨 아이오와대 호키스 오하이오 주립대 경기 중계 채널 오하이오 주립대 버키스 대 아이오와대 호키스 미식축구 경기 시청 방법 오늘 오하이오 주립대 경기 중계 채널 파드리스 대 브루어스 브루어스 브루어스 경기 밀워키 브루어스 브루어스 대 파드리스 브루어스 점수 파드리스 파드리스 경기 오늘 파드리스 경기 오늘 브루어스 경기 샌디에이고 파드리스 타이 프랑스 매니 마차도 윌리엄 콘트레라스 밀워키 파드리스 - 브루어스 파드리스 점수 트레버 메길 브루어스 일정 파드리스 브루어스 메길 브루어스 브루어스 경기 브루어스 파드리스 콘트레라스 브루어스 파드리스 대 밀워키 브루어스 오늘 MLB 경기 베이스볼 사반트 럭키(Lucki) 럭키 피습 럭키가 칼에 찔렸나요? 래퍼 럭키 럭키 피습 사건 미국 - 멕시코 멕시코 대 미국 멕시코 국가대표팀 미국 대 멕시코 디에고 캄필로 멕시코 축구 국가대표팀 라울 랑헬 친선 경기 루이스 로모 멕시코 경기 일정 멕시코 대 미국 미국 미국 대 멕시코 멕시코 대 오르벨린 피네다 마이애미 대 클렘슨 마이애미 풋볼 클렘슨 대 마이애미 마이애미 대 클렘슨 마이애미 허리케인스 마이애미 허리케인스 풋볼 다리안 멘사 마이애미 마이애미 클렘슨 UM 풋볼 클렘슨 마이애미 쿠퍼 바케이트 마이애미 대 클렘슨 경기 예측 맥니스 주립대 대 LSU LSU 대 맥니스 맥니스 풋볼 오늘 LSU 경기 맥니스 브레이브스 대 다저스 오늘 다저스 경기 타릭 스쿠발 다저스 일정 오늘 브레이브스 경기 스쿠발 애틀랜타 브레이브스 대 다저스 양키스 대 레이스 드류 라스무센 양키스 오늘 양키스 경기 탬파베이 레이스 레이스 양키스 경기 뉴욕 양키스 오늘 양키스 경기 레이스 경기 양키스 경기 오늘 레이스 경기 NYY 양키스 레이스 오스틴 웰스 NY 양키스 양키 아칸소 대 텍사스 A&M A&M 풋볼 텍사스 공대 대 콜로라도 텍사스 공대 풋볼 디온 샌더스 CU 풋볼 텍사스 공대 콜로라도 대 텍사스 공대 CU 버프스 풋볼 アルゼンチン対ブルキナファソ アルゼンチン - ブルキナファソ アルゼンチン対 アルゼンチン アルゼンチン代表(サッカー) ブルキナファソ代表(サッカー) アルゼンチン代表対ブルキナファソ代表の出場メンバー アルゼンチンの試合 アルゼンチン代表対ブルキナファソ代表の視聴方法 アルゼンチン対ブルキナファソ オハイオ州立大対アイオワ大 アイオワ大対オハイオ州立大 アイオワ大フットボール ジェレマイア・スミス ジェレマイア・スミスの成績 アイオワ大・オハイオ州立大 OSU対アイオワ大 ジュリアン・サイン アイオワ大の試合 オハイオ州立大・アイオワ大 オハイオ州立大バッカイズ・フットボール オハイオ州立大のスコア アイオワ大のスコア オハイオ州立大バッカイズ対アイオワ大ホークアイズの試合・選手成績 オハイオ州立大バッカイズ バッカイズ・フットボール ホークアイズ・フットボール カーク・フェレンツ ハンク・ブラウン オハイオ州立大フットボールの日程 ジャコビ・ジャクソン アイオワ大ホークアイズ オハイオ州立大の試合の放送チャンネル オハイオ州立大バッカイズ対アイオワ大ホークアイズの視聴方法 今日のオハイオ州立大の試合の放送チャンネル パドレス対ブルワーズ ブルワーズ ブルワーズの試合 ミルウォーキー・ブルワーズ ブルワーズ対パドレス ブルワーズのスコア パドレス パドレスの試合 今日のパドレスの試合 今日のブルワーズの試合 サンディエゴ・パドレス タイ・フランス マニー・マチャド ウィリアム・コントレラス ミルウォーキー パドレス - ブルワーズ パドレスのスコア トレバー・メギル ブルワーズの日程 パドレス・ブルワーズ メギル・ブルワーズ ブルワーズの試合 ブルワーズ・パドレス コントレラス・ブルワーズ パドレス対ミルウォーキー・ブルワーズ 今日のMLBの試合 ベースボール・サバント Lucki Lucki 刺される Luckiは刺されたのか ラッパー Lucki Lucki 刺傷事件 アメリカ対メキシコ メキシコ対アメリカ メキシコ代表 アメリカ対メキシコ ディエゴ・カンピージョ メキシコ代表(サッカー) ラウル・ランヘル 親善試合 ルイス・ロモ メキシコの試合日程 メキシコ対USA アメリカ米国対メキシコ メキシコ対 オルベリン・ピネダ マイアミ対クレムソン マイアミ・フットボール クレムソン対マイアミ マイアミ対クレムソン マイアミ・ハリケーンズ マイアミ・ハリケーンズ・フットボール ダリアン・メンサ マイアミ マイアミ・クレムソン UMフットボール クレムソン・マイアミ クーパー・バーケイト マイアミ対クレムソン 予想 マクニース州立大対LSU LSU対マクニース マクニース・フットボール LSUの今日の試合 マクニース ブレーブス対ドジャース ドジャースの今日の試合 タリク・スクーバル ドジャースの日程 ブレーブスの今日の試合 スクーバル アトランタ・ブレーブス対ドジャース ヤンキース対レイズ ドリュー・ラスムッセン ヤンキース ヤンキースの今日の試合 タンパベイ・レイズ レイズ ヤンキースの試合 ニューヨーク・ヤンキース ヤンキースの今日の試合 レイズの試合 ヤンキースの試合 レイズの今日の試合 NYY