Example #1
0
 /**
  * Checks if any of the conditions for the disease are met.
  *
  * @param selected is the list of selected genes.
  * @return true if conditions met.
  */
 public boolean isAffected(ArrayList<Gene> selected) {
   for (ArrayList<Gene> x : causes) {
     boolean conditions = true;
     // check if the list of conditions are met.
     int j = 0;
     while (conditions == true && j < x.size()) { // goes through sub list
       Gene gene_x = x.get(j); // gets current gene
       boolean gene_found = false;
       int i = 0;
       // check input list against condition
       while (gene_found == false && i < selected.size()) {
         if (gene_x.equals(selected.get(i))) {
           gene_found = true;
         }
         i++;
       }
       if (gene_found == false) {
         conditions = false;
       }
       j++;
     }
     if (conditions == true) {
       return true;
     }
   }
   return false;
 }
Example #2
0
 /**
  * Gets a list of the affected genes.
  *
  * @param selected is the list of selected genes.
  * @return the list of affected genes.
  */
 public ArrayList<ArrayList<Gene>> getAffected(ArrayList<Gene> selected) {
   ArrayList<ArrayList<Gene>> results = new ArrayList<ArrayList<Gene>>();
   for (ArrayList<Gene> x : causes) {
     boolean conditions = true;
     // check if the list of conditions are met.
     int j = 0;
     while (conditions == true && j < x.size()) {
       boolean gene_found = false;
       int i = 0;
       Gene gene_x = x.get(j);
       // check input list against condision
       while (gene_found == false && i < selected.size()) {
         if (gene_x.equals(selected.get(i))) {
           gene_found = true;
         }
         i++;
       }
       if (gene_found == false) {
         conditions = false;
       }
       j++;
     }
     if (conditions == true) {
       results.add(x);
     }
   }
   return results;
 }
Example #3
0
  /*
   * This method lines up two AI's links, aka genes, and returns the order of the lined up genes, and where they occur.
   * This method returns an arraylist of arraylist of Integer.
   * The outer arraylist contains arraylists on:
   * 0: neuron historical ID of links present in the two AI
   * 1: where in the first ai's link list the link occurs
   * 2: where in the second ai's link list the link occurs
   */
  public ArrayList<ArrayList<Integer>> lineUpAILinks(NeatAI second) {

    ArrayList<Gene> secondL = second.getCloneLinks();

    ArrayList<Integer> ai1histIDlist = new ArrayList<Integer>();
    ArrayList<Integer> ai2histIDlist = new ArrayList<Integer>();

    ArrayList<Integer> linkID = new ArrayList<Integer>();
    ArrayList<Integer> linkList1Pos = new ArrayList<Integer>();
    ArrayList<Integer> linkList2Pos = new ArrayList<Integer>();

    // Get genes.
    int histID;
    for (Gene l : links) {
      histID = l.getHistID();
      linkID.add(histID);
      ai1histIDlist.add(histID);
    }

    int pos;
    for (Gene l : secondL) {
      histID = l.getHistID();
      pos = linkID.indexOf(histID);
      if (pos == -1) {
        // New histID found
        linkID.add(histID);
      }
      ai2histIDlist.add(histID);
    }

    // Sort genes
    // Bubble sort, meh
    int lowest;
    for (int i = 0; i < linkID.size(); i++) {
      lowest = i;
      for (int j = i + 1; j < linkID.size(); j++) {
        if (linkID.get(j) < linkID.get(lowest)) {
          lowest = j;
        }
      }

      int temp = linkID.get(i);
      linkID.set(i, linkID.get(lowest));
      linkID.set(lowest, temp);
    }

    // Add gene positions
    for (Integer tempID : linkID) {
      linkList1Pos.add(ai1histIDlist.indexOf(tempID));
      linkList2Pos.add(ai2histIDlist.indexOf(tempID));
    }

    ArrayList<ArrayList<Integer>> temp = new ArrayList<ArrayList<Integer>>();

    temp.add(linkID);
    temp.add(linkList1Pos);
    temp.add(linkList2Pos);

    return temp;
  }
Example #4
0
 public ArrayList<Gene> getCloneLinks() {
   ArrayList<Gene> temp = new ArrayList<Gene>();
   for (Gene l : links) {
     temp.add(l.clone());
   }
   return temp;
 }
