#include <bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
long long POW(long long a, long long b, long long MMM = MOD) {
  long long ret = 1;
  for (; b; b >>= 1, a = (a * a) % MMM)
    if (b & 1) ret = (ret * a) % MMM;
  return ret;
}
long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }
long long lcm(long long a, long long b) {
  if (a == 0 || b == 0) return a + b;
  return a * (b / gcd(a, b));
}
int dx[] = {0, 1, 0, -1, 1, 1, -1, -1}, dy[] = {1, 0, -1, 0, 1, -1, 1, -1};
int ddx[] = {-1, -2, 1, -2, 2, -1, 2, 1}, ddy[] = {-2, -1, -2, 1, -1, 2, 1, 2};
int f[100001];
map<int, int> col[100001];
set<int> adj[100001];
int n, m, c, q;
int find(int x) {
  if (f[x] == x) return x;
  return f[x] = find(f[x]);
}
void merge(int x, int y) {
  x = find(x), y = find(y);
  if (x == y) return;
  if (adj[x].size() > adj[y].size()) swap(x, y);
  f[x] = y;
  while (!adj[x].empty()) {
    adj[y].insert(*adj[x].begin());
    adj[x].erase(adj[x].begin());
  }
}
void add(int x, int y, int z) {
  if (col[x].count(z))
    merge(y, col[x][z]);
  else
    col[x][z] = y;
  if (col[y].count(z))
    merge(x, col[y][z]);
  else
    col[y][z] = x;
  adj[find(x)].insert(y);
  adj[find(y)].insert(x);
}
int main() {
  scanf("%d%d%d%d", &n, &m, &c, &q);
  for (int(i) = (1); (i) <= (n); (i) += (1)) f[i] = i;
  while (m--) {
    int x, y, z;
    scanf("%d%d%d", &x, &y, &z);
    add(x, y, z);
  }
  while (q--) {
    char c;
    int x, y, z;
    scanf(" %c%d%d", &c, &x, &y);
    if (c == '+') {
      scanf("%d", &z);
      add(x, y, z);
    } else {
      if (find(x) == find(y) || adj[find(x)].find(y) != adj[find(x)].end())
        puts("Yes");
      else
        puts("No");
    }
  }
}
