#include <bits/stdc++.h>
using namespace std;
const double pi = acos(-1.0);
const int mod = 1000000007;
const vector<int> mods = {998244353, 1000000007, 1000000009};
const long long inf = 3e18;
const double eps = 0.0000001;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
long long n, m, c, q, x, y, z;
string s;
unordered_map<long long, long long> cg;
unordered_map<long long, unordered_set<long long>> g;
long long par[100100], siz[100100];
long long fnd(long long n1) {
  if (par[n1] != n1) par[n1] = fnd(par[n1]);
  return par[n1];
}
void unn(long long n1, long long n2) {
  long long p1 = fnd(n1), p2 = fnd(n2);
  if (p1 == p2) return;
  if (siz[p1] < siz[p2]) swap(p1, p2);
  par[p2] = p1;
  siz[p1] += siz[p2];
  for (auto& nx : g[p2]) g[p1].insert(nx);
}
void add() {
  cin >> x >> y >> z;
  x--;
  y--;
  if ((cg.find(x * 100100 + z) != end(cg)))
    unn(fnd(y), fnd(cg[x * 100100 + z]));
  else
    cg[x * 100100 + z] = fnd(y);
  if ((cg.find(y * 100100 + z) != end(cg)))
    unn(fnd(x), fnd(cg[y * 100100 + z]));
  else
    cg[y * 100100 + z] = fnd(x);
  g[fnd(x)].insert(y);
  g[fnd(y)].insert(x);
}
int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  cout.precision(13);
  cin >> n >> m >> c >> q;
  for (long long i = (0); i < (n); ++i) {
    par[i] = i;
    siz[i] = 1;
    g[i].insert(i);
  }
  for (long long i = (0); i < (m); ++i) add();
  for (long long _q = (0); _q < (q); ++_q) {
    cin >> s;
    if (s[0] == '?') {
      cin >> x >> y;
      x--;
      y--;
      if ((g[fnd(x)].find(y) != end(g[fnd(x)])))
        cout << "Yes\n";
      else
        cout << "No\n";
    } else
      add();
  }
  return 0;
}