Example #5
0
  public void setEntrezGeneInfo(Element node) {
    // check to make sure ids match
    NodeList idList = node.getElementsByTagName("Id");
    if (!idList.item(0).getTextContent().equals(this.getAttribute("Xref", "ID"))) return;

    gene = new Gene(Gene.geneType.ENTREZ, this.getAttribute("Xref", "ID"));

    NodeList items = node.getElementsByTagName("Item");
    for (int i = 0; i < items.getLength(); i++) {
      Node n = items.item(i);
      String name = ((Element) n).getAttribute("Name");
      if (name.equals("GenomicInfo")) {
        NodeList subItems = ((Element) n).getElementsByTagName("Item");
        for (int j = 0; j < subItems.getLength(); j++) {
          Node m = subItems.item(j);
          String subName = ((Element) m).getAttribute("Name");
          if (subName.equals("ChrStart")) {
            gene.setStart(m.getTextContent());
          } else if (subName.equals("ChrStop")) {
            gene.setEnd(m.getTextContent());
          }
        }
      } else if (name.equals("Chromosome")) {
        gene.setChromosome(n.getTextContent());
      } else if (name.equals("Name")) {
        gene.setName(n.getTextContent());
      } else if (name.equals("Description")) {
        gene.setDescription(n.getTextContent());
      }
    }

    geneInfoSet = true;
  }
Example #6
0
  public NeatAI crossOver(NeatAI second, double fitness1, double fitness2, double disableRate) {
    NeatAI first;

    // Line up links/genes
    ArrayList<Integer> ai1linkListPos;
    ArrayList<Integer> ai2linkListPos;
    ArrayList<ArrayList<Integer>> temp = lineUpAILinks(second);
    ArrayList<Integer> linkIDs = temp.get(0);

    // Make it so first is the fitter individual.
    if (fitness2 > fitness1) {
      first = second;
      second = this;

      ai1linkListPos = temp.get(2);
      ai2linkListPos = temp.get(1);
    } else {
      first = this;

      ai1linkListPos = temp.get(1);
      ai2linkListPos = temp.get(2);
    }

    // Clone data.
    // System.out.println("p2");
    ArrayList<Gene> firstL = first.getCloneLinks();
    ArrayList<Gene> secondL = second.getCloneLinks();

    ArrayList<Neuron> newN = new ArrayList<Neuron>();
    ArrayList<Gene> newL = new ArrayList<Gene>();

    newN = first.getCloneNeurons();

    // System.out.println("p3");
    for (int i = 0; i < firstL.size(); i++) {
      Gene gene1 = firstL.get(i);
      Gene gene2;

      int gene2pos = ai2linkListPos.get(linkIDs.indexOf(gene1.getHistID()));
      if (gene2pos == -1) {
        gene2 = null;
      } else {
        gene2 = secondL.get(gene2pos);
      }

      if (gene2 != null && rand.nextBoolean() && !gene2.isDisabled()) {
        newL.add(gene2);
      } else {
        newL.add(gene1);
      }
    }

    // System.out.println("New AI");
    // (SimpleMap sm_, ArrayList<Neuron> n, ArrayList<Link> l, int numInputs_, int numOutputs_) {
    // System.out.println("p4");
    NeatAI newai = new NeatAI(sm, newN, newL, numInputs, numOutputs);

    return newai;
  }
Example #7
0
  private boolean containsLink(List<Gene> genes, Gene link) {

    for (Gene gene : genes) {
      if (gene.getNeuralInIndex() == link.getNeuralInIndex()
          && gene.getNeuralOutIndex() == link.getNeuralOutIndex()) return true;
    }
    return false;
  }
Example #8
0
  public void setEnsemblGeneInfo(String id, String chrom, String start, String end) {
    gene = new Gene(Gene.geneType.ENSEMBL, id);
    gene.setChromosome(chrom);
    gene.setStart(start);
    gene.setEnd(end);

    geneInfoSet = true;
  }
Example #9
0
  /**
   * Initializes a chromosome based on the sample chromosome's gene set. The genes of this
   * chromosome are generated randomly in the range specified in the gene set.
   *
   * @param sample the sample chromosome.
   */
  public Chromosome(Chromosome sample) {
    genes = new Vector<Gene>();
    Vector<Gene> sample_genes = sample.getGenes();

    for (Gene curr : sample_genes) {
      genes.add(curr.generate());
    }
  }
