m, n = gets.split.map(&:to_i)

dimensions = (0..n).map { (0..m).map { [0, Float::INFINITY] } }

(1..m).each do |i|
    k = gets.to_i
    k.times do
        gets =~ /(\d+) ([<>])= (\d+)/
        d, c, x = $1.to_i, $2, $3.to_i
        if c == ?<
            dimensions[d][i][1] = x if x < dimensions[d][i][1]
        else
            dimensions[d][i][0] = x if x > dimensions[d][i][0]
        end
        if dimensions[d][i][1] < dimensions[d][i][0]
            puts 'No'
            exit
        end
    end
end

require 'set'
require 'tsort'

class Hash
    include TSort
    alias tsort_each_node each_key
    def tsort_each_child(u)
        self[u].each {|v| yield v}
    end
end

g = {}
(1..m).each {|i| g[i] = Set.new}

(1..n).each do |d|
    (1..m).to_a.combination(2) do |i, j|
        u, v = dimensions[d][i], dimensions[d][j]
        g[i] << j if u[1] < v[0]
        g[j] << i if v[1] < u[0]
    end
end

begin
    g.tsort
    puts 'Yes'
rescue
    puts 'No'
end