#include <bits/stdc++.h>
using namespace std;
template <class T>
bool umin(T& a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
bool umax(T& a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
int ata[500009], node;
set<int> s[500009];
map<pair<int, int>, int> pm;
int tap(int x) {
  if (!ata[x]) return x;
  return ata[x] = tap(ata[x]);
}
void merge(int x, int y) {
  if ((x = tap(x)) == (y = tap(y))) return;
  if (s[x].size() < s[y].size()) swap(x, y);
  ata[y] = x;
  for (__typeof((s[y]).begin()) it = (s[y]).begin(); it != (s[y]).end(); it++)
    s[x].insert(*it);
  s[y].clear();
}
int get(int x, int y) {
  if (!pm[make_pair(x, y)]) pm[make_pair(x, y)] = ++node;
  return pm[make_pair(x, y)];
}
void add(int x, int y, int z) {
  merge(y, get(x, z));
  merge(x, get(y, z));
  s[tap(x)].insert(y);
  s[tap(y)].insert(x);
}
int main() {
  int n, m, c, q;
  scanf("%d%d%d%d", &n, &m, &c, &q);
  node = n;
  while (m--) {
    int u, v, w;
    scanf("%d%d%d", &u, &v, &w);
    add(u, v, w);
  }
  while (q--) {
    char c;
    scanf(" %c", &c);
    if (c == '+') {
      int x, y, z;
      scanf("%d%d%d", &x, &y, &z);
      add(x, y, z);
    } else {
      int x, y;
      scanf("%d%d", &x, &y);
      int tmp = tap(x);
      if (tmp == tap(y) or s[tmp].find(y) != s[tmp].end())
        puts("Yes");
      else
        puts("No");
    }
  }
  return 0;
}
