Esempio n. 1
0
    def attack(self,
               num_budgets=0.05,
               dim=32,
               window_size=5,
               K=100,
               attack_type="add_by_remove",
               structure_attack=True,
               feature_attack=False):

        if not attack_type in ["remove", "add", "add_by_remove"]:
            raise RuntimeError(
                'attack_type should be one of "remove", "add", "add_by_remove".'
            )

        super().attack(num_budgets, structure_attack, feature_attack)
        num_budgets = self.num_budgets

        adj = self.graph.adj_matrix

        if attack_type.startswith("add"):
            num_candidates = min(5 * num_budgets, self.num_edges)
            # num_candidates = 10000
            candidates = self.generate_candidates_addition(adj, num_candidates)
        else:
            candidates = self.generate_candidates_removal(adj)

        if attack_type == "add_by_remove":
            adj = gf.flip_adj(adj, candidates)
            deg_matrix = sp.diags(adj.sum(1).A1, dtype=adj.dtype)
            if K:
                vals_org, vecs_org = sp.linalg.eigsh(adj, k=K, M=deg_matrix)
            else:
                vals_org, vecs_org = spl.eigh(adj.toarray(),
                                              deg_matrix.toarray())
            delta_w = 1. - 2 * adj[candidates[:, 0], candidates[:, 1]].A1

            loss_for_candidates = estimate_loss_with_delta_eigenvals(
                candidates, delta_w, vals_org, vecs_org, self.num_nodes, dim,
                window_size)

            self.adj_flips = candidates[loss_for_candidates.argsort()
                                        [:num_budgets]]
        else:
            # vector indicating whether we are adding an edge (+1) or removing an edge (-1)
            delta_w = 1. - 2 * adj[candidates[:, 0], candidates[:, 1]].A1

            deg_matrix = sp.diags(adj.sum(1).A1, dtype=adj.dtype)
            if K:
                vals_org, vecs_org = sp.linalg.eigsh(adj, k=K, M=deg_matrix)
            else:
                vals_org, vecs_org = spl.eigh(adj.toarray(),
                                              deg_matrix.toarray())

            loss_for_candidates = estimate_loss_with_delta_eigenvals(
                candidates, delta_w, vals_org, vecs_org, self.num_nodes, dim,
                window_size)
            self.adj_flips = candidates[loss_for_candidates.argsort()
                                        [-num_budgets:]]
        return self
Esempio n. 2
0
 def from_flips(self, **flips):
     """Return a new graph from:
     'edge_flips' or 'feat_flips'
     """
     allowed = ("edge_flips", "feat_flips")
     g = self.copy()
     for k, v in flips.items():
         if v is None:
             continue
         if k == "edge_flips":
             g.update(adj_matrix=gf.flip_adj(g.adj_matrix, v))
         elif k == "feat_flips":
             g.update(attr_matrix=gf.flip_attr(g.attr_matrix, v))
         else:
             raise ValueError(f"Unrecognized key {k}, allowed: {allowed}.")
     return g
Esempio n. 3
0
    def A(self):
        adj_flips = self.edge_flips
        if self.modified_adj is None:
            if adj_flips is not None:
                self.modified_adj = gf.flip_adj(self.graph.adj_matrix,
                                                adj_flips)
            else:
                self.modified_adj = self.graph.adj_matrix

        adj = self.modified_adj

        if gf.is_anytensor(adj):
            adj = gf.tensoras(adj)

        if isinstance(adj, np.ndarray):
            adj = sp.csr_matrix(adj)
        elif sp.isspmatrix(adj):
            adj = adj.tocsr(copy=False)
        else:
            raise TypeError(adj)

        return adj