in tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/ConcreteFunction.java [535:618]
private static ConcreteFunction buildFromGraph(Graph graph, Signature signature) {
try (PointerScope scope = new PointerScope();
Reference ref = graph.ref()) {
TF_Status status = TF_Status.newStatus();
List<Operand<?>> inputs =
signature.getInputs().entrySet().stream()
.map(
(x) ->
TensorFunction.validateDescription(x.getValue(), graph, x.getKey(), "Input"))
.collect(Collectors.toList());
List<Operand<?>> outputs =
signature.getOutputs().entrySet().stream()
.map(
(x) ->
TensorFunction.validateDescription(x.getValue(), graph, x.getKey(), "Output"))
.collect(Collectors.toList());
List<GraphOperation> ops =
new ArrayList<>(graph.completeSubgraph(new HashSet<>(inputs), new HashSet<>(outputs)));
inputs.forEach(input -> ops.remove((GraphOperation) input.op()));
ops.forEach(
x -> {
if (x.type().equals(Placeholder.OP_NAME)
|| x.type().equals(PlaceholderWithDefault.OP_NAME)) {
throw new IllegalArgumentException(
"Can't calculate outputs ("
+ outputs
+ ") from inputs ("
+ inputs
+ "), "
+ "they also depend on \""
+ x
+ "\"");
}
});
// Python sometimes has NoOps as outputs
Ops tf = Ops.create(graph).withSubScope("functionControlOutputs");
for (int i = 0; i < outputs.size(); i++) {
Operand<?> output = outputs.get(i);
if (output.op().numOutputs() < 1) {
Operand<TBool> realOutput =
tf.withControlDependencies(Collections.singletonList(output))
.withName(output.op().name() + "_control")
.constant(false);
ops.add((GraphOperation) realOutput.op());
outputs.set(i, realOutput);
}
}
PointerPointer<TF_Operation> operations = new PointerPointer<>(ops.size());
for (int i = 0; i < ops.size(); i++) {
operations.put(i, ops.get(i).getUnsafeNativeHandle());
}
TF_Function handle =
TF_GraphToFunction(
ref.nativeHandle(),
new BytePointer(signature.key()),
(byte) 1,
ops.size(),
operations,
inputs.size(),
resolveToOutput(graph, inputs),
outputs.size(),
resolveToOutput(graph, outputs),
null,
null,
new BytePointer(
signature.methodName() != null
? signature.methodName()
: "Method " + signature.key()),
status);
handle.withDeallocator();
status.throwExceptionIfNotOK();
return new ConcreteFunction(
signature, new NativeFunction(handle), graph.getNativeFunctions(scope));
}
}