Example #10
0
 /**
  * Provides implementation-independent means for creating new Gene instances. The new instance
  * that is created and returned should be setup with any implementation-dependent configuration
  * that this Gene instance is setup with (aside from the actual value, of course). For example, if
  * this Gene were setup with bounds on its value, then the Gene instance returned from this method
  * should also be setup with those same bounds. This is important, as the JGAP core will invoke
  * this method on each Gene in the sample Chromosome in order to create each new Gene in the same
  * respective gene position for a new Chromosome.
  *
  * @return a new Gene instance of the same type and with the same setup as this concrete Gene
  * @author Neil Rostan
  * @author Klaus Meffert
  * @since 2.6 (since 1.0 in IntegerGene)
  */
 public Gene newGene() {
   Gene result = newGeneInternal();
   result.setConstraintChecker(getConstraintChecker());
   result.setEnergy(getEnergy());
   /** @todo clone app.data */
   result.setApplicationData(getApplicationData());
   return result;
 }
Example #11
0
  /*
   * This method wipes all neuron data on links and reconstructs it.
   */
  public void hardCorrectNeuron() {
    for (Neuron n : neurons) {
      n.clearLink();
    }

    for (Gene l : links) {
      getNeuron(l.getTo()).addLink(l);
    }
  }
Example #12
0
  /**
   * split the neighbor hood in two groups based on 2 k-means
   *
   * @param neighborhood
   * @return
   */
  private Pair<List<Gene>, List<Gene>> twoMeanClusterSplit(List<Gene> neighborhood) {
    final int n = neighborhood.size();

    final int maxit = desc.getMaxit();
    final double eps = desc.getEps();

    int a_start = r.nextInt(n);
    int b_start = r.nextInt(n);
    Gene a_center = new Gene(1, -1, Arrays.copyOf(neighborhood.get(a_start).data, samples));
    Gene b_center = new Gene(1, -1, Arrays.copyOf(neighborhood.get(b_start).data, samples));
    float[] a_center_pong = new float[samples];
    Arrays.fill(a_center_pong, Float.NaN);
    float[] b_center_pong = new float[samples];
    Arrays.fill(b_center_pong, Float.NaN);

    float[] tmp;
    BitSet partOf_a = new BitSet(n);

    double d_old = 0;
    for (int i = 0; i < maxit; ++i) {
      int j = 0;
      int changed = 0;
      double d_new = 0;
      for (Gene gene : neighborhood) {
        final double a_distance = distance(a_center, gene);
        final double b_distance = distance(b_center, gene);
        final boolean in_a = a_distance < b_distance;
        if (partOf_a.get(j) != in_a) {
          changed++;
          partOf_a.set(j, in_a);
        }
        d_new += in_a ? a_distance : b_distance;
        tmp = in_a ? a_center_pong : b_center_pong;
        // shift new center
        for (int k = 0; k < samples; ++k) {
          if (!gene.isNaN(k)) {
            if (Float.isNaN(tmp[k])) tmp[k] = gene.get(k);
            else tmp[k] += gene.get(k);
          }
        }
        j++;
      }
      if (changed == 0 || d_new == 0) break;
      final double ratio = Math.abs(d_new - d_old) / d_old;
      if (i > 0 && ratio < eps) break;
      d_old = d_new;
      int a_n = partOf_a.cardinality();
      int b_n = n - a_n;
      if (a_n == 0 || b_n == 0) {
        // FIXME
      }
      updateCenter(a_center, a_center_pong, a_n);
      updateCenter(b_center, b_center_pong, b_n);
    }

    return split(neighborhood, partOf_a);
  }
Example #13
0
  public Object clone() {
    Chromosome clone = new Chromosome();
    clone.genes = new Vector<Gene>();

    for (Gene curr : genes) {
      clone.genes.add((Gene) curr.clone());
    }

    return clone;
  }
Example #14
0
 public Translation(Gene gene, Substance aa) {
   if (gene != null) {
     setGene(gene);
     setName("Translation_" + gene.getName());
     setSystem(gene.getGeneticSystem());
   }
   if (aa != null) {
     setAminoAcid(aa);
   }
   setToPrint(false);
 }
