code: func GetMinimumGatewaySet(rxInfoSets []storage.DeviceGatewayRXInfoSet) ([]lorawan.EUI64, error) {
  	g := simple.NewWeightedUndirectedGraph(0, math.Inf(1))
  
  	gwSet := getGatewaySet(rxInfoSets)
  
  	// connect all gateways
  	// W -999 is used so that the mst algorithm will remove the edge between
  	// the gateway and a device first, over removing an edge between two
  	// gateways.
  	for i, gatewayID := range gwSet {
  		if i == 0 {
  			continue
  		}
  
  		g.SetWeightedEdge(simple.WeightedEdge{
  			F: simple.Node(eui64Int64(gwSet[0])),
  			T: simple.Node(eui64Int64(gatewayID)),
  			W: -999,
  		})
  	}
  
  	// connect all devices to the gateways
  	addDeviceEdges(g, rxInfoSets)
  
  	dst := simple.NewWeightedUndirectedGraph(0, math.Inf(1))
  	path.Kruskal(dst, g)
  
  	outMap := make(map[lorawan.EUI64]struct{})
  
  	edges := dst.Edges()
  	for edges.Next() {
  		e := edges.Edge()
  
  		fromEUI := int64ToEUI64(e.From().ID())
  		toEUI := int64ToEUI64(e.To().ID())
  
  		fromIsGW := gwInGWSet(fromEUI, gwSet)
  		toIsGW := gwInGWSet(toEUI, gwSet)
  
  		// skip gateway to gateway edges
  		if !(fromIsGW && toIsGW) {
  			if fromIsGW {
  				outMap[fromEUI] = struct{}{}
  			}
  
  			if toIsGW {
  				outMap[toEUI] = struct{}{}
  			}
  		}
  	}
  
  	var outSlice []lorawan.EUI64
  	for k := range outMap {
  		outSlice = append(outSlice, k)
  	}
  
  	return outSlice, nil
  }
docs: // GetMinimumGatewaySet returns the minimum set of gateways to cover all
  // devices.