#include <bits/stdc++.h>
using namespace std;
inline long long read() {
  long long x = 0, f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    x = (x << 1) + (x << 3) + c - '0';
    c = getchar();
  }
  return x * f;
}
int n, m, C, Q;
map<int, vector<int> > mp[100020];
struct Union_Set {
  int f[100020];
  void init(int n) {
    for (int i = 1; i <= n; ++i) f[i] = i;
  }
  inline int getf(int x) { return f[x] == x ? x : f[x] = getf(f[x]); }
  inline int Merge(int x, int y) {
    int fx = getf(x), fy = getf(y);
    if (fx == fy) return 0;
    f[fy] = fx;
    return 1;
  }
} S;
set<int> s[100020];
void Merge(int x, int y) {
  x = S.getf(x), y = S.getf(y);
  if (mp[x].size() < mp[y].size()) {
    swap(x, y);
  }
  if (!S.Merge(x, y)) return;
  for (auto u : s[y]) s[x].insert(u);
}
void Add(int u, int v, int w) {
  s[S.getf(u)].insert(v);
  s[S.getf(v)].insert(u);
  mp[u][w].push_back(v);
  mp[v][w].push_back(u);
  Merge(mp[u][w][0], v);
  Merge(mp[v][w][0], u);
}
int main() {
  n = read(), m = read(), C = read(), Q = read();
  S.init(n);
  for (int i = 1; i <= m; ++i) {
    int u = read(), v = read(), w = read();
    Add(u, v, w);
  }
  while (Q--) {
    char opt;
    do {
      opt = getchar();
    } while (opt != '?' && opt != '+');
    if (opt == '+') {
      int u = read(), v = read(), w = read();
      Add(u, v, w);
    } else {
      int u = read(), v = read();
      printf(S.getf(u) == S.getf(v) || s[S.getf(u)].count(v) ? "Yes\n"
                                                             : "No\n");
    }
  }
  return 0;
}