Example #15
0
  public void perturbe(double uniformPerturbeRate, double perturbeMagnitude) {
    Random rand = new Random();

    for (Gene l : links) {
      if (rand.nextDouble() < uniformPerturbeRate) {
        l.perturbe(perturbeMagnitude);
      } else {
        l.newWeight();
      }
    }
  }
Example #16
0
 /*
 Sort Method (in terms of Fitness)
 NOTE-TO-SELF: IMPLEMENT O(nlogn) LATER
  */
 void sort(Gene[] g) {
   for (int i = 1; i < g.length; i++) {
     Gene g1 = g[i];
     int j = i - 1;
     while (i > 0 && g[i].getFitness() > g1.getFitness()) {
       g[i + 1] = g[i];
       i = i - 1;
     }
     g[i + 1] = g1;
   }
 }
Example #17
0
  private void pointMutate(Genome genome) {
    float step = genome.mutationRates.get("step");

    for (int i = 0; i < genome.genes.size(); i++) {
      Gene gene = genome.genes.get(i);
      if (rand.nextFloat() < PerturbChance) {
        gene.setWeight(gene.getWeight() + rand.nextFloat() * step * 2 - step);
      } else {
        gene.setWeight(rand.nextFloat() * 4 - 2);
      }
    }
  }
Example #18
0
 public static void writeGene(PrintStream ps, Gene gene) {
   ps.println(
       "\t<gene length=\""
           + Double.toString(gene.getLength())
           + "\" theta=\""
           + //$NON-NLS-1$ //$NON-NLS-2$
           Double.toString(gene.getTheta())
           + "\" color=\""
           + //$NON-NLS-1$
           colorToString(gene.getColor())
           + "\" />"); //$NON-NLS-1$
 }
Example #19
0
 @Override
 protected void compute() {
   if (neighborhood.size() <= desc.getMaxp()) {
     Collection<ImputeKNNMeanImpl> tasks = new ArrayList<>();
     for (Gene gene : neighborhood) {
       if (gene.getNaNs() > 0) tasks.add(new ImputeKNNMeanImpl(neighborhood, gene));
     }
     invokeAll(tasks);
   } else {
     Pair<List<Gene>, List<Gene>> r = twoMeanClusterSplit(neighborhood);
     invokeAll(new ImputeKNNMean(r.getFirst()), new ImputeKNNMean(r.getSecond()));
   }
 }
Example #20
0
  public int addLink(int historicalID) {
    int attempts = 0;
    int maxAttempts = 5;
    boolean success = false;

    int input;
    int output;
    Gene link;
    do {
      input = rand.nextInt(numInputs + neurons.size() - numOutputs);
      if (rand.nextDouble() < GeneticAlgorithm.biasRate) {
        input = numInputs - 1;
      } else if (input >= numInputs) {
        input += numOutputs;
      }
      do {
        output = rand.nextInt(neurons.size()) + numInputs;
      } while (output == input);

      // make sure link is not backwards
      if (neuronType(input) == 1 && neuronType(output) == 1) {
        if (getNeuron(input).getx() > getNeuron(output).getx()) {
          // if input is ahead of output, swap
          int temp = input;
          input = output;
          output = temp;
        } else if (getNeuron(input).getx() == getNeuron(output).getx()) {
          // if input is same as output, move one
          getNeuron(output).setx(getNeuron(output).getx() + 0.1);
        }
      }

      link = new Gene(input, output, historicalID, false);

      success = true;
      for (Gene l : links) {
        if (l.equals(link)) {
          success = false;
        }
      }
      attempts++;
    } while (attempts < maxAttempts && !success);

    if (success) {
      addLink(link);

      return historicalID + 1;
    } else {
      return historicalID;
    }
  }
