12class TensorBackend final :
public IPolicyBackend {
14 std::string
name()
const override {
return "tensor-cpu"; }
15 Result<std::vector<double>>
evaluate(
const Policy&
p,
const Observation& o)
override {
17 tensor::Tensor
x(1,
int(
p.featureCount));
18 for (std::size_t i = 0; i < o.features.size(); ++i)
x.set(
int(i), o.features[i]);
20 auto layer = [&](
const tensor::Tensor&
input, std::uint32_t outputs,
bool activate) {
23 for (std::uint32_t j = 0; j < outputs; ++j)
24 for (
int i = 0; i <
inputs; ++i)
26 std::unique_ptr<tensor::Tensor> out(
input.matmul(&
weights));
27 for (std::uint32_t j = 0; j < outputs; ++j)
31 std::unique_ptr<tensor::Tensor> activated(out->tanh());
36 auto h1 =
layer(
x,
p.hiddenWidth,
true);
37 auto h2 =
layer(*h1,
p.hiddenWidth,
true);
38 auto logits =
layer(*h2,
p.actionCount,
false);
39 std::vector<float> masked(
p.actionCount, -std::numeric_limits<float>::infinity()), probabilities(
p.actionCount);
40 for (
auto action : o.legalActions) masked[
action] = logits->get(int(
action));
41 const int dims[] = {1, int(
p.actionCount)};
43 return Result<std::vector<double>>::success({probabilities.begin(), probabilities.end()});
Move-only operation result carrying either a value or Status.
Result< std::unique_ptr< IPolicyBackend > > makeTensorBackend()
Create an owning tensor eager CPU inference provider; caller owns registration.
void softmax(const float *in, const int *dims, int rank, int axis, bool logMode, float *out)
Softmax.
std::vector< OnnxNamedTensor > evaluate(const ModelData &, std::span< const OnnxNamedTensor >, const std::vector< std::string > &, OnnxCompute *, OnnxRunOptions options)
Evaluate.