Fiduccia-Mattheyses-algoritmus
Kiejtés
- IPA: [ ˈfidut͡sːijɒmɒthɛiʃɛʃɒlɡoritmuʃ]
Főnév
Fiduccia-Mattheyses-algoritmus
Fiduccia-Mattheyses (FM) algoritmus
A Fiduccia-Mattheyses-algoritmus egy gyors és hatékony algoritmus gráfok particionálására, amelyet főként az elektronikai tervezésben (VLSI áramkörök optimalizálása) használnak. Az algoritmus célja egy gráf csúcsainak két részre bontása úgy, hogy a két rész közötti élkapcsolatok száma minimális legyen, miközben a particiók egyensúlyban maradnak (azaz hasonló méretűek).
Algoritmus jellemzői
- Bemenet:
- Egy súlyozott gráf ( G(V, E) ), ahol ( V ) a csúcsok, ( E ) az élek halmaza.
- A csúcsokhoz és élekhez súlyok rendelhetők.
- Kimenet:
- Két partició: ( P_1 ) és ( P_2 ), amelyek egyensúlyban vannak.
- Az élvágások száma (cut size) minimális.
- Alapötlet:
- Greedy csúcsmozgás: Minden iterációban egy csúcsot mozgatunk az egyik particióból a másikba, amely a legnagyobb javulást hozza az élvágások számában.
- Gain: Egy csúcs mozgatása által okozott javulás vagy romlás az élvágások számában.
- Hatékonyság:
- Az algoritmus időkomplexitása ( O(|E| + |V| |V|) ), ami gyorsnak számít nagy gráfokra.
Algoritmus lépései
- Kezdeti partició:
- Osszuk két részre a gráf csúcsait valamilyen kezdeti módszerrel (pl. véletlenszerűen).
- Gain számítás:
- Számítsuk ki minden csúcsra a particiók közötti mozgatás által okozott gain értéket: [ (v) = {}(v) - {}(v), ] ahol ( {} ) az élek súlyainak összege a csúcs jelenlegi particiójában, és ( {} ) az élek súlyainak összege a másik particióban.
- Csúcs mozgatása:
- Mozgassuk azt a csúcsot, amely a legnagyobb gain-t eredményezi, miközben fenntartjuk a particiók egyensúlyát.
- Locking:
- Zárjuk le a már mozgatott csúcsokat, hogy ne kerüljenek vissza ugyanabban az iterációban.
- Iteráció:
- Ismételjük addig, amíg nem érünk el lokális optimumot.
- Globális optimum keresése:
- Az algoritmust többször futtathatjuk különböző kezdeti particiókkal, hogy közelebb kerüljünk a globális optimumhoz.
Python Implementáció
Az alábbi Python-kód egyszerűsíti az FM-algoritmus lényegét.
import random
from collections import defaultdict
def calculate_gain(graph, part1, part2, vertex):
"""Gain kiszámítása a csúcs mozgatásához."""
E_from = sum(weight for neighbor, weight in graph[vertex] if neighbor in part1)
E_to = sum(weight for neighbor, weight in graph[vertex] if neighbor in part2)
return E_to - E_from
def fiduccia_mattheyses(graph, initial_part1):
"""
Fiduccia-Mattheyses algoritmus implementáció.
:param graph: Gráf (szomszédsági lista súlyokkal)
:param initial_part1: Az első partició kezdeti csúcsai
:return: Optimalizált particiók
"""
vertices = set(graph.keys())
part1 = set(initial_part1)
part2 = vertices - part1
locked = set()
best_cut_size = float('inf')
best_part1, best_part2 = None, None
while len(locked) < len(vertices):
gains = {}
for vertex in vertices - locked:
if vertex in part1:
gains[vertex] = calculate_gain(graph, part1, part2, vertex)
else:
gains[vertex] = calculate_gain(graph, part2, part1, vertex)
# Legnagyobb gain csúcs kiválasztása
max_gain_vertex = max(gains, key=gains.get)
max_gain = gains[max_gain_vertex]
# Csúcs mozgatása
if max_gain_vertex in part1:
part1.remove(max_gain_vertex)
part2.add(max_gain_vertex)
else:
part2.remove(max_gain_vertex)
part1.add(max_gain_vertex)
locked.add(max_gain_vertex)
# Cut size újraszámítása
cut_size = sum(weight for v in part1 for neighbor, weight in graph[v] if neighbor in part2)
if cut_size < best_cut_size:
best_cut_size = cut_size
best_part1, best_part2 = set(part1), set(part2)
return best_part1, best_part2
# Példa gráf
graph = {
'a': [('b', 1), ('c', 2)],
'b': [('a', 1), ('d', 1)],
'c': [('a', 2), ('d', 2)],
'd': [('b', 1), ('c', 2)],
}
initial_part1 = ['a', 'b']
part1, part2 = fiduccia_mattheyses(graph, initial_part1)
print("Particiók:")
print("Part1:", part1)
print("Part2:", part2)
C++ Implementáció
Az alábbi C++ kód az FM-algoritmus alapjait illusztrálja:
#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <queue>
using namespace std;
struct Edge {
int to, weight;
};
using Graph = unordered_map<int, vector<Edge>>;
int calculateGain(const Graph& graph, const unordered_set<int>& part1, const unordered_set<int>& part2, int vertex) {
int E_from = 0, E_to = 0;
for (const auto& edge : graph.at(vertex)) {
if (part1.count(edge.to)) {
E_from += edge.weight;
} else if (part2.count(edge.to)) {
E_to += edge.weight;
}
}
return E_to - E_from;
}
pair<unordered_set<int>, unordered_set<int>> fiducciaMattheyses(const Graph& graph, unordered_set<int> initialPart1) {
unordered_set<int> part1 = initialPart1;
unordered_set<int> part2;
for (const auto& [vertex, _] : graph) {
if (!part1.count(vertex)) {
part2.insert(vertex);
}
}
unordered_set<int> locked;
int bestCutSize = INT_MAX;
unordered_set<int> bestPart1 = part1, bestPart2 = part2;
while (locked.size() < graph.size()) {
unordered_map<int, int> gains;
for (int vertex : part1) {
if (!locked.count(vertex)) {
gains[vertex] = calculateGain(graph, part1, part2, vertex);
}
}
for (int vertex : part2) {
if (!locked.count(vertex)) {
gains[vertex] = calculateGain(graph, part2, part1, vertex);
}
}
int maxGainVertex = max_element(gains.begin(), gains.end(), [](auto& a, auto& b) {
return a.second < b.second;
})->first;
if (part1.count(maxGainVertex)) {
part1.erase(maxGainVertex);
part2.insert(maxGainVertex);
} else {
part2.erase(maxGainVertex);
part1.insert(maxGainVertex);
}
locked.insert(maxGainVertex);
int cutSize = 0;
for (int v : part1) {
for (const auto& edge : graph.at(v)) {
if (part2.count(edge.to)) {
cutSize += edge.weight;
}
}
}
if (cutSize < bestCutSize) {
bestCutSize = cutSize;
bestPart1 = part1;
bestPart2 = part2;
}
}
return {bestPart1, bestPart2};
}
int main() {
Graph graph = {
{1, {{2, 1}, {3, 2}}},
{2, {{1, 1}, {4, 1}}},
{3, {{1, 2}, {4, 2}}},
{4, {{2, 1}, {3, 2}}}
};
unordered_set<int> initialPart1 = {1, 2};
auto [part1, part2] = fiducciaMattheyses(graph, initialPart1);
cout << "Part1: ";
for (int v : part1) cout << v << " ";
cout << "\nPart2: ";
for (int v : part2) cout << v << " ";
cout << endl;
return 0;
}
Felhasználás
- Elektronikai áramkörök tervezése: VLSI áramkörök optimalizálása.
- Hálózatok particionálása: Nagy hálózatok hatékony feldolgozása.
- Grafikai és térképezési problémák.
Fordítások
Tartalom
- Fiduccia-Mattheyses-algoritmus - Értelmező szótár (MEK)
- Fiduccia-Mattheyses-algoritmus - Etimológiai szótár (UMIL)
- Fiduccia-Mattheyses-algoritmus - Szótár.net (hu-hu)
- Fiduccia-Mattheyses-algoritmus - DeepL (hu-de)
- Fiduccia-Mattheyses-algoritmus - Яндекс (hu-ru)
- Fiduccia-Mattheyses-algoritmus - Google (hu-en)
- Fiduccia-Mattheyses-algoritmus - Helyesírási szótár (MTA)
- Fiduccia-Mattheyses-algoritmus - Wikidata
- Fiduccia-Mattheyses-algoritmus - Wikipédia (magyar)