#include <bits/stdc++.h>
using namespace std;
int n, m, c, q, cnt;
int ata[500005];
set<int> s[500005];
map<pair<int, int>, int> mp;
int bul(int node) {
  if (ata[node] == node) return node;
  return ata[node] = bul(ata[node]);
}
void merge(int a, int b) {
  if ((a = bul(a)) != (b = bul(b))) {
    if (((int)s[a].size()) < ((int)s[b].size())) swap(a, b);
    for (auto x : s[b]) s[a].insert(x);
    s[b].clear();
    ata[b] = a;
  }
}
void nn(int a, int c) {
  mp[{a, c}] = ++cnt;
  ata[cnt] = cnt;
  s[cnt].insert(a);
}
void add(int x, int y, int z) {
  if (!mp[{x, z}]) nn(x, z);
  if (!mp[{y, z}]) nn(y, z);
  merge(x, mp[{y, z}]);
  merge(y, mp[{x, z}]);
}
int main() {
  scanf("%d %d %d %d", &n, &m, &c, &q);
  for (int i = 1; i <= n; i++) ata[i] = ++cnt;
  for (int i = 1; i <= m; i++) {
    int x, y, z;
    scanf("%d %d %d", &x, &y, &z);
    add(x, y, z);
  }
  while (q--) {
    char t;
    scanf(" %c", &t);
    if (t == '?') {
      int x, y;
      scanf("%d %d", &x, &y);
      if (bul(x) == bul(y) || s[bul(x)].find(y) != s[bul(x)].end())
        printf("Yes\n");
      else
        printf("No\n");
    } else {
      int x, y, z;
      scanf("%d %d %d", &x, &y, &z);
      add(x, y, z);
    }
  }
}
