#include <bits/stdc++.h>
using namespace std;
int n, m, c, q;
vector<int> e[100007];
int F[100007];
int Find(int x) { return F[x] == x ? x : F[x] = Find(F[x]); }
set<int> S[100007], s[100007];
int idx;
map<int, int> id[100007];
int a[100007 * 4], b[100007 * 4], f[100007 * 4], g[100007 * 4];
int find(int x) {
  if (f[x] == x) return x;
  int fx = find(f[x]);
  g[x] ^= g[f[x]];
  return f[x] = fx;
}
void join(int x, int y) {
  int fx = Find(x), fy = Find(y);
  if (fx == fy) return;
  if (S[fx].size() > S[fy].size()) swap(fx, fy);
  for (auto u : S[fx]) {
    S[fy].insert(u);
    for (int v : e[u]) s[v].erase(fx), s[v].insert(fy);
  }
  F[fx] = fy;
}
void add(int x, int y, int z) {
  if (id[z].find(x) == id[z].end()) {
    id[z][x] = ++idx;
    a[idx] = x, b[idx] = 0;
    g[f[idx] = idx] = 0;
  }
  if (id[z].find(y) == id[z].end()) {
    id[z][y] = ++idx;
    a[idx] = y, b[idx] = 0;
    g[f[idx] = idx] = 0;
  }
  int zx = id[z][x], zy = id[z][y];
  int fzx = find(zx), fzy = find(zy);
  if (fzx != fzy) {
    f[fzx] = fzy, g[fzx] = g[zx] ^ g[zy] ^ 1;
    if (!b[fzy]) b[fzy] = a[g[zy] ? zy : zx];
    if (!g[fzx]) {
      join(a[fzx], a[fzy]);
      if (b[fzx]) join(b[fzx], b[fzy]);
    } else {
      join(a[fzx], b[fzy]);
      if (b[fzx]) join(b[fzx], a[fzy]);
    }
  } else if (g[zx] ^ g[zy] ^ 1)
    join(b[fzx], a[fzx]);
  e[x].push_back(y), s[x].insert(Find(y));
  e[y].push_back(x), s[y].insert(Find(x));
}
int main() {
  scanf("%d%d%d%d", &n, &m, &c, &q);
  for (int i = 1; i <= n; ++i) F[i] = i, S[i].insert(i);
  while (m--) {
    int x, y, z;
    scanf("%d%d%d", &x, &y, &z);
    add(x, y, z);
  }
  while (q--) {
    char o = getchar();
    while (o != '+' && o != '?') o = getchar();
    int x, y, z;
    if (o == '+') {
      scanf("%d%d%d", &x, &y, &z);
      add(x, y, z);
    } else {
      scanf("%d%d", &x, &y);
      if (Find(x) == Find(y) || s[y].find(Find(x)) != s[y].end())
        puts("Yes");
      else
        puts("No");
    }
  }
}
