def asarray(x: Any, dtype: Optional[str] = None) -> np.ndarray: """Convert `x` to interger Numpy array. Parameters: ---------- x: Tensor, Scipy sparse matrix, Numpy array-like, etc. Returns: ---------- Integer Numpy array with dtype or `'int64'` """ if dtype is None: dtype = 'int64' if torch.is_tensor(x): if x.dtype != dtype: return x.to(getattr(torch, dtype)) else: return x if gg.is_intscalar(x): x = np.asarray([x], dtype=dtype) elif gg.is_listlike(x) or (isinstance(x, np.ndarray) and x.dtype != "O"): x = np.asarray(x, dtype=dtype) else: raise ValueError( f"Invalid input which should be either array-like or integer scalar, but got {type(x)}." ) return x
def attack(self, target, num_budgets, direct_attack, structure_attack, feature_attack): if not self.is_reseted: raise RuntimeError( 'Before calling attack, you must reset your attacker. Use `attacker.reset()`.' ) if not gg.is_intscalar(target): raise ValueError(target) if not (structure_attack or feature_attack): raise RuntimeError( 'Either `structure_attack` or `feature_attack` must be True.') if feature_attack and not self.allow_feature_attack: raise RuntimeError( f"{self.name} does NOT support attacking features." " If the model can conduct feature attack, please call `attacker.allow_feature_attack=True`." ) if structure_attack and not self.allow_structure_attack: raise RuntimeError( f"{self.name} does NOT support attacking structures." " If the model can conduct structure attack, please call `attacker.allow_structure_attack=True`." ) if num_budgets is None: num_budgets = int(self.graph.degree[target]) else: num_budgets = self.budget_as_int( num_budgets, max_perturbations=self.graph.degree[target]) self.target = target self.target_label = self.graph.node_label[ target] if self.graph.node_label is not None else None self.num_budgets = num_budgets self.direct_attack = direct_attack self.structure_attack = structure_attack self.feature_attack = feature_attack self.is_reseted = False
def __init__(self, target, width=30, verbose=1, interval=0.05, unit_name='step'): assert gg.is_intscalar(target), target self.target = target self.width = width self.verbose = verbose self.interval = interval self.unit_name = unit_name self._dynamic_display = ((hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()) or 'ipykernel' in sys.modules or 'posix' in sys.modules or 'PYCHARM_HOSTED' in os.environ) self._total_width = 0 self._seen_so_far = 0 self._start = time.perf_counter() self._last_update = 0
def augment_edge(edge_index: np.ndarray, nodes: np.ndarray, edge_weight: np.ndarray = None, *, nbrs_to_link: Optional[np.ndarray] = None, common_nbrs: Optional[np.ndarray] = None, fill_weight: float = 1.0) -> tuple: """Augment a set of edges by connecting nodes to element in ``nbrs_to_link``. Parameters ---------- edge_index: shape [M, 2] or [2, M] edge indices of a Scipy sparse adjacency matrix. nodes: the nodes that will be linked to the graph. list or np.array: the nodes connected to `nbrs_to_link` int: new added nodes connected to ``nbrs_to_link``, node ids [num_nodes, ..., num_nodes+nodes-1]. edge_weight: shape [M,] edge weights of a Scipy sparse adjacency matrix. nbrs_to_link: a list of N elements, where N is the length of 'nodes'. the specified neighbor(s) for each added node. if `None`, it will be set to `[0, ..., N-1]`. common_nbrs: shape [None,]. specified common neighbors for each added node. fill_weight: edge weight for the augmented edges. NOTE: ----- Both ``nbrs_to_link`` and ``common_nbrs`` should NOT be specified together. See Also -------- graphgallery.functional.augment_adj """ if nbrs_to_link is not None and common_nbrs is not None: raise RuntimeError("Only one of them should be specified.") edge_index = asedge(edge_index) if edge_weight is None: edge_weight = np.ones(edge_index.shape[1], dtype=gg.floatx()) num_nodes = edge_index.max() + 1 if gg.is_intscalar(nodes): # int, add nodes to the graph nodes = np.arange(num_nodes, num_nodes + nodes, dtype=edge_index.dtype) else: # array-like, link nodes to the graph nodes = np.asarray(nodes, dtype=edge_index.dtype) if common_nbrs is None and nbrs_to_link is None: nbrs_to_link = np.arange(nodes.size, dtype=edge_index.dtype) if not nodes.size == len(nbrs_to_link): raise ValueError( "The length of 'nbrs_to_link' should equal to 'nodes'.") if nbrs_to_link is not None: edges_to_link = np.hstack([ np.vstack([np.tile(node, get_length(nbr)), nbr]) for node, nbr in zip(nodes, nbrs_to_link) ]) else: n_repeat = len(common_nbrs) edges_to_link = np.hstack([ np.vstack([np.tile(node, n_repeat), common_nbrs]) for node in nodes ]) edges_to_link = np.hstack([edges_to_link, edges_to_link[[1, 0]]]) added_edge_weight = np.zeros(edges_to_link.shape[1], dtype=edge_weight.dtype) + fill_weight augmented_edge_index = np.hstack([edge_index, edges_to_link]) augmented_edge_weight = np.hstack([edge_weight, added_edge_weight]) return augmented_edge_index, augmented_edge_weight