Example #21
0
  OverlapDetector<Gene> load() {
    final OverlapDetector<Gene> overlapDetector = new OverlapDetector<Gene>(0, 0);

    final int expectedColumns = RefFlatColumns.values().length;
    final TabbedTextFileWithHeaderParser parser =
        new TabbedTextFileWithHeaderParser(refFlatFile, RefFlatColumnLabels);
    final Map<String, List<TabbedTextFileWithHeaderParser.Row>> refFlatLinesByGene =
        new HashMap<String, List<TabbedTextFileWithHeaderParser.Row>>();

    for (final TabbedTextFileWithHeaderParser.Row row : parser) {
      final int lineNumber =
          parser.getCurrentLineNumber(); // getCurrentLineNumber returns the number of the next line
      if (row.getFields().length != expectedColumns) {
        throw new AnnotationException(
            "Wrong number of fields in refFlat file " + refFlatFile + " at line " + lineNumber);
      }
      final String geneName = row.getField(RefFlatColumns.GENE_NAME.name());
      final String transcriptName = row.getField(RefFlatColumns.TRANSCRIPT_NAME.name());
      final String transcriptDescription = geneName + ":" + transcriptName;
      final String chromosome = row.getField(RefFlatColumns.CHROMOSOME.name());
      if (!isSequenceRecognized(chromosome)) {
        LOG.debug(
            "Skipping " + transcriptDescription + " due to unrecognized sequence " + chromosome);
      } else {
        List<TabbedTextFileWithHeaderParser.Row> transcriptLines = refFlatLinesByGene.get(geneName);
        if (transcriptLines == null) {
          transcriptLines = new ArrayList<TabbedTextFileWithHeaderParser.Row>();
          refFlatLinesByGene.put(geneName, transcriptLines);
        }
        transcriptLines.add(row);
      }
    }

    int longestInterval = 0;
    int numIntervalsOver1MB = 0;

    for (final List<TabbedTextFileWithHeaderParser.Row> transcriptLines :
        refFlatLinesByGene.values()) {
      try {
        final Gene gene = makeGeneFromRefFlatLines(transcriptLines);
        overlapDetector.addLhs(gene, gene);
        if (gene.length() > longestInterval) longestInterval = gene.length();
        if (gene.length() > 1000000) ++numIntervalsOver1MB;
      } catch (AnnotationException e) {
        LOG.debug(e.getMessage() + " -- skipping");
      }
    }
    LOG.debug(
        "Longest gene: " + longestInterval + "; number of genes > 1MB: " + numIntervalsOver1MB);
    return overlapDetector;
  }
Example #22
0
 private Sample computeSample(final int sample) {
   int nans = 0;
   double sum = 0;
   int n = 0;
   for (Gene gene : genes) {
     double v = gene.get(sample);
     if (isNaN(v)) nans++;
     else {
       sum += v;
       n++;
     }
   }
   return new Sample(sum / n, nans);
 }
Example #23
0
  /*
   * aka. addNeuron ()
   */
  public int addNode(int historicalID) {
    Gene randLink;

    do {
      randLink = links.get(rand.nextInt(links.size()));
    } while (randLink.isDisabled());
    double[] from = getNeuronPos(randLink.getFrom());
    double[] to = getNeuronPos(randLink.getTo());

    int minx = sm.getCornerOffset() + sm.getWidth() * (sm.getSmallTileSize() + 2) + 2;
    if (from[0] < minx) {
      from[0] = minx;
    }

    randLink.setDisabled(true);

    int neuralID = neurons.size() + numInputs;
    neurons.add(new Neuron((from[0] + to[0]) / 2, (int) (from[1] + to[1]) / 2));

    // (int from_, int to_, double weight_, int histID_, boolean negative_, boolean disabled_
    addLink(randLink.getFrom(), neuralID, 1.0, historicalID, false);
    addLink(neuralID, randLink.getTo(), randLink.getWeight(), historicalID + 1, false);

    bubbleSortNeurons();

    return historicalID + 2;
  }
Example #24
0
  @Override
  public String toString() {
    String temp =
        "Num inputs: "
            + numInputs
            + " : Num neurons: "
            + neurons.size()
            + "\n Links \n From : To : HistID";

    for (Gene l : links) {
      temp += "\n" + l.getFrom() + ":" + l.getTo() + ":" + l.getHistID();
    }

    return temp;
  }
Example #25
0
 private double distance(Gene target, Gene neighbor) {
   double acc = 0;
   int n = 0;
   for (int sample = 0; sample < samples; ++sample) {
     if (target.isNaN(sample) || neighbor.isNaN(sample)) // skip missing
     continue;
     double dx = target.get(sample) - neighbor.get(sample);
     acc += dx * dx;
     n++;
   }
   if (n > 0) {
     return acc / n; // FIXME according to the fortran code, this is not the eucledian distance
     // return Math.sqrt(acc);
   }
   return Double.POSITIVE_INFINITY;
 }
