Aufgrund eines Versionsupdates wird GitLab am 17.12. zwischen 9:00 und 9:30 Uhr kurzzeitig nicht zur Verfügung stehen. / Due to a version upgrade, GitLab won't be accessible at 17.12. between 9 and 9:30 a.m.

Commit 82fca86d authored by Evgeny Kusmenko's avatar Evgeny Kusmenko

Merge branch 'develop' into 'master'

Added new layers

See merge request !24
parents 1bf276d6 0bef9f58
Pipeline #173386 passed with stages
in 20 minutes and 20 seconds
......@@ -30,7 +30,7 @@
<groupId>de.monticore.lang.monticar</groupId>
<artifactId>cnn-arch</artifactId>
<version>0.3.2-SNAPSHOT</version>
<version>0.3.3-SNAPSHOT</version>
......
......@@ -253,13 +253,6 @@ public class LayerSymbol extends ArchitectureElementSymbol {
public List<ArchTypeSymbol> computeOutputTypes() {
if (getResolvedThis().isPresent()) {
if (getResolvedThis().get() == this) {
// if LayerSymbol has no output element and layer can be output, then return empty output types array
if (!getOutputElement().isPresent()) {
if (((PredefinedLayerDeclaration) getDeclaration()).canBeOutput(VariableSymbol.Member.NONE)) {
return new ArrayList<>();
}
}
return ((PredefinedLayerDeclaration) getDeclaration()).computeOutputTypes(getInputTypes(), this, VariableSymbol.Member.NONE);
}
else {
......
......@@ -189,16 +189,6 @@ abstract public class PredefinedLayerDeclaration extends LayerDeclarationSymbol
}
}
protected static void computeOneHotOutputSize(LayerSymbol layer){
int outputChannels = 0;
if (layer.getOutputElement().get() instanceof VariableSymbol && layer.getOutputElement().get().isOutput()) {
outputChannels = ((VariableSymbol) layer.getOutputElement().get()).getIoDeclaration().getType().getChannels();
}
layer.setIntValue(AllPredefinedLayers.SIZE_NAME, outputChannels);
}
//padding with border_mode=valid, no padding
private static List<ArchTypeSymbol> computeOutputShapeWithValidPadding(ArchTypeSymbol inputType, LayerSymbol method, int channels){
int strideHeight = method.getIntTupleValue(AllPredefinedLayers.STRIDE_NAME).get().get(0);
......
......@@ -342,7 +342,8 @@ public class VariableSymbol extends ArchitectureElementSymbol {
public List<ArchTypeSymbol> computeOutputTypes() {
if (isAtomic()) {
if (getType() == Type.IO) {
if (isInput()) {
// Allow inputs and outputs to be used as input
if (isInput() || getOutputElement().isPresent()) {
return Collections.singletonList(((IODeclarationSymbol) getDeclaration()).getType());
}
else {
......@@ -387,15 +388,20 @@ public class VariableSymbol extends ArchitectureElementSymbol {
}
if (getInputTypes().size() != 1) {
Log.error("0" + ErrorCodes.INVALID_ELEMENT_INPUT_SHAPE + " Invalid number of input streams. " +
"The number of input streams for the output '" + name + "' is " + getInputTypes().size() + "."
, getSourcePosition());
// Allow no input when output is used as input
if (!(getInputTypes().size() == 0 && getOutputElement().isPresent())) {
Log.error("0" + ErrorCodes.INVALID_ELEMENT_INPUT_SHAPE + " Invalid number of input streams. " +
"The number of input streams for the output '" + name + "' is " + getInputTypes().size() + "."
, getSourcePosition());
}
} else {
ASTElementType inputType = getInputTypes().get(0).getDomain();
if (!Utils.equals(inputType, ioDeclaration.getType().getDomain())) {
ASTElementType outputType = ioDeclaration.getType().getDomain();
if (!Utils.contains(outputType, inputType)) {
Log.error("0" + ErrorCodes.INVALID_ELEMENT_INPUT_DOMAIN + " " +
"The declared output type of '" + name + "' does not match with the actual type. " +
"Declared type: " + ioDeclaration.getType().getDomain().getName() + ". " +
"Declared type: " + outputType.getName() + ". " +
"Actual type: " + inputType.getName() + ".");
}
}
......
......@@ -199,6 +199,79 @@ public class Utils {
return true;
}
// Checks if firstType contains secondType
public static boolean contains(ASTElementType firstType, ASTElementType secondType){
if (firstType.isBoolean()) {
if (!secondType.isBoolean()) {
return false;
}
}
if (firstType.isNaturalNumber()) {
if (secondType.isWholeNumber() || secondType.isRational() || secondType.isComplex()) {
return false;
}
}
if (firstType.isWholeNumber()) {
if (secondType.isRational() || secondType.isComplex()) {
return false;
}
}
if (firstType.isRational()) {
if (secondType.isComplex()) {
return false;
}
}
if (firstType.isPresentRange()) {
if (!secondType.isPresentRange()) {
return false;
}
}
else {
return true;
}
return contains(firstType.getRange(), secondType.getRange());
}
public static boolean contains(ASTRange firstRange, ASTRange secondRange) {
if (!firstRange.hasNoLowerLimit() && secondRange.hasNoLowerLimit()) {
return false;
}
if (!firstRange.hasNoUpperLimit() && secondRange.hasNoUpperLimit()) {
return false;
}
if (!firstRange.hasNoLowerLimit() && firstRange.getStartValue().compareTo(secondRange.getStartValue()) > 0) {
return false;
}
if (!firstRange.hasNoUpperLimit() && firstRange.getEndValue().compareTo(secondRange.getEndValue()) < 0){
return false;
}
if (firstRange.isPresentStep()){
if (!secondRange.isPresentStep()) {
return false;
}
}
else {
return true;
}
if (!firstRange.getStepValue().equals(secondRange.getStepValue())){
return false;
}
// TODO: Check for different step sizes; too complex and not necessary for current use
return true;
}
public static void recursiveSetResolvingFilters(Scope scope, Collection<ResolvingFilter<? extends Symbol>> resolvingFilters){
scope.getAsMutableScope().setResolvingFilters(resolvingFilters);
for (Scope subScope : scope.getSubScopes()){
......
......@@ -47,6 +47,9 @@ public class AllPredefinedLayers {
public static final String ONE_HOT_NAME = "OneHot";
public static final String BEAMSEARCH_NAME = "BeamSearchStart";
public static final String RNN_NAME = "RNN";
public static final String LSTM_NAME = "LSTM";
public static final String GRU_NAME = "GRU";
public static final String EMBEDDING_NAME = "Embedding";
//predefined argument names
public static final String KERNEL_NAME = "kernel";
......@@ -66,6 +69,10 @@ public class AllPredefinedLayers {
public static final String POOL_TYPE_NAME = "pool_type";
public static final String SIZE_NAME = "size";
public static final String LAYERS_NAME = "layers";
public static final String INPUT_DIM_NAME = "input_dim";
public static final String OUTPUT_DIM_NAME = "output_dim";
public static final String BIDIRECTIONAL_NAME = "bidirectional";
public static final String FLATTEN_PARAMETER_NAME = "flatten";
public static final String BEAMSEARCH_MAX_LENGTH = "max_length";
public static final String BEAMSEARCH_WIDTH_NAME = "width";
......@@ -97,7 +104,10 @@ public class AllPredefinedLayers {
Add.create(),
Concatenate.create(),
OneHot.create(),
RNN.create());
RNN.create(),
LSTM.create(),
GRU.create(),
Embedding.create());
}
}
/**
*
* ******************************************************************************
* MontiCAR Modeling Family, www.se-rwth.de
* Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
* All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package de.monticore.lang.monticar.cnnarch.predefined;
import de.monticore.lang.monticar.cnnarch._symboltable.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
abstract public class BaseRNN extends PredefinedLayerDeclaration {
public BaseRNN(String name) {
super(name);
}
@Override
public boolean isTrainable(VariableSymbol.Member member) {
return member == VariableSymbol.Member.NONE;
}
@Override
public List<ArchTypeSymbol> computeOutputTypes(List<ArchTypeSymbol> inputTypes, LayerSymbol layer, VariableSymbol.Member member) {
boolean bidirectional = layer.getBooleanValue(AllPredefinedLayers.BIDIRECTIONAL_NAME).get();
int units = layer.getIntValue(AllPredefinedLayers.UNITS_NAME).get();
if (member == VariableSymbol.Member.STATE) {
int layers = layer.getIntValue(AllPredefinedLayers.LAYERS_NAME).get();
return Collections.singletonList(new ArchTypeSymbol.Builder()
.channels(bidirectional ? 2 * layers : layers)
.height(units)
.elementType("-oo", "oo")
.build());
}
else {
return Collections.singletonList(new ArchTypeSymbol.Builder()
.channels(layer.getInputTypes().get(0).getChannels())
.height(bidirectional ? 2 * units : units)
.elementType("-oo", "oo")
.build());
}
}
@Override
public void checkInput(List<ArchTypeSymbol> inputTypes, LayerSymbol layer, VariableSymbol.Member member) {
boolean bidirectional = layer.getBooleanValue(AllPredefinedLayers.BIDIRECTIONAL_NAME).get();
int units = layer.getIntValue(AllPredefinedLayers.UNITS_NAME).get();
int layers = layer.getIntValue(AllPredefinedLayers.LAYERS_NAME).get();
if (member == VariableSymbol.Member.STATE) {
errorIfInputSizeIsNotOne(inputTypes, layer);
errorIfInputChannelSizeIsInvalid(inputTypes, layer, bidirectional ? 2 * layers : layers);
errorIfInputHeightIsInvalid(inputTypes, layer, units);
errorIfInputWidthIsInvalid(inputTypes, layer, 1);
}
else {
errorIfInputSizeIsNotOne(inputTypes, layer);
errorIfInputChannelSizeIsInvalid(inputTypes, layer, layer.getInputTypes().get(0).getChannels());
errorIfInputWidthIsInvalid(inputTypes, layer, 1);
}
}
@Override
public boolean isValidMember(VariableSymbol.Member member) {
return member == VariableSymbol.Member.NONE ||
member == VariableSymbol.Member.OUTPUT ||
member == VariableSymbol.Member.STATE;
}
@Override
public boolean canBeInput(VariableSymbol.Member member) {
return member == VariableSymbol.Member.OUTPUT || member == VariableSymbol.Member.STATE;
}
@Override
public boolean canBeOutput(VariableSymbol.Member member) {
return member == VariableSymbol.Member.NONE || member == VariableSymbol.Member.STATE;
}
protected static List<ParameterSymbol> createParameters() {
return new ArrayList<>(Arrays.asList(
new ParameterSymbol.Builder()
.name(AllPredefinedLayers.UNITS_NAME)
.constraints(Constraints.INTEGER, Constraints.POSITIVE)
.build(),
new ParameterSymbol.Builder()
.name(AllPredefinedLayers.LAYERS_NAME)
.constraints(Constraints.INTEGER, Constraints.POSITIVE)
.defaultValue(1)
.build(),
new ParameterSymbol.Builder()
.name(AllPredefinedLayers.BIDIRECTIONAL_NAME)
.constraints(Constraints.BOOLEAN)
.defaultValue(false)
.build()));
}
}
/**
*
* ******************************************************************************
* MontiCAR Modeling Family, www.se-rwth.de
* Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
* All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package de.monticore.lang.monticar.cnnarch.predefined;
import de.monticore.lang.monticar.cnnarch._symboltable.*;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.monticore.lang.monticar.types2._ast.ASTElementType;
import de.se_rwth.commons.logging.Log;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Embedding extends PredefinedLayerDeclaration {
private Embedding() {
super(AllPredefinedLayers.EMBEDDING_NAME);
}
@Override
public List<ArchTypeSymbol> computeOutputTypes(List<ArchTypeSymbol> inputTypes, LayerSymbol layer, VariableSymbol.Member member) {
int outputDim = layer.getIntValue(AllPredefinedLayers.OUTPUT_DIM_NAME).get();
ArchTypeSymbol inputType = layer.getInputTypes().get(0);
if (inputType.getHeight() == 1) {
return Collections.singletonList(new ArchTypeSymbol.Builder()
.channels(inputType.getChannels())
.height(outputDim)
.elementType("-oo", "oo")
.build());
}
else {
return Collections.singletonList(new ArchTypeSymbol.Builder()
.channels(inputType.getChannels())
.height(inputType.getHeight())
.width(outputDim)
.elementType("-oo", "oo")
.build());
}
}
private static void inferInputDim(LayerSymbol layer) {
ASTElementType domain = layer.getInputTypes().get(0).getDomain();
// Only infer when not already done and upper limit is available
if (layer.getIntValue(AllPredefinedLayers.INPUT_DIM_NAME).get() == 0
&& domain.isPresentRange()
&& !domain.getRange().hasNoUpperLimit()) {
int inputDim = domain.getRange().getEndValue().intValue();
layer.setIntValue(AllPredefinedLayers.INPUT_DIM_NAME, inputDim);
}
}
@Override
public void checkInput(List<ArchTypeSymbol> inputTypes, LayerSymbol layer, VariableSymbol.Member member) {
inferInputDim(layer);
errorIfInputSizeIsNotOne(inputTypes, layer);
// Only up to 3 dimensions are supported so the input needs to be at maximum 2-dimensional as the output has one
// more dimension than the output
errorIfInputWidthIsInvalid(inputTypes, layer, 1);
int inputDim = layer.getIntValue(AllPredefinedLayers.INPUT_DIM_NAME).get();
if (inputDim == 0) {
Log.error("0" + ErrorCodes.MISSING_ARGUMENT + " Missing argument. The argument 'input_dim' is in this case required. ", layer.getSourcePosition());
}
ASTElementType domain = layer.getInputTypes().get(0).getDomain();
if (!domain.isNaturalNumber()) {
Log.error("0" + ErrorCodes.INVALID_ELEMENT_INPUT_DOMAIN + " Invalid layer input domain: Input must be natural. ", layer.getSourcePosition());
}
else if (!domain.isPresentRange() || domain.getRange().hasNoUpperLimit()) {
Log.error("0" + ErrorCodes.INVALID_ELEMENT_INPUT_DOMAIN + " Invalid layer input domain: Input range must have an upper limit. ", layer.getSourcePosition());
}
else if (domain.getRange().getEndValue().intValue() > inputDim) {
Log.error("0" + ErrorCodes.INVALID_ELEMENT_INPUT_DOMAIN + " Invalid layer input domain: Input upper limit must be smaller than 'input_dim'. ", layer.getSourcePosition());
}
}
public static Embedding create(){
Embedding declaration = new Embedding();
List<ParameterSymbol> parameters = new ArrayList<>(Arrays.asList(
new ParameterSymbol.Builder()
.name(AllPredefinedLayers.INPUT_DIM_NAME)
.constraints(Constraints.INTEGER, Constraints.POSITIVE)
.defaultValue(0)
.build(),
new ParameterSymbol.Builder()
.name(AllPredefinedLayers.OUTPUT_DIM_NAME)
.constraints(Constraints.INTEGER, Constraints.POSITIVE)
.build()));
declaration.setParameters(parameters);
return declaration;
}
}
......@@ -35,12 +35,45 @@ public class FullyConnected extends PredefinedLayerDeclaration {
@Override
public List<ArchTypeSymbol> computeOutputTypes(List<ArchTypeSymbol> inputTypes, LayerSymbol layer, VariableSymbol.Member member) {
return Collections.singletonList(new ArchTypeSymbol.Builder()
.height(1)
.width(1)
.channels(layer.getIntValue(AllPredefinedLayers.UNITS_NAME).get())
.elementType("-oo", "oo")
.build());
boolean flatten = layer.getBooleanValue(AllPredefinedLayers.FLATTEN_PARAMETER_NAME).get();
int units = layer.getIntValue(AllPredefinedLayers.UNITS_NAME).get();
if (flatten) {
return Collections.singletonList(new ArchTypeSymbol.Builder()
.channels(units)
.height(1)
.width(1)
.elementType("-oo", "oo")
.build());
}
else {
ArchTypeSymbol inputType = layer.getInputTypes().get(0);
if (inputType.getWidth() == 1) {
if (inputType.getHeight() == 1) {
return Collections.singletonList(new ArchTypeSymbol.Builder()
.channels(units)
.height(1)
.width(1)
.elementType("-oo", "oo")
.build());
}
return Collections.singletonList(new ArchTypeSymbol.Builder()
.channels(inputType.getChannels())
.height(units)
.width(1)
.elementType("-oo", "oo")
.build());
}
return Collections.singletonList(new ArchTypeSymbol.Builder()
.channels(inputType.getChannels())
.height(inputType.getHeight())
.width(units)
.elementType("-oo", "oo")
.build());
}
}
@Override
......@@ -59,6 +92,11 @@ public class FullyConnected extends PredefinedLayerDeclaration {
.name(AllPredefinedLayers.NOBIAS_NAME)
.constraints(Constraints.BOOLEAN)
.defaultValue(false)
.build(),
new ParameterSymbol.Builder()
.name(AllPredefinedLayers.FLATTEN_PARAMETER_NAME)
.constraints(Constraints.BOOLEAN)
.defaultValue(true)
.build()));
declaration.setParameters(parameters);
return declaration;
......
/**
*
* ******************************************************************************
* MontiCAR Modeling Family, www.se-rwth.de
* Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
* All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package de.monticore.lang.monticar.cnnarch.predefined;
public class GRU extends BaseRNN {
private GRU() {
super(AllPredefinedLayers.GRU_NAME);
}
public static GRU create() {
GRU declaration = new GRU();
declaration.setParameters(createParameters());
return declaration;
}
}
/**
*
* ******************************************************************************
* MontiCAR Modeling Family, www.se-rwth.de
* Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
* All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package de.monticore.lang.monticar.cnnarch.predefined;
public class LSTM extends BaseRNN {
private LSTM() {
super(AllPredefinedLayers.LSTM_NAME);
}
public static LSTM create() {
LSTM declaration = new LSTM();
declaration.setParameters(createParameters());
return declaration;
}
}
......@@ -34,8 +34,6 @@ public class OneHot extends PredefinedLayerDeclaration {
super(AllPredefinedLayers.ONE_HOT_NAME);
}
int size;
@Override
public boolean isTrainable() {
return false;
......@@ -51,10 +49,20 @@ public class OneHot extends PredefinedLayerDeclaration {
.build());
}
private static void inferSizeFromOutput(LayerSymbol layer){
// Only infer when not already done and next element is output
if (layer.getIntValue(AllPredefinedLayers.SIZE_NAME).get() == 0
&& layer.getOutputElement().isPresent()
&& layer.getOutputElement().get().isOutput()) {
int outputChannels = ((VariableSymbol) layer.getOutputElement().get()).getIoDeclaration().getType().getChannels();
layer.setIntValue(AllPredefinedLayers.SIZE_NAME, outputChannels);
}
}
@Override
public void checkInput(List<ArchTypeSymbol> inputTypes, LayerSymbol layer, VariableSymbol.Member member) {
computeOneHotOutputSize(layer);
size = layer.getIntValue(AllPredefinedLayers.SIZE_NAME).get();
inferSizeFromOutput(layer);
errorIfInputSizeIsNotOne(inputTypes, layer);
errorIfInputChannelSizeIsInvalid(inputTypes, layer, 1);
......@@ -62,14 +70,16 @@ public class OneHot extends PredefinedLayerDeclaration {
errorIfInputWidthIsInvalid(inputTypes, layer, 1);
// Check range of input
ASTElementType domain = inputTypes.get(0).getDomain();
int size = layer.getIntValue(AllPredefinedLayers.SIZE_NAME).get();
if (layer.getIntValue(AllPredefinedLayers.SIZE_NAME).get() == 0) {
if (size == 0) {
Log.error("0" + ErrorCodes.MISSING_ARGUMENT + " Missing argument. The argument 'size' is in this case required. "
, layer.getSourcePosition());
}
ASTElementType domain = inputTypes.get(0).getDomain();
if (!domain.isNaturalNumber() && !domain.isWholeNumber()) {
Log.error("0" + ErrorCodes.INVALID_ELEMENT_INPUT_DOMAIN + " Invalid layer input domain: Input needs to be natural or whole. "
, layer.getSourcePosition());
......@@ -96,8 +106,6 @@ public class OneHot extends PredefinedLayerDeclaration {
, layer.getSourcePosition());
}
int size = layer.getIntValue(AllPredefinedLayers.SIZE_NAME).get();
// Check if maximum < size
if (max >= size) {
Log.error("0" + ErrorCodes.INVALID_ELEMENT_INPUT_DOMAIN + " Invalid layer input domain: "
......@@ -107,7 +115,6 @@ public class OneHot extends PredefinedLayerDeclaration {
}
}
}
}
public static OneHot create(){
......@@ -116,7 +123,7 @@ public class OneHot extends PredefinedLayerDeclaration {
new ParameterSymbol.Builder()
.name(AllPredefinedLayers.SIZE_NAME)
.constraints(Constraints.POSITIVE, Constraints.INTEGER)
.defaultValue(declaration.size)
.defaultValue(0)
.build()));
declaration.setParameters(parameters);
return declaration;
......
......@@ -20,91 +20,15 @@
*/
package de.monticore.lang.monticar.cnnarch.predefined;
import de.monticore.lang.monticar.cnnarch._symboltable.*;
import java.util.*;
public class RNN extends PredefinedLayerDeclaration {
public class RNN extends BaseRNN {
private RNN() {
super(AllPredefinedLayers.RNN_NAME);
}
@Override
public boolean isTrainable(VariableSymbol.Member member) {
return member == VariableSymbol.Member.NONE;
}
@Override
public List<ArchTypeSymbol> computeOutputTypes(List<ArchTypeSymbol> inputTypes, LayerSymbol layer, VariableSymbol.Member member) {
int units = layer.getIntValue(AllPredefinedLayers.UNITS_NAME).get();
if (member == VariableSymbol.Member.STATE) {
int layers = layer.getIntValue(AllPredefinedLayers.LAYERS_NAME).get();
return Collections.singletonList(new ArchTypeSymbol.Builder()