#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int n, m, c, q, fa[N], siz[N];
set<int> s[N];
map<int, vector<int> > mp[N];
inline int read() {
  int f = 1, x = 0;
  char ch = getchar();
  while (ch > '9' || ch < '0') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return f * x;
}
inline int findfa(int x) {
  if (fa[x] != x) fa[x] = findfa(fa[x]);
  return fa[x];
}
inline void unionn(int x, int y) {
  x = findfa(x), y = findfa(y);
  if (x != y) {
    if (siz[x] < siz[y]) swap(x, y);
    for (auto i : s[y]) s[x].insert(i);
    fa[y] = x, siz[x] += siz[y];
  }
}
inline void add() {
  int x = read(), y = read(), z = read();
  s[findfa(x)].insert(y), s[findfa(y)].insert(x);
  if (mp[x][z].size()) unionn(y, mp[x][z][0]);
  if (mp[y][z].size()) unionn(x, mp[y][z][0]);
  mp[x][z].push_back(y), mp[y][z].push_back(x);
}
inline void query() {
  int x = read(), y = read();
  if (findfa(x) == findfa(y) || s[findfa(x)].count(y))
    printf("Yes\n");
  else
    printf("No\n");
  return;
}
int main() {
  n = read(), m = read(), c = read(), q = read();
  for (int i = (1), iend = (n); i <= iend; i++) fa[i] = i, siz[i] = 1;
  for (int i = (1), iend = (m); i <= iend; i++) add();
  for (int i = (1), iend = (q); i <= iend; i++) {
    char ch;
    scanf("%c", &ch);
    if (ch == '+')
      add();
    else
      query();
  }
  return 0;
}
