Il y a une zone comme indiqué ci-dessous.
--Un capteur sera installé au centre de ce triangle pour collecter des données.
Nombre de capteurs autour | Quantité de données acquises | Quantité de données d'interférence | La quantité de données qui augmente dans son ensemble |
---|---|---|---|
0 | 3 | 0 | 3 |
1 | 3 | 2 | 1 |
2 | 3 | 4 | -1 |
3 | 3 | 6 | -3 |
Modélisons-le comme un problème d'optimisation d'entiers mixtes (MIP). Veuillez consulter Utiliser l'optimisation de la combinaison pour la formulation et le concept.
Maximiser td> | $ Quantité de données acquises \\ = 3 \ fois S'il faut installer-2 \ fois S'il faut interférer $ td> tr> |
Variables td> | $ (Sensor) Indique s'il faut installer \ in \ {0, 1 \} \ forall Emplacement d'installation $ td> tr> |
$ S'il faut interférer \ ge 0 \ forall Adjacent $ td> tr> | |
Contraintes td> | $ S'il faut installer _1 + S'il faut installer _2 --S'il faut interférer \ le 1 $ td> tr> |
[Problème de coupe minimale] dans la théorie des graphes (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) Il ya quelque chose.
Considérez le graphe s-t suivant. Trouver la coupe minimale s-t pour ce graphique orienté vous donnera la meilleure solution au problème d'installation du capteur d'origine. Le problème original est le problème de la maximisation, mais en considérant la "quantité de données acquises en 3" comme le coût, il peut être considéré comme le problème de minimisation. Pour plus de détails, consultez le site de référence ci-dessous.
-La figure ci-dessus montre trois exemples de (0,0), (0,1), (1,0).
Le problème de coupe minimale est un problème facile à résoudre qui peut être résolu en temps polymorphe. Dans le programme décrit plus loin, il sera résolu en utilisant networkx de Python. Soit dit en passant, le problème de coupure minimale problème de la dualité est le problème de débit maximal.
Sois prêt.
python3
import numpy as np, networkx as nx
from pulp import *
def addvar(lowBound=0, var_count=[0], *args, **kwargs):
"""Utilitaire de création de variables"""
var_count[0] += 1
return LpVariable('v%d' % var_count[0], lowBound=lowBound, *args, **kwargs)
def calc(a, r):
"""Calculez la quantité de données acquises avec r comme emplacement d'installation"""
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
résoudre_by_mip est une solution MIP. Renvoie l'emplacement d'installation.
python3
def solve_by_mip(a):
"""Résolvez le problème avec MIP et renvoyez l'emplacement d'installation"""
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):
"""Ajouter une contrainte pour réduire la fonction objectif de 2 si e contient des variables"""
if isinstance(e, LpAffineExpression):
v = addvar()
vv2.append(v)
m += e - v <= 1
résoudre_by_graph est une solution de coupe minimale. Renvoyez également l'emplacement d'installation.
python3
def solve_by_graph(a):
"""Résolvez le problème avec le problème de coupure minimum et renvoyez l'emplacement d'installation"""
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)
Comparons les résultats en définissant aléatoirement des points fixes d'une taille de 40 x 80.
python3
nn, nm = 40, 80 #Horizontal Vertical
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
―― Vous pouvez voir que les deux méthodes ont la même quantité de données acquises (rmip == rgrp). --MIP est plus de deux fois plus lent.
Site de référence
c'est tout
Recommended Posts