import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.StringTokenizer;
// TODO: https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV4yLUiKDUoDFAUx&categoryId=AV4yLUiKDUoDFAUx&categoryType=CODE&&&
public class Solution {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StringBuilder sb;
static StringTokenizer tokens;
static int T, R, C;
static char[][] map;
static boolean isEnd;
static int[][] dirs = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } };
static int DU = 0, DR = 1, DD = 2, DL = 3;
public static void main(String[] args) throws NumberFormatException, IOException {
sb = new StringBuilder();
br = new BufferedReader(new StringReader(src));
T = Integer.parseInt(br.readLine());
for (int t = 1; t <= T; t++) {
isEnd = false;
String answer = null;
tokens = new StringTokenizer(br.readLine());
R = Integer.parseInt(tokens.nextToken());
C = Integer.parseInt(tokens.nextToken());
map = new char[R][C];
// 맵 구성
boolean canFinish = false;
for (int r = 0; r < R; r++) {
map[r] = br.readLine().toCharArray();
for (int c = 0; c < C; c++) { //@가 없다면 전혀 고민할 필요도 없다.
if (map[r][c] == '@') {
canFinish = true;
}
}
}
// 입력 확인
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (canFinish) {
check(0, 0, DR, 0, new boolean[R][C][4][16]);
}
answer = isEnd ? "YES" : "NO";
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sb.append(String.format("#%d %s\n", t, answer));
}
System.out.println(sb);
}
static void check(int r, int c, int d, int m, boolean[][][][] visited) {
if (visited[r][c][d][m]) {// 동일한 조건에서 이미 왔던 자리면 그만하자.
isEnd = false;
return;
} else { // 방문 처리 후 효과 처리
visited[r][c][d][m] = true;
char info = map[r][c];
if (info == '@') {
isEnd = true;
return;
} else if (info == '<') {
d = DL;
} else if (info == '>') {
d = DR;
} else if (info == '^') {
d = DU;
} else if (info == 'v') {
d = DD;
} else if (info == '_') {
d = m == 0 ? DR : DL;
} else if (info == '|') {
d = m == 0 ? DD : DU;
} else if (info == '+') {
m = m == 15 ? 0 : m + 1;
} else if (info == '-') {
m = m == 0 ? 15 : m - 1;
} else if (info == '.') {
} else if (info == '?') {
for (int i = 0; i < 4 && !isEnd; i++) { // 4 방향을 가보는데 종료되지 않은 경우만 가보자
int [] newC = move(r, c, i);
check(newC[0], newC[1], i, m, visited);
}
return;// 새로운 흐름을 각자 간다.
} else {
m = info - '0';
}
int [] newC =move(r, c, d);
check(newC[0], newC[1], d, m, visited);
}
}
static int[] move(int r, int c, int d) {
int nR = r + dirs[d][0];
int nC = c + dirs[d][1];
r = nR == -1 ? R - 1 : nR == R ? 0 : nR;
c = nC == -1 ? C - 1 : nC == C ? 0 : nC;
return new int[] { r, c };
}
static String src = "3\r\n" +
"2 6\r\n" +
"6>--v.\r\n" +
".^--_@\r\n" +
"2 6\r\n" +
"5>--v.\r\n" +
".^--_@\r\n" +
"2 6\r\n" +
".>--v.\r\n" +
".^--?@";
}