#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100007;
vector<int> grp[MAXN];
int pr[MAXN];
set<int> neighbors[MAXN];
vector<pair<int, int> > edg[MAXN];
void unite(int u, int v) {
  u = pr[u];
  v = pr[v];
  if (u == v) return;
  if (grp[u].size() < grp[v].size()) swap(u, v);
  for (int x : grp[v]) {
    pr[x] = u;
    grp[u].push_back(x);
    for (pair<int, int> pr : edg[x]) {
      neighbors[pr.first].erase(v);
      neighbors[pr.first].insert(u);
    }
  }
  grp[v].clear();
}
map<int, int> first[MAXN];
void fixcolor(int u, int v, int c) {
  if (first[u].find(c) == first[u].end()) first[u][c] = v;
  unite(v, first[u][c]);
}
void addEdge(int u, int v, int c) {
  edg[u].emplace_back(v, c);
  edg[v].emplace_back(u, c);
  neighbors[u].insert(pr[v]);
  neighbors[v].insert(pr[u]);
  fixcolor(u, v, c);
  fixcolor(v, u, c);
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m, c, q;
  cin >> n >> m >> c >> q;
  for (int i = 1; i <= n; i++) {
    pr[i] = i;
    grp[i].push_back(i);
  }
  while (m--) {
    int u, v, c;
    cin >> u >> v >> c;
    addEdge(u, v, c);
  }
  while (q--) {
    char op;
    int u, v;
    cin >> op >> u >> v;
    if (op == '+') {
      int c;
      cin >> c;
      addEdge(u, v, c);
    } else {
      bool flag = false;
      if (pr[u] == pr[v]) {
        flag = true;
      } else if (neighbors[v].find(pr[u]) != neighbors[v].end()) {
        flag = true;
      }
      cout << (flag ? "Yes" : "No") << "\n";
    }
  }
  return 0;
}
