#include <bits/stdc++.h>
using namespace std;
set<pair<int, int> > g[100005];
multiset<int> son[100005];
int parent[100005];
vector<int> spis[100005];
int find_parent(int v) {
  if (parent[v] == v) return v;
  return parent[v] = find_parent(parent[v]);
}
void unions(int a, int b) {
  a = find_parent(a), b = find_parent(b);
  if (a != b) {
    if ((int)spis[a].size() < (int)spis[b].size()) swap(a, b);
    parent[b] = a;
    for (int i = 0; i < (int)spis[b].size(); i++) {
      int v = spis[b][i];
      spis[a].push_back(v);
      for (auto it = g[v].begin(); it != g[v].end(); it++) {
        pair<int, int> A = *it;
        son[A.second].erase(son[A.second].find(b));
        son[A.second].insert(a);
      }
    }
  }
  return;
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n, m, col, quer;
  cin >> n >> m >> col >> quer;
  for (int i = 1; i <= m; i++) {
    int u, v, w;
    cin >> u >> v >> w;
    g[u].insert(make_pair(w, v)), g[v].insert(make_pair(w, u));
  }
  for (int i = 1; i <= n; i++) parent[i] = i, spis[i].push_back(i);
  for (int i = 1; i <= n; i++) {
    for (auto it = g[i].begin(); it != g[i].end(); it++) {
      pair<int, int> A = *it;
      son[A.second].insert(i);
    }
  }
  for (int i = 1; i <= n; i++) {
    for (auto it = g[i].begin(); it != g[i].end(); it++) {
      auto its = it;
      its++;
      if (its == g[i].end()) break;
      pair<int, int> A = *it, B = *its;
      if (A.first == B.first) unions(A.second, B.second);
    }
  }
  for (int rep = 1; rep <= quer; rep++) {
    char c;
    cin >> c;
    if (c == '+') {
      int u, v, w;
      cin >> u >> v >> w;
      g[u].insert(make_pair(w, v)), g[v].insert(make_pair(w, u));
      son[u].insert(find_parent(v)), son[v].insert(find_parent(u));
      auto it = g[u].find(make_pair(w, v));
      it++;
      if (it != g[u].end() && w == (*it).first) unions(v, (*it).second);
      it--;
      if (it != g[u].begin()) {
        it--;
        if (w == (*it).first) unions(v, (*it).second);
      }
      it = g[v].find(make_pair(w, u));
      it++;
      if (it != g[v].end() && w == (*it).first) unions(u, (*it).second);
      it--;
      if (it != g[v].begin()) {
        it--;
        if (w == (*it).first) unions(u, (*it).second);
      }
    } else {
      int u, v;
      cin >> u >> v;
      int a = find_parent(u), b = find_parent(v);
      if (a == b || son[v].find(a) != son[v].end())
        cout << "Yes\n";
      else
        cout << "No\n";
    }
  }
  return 0;
}
