#include <bits/stdc++.h>
using namespace std;
struct bian {
  int to, nxt, va;
} bi[400040];
int n, m, c, q, siz, head[100010], num, tot, f[100010], id[100010], idnum,
    d[100010];
int query[100010][4];
bitset<700> lt[100010];
map<int, int> mp[100010];
void add(int from, int to, int va) {
  bi[++num].nxt = head[from];
  head[from] = num;
  bi[num].to = to;
  bi[num].va = va;
}
int find(int x) {
  if (x != f[x]) return f[x] = find(f[x]);
  return x;
}
int main() {
  scanf("%d %d %d %d", &n, &m, &c, &q);
  int x, y, z;
  for (int i = 1; i <= m; ++i) {
    scanf("%d %d %d", &x, &y, &z);
    add(x, y, z);
    ++d[x];
    add(y, x, z);
    ++d[y];
  }
  tot = 2 * m;
  char op;
  for (int i = 1; i <= q; ++i) {
    scanf(" %c", &op);
    if (op == '+') {
      scanf("%d %d %d", &x, &y, &z);
      query[i][1] = x, query[i][2] = y, query[i][3] = z;
      ++d[x], ++d[y];
      tot += 2;
    } else {
      scanf("%d %d", &x, &y);
      query[i][0] = 1, query[i][1] = x, query[i][2] = y;
    }
  }
  siz = sqrt(tot);
  for (int i = 1; i <= n; ++i) f[i] = i;
  for (int i = 1; i <= n; ++i)
    if (d[i] >= siz) {
      id[i] = ++idnum;
      for (int j = head[i]; j; j = bi[j].nxt) lt[bi[j].to].set(idnum);
    }
  for (int i = 1; i <= n; ++i)
    for (int j = head[i]; j; j = bi[j].nxt) {
      if (mp[i].count(bi[j].va)) {
        x = find(bi[j].to), y = find(mp[i][bi[j].va]);
        if (x != y) lt[y] |= lt[x], f[x] = y;
      } else
        mp[i][bi[j].va] = bi[j].to;
    }
  for (int i = 1; i <= q; ++i) {
    if (query[i][0]) {
      x = query[i][1], y = query[i][2];
      if (find(x) == find(y)) {
        printf("Yes\n");
        continue;
      }
      bool flag = 0;
      if (d[y] < siz) {
        for (int j = head[y]; j; j = bi[j].nxt)
          if (find(x) == find(bi[j].to)) {
            flag = 1;
            break;
          }
      } else
        flag = lt[find(x)][id[y]];
      if (flag)
        printf("Yes\n");
      else
        printf("No\n");
    } else {
      x = query[i][1], y = query[i][2], z = query[i][3];
      add(x, y, z), add(y, x, z);
      if (id[y]) lt[find(x)].set(id[y]);
      if (id[x]) lt[find(y)].set(id[x]);
      if (mp[x][z]) {
        if (find(mp[x][z]) != find(y)) {
          lt[find(y)] |= lt[find(mp[x][z])];
          f[find(mp[x][z])] = find(y);
        }
      } else
        mp[x][z] = y;
      swap(x, y);
      if (mp[x][z]) {
        if (find(mp[x][z]) != find(y)) {
          lt[find(y)] |= lt[find(mp[x][z])];
          f[find(mp[x][z])] = find(y);
        }
      } else
        mp[x][z] = y;
    }
  }
  return 0;
}
