const REGEX_FLOATING_POINT = r"[-+]?[0-9]*\.?[0-9]+"

"""
    Read a `.alpha` file as generated by pomdp-solve.
    Works the same was as `read_pomdp` in `POMDPXFile.jl`.

    The `.alpha` file format is recapped here as follows,
    see: http://www.pomdp.org/code/alpha-file-spec.html

    A set of vectors is the representation use for the value function and each
    vector has an action associated with it. The vectors represent the coefficients
    of a hyperplane passing through the origin. The format specified here is what is
    output from the 'pomdp-solve' program and what will be necessary for input to
    the 'pomdp-solve' program with the '-terminal_values' command line option.

    The format is simply:

    A
    V1 V2 V3 ... VN

    A
    V1 V2 V3 ... VN

    ...


    Where `A` is an action number and the `V1` through `VN` are real values
    representing the components of a particular vector that has the associated
    action. The action number is the 0-based index of the action as specificed in
    the input POMDP file. The vector represents the coefficients of a hyperplane
    representing one facet of the piecewise linear and convex value function.
    Note that the length of the lists needs to be equal to the number of states in
    the POMDP.

    To find which action is the "best" for a given set of alpha vectors, the belief
    state probabilities would be used in a dot product against each alpha vectors'
    coefficients. The action associated with the vector with the highest value is
    the best action to take for that belief state given the value function.
"""
function read_alpha(filename::AbstractString)

    @assert isfile(filename) "filename $(filename) does not exist"

    lines = readlines(open(filename))

    alpha_vector_line_indeces = Int[]
    vector_length = -1
    for i in 1:length(lines)
        
        matches = collect((m.match for m = eachmatch(REGEX_FLOATING_POINT, lines[i])))
        
        if length(matches) > 1
            push!(alpha_vector_line_indeces, i)
            @assert occursin(r"^(\d)*$", lines[i-1]) "previous line must contain an action index"

            if vector_length == -1
                vector_length = length(matches)
            else
                @assert vector_length == length(matches) "vector length is inconsistent. Was $vector_length, is $(length(matches)) on line $i"
            end
        end
    end
    num_alpha_vectors = length(alpha_vector_line_indeces)

    # Initialize the Γ matrix.
    # The α-vectors are the columns
    alpha_vectors = Array{Float64}(undef, vector_length, num_alpha_vectors)

    # Initialize the alpha_actions vector
    # alpha_actions[i] is the index of the action associated with
    # the alpha-vector in the ith column of alpha_vectors
    # Note that these are 0-indexed
    alpha_actions = Array{Int}(undef, num_alpha_vectors)

    for (i,line_index) in enumerate(alpha_vector_line_indeces)
        alpha_actions[i] = parse(Int, lines[line_index-1])

        for (j,match) in enumerate(eachmatch(REGEX_FLOATING_POINT, lines[line_index]))
            alpha_vectors[j,i] = parse(Float64, match.match)
        end
    end

    return alpha_vectors, alpha_actions
end
