#include <bits/stdc++.h>
using namespace std;
set<pair<int, int> > *e;
int *parent;
set<int> *v;
int fp(int a) {
  if (parent[a] != a) parent[a] = fp(parent[a]);
  return parent[a];
}
void dsu(int a, int b) {
  a = fp(a);
  b = fp(b);
  if (a != b) {
    if (v[a].size() < v[b].size()) swap(a, b);
    for (set<int>::iterator i = v[b].begin(); i != v[b].end(); i++)
      v[a].insert(*i);
    v[b].clear();
    parent[b] = a;
  }
}
void add(int a, int b, int c) {
  v[fp(a)].insert(b);
  v[fp(b)].insert(a);
  set<pair<int, int> >::iterator t = e[b].lower_bound(make_pair(c, -1));
  if ((t == e[b].end()) || (t->first != c)) {
    e[b].insert(make_pair(c, a));
  } else {
    dsu(a, t->second);
  }
  t = e[a].lower_bound(make_pair(c, -1));
  if ((t == e[a].end()) || (t->first != c)) {
    e[a].insert(make_pair(c, b));
  } else {
    dsu(b, t->second);
  }
}
int main() {
  int n, m, c, q;
  int i;
  char ch;
  scanf("%d %d %d %d", &n, &m, &c, &q);
  parent = new int[100010];
  v = new set<int>[100010];
  e = new set<pair<int, int> >[100010];
  for (i = 0; i < n; i++) {
    parent[i] = i;
  }
  int a, b, cl;
  while (m--) {
    scanf("%d %d %d", &a, &b, &cl);
    add(a, b, cl);
  }
  while (q--) {
    scanf(" %c", &ch);
    if (ch == '?') {
      scanf("%d %d", &a, &b);
      if (fp(a) == fp(b) || (v[fp(a)].find(b) != v[fp(a)].end()))
        printf("Yes\n");
      else
        printf("No\n");
    } else {
      scanf("%d %d %d", &a, &b, &cl);
      add(a, b, cl);
    }
  }
}