Example #26
0
 /**
  * Verifies the state of the chromosome. Especially takes care of the given constraint checker.
  *
  * @param a_constraintChecker the constraint checker to verify
  * @throws InvalidConfigurationException
  * @author Klaus Meffert
  * @since 2.5
  */
 protected void verify(IGeneConstraintChecker a_constraintChecker)
     throws InvalidConfigurationException {
   if (a_constraintChecker != null && getGenes() != null) {
     int len = getGenes().length;
     for (int i = 0; i < len; i++) {
       Gene gene = getGene(i);
       if (!a_constraintChecker.verify(gene, null, this, i)) {
         throw new InvalidConfigurationException(
             "The gene type "
                 + gene.getClass().getName()
                 + " is not allowed to be used in the chromosome due to the"
                 + " constraint checker used.");
       }
     }
   }
 }
Example #27
0
  /*
   * This method ensures that no links are pointing backwards.
   */
  public void correctLinks() {
    double pos1;
    double pos2;
    for (Gene l : links) {

      pos1 = getNeuronPos(l.getFrom())[0];
      // System.out.println("link");
      // System.out.println(l.getTo());
      // System.out.println(neurons.size());
      pos2 = getNeuronPos(l.getTo())[0];
      // System.out.println("link2");
      if (pos1 > pos2) {
        // System.out.println("swap");
        l.swapFromTo();
      }
    }
    // System.out.println("fully done");
  }
Example #28
0
  public void enableDisableMutate(Genome genome, boolean enable) {
    List<Gene> candidates = new ArrayList<Gene>();

    // find the genes that are not this enablestate
    for (Gene gene : genome.genes) {
      if (gene.isEnabled() != enable) {
        candidates.add(gene);
      }
    }

    if (candidates.isEmpty()) {
      return;
    }

    // flip the enablestate of a random candidate
    int randomIndex = rand.nextInt(candidates.size());
    Gene gene = candidates.get(randomIndex);
    gene.setEnabled(!gene.isEnabled());
  }
Example #29
0
 /**
  * Retrieve a hash code for this Chromosome. Does not considers the order of the Genes for all
  * cases (especially when gene is empty).
  *
  * @return the hash code of this Chromosome
  * @author Neil Rotstan
  * @author Klaus Meffert
  * @since 1.0
  */
 public int hashCode() {
   // Do what java.util.AbstractList does.
   // ------------------------------------
   int geneHashcode;
   int hashCode = 1;
   if (getGenes() != null) {
     int size = size();
     for (int i = 0; i < size; i++) {
       Gene gene = getGene(i);
       if (gene == null) {
         geneHashcode = -55;
       } else {
         geneHashcode = gene.hashCode();
       }
       hashCode = 31 * hashCode + geneHashcode;
     }
   }
   return hashCode;
 }
  public BufferedImage generateImageFromDna(
      List<Gene> dna, GAParameters parameters, double multiplier) {
    //        long timestamp = System.currentTimeMillis();
    BufferedImage image =
        new BufferedImage(
            (int) (parameters.getTargetImage().getWidth() * multiplier),
            (int) (parameters.getTargetImage().getHeight() * multiplier),
            BufferedImage.TYPE_INT_ARGB);
    Graphics2D graphics = image.createGraphics();
    graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    graphics.setRenderingHint(
        RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);

    drawBlackBackground(graphics, parameters, multiplier);

    for (Gene gene : dna) {
      int[] x = new int[gene.getPoints().size()];
      int[] y = new int[gene.getPoints().size()];

      for (int i = 0; i < gene.getPoints().size(); i++) {
        x[i] = (int) (gene.getPoints().get(i).getX() * multiplier);
        y[i] = (int) (gene.getPoints().get(i).getY() * multiplier);
      }

      Polygon p = new Polygon(x, y, gene.getPoints().size());
      graphics.setColor(gene.getColor());
      graphics.fillPolygon(p);
    }
    //        System.out.println("rendering took : " + (System.currentTimeMillis() - timestamp));
    return image;
  }