Es gibt einen Bereich wie unten gezeigt.
Anzahl der Sensoren in der Nähe | Menge der erfassten Daten | Menge der Interferenzdaten | Die Datenmenge, die insgesamt zunimmt |
---|---|---|---|
0 | 3 | 0 | 3 |
1 | 3 | 2 | 1 |
2 | 3 | 4 | -1 |
3 | 3 | 6 | -3 |
Lassen Sie es uns als Mixed Integer Optimization Problem (MIP) modellieren. Formulierungen und Ideen finden Sie unter Kombinationsoptimierung verwenden.
Maximieren td> | $ Menge der erfassten Daten \\ = 3 \-mal Ob 2-mal installiert werden soll. Ob $ td> tr> gestört werden soll |
Variablen td> | $ (Sensor) Gibt an, ob \ in \ {0, 1 \} \ für alle Installationsorte $ td> tr> installiert werden soll |
$ Gibt an, ob \ ge 0 \ für alle benachbarten $ td> tr> gestört werden soll | |
Einschränkungen td> | $ Ob _1 installiert werden soll + Ob _2 installiert werden soll - Ob \ le 1 $ td> tr> gestört werden soll |
[Minimum Cut Problem] in der Graphentheorie (https://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%83%E3%83%88_(%E3%82%B0%E3%83] % A9% E3% 83% 95% E7% 90% 86% E8% AB% 96) # .E6.9C.80.E5.B0.8F.E3.82.AB.E3.83.83.E3.83.88) Da ist etwas.
Betrachten Sie das folgende s-t-Diagramm. Wenn Sie den s-t-Mindestschnitt für dieses gerichtete Diagramm finden, erhalten Sie die beste Lösung für das ursprüngliche Problem der Sensorinstallation. Das ursprüngliche Problem ist das Maximierungsproblem, aber wenn "3 erfasste Datenmenge" als Kosten betrachtet wird, kann es als Minimierungsproblem angesehen werden. Einzelheiten finden Sie auf der Referenzseite unten.
-Die obige Abbildung zeigt drei Beispiele für (0,0), (0,1), (1,0).
Das Minimum-Cut-Problem ist ein leicht zu lösendes Problem, das in polymorpher Zeit gelöst werden kann. In dem später beschriebenen Programm wird es mit networkx von Python gelöst. Das Problem des minimalen Schnitts Dualitätsproblem ist übrigens das Problem des maximalen Durchflusses.
Sich fertig machen.
python3
import numpy as np, networkx as nx
from pulp import *
def addvar(lowBound=0, var_count=[0], *args, **kwargs):
"""Dienstprogramm zur Variablenerstellung"""
var_count[0] += 1
return LpVariable('v%d' % var_count[0], lowBound=lowBound, *args, **kwargs)
def calc(a, r):
"""Berechnen Sie die Menge der erfassten Daten mit r als Installationsort"""
b = a.copy()
b[b > 1] = 0
for x, y in r:
b[y, x] = 1
s = b.sum() * 3
for y in range(0, b.shape[0], 2):
for x in range(b.shape[1]):
s -= 2 * b[y, x] * b[y+1,x]
if x:
s -= 2 * b[y, x] * b[y+1,x-1]
if y:
s -= 2 * b[y, x] * b[y-1,x]
return s
Solve_by_mip ist eine MIP-Lösung. Gibt den Installationsort zurück.
python3
def solve_by_mip(a):
"""Lösen Sie das Problem mit MIP und geben Sie den Installationsort zurück"""
nm, nn = a.shape
b = a.astype(object)
vv1 = [addvar(cat=LpBinary) for _ in range((b > 1).sum())]
b[b > 1] = vv1
vv2 = []
m = LpProblem(sense=LpMaximize)
for y in range(0, nm, 2):
for x in range(nn):
chk(m, vv2, b[y,x] + b[y+1,x])
if x: chk(m, vv2, b[y,x] + b[y+1,x-1])
if y: chk(m, vv2, b[y,x] + b[y-1,x])
m += 3 * lpSum(vv1) - 2 * lpSum(vv2)
m.solve()
return [(x, y) for x in range(nn) for y in range(nm)
if isinstance(b[y,x], LpVariable) and value(b[y, x]) > 0.5]
def chk(m, vv2, e):
"""Wenn e Variablen enthält, fügen Sie eine Einschränkung hinzu, die die Zielfunktion um 2 reduziert, wenn beide 1 sind."""
if isinstance(e, LpAffineExpression):
v = addvar()
vv2.append(v)
m += e - v <= 1
Solve_by_graph ist eine minimale Schnittlösung. Geben Sie auch den Installationsort zurück.
python3
def solve_by_graph(a):
"""Lösen Sie das Problem mit dem Minimum-Cut-Problem und geben Sie den Installationsort zurück"""
nm, nn = a.shape
g = nx.DiGraph()
for y in range(0, nm, 2):
for x in range(nn):
if a[y, x] == 0: # off
g.add_edge('s', (x,y), capacity=7)
elif a[y, x] == 1: # on
g.add_edge((x,y), 't', capacity=7)
else:
g.add_edge('s', (x,y), capacity=0)
g.add_edge((x,y), 't', capacity=3)
if a[y+1, x] == 0: # off
g.add_edge((x,y+1), 't', capacity=7)
elif a[y+1, x] == 1: # on
g.add_edge('s', (x,y+1), capacity=7)
else:
g.add_edge('s', (x,y+1), capacity=3)
g.add_edge((x,y+1), 't', capacity=0)
g.add_edge((x,y+1), (x,y), capacity=2)
if x:
g.add_edge((x-1,y+1), (x,y), capacity=2)
if y:
g.add_edge((x,y-1), (x,y), capacity=2)
r = []
for s in nx.minimum_cut(g, 's', 't')[1]:
b = 's' in s
for t in s:
if isinstance(t, str): continue
x, y = t
if a[y, x] > 1 and b == (y%2 != 0):
r.append((x, y))
return sorted(r)
Vergleichen wir die Ergebnisse, indem wir zufällig Fixpunkte in einer Größe von 40 x 80 festlegen.
python3
nn, nm = 40, 80 #Horizontal, Vertikal
np.random.seed(1)
a = np.random.randint(0, 6, (nm, nn)) # 0; fix off, 1: fix on, ow:select
%time rmip = calc(a, solve_by_mip(a))
%time rgrp = calc(a, solve_by_graph(a))
print(rmip == rgrp)
>>>
Wall time: 455 ms
Wall time: 185 ms
True
Referenzseite
das ist alles
Recommended Posts