• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 package org.tensorflow.op;
17 
18 import org.tensorflow.ExecutionEnvironment;
19 import org.tensorflow.Operand;
20 import org.tensorflow.OperationBuilder;
21 
22 import java.util.ArrayList;
23 
24 /**
25  * Manages groups of related properties when creating Tensorflow Operations, such as a common name
26  * prefix.
27  *
28  * <p>A {@code Scope} is a container for common properties applied to TensorFlow Ops. Normal user
29  * code initializes a {@code Scope} and provides it to Operation building classes. For example:
30  *
31  * <pre>{@code
32  * Scope scope = new Scope(graph);
33  * Constant c = Constant.create(scope, 42);
34  * }</pre>
35  *
36  * <p>An Operation building class acquires a Scope, and uses it to set properties on the underlying
37  * Tensorflow ops. For example:
38  *
39  * <pre>{@code
40  * // An operator class that adds a constant.
41  * public class Constant {
42  *   public static Constant create(Scope scope, ...) {
43  *      scope.graph().opBuilder(
44  *        "Const", scope.makeOpName("Const"))
45  *        .setAttr(...)
46  *        .build()
47  *      ...
48  *   }
49  * }
50  * }</pre>
51  *
52  * <p><b>Scope hierarchy:</b>
53  *
54  * <p>A {@code Scope} provides various {@code with()} methods that create a new scope. The new scope
55  * typically has one property changed while other properties are inherited from the parent scope.
56  *
57  * <p>An example using {@code Constant} implemented as before:
58  *
59  * <pre>{@code
60  * Scope root = new Scope(graph);
61  *
62  * // The linear subscope will generate names like linear/...
63  * Scope linear = Scope.withSubScope("linear");
64  *
65  * // This op name will be "linear/W"
66  * Constant.create(linear.withName("W"), ...);
67  *
68  * // This op will be "linear/Const", using the default
69  * // name provided by Constant
70  * Constant.create(linear, ...);
71  *
72  * // This op will be "linear/Const_1", using the default
73  * // name provided by Constant and making it unique within
74  * // this scope
75  * Constant.create(linear, ...);
76  * }</pre>
77  *
78  * <p>Scope objects are <b>not</b> thread-safe.
79  */
80 public final class Scope {
81 
82   /**
83    * Create a new top-level scope.
84    *
85    * @param env The execution environment used by the scope.
86    */
Scope(ExecutionEnvironment env)87   public Scope(ExecutionEnvironment env) {
88     this(env, new NameScope(), new ArrayList<Operand<?>>());
89   }
90 
91   /** Returns the execution environment used by this scope. */
env()92   public ExecutionEnvironment env() {
93     return env;
94   }
95 
96   /**
97    * Returns a new scope where added operations will have the provided name prefix.
98    *
99    * <p>Ops created with this scope will have {@code name/childScopeName/} as the prefix. The actual
100    * name will be unique in the returned scope. All other properties are inherited from the current
101    * scope.
102    *
103    * <p>The child scope name must match the regular expression {@code [A-Za-z0-9.][A-Za-z0-9_.\-]*}
104    *
105    * @param childScopeName name for the new child scope
106    * @return a new subscope
107    * @throws IllegalArgumentException if the name is invalid
108    */
withSubScope(String childScopeName)109   public Scope withSubScope(String childScopeName) {
110     return new Scope(env, nameScope.withSubScope(childScopeName), controlDependencies);
111   }
112 
113   /**
114    * Return a new scope that uses the provided name for an op.
115    *
116    * <p>Operations created within this scope will have a name of the form {@code
117    * name/opName[_suffix]}. This lets you name a specific operator more meaningfully.
118    *
119    * <p>Names must match the regular expression {@code [A-Za-z0-9.][A-Za-z0-9_.\-]*}
120    *
121    * @param opName name for an operator in the returned scope
122    * @return a new Scope that uses opName for operations.
123    * @throws IllegalArgumentException if the name is invalid
124    */
withName(String opName)125   public Scope withName(String opName) {
126     return new Scope(env, nameScope.withName(opName), controlDependencies);
127   }
128 
129   /**
130    * Create a unique name for an operator, using a provided default if necessary.
131    *
132    * <p>This is normally called only by operator building classes.
133    *
134    * <p>This method generates a unique name, appropriate for the name scope controlled by this
135    * instance. Typical operator building code might look like
136    *
137    * <pre>{@code
138    * scope.env().opBuilder("Const", scope.makeOpName("Const"))...
139    * }</pre>
140    *
141    * <p><b>Note:</b> if you provide a composite operator building class (i.e, a class that creates a
142    * set of related operations by calling other operator building code), the provided name will act
143    * as a subscope to all underlying operators.
144    *
145    * @param defaultName name for the underlying operator.
146    * @return unique name for the operator.
147    * @throws IllegalArgumentException if the default name is invalid.
148    */
makeOpName(String defaultName)149   public String makeOpName(String defaultName) {
150     return nameScope.makeOpName(defaultName);
151   }
152 
Scope( ExecutionEnvironment env, NameScope nameScope, Iterable<Operand<?>> controlDependencies)153   private Scope(
154       ExecutionEnvironment env, NameScope nameScope, Iterable<Operand<?>> controlDependencies) {
155     this.env = env;
156     this.nameScope = nameScope;
157     this.controlDependencies = controlDependencies;
158   }
159 
160   /**
161    * Returns a new scope where added operations will have the provided control dependencies.
162    *
163    * <p>Ops created with this scope will have a control edge from each of the provided controls. All
164    * other properties are inherited from the current scope.
165    *
166    * @param controls control dependencies for ops created with the returned scope
167    * @return a new scope with the provided control dependencies
168    */
withControlDependencies(Iterable<Operand<?>> controls)169   public Scope withControlDependencies(Iterable<Operand<?>> controls) {
170     return new Scope(env, nameScope, controls);
171   }
172 
173   /**
174    * Adds each Operand in controlDependencies as a control input to the provided builder.
175    *
176    * @param builder OperationBuilder to add control inputs to
177    */
applyControlDependencies(OperationBuilder builder)178   public OperationBuilder applyControlDependencies(OperationBuilder builder) {
179     for (Operand<?> control : controlDependencies) {
180       builder = builder.addControlInput(control.asOutput().op());
181     }
182     return builder;
183   }
184 
185   private final ExecutionEnvironment env;
186   private final Iterable<Operand<?>> controlDependencies;
187   private final NameScope nameScope;
188 }
189