├── .travis.yml
├── .gitignore
├── run.bat
├── run.sh
├── src
├── main
│ ├── resources
│ │ ├── images
│ │ │ ├── add.png
│ │ │ ├── disk.png
│ │ │ ├── play.png
│ │ │ ├── step.png
│ │ │ ├── stop.png
│ │ │ ├── cleanup.png
│ │ │ ├── delete.png
│ │ │ ├── eraser.png
│ │ │ ├── refresh.png
│ │ │ ├── book_open.png
│ │ │ ├── bullet_go.png
│ │ │ ├── cog_edit.png
│ │ │ ├── resultset_next.png
│ │ │ └── arrow_rotate_clockwise.png
│ │ ├── log4j.properties
│ │ └── config.xml
│ ├── java
│ │ └── htm
│ │ │ ├── model
│ │ │ ├── algorithms
│ │ │ │ ├── spatial
│ │ │ │ │ ├── NUPICSpatialPooler.java
│ │ │ │ │ ├── SpatialPooler.java
│ │ │ │ │ └── WhitePaperSpatialPooler.java
│ │ │ │ ├── temporal
│ │ │ │ │ ├── NUPICTemporalPooler.java
│ │ │ │ │ └── TemporalPooler.java
│ │ │ │ └── Pooler.java
│ │ │ ├── fractal
│ │ │ │ ├── Fractal.java
│ │ │ │ └── Composite.java
│ │ │ ├── Region.java
│ │ │ ├── space
│ │ │ │ ├── Element.java
│ │ │ │ ├── InputSpace.java
│ │ │ │ └── BaseSpace.java
│ │ │ ├── DistalDendriteSegment.java
│ │ │ ├── Synapse.java
│ │ │ ├── Layer.java
│ │ │ ├── Cell.java
│ │ │ └── Column.java
│ │ │ ├── utils
│ │ │ ├── CollectionUtils.java
│ │ │ ├── CircularArrayList.java
│ │ │ ├── MathUtils.java
│ │ │ └── UIUtils.java
│ │ │ └── visualizer
│ │ │ ├── surface
│ │ │ ├── CellSurface.java
│ │ │ ├── ColumnSDRSurface.java
│ │ │ ├── SensoryInputSurface.java
│ │ │ ├── LayerColumnsVerticalView.java
│ │ │ ├── BaseSurface.java
│ │ │ └── LayerSlicedHorizontalView.java
│ │ │ ├── SpatialInfo.java
│ │ │ ├── ParametersEditor.java
│ │ │ └── Parameters.java
│ ├── groovy
│ │ └── htm
│ │ │ └── utils
│ │ │ └── MathUtilsExt.groovy
│ └── assembly
│ │ └── distribution.xml
└── test
│ └── groovy
│ └── htm
│ ├── AbstractSpockTest.groovy
│ └── utils
│ └── MathUtilsTest.groovy
├── README.md
├── examples
├── 2-1.xml
├── aaax.xml
├── 2-1-2.xml
├── balls-reflect.xml
├── balls-reflect-with-spatial.xml
├── balls-reflect_overlap-spatial.xml
├── balls-reflect_overlap.xml
└── pong.xml
├── License_Numenta.txt
└── pom.xml
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | cache:
3 | directories:
4 | - $HOME/.m2
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .*
2 | *~
3 | target/*
4 | *.class
5 | bin/
6 | build/
7 | .project
8 | .idea/
9 | *.iml
10 | *.log
--------------------------------------------------------------------------------
/run.bat:
--------------------------------------------------------------------------------
1 | java -classpath "lib\commons-logging-1.1.3.jar;lib\log4j-1.2.9.jar;htm-visualizer.jar" htm.visualizer.Viewer
2 |
3 |
4 |
--------------------------------------------------------------------------------
/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | java -classpath "lib/commons-logging-1.1.3.jar:lib/log4j-1.2.9.jar:htm-visualizer.jar" htm.visualizer.Viewer
3 |
--------------------------------------------------------------------------------
/src/main/resources/images/add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/add.png
--------------------------------------------------------------------------------
/src/main/resources/images/disk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/disk.png
--------------------------------------------------------------------------------
/src/main/resources/images/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/play.png
--------------------------------------------------------------------------------
/src/main/resources/images/step.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/step.png
--------------------------------------------------------------------------------
/src/main/resources/images/stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/stop.png
--------------------------------------------------------------------------------
/src/main/resources/images/cleanup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/cleanup.png
--------------------------------------------------------------------------------
/src/main/resources/images/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/delete.png
--------------------------------------------------------------------------------
/src/main/resources/images/eraser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/eraser.png
--------------------------------------------------------------------------------
/src/main/resources/images/refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/refresh.png
--------------------------------------------------------------------------------
/src/main/resources/images/book_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/book_open.png
--------------------------------------------------------------------------------
/src/main/resources/images/bullet_go.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/bullet_go.png
--------------------------------------------------------------------------------
/src/main/resources/images/cog_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/cog_edit.png
--------------------------------------------------------------------------------
/src/main/resources/images/resultset_next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/resultset_next.png
--------------------------------------------------------------------------------
/src/main/resources/images/arrow_rotate_clockwise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solovyevk/htm-cla-visualizer/HEAD/src/main/resources/images/arrow_rotate_clockwise.png
--------------------------------------------------------------------------------
/src/main/java/htm/model/algorithms/spatial/NUPICSpatialPooler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.model.algorithms.spatial;
10 |
11 | public class NUPICSpatialPooler {
12 | }
13 |
--------------------------------------------------------------------------------
/src/test/groovy/htm/AbstractSpockTest.groovy:
--------------------------------------------------------------------------------
1 | package htm
2 | import org.junit.Ignore
3 | /**
4 | * Created with IntelliJ IDEA.
5 | * User: miao.lin
6 | * Date: 14-3-12
7 | * Time: 上午11:25
8 | * To change this template use File | Settings | File Templates.
9 | */
10 | import spock.lang.Specification
11 |
12 | @Ignore
13 | class AbstractSpockTest extends Specification {
14 |
15 |
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/fractal/Fractal.java:
--------------------------------------------------------------------------------
1 | package htm.model.fractal;
2 |
3 | import java.util.List;
4 |
5 | public interface Fractal
{
6 | public void reset();
7 | public P getOwner();
8 | public E getElementByIndex(int inx);
9 | public List getElements();
10 | public boolean addElement(E element);
11 | public boolean addAll(List all);
12 | public void removeElement(E element);
13 | }
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/main/groovy/htm/utils/MathUtilsExt.groovy:
--------------------------------------------------------------------------------
1 | package htm.utils
2 |
3 | import groovy.transform.CompileStatic
4 |
5 | /**
6 | * Created with IntelliJ IDEA.
7 | * User: miao.lin
8 | * Date: 14-3-12
9 | * Time: 上午11:21
10 | * To change this template use File | Settings | File Templates.
11 | */
12 | @CompileStatic
13 | class MathUtilsExt extends MathUtils{
14 | static public double findMax(double... values) {
15 | return GroovyCollections.max(values.toList())
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/Region.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.model;
10 |
11 | import java.util.HashMap;
12 | import java.util.Map;
13 |
14 | public class Region extends htm.model.fractal.Composite {
15 | public static final int BRAIN_REGION_LAYERS_NUMBER = 6;
16 |
17 | protected final Map layers = new HashMap(BRAIN_REGION_LAYERS_NUMBER);
18 |
19 | public Layer getLayer(String level){
20 | return layers.get(level);
21 | }
22 |
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/src/test/groovy/htm/utils/MathUtilsTest.groovy:
--------------------------------------------------------------------------------
1 | package htm.utils
2 |
3 | import htm.AbstractSpockTest
4 | import org.junit.Test
5 |
6 | /**
7 | * Created with IntelliJ IDEA.
8 | * User: miao.lin
9 | * Date: 14-3-12
10 | * Time: 上午11:28
11 | * To change this template use File | Settings | File Templates.
12 | */
13 | class MathUtilsTest extends AbstractSpockTest{
14 | @Test
15 | void testFindMax(){
16 | expect:
17 | MathUtilsExt.findMax(a,b,c,d)==c
18 |
19 | where:
20 | a | b | c | d
21 | 1.1 | 2.2 | 10.8 | 9.9
22 |
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/algorithms/temporal/NUPICTemporalPooler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.model.algorithms.temporal;
10 |
11 | import htm.model.Cell;
12 | import htm.model.DistalDendriteSegment;
13 |
14 | public class NUPICTemporalPooler extends WhitePaperTemporalPooler {
15 | public NUPICTemporalPooler(Config cfg) {
16 | super(cfg);
17 | }
18 |
19 | @Override
20 | public DistalDendriteSegment getActiveSegment(Cell cell, int time, Cell.State state) {
21 | return super.getActiveSegment(cell, time, state);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | htm-visualizer
2 | ==============
3 |
4 | Visualization of Hierarchical Temporal Memory (HTM) Cortical Learning Algorithms (CLA) in JAVA
5 |
6 |
7 | Implementation is based on Numenta's CLA white paper:
8 | https://www.groksolutions.com/htm-overview/education/HTM_CorticalLearningAlgorithms.pdf
9 |
10 | Videos:
11 |
12 | 1) Introduction: https://www.youtube.com/watch?v=nRgbQhdfL9Q
13 |
14 | 2) Debugging Temporal Pooler segments formation: https://www.youtube.com/watch?v=9twCUKrAqPo
15 |
16 |
17 | Build Steps:
18 |
19 | 1) Download and install Maven: http://maven.apache.org/download.cgi
20 |
21 | 2) Execute "mvn package" command in the project home directory (where pom.xml file located)
22 |
--------------------------------------------------------------------------------
/src/main/java/htm/utils/CollectionUtils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.utils;
10 |
11 | import java.util.ArrayList;
12 | import java.util.Collection;
13 | import java.util.List;
14 |
15 | public class CollectionUtils {
16 |
17 | private CollectionUtils() {
18 | }
19 |
20 | public static List filter(Collection target, Predicate predicate) {
21 | List result = new ArrayList();
22 | for (T element: target) {
23 | if (predicate.apply(element)) {
24 | result.add(element);
25 | }
26 | }
27 | return result;
28 | }
29 |
30 | public static interface Predicate { boolean apply(T type); }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/assembly/distribution.xml:
--------------------------------------------------------------------------------
1 |
2 | dist
3 | false
4 |
5 | zip
6 |
7 |
8 |
9 | target/${project.build.finalName}.jar
10 | htm-visualizer.jar
11 | 0644
12 |
13 |
14 | run.bat
15 | run.bat
16 | true
17 | 0644
18 |
19 |
20 | run.sh
21 | run.sh
22 | true
23 | 0755
24 |
25 |
26 |
27 |
28 | /lib
29 |
30 | htm:htm-visualizer
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/algorithms/Pooler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.model.algorithms;
10 |
11 | import htm.model.Layer;
12 | import htm.model.algorithms.spatial.SpatialPooler;
13 | import htm.model.algorithms.temporal.TemporalPooler;
14 |
15 | public abstract class Pooler {
16 | protected Layer layer;
17 | protected boolean learningMode = true;
18 |
19 | public boolean isLearningMode() {
20 | return learningMode;
21 | }
22 |
23 | public void setLearningMode(boolean learningMode) {
24 | this.learningMode = learningMode;
25 | }
26 |
27 | public Pooler setLayer(Layer layer) {
28 | this.layer = layer;
29 | if(TemporalPooler.class.isAssignableFrom(this.getClass())){
30 | layer.setTemporalPooler((TemporalPooler)this);
31 | } else {
32 | layer.setSpatialPooler((SpatialPooler)this);
33 | }
34 | return this;
35 | }
36 |
37 | public abstract void execute();
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | # This is a configuration file for using log4j with Kodo logging.
2 | # For details about log4j configuration, see:
3 | # http://jakarta.apache.org/log4j/docs/index.html
4 |
5 | log4j.rootCategory=WARN, console, testLog
6 |
7 | log4j.category.htm=DEBUG
8 | log4j.category.htm.visualizer.HTMGraphicInterface=INFO
9 | log4j.category.htm.model.Column=INFO
10 | log4j.category.htm.model.Region=INFO
11 |
12 |
13 | # Set appender specific options.
14 | log4j.appender.testLog=org.apache.log4j.RollingFileAppender
15 | log4j.appender.testLog.File=visualizer.log
16 | log4j.appender.testLog.Append=true
17 | log4j.appender.testLog.MaxFileSize=10mb
18 | log4j.appender.testLog.MaxBackupIndex=9
19 | log4j.appender.testLog.layout=org.apache.log4j.PatternLayout
20 | log4j.appender.testLog.layout.ConversionPattern=%-5r %-5p - %m%n
21 |
22 | log4j.appender.console=org.apache.log4j.ConsoleAppender
23 | log4j.appender.console.layout=org.apache.log4j.PatternLayout
24 | log4j.appender.console.layout.ConversionPattern=%-5r %-5p - %m%n
25 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/space/Element.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.model.space;
10 |
11 |
12 | import htm.model.fractal.Composite;
13 |
14 | import java.awt.*;
15 |
16 | public class Element extends Composite
{
17 | protected final Point position;
18 | private final int index;
19 |
20 | public Element(P owner, Point position, int index) {
21 | this.owner = owner;
22 | this.position = position;
23 | this.index = index;
24 | }
25 |
26 | public Point getPosition() {
27 | return position;
28 | }
29 |
30 | public int getIndex() {
31 | return index;
32 | }
33 |
34 | /**
35 | * Kind unique identifier for position
36 | */
37 | public int getLocationSeed() {
38 | int length = position.y == 0 ? 1 : (int)(Math.log10(position.y) + 1);
39 | return (position.x + 1) * (int)Math.pow(10, length) + position.y;
40 | }
41 |
42 | @Override
43 | public String toString() {
44 | return "locationSeed:" + getLocationSeed() + ", X:" + getPosition().x + ", Y:" + getPosition().y + ", index:" + getIndex();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/resources/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 | 5.0
6 | 4.0
7 | 3
8 | 12
9 | 12
10 |
11 |
12 | 12
13 | 12
14 |
15 |
16 | 20
17 | 3
18 | 3
19 | 0.01
20 |
21 | |
22 | 5
23 | 2
24 | 0
25 | 30
26 | 6
27 | |
28 |
29 | 0.2
30 | 0.005
31 | 0.005
32 |
33 |
34 | 0.2
35 | 0.005
36 | 0.005
37 |
38 |
--------------------------------------------------------------------------------
/src/main/java/htm/utils/CircularArrayList.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.utils;
10 |
11 | import java.util.ArrayList;
12 |
13 |
14 | public class CircularArrayList extends ArrayList {
15 |
16 | protected final int maxCapacity;
17 |
18 | /**
19 | * ArrayList has a capacity, if full,
20 | * remove the oldest element
21 | *
22 | * @param capacity
23 | */
24 | public CircularArrayList(int capacity) {
25 | super(capacity + 1);
26 | this.maxCapacity = capacity;
27 | }
28 |
29 | /**
30 | *
31 | * if full, remove oldest element
32 | * @param element
33 | */
34 |
35 | @Override public boolean add(E element) {
36 | boolean result = super.add(element);
37 | removeExcess();
38 | return result;
39 | }
40 |
41 | /**
42 | * if full, remove oldest element
43 | *
44 | * @param index
45 | * @param element
46 | */
47 | @Override
48 | public void add(int index, E element) {
49 | super.add(index, element);
50 | removeExcess();
51 | }
52 |
53 | private void removeExcess() {
54 | if (this.size() > maxCapacity) {
55 | this.remove(maxCapacity);
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/fractal/Composite.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.model.fractal;
10 |
11 | import java.util.ArrayList;
12 | import java.util.Collections;
13 | import java.util.List;
14 |
15 | public class Composite implements Fractal
{
16 | protected final List elementList = new ArrayList();
17 | protected P owner;
18 |
19 | @Override public void reset() {
20 | //DO NOTHING BY DEFAULT
21 | }
22 |
23 | @Override public List getElements() {
24 | return Collections.unmodifiableList(elementList);
25 | }
26 |
27 | public List getElementsList() {
28 | return elementList;
29 | }
30 |
31 | @Override public boolean addAll(List all) {
32 | return elementList.addAll(all);
33 | }
34 |
35 | @Override
36 | public P getOwner() {
37 | return owner;
38 | }
39 |
40 | @Override public E getElementByIndex(int index) {
41 | return elementList.get(index);
42 | }
43 |
44 | @Override public boolean addElement(E element) {
45 | return elementList.add(element);
46 | }
47 |
48 | @Override public void removeElement(E element) {
49 | elementList.remove(element);
50 | }
51 |
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/examples/2-1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 | 5.0
6 | 8.0
7 | 3
8 | 12
9 | 12
10 |
11 |
12 | 12
13 | 12
14 |
15 |
16 | 20
17 | 3
18 | 3
19 | 0.01
20 |
21 | |
22 | 5
23 | 2
24 | 1
25 | 30
26 | 6
27 | |
28 |
29 | 0.2
30 | 0.0050
31 | 0.0050
32 |
33 |
34 | 0.2
35 | 0.0050
36 | 0.0050
37 |
38 |
39 | 100000000000100000000000100000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
40 | 100000000000100000000000100000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
41 | 011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/main/java/htm/utils/MathUtils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.utils;
10 |
11 | import java.math.BigDecimal;
12 | import java.util.List;
13 |
14 | public class MathUtils {
15 | // private MathUtils() {
16 | // }
17 |
18 | static public double findMax(Double... values) {
19 | double max = Double.MIN_VALUE;
20 | for (double d : values) {
21 | if (d > max) max = d;
22 | }
23 | return max;
24 | }
25 |
26 | static public double findMax(List values) {
27 | double max = Double.MIN_VALUE;
28 | for (Double d : values) {
29 | if (d > max) max = d;
30 | }
31 | return max;
32 | }
33 |
34 | static public double findMin(Double... values) {
35 | double min = Double.MAX_VALUE;
36 | for (double d : values) {
37 | if (d < min) min = d;
38 | }
39 | return min;
40 | }
41 |
42 | static public double findMin(List values) {
43 | double min = Double.MAX_VALUE;
44 | for (double d : values) {
45 | if (d < min) min = d;
46 | }
47 | return min;
48 | }
49 |
50 | public static boolean inRange(int value, int lowerBound, int upperBound) {
51 | return (lowerBound <= value && value <= upperBound);
52 | }
53 |
54 | public static boolean inRange(double value, double lowerBound, double upperBound) {
55 | return (lowerBound <= value && value <= upperBound);
56 | }
57 |
58 | public static double round(double value, int places) {
59 | if (places < 0) throw new IllegalArgumentException("places should not be negative");
60 | BigDecimal bd = new BigDecimal(value);
61 | bd = bd.setScale(places, BigDecimal.ROUND_HALF_UP);
62 | return bd.doubleValue();
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/examples/aaax.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 | 5.0
6 | 23.275
7 | 4
8 | 12
9 | 12
10 |
11 |
12 | 12
13 | 12
14 |
15 |
16 | 20
17 | 3
18 | 3
19 | 0.01
20 |
21 |
22 | 7
23 | 4
24 | 0
25 | 30
26 | 6
27 | |
28 |
29 | 0.2
30 | 0.0050
31 | 0.0050
32 |
33 |
34 | 0.2
35 | 0.0050
36 | 0.02
37 |
38 |
39 | 000000000000000000000000000001000000000011100000000010100000000111110000000100010000000100010000000000000000000000000000000000000000000000000000
40 | 000000000000000000000000000001000000000011100000000010100000000111110000000100010000000100010000000000000000000000000000000000000000000000000000
41 | 000000000000000000000000000001000000000011100000000010100000000111110000000100010000000100010000000000000000000000000000000000000000000000000000
42 | 000000000000000000000000000100010000000010100000000001000000000001000000000010100000000100010000000000000000000000000000000000000000000000000000
43 |
44 |
45 |
--------------------------------------------------------------------------------
/examples/2-1-2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 | 5.0
6 | 8.0
7 | 3
8 | 12
9 | 12
10 |
11 |
12 | 12
13 | 12
14 |
15 |
16 | 20
17 | 3
18 | 3
19 | 0.01
20 |
21 |
22 | 5
23 | 2
24 | 1
25 | 30
26 | 6
27 | |
28 |
29 | 0.2
30 | 0.0050
31 | 0.0050
32 |
33 |
34 | 0.2
35 | 0.0050
36 | 0.0050
37 |
38 |
39 | 100000000000100000000000100000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
40 | 100000000000100000000000100000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
41 | 011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
42 | 000000000000000000100000000000100000000000100000000000100000000000100000000000100000000000000000000000000000000000000000000000000000000000000000
43 | 000000000000000000100000000000100000000000100000000000100000000000100000000000100000000000000000000000000000000000000000000000000000000000000000
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/algorithms/spatial/SpatialPooler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.model.algorithms.spatial;
10 |
11 | public abstract class SpatialPooler extends htm.model.algorithms.Pooler {
12 |
13 | private final int minimalOverlap;
14 |
15 | private final double boostRate;
16 |
17 | private final int desiredLocalActivity;
18 |
19 | protected SpatialPooler(Config cfg) {
20 | this.minimalOverlap = cfg.getMinOverlap();
21 | this.boostRate = cfg.getBoostRate();
22 | this.desiredLocalActivity = cfg.getDesiredLocalActivity();
23 | }
24 |
25 | /**
26 | * WP
27 | * A minimum number of inputs that must be active for a
28 | * column to be considered during the inhibition step.
29 | */
30 | public int getMinimalOverlap() {
31 | return minimalOverlap;
32 | }
33 |
34 | /**
35 | * The amount that is added to a Column's Boost value in a single time step, when it is being boosted.
36 | */
37 | public double getBoostRate() {
38 | return boostRate;
39 | }
40 |
41 | /**
42 | * WP
43 | * desiredLocalActivity A parameter controlling the number of columns that
44 | * will be winners after the inhibition step.
45 | */
46 | public int getDesiredLocalActivity() {
47 | return desiredLocalActivity;
48 | }
49 |
50 | public static class Config {
51 | private final int minOverlap;
52 | private final int desiredLocalActivity;
53 | private final double boostRate;
54 |
55 | public Config(int minOverlap, int desiredLocalActivity,
56 | double boostRate) {
57 | this.minOverlap = minOverlap;
58 | this.desiredLocalActivity = desiredLocalActivity;
59 | this.boostRate = boostRate;
60 | }
61 |
62 |
63 | public int getMinOverlap() {
64 | return minOverlap;
65 | }
66 |
67 | public int getDesiredLocalActivity() {
68 | return desiredLocalActivity;
69 | }
70 |
71 | public double getBoostRate() {
72 | return boostRate;
73 | }
74 | }
75 | }
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/space/InputSpace.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.model.space;
10 |
11 |
12 | import java.awt.*;
13 | import java.util.List;
14 | import java.util.NoSuchElementException;
15 |
16 | public class InputSpace extends BaseSpace {
17 | public InputSpace(int xSize, int ySize) {
18 | super(xSize, ySize);
19 | initElementSpace();
20 | }
21 |
22 | public InputSpace(Dimension dimension) {
23 | super(dimension);
24 | initElementSpace();
25 | }
26 |
27 | @Override
28 | protected Input createElement(int index,
29 | Point position) {
30 | return new Input(this, position, index, false);
31 | }
32 |
33 |
34 | public void setInputValue(int index, boolean value) {
35 | this.getElementByIndex(index).setValue(value);
36 | }
37 |
38 | public boolean getInputValue(int index) {
39 | return this.getElementByIndex(index).getValue();
40 | }
41 |
42 |
43 | public static class Input extends Element {
44 | private boolean value;
45 |
46 | public Input(InputSpace space, Point position, int index, boolean value) {
47 | super(space, position, index);
48 | this.value = value;
49 | }
50 |
51 | public boolean getValue() {
52 | return value;
53 | }
54 |
55 | @Override public boolean addAll(List all) {
56 | throw new NoSuchElementException("Not supported for Input. It is a Leaf Element");
57 | }
58 |
59 | @Override public Input getElementByIndex(int index) {
60 | throw new NoSuchElementException("Not supported for Input. It is a Leaf Element");
61 | }
62 |
63 | @Override public boolean addElement(Input element) {
64 | throw new NoSuchElementException("Not supported for Input. It is a Leaf Element");
65 | }
66 |
67 | @Override public void removeElement(Input element) {
68 | throw new NoSuchElementException("Not supported for Input. It is a Leaf Element");
69 | }
70 |
71 | public void setValue(boolean sourceInput) {
72 | this.value = sourceInput;
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/htm/visualizer/surface/CellSurface.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.visualizer.surface;
10 |
11 | import htm.model.Cell;
12 | import htm.model.Layer;
13 | import htm.utils.UIUtils;
14 |
15 | import java.awt.*;
16 |
17 | public abstract class CellSurface extends BaseSurface.CircleElementsSurface {
18 | public static final Color PREDICTED_COLOR = Color.BLUE;
19 | public static final Color PREDICTED_IN_STEP_COLOR = UIUtils.LIGHT_BLUE;
20 | public static final Color LEARNING_COLOR = Color.RED;
21 | protected final Layer region;
22 |
23 | public CellSurface(int xSize, int ySize, Layer region) {
24 | super(xSize, ySize);
25 | this.region = region;
26 | }
27 |
28 | protected Layer getRegion() {
29 | return region;
30 | }
31 |
32 | @Override
33 | protected void drawElement(Graphics2D g2d, int columnIndex, int x, int y, int width, int height) {
34 | Cell currentCell = getCell(columnIndex);
35 | drawCell(g2d, x, y, width, height, currentCell, Cell.NOW);
36 | }
37 |
38 | public static void drawCell(Graphics2D g2d, Rectangle rect, Cell cell, int time) {
39 | drawCell(g2d, rect.x, rect.y, rect.width, rect.height, cell, time);
40 | }
41 |
42 | public static void drawCell(Graphics2D g2d, int x, int y, int width, int height, Cell cell, int time) {
43 | int predictInStep = cell.getPredictInStepState(time);
44 | Color predictedColor = predictInStep > 1 ? PREDICTED_IN_STEP_COLOR : PREDICTED_COLOR;
45 | if (cell.getPredictiveState(time) && cell.getActiveState(time)) {
46 | UIUtils.drawStatesInCircle(g2d, x, y, width, height, predictedColor, ACTIVE_COLOR);
47 | } else if (cell.getPredictiveState(time)) {
48 | UIUtils.drawStatesInCircle(g2d, x, y, width, height, predictedColor);
49 | } else if (cell.getActiveState(time)) {
50 | UIUtils.drawStatesInCircle(g2d, x, y, width, height, ACTIVE_COLOR);
51 | } else {
52 | UIUtils.drawStatesInCircle(g2d, x, y, width, height);
53 | }
54 | if (cell.getLearnState(time)) {
55 | //third of cell width
56 | int newWidth = width / 3;
57 | g2d.setColor(LEARNING_COLOR);
58 | g2d.fillRect(x + newWidth + 1, y + newWidth + 1, newWidth, newWidth);
59 | }
60 | if(predictInStep > 1){
61 | String predictInStepStr = predictInStep+"";
62 | UIUtils.drawTextInCenter(g2d, x, y, width, height, predictInStepStr);
63 | }
64 | }
65 |
66 | public abstract Cell getCell(int index);
67 |
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/algorithms/temporal/TemporalPooler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.model.algorithms.temporal;
10 |
11 | import htm.model.Cell;
12 | import htm.model.DistalDendriteSegment;
13 |
14 | public abstract class TemporalPooler extends htm.model.algorithms.Pooler {
15 |
16 | private final int newSynapseCount;
17 | private final int activationThreshold;
18 | private final int minThreshold;
19 |
20 | protected TemporalPooler(Config cfg) {
21 | this.newSynapseCount = cfg.getNewSynapseCount();
22 | this.activationThreshold = cfg.getActivationThreshold();
23 | this.minThreshold = cfg.getMinThreshold();
24 | }
25 |
26 |
27 | /**
28 | * WP
29 | *
30 | * newSynapseCount
31 | * The maximum number of synapses added to a segment during learning.
32 | */
33 | public int getNewSynapseCount() {
34 | return newSynapseCount;
35 | }
36 |
37 | /**
38 | * WP
39 | * activationThreshold
40 | *
41 | * Activation threshold for a segment. If the number of active connected
42 | * synapses in a segment is greater than activationThreshold, the segment is said to be active.
43 | */
44 | public int getActivationThreshold() {
45 | return activationThreshold;
46 | }
47 |
48 | /**
49 | * WP
50 | * minThreshold Minimum segment activity for learning.
51 | */
52 | public int getMinThreshold() {
53 | return minThreshold;
54 | }
55 |
56 |
57 | /**
58 | * WP
59 | * segmentActive(s, t, state)
60 | *
61 | * This routine returns true if the number of connected synapses on segments that are active due to the given
62 | * state at time t is greater than activationThreshold. The parameter state can be activeState, or learnState.
63 | */
64 | public boolean segmentActive(DistalDendriteSegment segment, int time, Cell.State state) {
65 | return segment.getConnectedWithStateCell(time, state).size() > activationThreshold;
66 | }
67 |
68 |
69 | public static class Config {
70 | private final int newSynapseCount;
71 | private final int activationThreshold;
72 | private final int minThreshold;
73 |
74 | public Config(int newSynapseCount, int activationThreshold, int minThreshold) {
75 | this.newSynapseCount = newSynapseCount;
76 | this.activationThreshold = activationThreshold;
77 | this.minThreshold = minThreshold;
78 | }
79 |
80 | public int getNewSynapseCount() {
81 | return newSynapseCount;
82 | }
83 |
84 | public int getActivationThreshold() {
85 | return activationThreshold;
86 | }
87 |
88 | public int getMinThreshold() {
89 | return minThreshold;
90 | }
91 |
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/examples/balls-reflect.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 | 5.0
6 | 17.5
7 | 2
8 | 12
9 | 12
10 |
11 |
12 | 12
13 | 12
14 |
15 |
16 | 20
17 | 3
18 | 3
19 | 0.01
20 |
21 |
22 | 5
23 | 2
24 | 0
25 | 30
26 | 6
27 | |
28 |
29 | 0.2
30 | 0.0050
31 | 0.0050
32 |
33 |
34 | 0.2
35 | 0.0050
36 | 0.0050
37 |
38 |
39 | 110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
40 | 000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
41 | 000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000
42 | 000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000
43 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000
44 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011
45 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000
46 | 000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000
47 | 000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000
48 | 000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
49 |
50 |
51 |
--------------------------------------------------------------------------------
/examples/balls-reflect-with-spatial.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 | 4.41
6 | 17.5
7 | 3
8 | 12
9 | 12
10 |
11 |
12 | 12
13 | 12
14 |
15 |
16 | 20
17 | 2
18 | 1
19 | 0.01
20 |
21 |
22 | 5
23 | 1
24 | 0
25 | 30
26 | 6
27 | |
28 |
29 | 0.2
30 | 0.0050
31 | 0.0050
32 |
33 |
34 | 0.2
35 | 0.0050
36 | 0.0050
37 |
38 |
39 | 110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
40 | 000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
41 | 000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000
42 | 000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000
43 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000
44 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011
45 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000
46 | 000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000
47 | 000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000
48 | 000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
49 |
50 |
51 |
--------------------------------------------------------------------------------
/License_Numenta.txt:
--------------------------------------------------------------------------------
1 | This software is based upon or includes certain works and algorithms related
2 | to hierarchical temporal memory ("HTM") technology published by Numenta Inc.
3 |
4 |
5 | Numenta holds patent rights related to HTM and the algorithms used in this
6 | software.
7 |
8 | Numenta has agreed not to assert its patent rights against
9 | development or use of independent HTM systems, as long as such development
10 | or use is for research purposes only, and not for any commercial or production
11 | use.
12 |
13 | Any commercial or production use of HTM technology that infringes on
14 | Numenta's patents will require a commercial license from Numenta.
15 |
16 |
17 |
18 | Based on the foregoing, this software is licensed under the terms below, for
19 | research purposes only and not for any commercial or production use.
20 |
21 | Numenta License for Non-Commercial Use:
22 |
23 | For
24 | purposes of this license, "commercial or production use" includes training an
25 | HTM network with the intent of later deploying the trained network or
26 | application for commercial or production purposes, and using or permitting
27 | others to use the output from HTM technology for commercial or production
28 | purposes.
29 |
30 | Redistribution and use in source and binary forms, with or without
31 | modification, are permitted (subject to the limitations in the disclaimer
32 | below) provided that the following conditions are met:
33 |
34 | * Redistributions of source code, including any modifications or derivative
35 | works, must retain the full text of this license and the following disclaimer,
36 | and be subject to the terms and conditions of this license.
37 |
38 | * Redistributions in binary form, including any modifications or derivative
39 | works, must reproduce the full text of this license and the following
40 | disclaimer in the documentation and/or other materials provided with the
41 | distribution, and be subject to the terms and conditions of this license.
42 |
43 | * Neither the name of Numenta, Inc., Barry Maturkanich, nor the names of other
44 | contributors may be used to endorse or promote products derived from this
45 | software without specific prior written permission.
46 |
47 | NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT RIGHTS ARE GRANTED BY THIS
48 | LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
50 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
52 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
54 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
55 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
56 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
57 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/src/main/java/htm/model/space/BaseSpace.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.model.space;
10 |
11 |
12 | import htm.utils.CollectionUtils;
13 | import org.apache.commons.logging.Log;
14 | import org.apache.commons.logging.LogFactory;
15 |
16 | import java.awt.*;
17 | import java.util.List;
18 |
19 |
20 | public abstract class BaseSpace> extends htm.model.fractal.Composite
{
21 | private static final Log LOG = LogFactory.getLog(
22 | BaseSpace.class);
23 |
24 | private final Dimension dimension;
25 |
26 |
27 | protected BaseSpace(int xSize, int ySize) {
28 | this.dimension = new Dimension(xSize, ySize);
29 | }
30 | /*Have to call it after construction and param initialization*/
31 | protected void initElementSpace() {
32 | int xSize = this.dimension.width; int ySize = this.dimension.height;
33 | int index = 0;
34 | for (int y = 0; y < ySize; y++) {
35 | for (int x = 0; x < xSize; x++) {
36 | elementList.add(index, createElement(index, new Point(x, y)));
37 | index++;
38 | }
39 | }
40 | }
41 |
42 | BaseSpace(Dimension dimension) {
43 | this(dimension.width, dimension.height);
44 | }
45 |
46 | public int getLongSide() {
47 | return Math.max(dimension.width, dimension.height);
48 | }
49 |
50 | public int getShortSide() {
51 | return Math.min(dimension.width, dimension.height);
52 | }
53 |
54 | protected abstract E createElement(int index, Point position);
55 |
56 | public E getElementByPosition(Point position) {
57 | for (E element : elementList) {
58 | if (element.getPosition().x == position.x && element.getPosition().y == position.y) {
59 | return element;
60 | }
61 | }
62 | throw new IllegalArgumentException("There in no element by this position" + position);
63 | }
64 |
65 |
66 | public List getAllWithinRadius(final Point center, final double radius) {
67 | CollectionUtils.Predicate withinRadius = new CollectionUtils.Predicate() {
68 | @Override public boolean apply(E element) {
69 | return Math.pow(center.x - element.getPosition().x, 2) + Math.pow(center.y - element.getPosition().y,
70 | 2) <= Math.pow(radius, 2);
71 | }
72 | };
73 | return CollectionUtils.filter(elementList, withinRadius);
74 | }
75 |
76 | public Dimension getDimension() {
77 | return dimension;
78 | }
79 |
80 | protected Point convertPositionToOtherSpace(Point srcPosition, Dimension srcDimension, Dimension targetDimension) {
81 | double xScale = targetDimension.getWidth() / srcDimension.getWidth();
82 | double yScale = targetDimension.getHeight() / srcDimension.getHeight();
83 | //apply function scale
84 | double xAdj = 0;// xScale/2 - (srcPosition.getX()/srcDimension.getWidth()) * xScale;
85 | double targetX = Math.min(Math.ceil(srcPosition.getX() * xScale + (xScale > 1 ? xAdj : 0)),
86 | targetDimension.width - 1);
87 | //LOG.debug("xAdj:" + xAdj + ", X:" + srcPosition.getX() * xScale + ", adj. targetX :" + targetX);
88 | double yAdj = 0;// yScale/2 - (srcPosition.getY()/srcDimension.getHeight()) * yScale;
89 | //double yAdj = yScale / 2 - srcPosition.getY() / ((yScale + 2) * yScale);
90 | double targetY = Math.min(Math.ceil(srcPosition.getY() * yScale + (yScale > 1 ? yAdj : 0)),
91 | targetDimension.height - 1);
92 | Point result = new Point();
93 | result.setLocation(targetX, targetY);
94 | return result;
95 | }
96 |
97 | /*
98 | helpers
99 | */
100 | public static double getDistance(Point pointOne, Point pointTwo) {
101 | int dX = pointOne.x - pointTwo.x;
102 | int dY = pointOne.y - pointTwo.y;
103 | return Math.sqrt(Math.pow(dX, 2) + Math.pow(dY, 2));
104 | }
105 |
106 |
107 | }
108 |
109 |
--------------------------------------------------------------------------------
/src/main/java/htm/visualizer/surface/ColumnSDRSurface.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.visualizer.surface;
10 |
11 |
12 | import htm.model.Cell;
13 | import htm.model.Column;
14 | import htm.model.Layer;
15 | import htm.utils.UIUtils;
16 |
17 | import java.awt.*;
18 | import java.util.HashSet;
19 | import java.util.Set;
20 |
21 | public class ColumnSDRSurface extends BaseSurface.CircleElementsSurface {
22 |
23 |
24 | protected final Layer region;
25 | private Column currentColumn; //clicked on
26 | private Integer selectedColumnIndex; //selected from neighbours table
27 |
28 | public ColumnSDRSurface(Layer region) {
29 | super(region.getDimension().width, region.getDimension().height);
30 | this.region = region;
31 | }
32 |
33 | @Override
34 | protected void drawElement(Graphics2D g2d, int index, int x, int y, int width, int height) {
35 | Column column = getColumn(index);
36 | Set cellStates = new HashSet();
37 | for (Cell cell : column.getElements()) {
38 | int predictInStep = cell.getPredictInStepState(Cell.NOW);
39 | if (predictInStep == 1) {
40 | cellStates.add(CellSurface.PREDICTED_COLOR);
41 | }
42 | if (predictInStep > 1) {
43 | cellStates.add(CellSurface.PREDICTED_IN_STEP_COLOR);
44 | }
45 | }
46 | if (column.isActive()) {
47 | cellStates.add(ACTIVE_COLOR);
48 | }
49 | UIUtils.drawStatesInCircle(g2d, x, y, width, height, cellStates.toArray(new Color[cellStates.size()]));
50 | }
51 |
52 | public Column getColumn(int columnIndex) {
53 | return region.getElementByIndex(columnIndex);
54 | }
55 |
56 | public void setCurrentColumn(Column currentColumn) {
57 | this.currentColumn = this.currentColumn != currentColumn ? currentColumn : null;
58 | this.selectedColumnIndex = null;
59 | this.repaint();
60 | }
61 |
62 | public void setSelectedColumn(int selectedColumnIndex) {
63 | this.selectedColumnIndex = selectedColumnIndex;
64 | this.repaint();
65 | }
66 |
67 | public void drawInhibitedColumns(Column currentColumn, Graphics2D g2d) {
68 | java.util.List inhibitedColumn = currentColumn.getNeighbors(region.getAverageReceptiveFieldSize());
69 | g2d.setColor(Color.LIGHT_GRAY);
70 | Composite original = g2d.getComposite();
71 | g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
72 | 0.4f));
73 | for (Column column : inhibitedColumn) {
74 | Rectangle columnRec = this.getElementArea(column.getPosition());
75 | g2d.fillOval(columnRec.x, columnRec.y, columnRec.width, columnRec.height);
76 | }
77 | g2d.setComposite(original);
78 | }
79 |
80 | @Override
81 | protected void doDrawing(Graphics2D g2d) {
82 | super.doDrawing(g2d);
83 | if (currentColumn != null) {
84 | drawInhibitedColumns(currentColumn, g2d);
85 | //Current Column selection
86 | Point center = currentColumn.getPosition();
87 | Rectangle aroundRec = getElementAreaWithScale(center,
88 | 1 / (Math.PI / 4) * 1.1);
89 | g2d.setColor(Color.ORANGE);
90 | g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
91 | 0.2f));
92 | g2d.fillOval(aroundRec.x, aroundRec.y, aroundRec.width, aroundRec.height);
93 | }
94 | if (selectedColumnIndex != null) {
95 | Composite original = g2d.getComposite();
96 | Rectangle aroundRec = getElementAreaWithScale(selectedColumnIndex, 1 / (Math.PI / 4) * 1.5);
97 | g2d.setColor(UIUtils.LIGHT_BLUE);
98 | g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
99 | 0.5f));
100 | g2d.fillOval(aroundRec.x, aroundRec.y, aroundRec.width, aroundRec.height);
101 | g2d.setComposite(original);
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/examples/balls-reflect_overlap-spatial.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 | 8.0
6 | 16.48
7 | 4
8 | 12
9 | 12
10 |
11 |
12 | 12
13 | 12
14 |
15 |
16 | 20
17 | 3
18 | 4
19 | 0.01
20 |
21 | |
22 | 5
23 | 3
24 | 2
25 | 30
26 | 6
27 | |
28 |
29 | 0.2
30 | 0.0050
31 | 0.0050
32 |
33 |
34 | 0.2
35 | 0.0050
36 | 0.0050
37 |
38 |
39 | 111000000000111000000000111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
40 | 000000000000011100000000011100000000011100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
41 | 000000000000000000000000001110000000001110000000001110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
42 | 000000000000000000000000000000000000000111000000000111000000000111000000000000000000000000000000000000000000000000000000000000000000000000000000
43 | 000000000000000000000000000000000000000000000000000011100000000011100000000011100000000000000000000000000000000000000000000000000000000000000000
44 | 000000000000000000000000000000000000000000000000000000000000000001110000000001110000000001110000000000000000000000000000000000000000000000000000
45 | 000000000000000000000000000000000000000000000000000000000000000000000000000000111000000000111000000000111000000000000000000000000000000000000000
46 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011100000000011100000000011100000000000000000000000000
47 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001110000000001110000000001110000000000000
48 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111000000000111000000000111
49 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001110000000001110000000001110000000000000
50 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011100000000011100000000011100000000000000000000000000
51 | 000000000000000000000000000000000000000000000000000000000000000000000000000000111000000000111000000000111000000000000000000000000000000000000000
52 | 000000000000000000000000000000000000000000000000000000000000000001110000000001110000000001110000000000000000000000000000000000000000000000000000
53 | 000000000000000000000000000000000000000000000000000011100000000011100000000011100000000000000000000000000000000000000000000000000000000000000000
54 | 000000000000000000000000000000000000000111000000000111000000000111000000000000000000000000000000000000000000000000000000000000000000000000000000
55 | 000000000000000000000000001110000000001110000000001110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
56 | 000000000000011100000000011100000000011100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
57 |
58 |
59 |
--------------------------------------------------------------------------------
/examples/balls-reflect_overlap.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 | 5.0
6 | 15.0
7 | 3
8 | 12
9 | 12
10 |
11 |
12 | 12
13 | 12
14 |
15 |
16 | 20
17 | 3
18 | 3
19 | 0.01
20 |
21 |
22 | 5
23 | 2
24 | 1
25 | 30
26 | 6
27 | |
28 |
29 | 0.2
30 | 0.0050
31 | 0.0050
32 |
33 |
34 | 0.2
35 | 0.0050
36 | 0.0050
37 |
38 |
39 | 110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
40 | 000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
41 | 000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
42 | 000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
43 | 000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000
44 | 000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000
45 | 000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000
46 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000
47 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000
48 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000
49 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011
50 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000
51 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000
52 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000
53 | 000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000
54 | 000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000
55 | 000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000
56 | 000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
57 | 000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
58 | 000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
59 |
60 |
61 |
--------------------------------------------------------------------------------
/src/main/java/htm/visualizer/surface/SensoryInputSurface.java:
--------------------------------------------------------------------------------
1 | package htm.visualizer.surface;
2 |
3 | import htm.model.Column;
4 | import htm.model.Synapse;
5 | import htm.model.space.InputSpace;
6 | import htm.utils.UIUtils;
7 |
8 | import java.awt.*;
9 | import java.util.List;
10 |
11 | /*
12 | This is our Sensory Input Interface, bits activated on mouse enter
13 | */
14 | public class SensoryInputSurface extends BaseSurface.SquareElementsSurface {
15 |
16 | private final InputSpace sensoryInput;
17 | private Column currentColumn;
18 | private Integer selectedInputIndex;
19 |
20 | public SensoryInputSurface(int xSize, int ySize) {
21 | this(new InputSpace(xSize, ySize));
22 | }
23 |
24 | public SensoryInputSurface(InputSpace sensoryInput) {
25 | super(sensoryInput.getDimension().width, sensoryInput.getDimension().height);
26 | this.sensoryInput = sensoryInput;
27 | this.addElementMouseEnterListener(new ElementMouseEnterListener() {
28 | @Override public void onElementMouseEnter(ElementMouseEnterEvent e) {
29 | int index = e.getIndex();
30 | setInputValue(index, !getInputValue(index));
31 | }
32 | });
33 | }
34 |
35 | @Override
36 | protected void drawElement(Graphics2D g2d, int index, int x, int y, int width, int height) {
37 | g2d.setColor(getInputValue(index) ? ACTIVE_COLOR : this.getBackground());
38 | g2d.fillRect(x, y, width, height);
39 | super.drawElement(g2d, index, x, y, width,
40 | height);
41 | }
42 |
43 | private void drawProximalSynapsesForColumn(Column column, Graphics2D g2d) {
44 | List synapsesToDraw = column.getPotentialSynapses();
45 | Point center = column.getInputSpacePosition();
46 | Rectangle aroundRec = getElementAreaWithScale(center,
47 | 1 / (Math.PI / 4) * (sensoryInput.getShortSide() / column.getOwner().getShortSide()) * 1.1);
48 | g2d.setColor(Color.ORANGE);
49 | Composite original = g2d.getComposite();
50 | g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
51 | 0.2f));
52 | g2d.fillOval(aroundRec.x, aroundRec.y, aroundRec.width, aroundRec.height);
53 | g2d.setComposite(original);
54 | for (Synapse.ProximalSynapse proximalSynapse : synapsesToDraw) {
55 | Rectangle insideRec = getElementAreaWithScale(this.getElementPositionByIndex(
56 | proximalSynapse.getConnectedSensoryInput().getIndex()), .5);
57 | renderSynapse(g2d, proximalSynapse.getPermanence(), insideRec);
58 | }
59 | g2d.setComposite(original);
60 | }
61 |
62 | public static void renderSynapse(Graphics2D g2d, double permanence, Rectangle insideRec) {
63 | Composite original = g2d.getComposite();
64 | Color synapseStateColor = permanence >= Synapse.ProximalSynapse.CONNECTED_PERMANENCE ? Color.GREEN : Color.RED;
65 | g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
66 | Math.min(1.0f, Math.max(0.2f, (float)Math.abs(
67 | permanence - Synapse.ProximalSynapse.CONNECTED_PERMANENCE) * 30))));
68 | g2d.setColor(synapseStateColor);
69 | g2d.fillRect(insideRec.x, insideRec.y, insideRec.width, insideRec.height);
70 | g2d.setComposite(original);
71 | }
72 |
73 |
74 | public void setInputValue(int index, boolean value) {
75 | sensoryInput.setInputValue(index, value);
76 | repaint(this.getElementAreaByIndex(index));
77 | }
78 |
79 | public boolean getInputValue(int index) {
80 | return sensoryInput.getInputValue(index);
81 | }
82 |
83 | public void setSensoryInputValues(boolean[] source) {
84 | for (int i = 0; i < source.length; i++) {
85 | sensoryInput.setInputValue(i, source[i]);
86 |
87 | }
88 | repaint();
89 | }
90 |
91 | public boolean[] getSensoryInputValues() {
92 | boolean[] result = new boolean[dimension.width * dimension.height];
93 | for (int i = 0; i < result.length; i++) {
94 | result[i] = sensoryInput.getInputValue(i);
95 |
96 | }
97 | return result;
98 | }
99 |
100 | public void reset() {
101 | setSensoryInputValues(new boolean[dimension.width * dimension.height]);
102 | }
103 |
104 | @Override protected void doDrawing(Graphics2D g2d) {
105 | super.doDrawing(g2d);
106 | if (currentColumn != null) {
107 | drawProximalSynapsesForColumn(currentColumn, g2d);
108 | }
109 | if (selectedInputIndex != null) {
110 | Composite original = g2d.getComposite();
111 | Rectangle aroundRec = getElementAreaWithScale(selectedInputIndex, 1 / (Math.PI / 4) * 1.5);
112 | g2d.setColor(UIUtils.LIGHT_BLUE);
113 | g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
114 | 0.5f));
115 | g2d.fillOval(aroundRec.x, aroundRec.y, aroundRec.width, aroundRec.height);
116 | g2d.setComposite(original);
117 | }
118 | }
119 |
120 | public InputSpace getSensoryInput() {
121 | return sensoryInput;
122 | }
123 |
124 | public void setCurrentColumn(Column currentColumn) {
125 | this.currentColumn = this.currentColumn != currentColumn ? currentColumn : null;
126 | selectedInputIndex = null;
127 | this.repaint();
128 | }
129 |
130 | public void setSelectedInput(Integer inputIndex) {
131 | this.selectedInputIndex = inputIndex;
132 | this.repaint();
133 | }
134 | }
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | htm
5 | htm-visualizer
6 | jar
7 | 1.1
8 | HTM-CLA Visualizer
9 |
10 |
11 | 2.5.6
12 |
13 |
14 |
15 |
16 | log4j
17 | log4j
18 | 1.2.9
19 | runtime
20 |
21 |
22 |
23 | commons-logging
24 | commons-logging
25 | 1.1.3
26 |
27 |
28 |
29 | junit
30 | junit
31 | 4.10
32 | test
33 |
34 |
35 |
36 | org.codehaus.groovy
37 | groovy-all
38 | 2.2.1
39 |
40 |
41 |
42 | org.spockframework
43 | spock-core
44 | 0.7-groovy-2.0
45 | test
46 |
47 |
48 |
49 |
50 |
51 |
59 |
60 | maven-assembly-plugin
61 |
62 |
63 | jar-assembly
64 | package
65 |
66 | single
67 |
68 |
69 |
70 |
71 | htm.visualizer.Viewer
72 | ${project.description}
73 | ${project.version}
74 |
75 |
76 |
77 | jar-with-dependencies
78 |
79 |
80 |
81 |
82 | distribution-assembly
83 | package
84 |
85 | single
86 |
87 |
88 |
89 | src/main/assembly/distribution.xml
90 |
91 |
92 |
93 |
94 |
95 |
96 | maven-source-plugin
97 |
98 |
99 |
100 | org.codehaus.mojo
101 | build-helper-maven-plugin
102 | 1.8
103 |
104 |
105 | add-source
106 | generate-sources
107 |
108 | add-source
109 |
110 |
111 |
112 | src/main/groovy
113 |
114 |
115 |
116 |
117 | add-test-source
118 | generate-test-sources
119 |
120 | add-test-source
121 |
122 |
123 |
124 | src/test/groovy
125 |
126 |
127 |
128 |
129 |
130 |
131 | org.apache.maven.plugins
132 | maven-compiler-plugin
133 | 3.1
134 |
135 | groovy-eclipse-compiler
136 | 1.6
137 | 1.6
138 |
139 |
140 |
141 | org.codehaus.groovy
142 | groovy-eclipse-compiler
143 | 2.8.0-01
144 |
145 |
146 | org.codehaus.groovy
147 | groovy-eclipse-batch
148 | 2.1.8-01
149 |
150 |
151 |
152 |
153 | org.codehaus.groovy
154 | groovy-eclipse-compiler
155 | 2.8.0-01
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/DistalDendriteSegment.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.model;
10 |
11 | import htm.model.fractal.Composite;
12 | import htm.utils.CollectionUtils;
13 |
14 | import java.util.List;
15 |
16 | public class DistalDendriteSegment extends Composite {
17 |
18 | protected final DistalDendriteSegment predictedBy;
19 |
20 |
21 | //We need to check if synapse connected to this cell is already exist before adding new one
22 | @Override public boolean addElement(Synapse.DistalSynapse distalSynapse) {
23 | Cell newSynapseCell = distalSynapse.getFromCell();
24 | for (Synapse.DistalSynapse existingSynapse : elementList) {
25 | if (existingSynapse.getFromCell() == newSynapseCell) {
26 | return false;
27 | }
28 | }
29 | distalSynapse.setSegment(this);
30 | return super.addElement(distalSynapse);
31 | }
32 |
33 | @Override public String toString() {
34 | StringBuilder result = new StringBuilder().append("Synapses Number:").append(this.elementList.size());
35 | result = result.append("; sequence Segment:").append(this.isSequenceSegment());
36 | result.append("; Belongs to Cell:").append(this.owner);
37 | return result.toString();
38 | }
39 |
40 |
41 | public DistalDendriteSegment(Cell belongsToCell, DistalDendriteSegment predictedBy) {
42 | this.owner = belongsToCell;
43 | this.predictedBy = predictedBy;
44 | attachToCell();
45 | }
46 |
47 | protected void attachToCell() {
48 | owner.addElement(this);
49 | }
50 |
51 | public boolean isSequenceSegment() {
52 | return predictedBy == null;
53 | }
54 |
55 | public int size(){return elementList.size();}
56 |
57 | public boolean contains(Synapse.DistalSynapse synapse){
58 | return elementList.contains(synapse);
59 | }
60 |
61 |
62 |
63 | public List getConnectedWithStateCell(int time, Cell.State state) {
64 | return CollectionUtils.filter(this.elementList, new ConnectedCellStateByTimePredicate(time, state));
65 | }
66 |
67 | public List getActiveCellSynapses(int time) {
68 | return CollectionUtils.filter(this.elementList, new ActiveCellByTimePredicate(time));
69 | }
70 |
71 |
72 |
73 | public int predictedInStep() {
74 | int result = 1;
75 | DistalDendriteSegment predictedBySegment = this.predictedBy;
76 | while (predictedBySegment != null) {
77 | result = result + 1;
78 | predictedBySegment = predictedBySegment.getPredictedBy();
79 | }
80 | return result;
81 | }
82 |
83 | public DistalDendriteSegment getPredictedBy() {
84 | return predictedBy;
85 | }
86 |
87 | private static class ActiveCellByTimePredicate implements CollectionUtils.Predicate {
88 | private final int time;
89 |
90 | private ActiveCellByTimePredicate(int time) {
91 | this.time = time;
92 | }
93 |
94 | @Override
95 | public boolean apply(Synapse.DistalSynapse synapse) {
96 | //return synapse.getFromCell().getActiveState(time);
97 | //By Kirill
98 | return synapse.getFromCell().getActiveState(time) && synapse.getFromCell().getLearnState(time);
99 | }
100 | }
101 |
102 |
103 | private static class ConnectedCellStateByTimePredicate implements CollectionUtils.Predicate {
104 | private final int time;
105 | private final Cell.State cellState;
106 |
107 | private ConnectedCellStateByTimePredicate(int time, Cell.State cellState) {
108 | this.time = time;
109 | this.cellState = cellState;
110 | }
111 |
112 | @Override
113 | public boolean apply(Synapse.DistalSynapse synapse) {
114 | boolean result = synapse.isConnected(
115 | Synapse.DistalSynapse.CONNECTED_PERMANENCE);
116 | switch (cellState) {
117 | case ACTIVE:
118 | return result && synapse.getFromCell().getActiveState(time);
119 | case LEARN:
120 | return result && synapse.getFromCell().getLearnState(time);
121 | }
122 | throw new RuntimeException("We shouldn't get here");
123 | }
124 | }
125 |
126 | public static class Update extends DistalDendriteSegment {
127 | private final DistalDendriteSegment target;
128 | private final int time;
129 |
130 | public Update(Cell belongsToCell, DistalDendriteSegment target, int time, DistalDendriteSegment predictedBy) {
131 | super(belongsToCell, predictedBy);
132 | this.target = target;
133 | this.time = time;
134 | }
135 |
136 | @Override
137 | public int predictedInStep() {
138 | //Segment for this update hasn't been created yet
139 | if (target == null) {
140 | return predictedBy == null ? 1 : predictedBy.predictedInStep() + 1;
141 | } else {
142 | return target.predictedInStep();
143 | }
144 | }
145 |
146 | @Override public boolean isSequenceSegment() {
147 | if (target == null) {
148 | return predictedBy == null;
149 | } else {
150 | return target.isSequenceSegment();
151 | }
152 | }
153 |
154 | @Override
155 | protected void attachToCell() {
156 | this.owner.getSegmentUpdates().add(this);
157 | }
158 |
159 | public boolean isNewSegment() {
160 | return target == null;
161 | }
162 |
163 | public DistalDendriteSegment getTarget() {
164 | return target;
165 | }
166 |
167 | public int getTime() {
168 | return time;
169 | }
170 |
171 | @Override
172 | public String toString() {
173 | StringBuilder result = new StringBuilder().append(" New Segment:").append(this.isNewSegment());
174 | result = result.append("; Time:").append(this.time);
175 | result.append(super.toString());
176 | return result.toString();
177 | }
178 |
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/Synapse.java:
--------------------------------------------------------------------------------
1 | package htm.model;
2 |
3 | import htm.model.space.BaseSpace;
4 | import htm.model.space.InputSpace;
5 | import htm.utils.CircularArrayList;
6 | import htm.utils.MathUtils;
7 |
8 | public class Synapse {
9 | private double permanence;
10 |
11 | public Synapse(double initPermanence) {
12 | this.permanence = initPermanence;
13 | }
14 |
15 | /**
16 | * synapse is considered connected if its permanence is bigger than
17 | * connectedPermanence
18 | *
19 | * @param connectedPermanence
20 | * @return
21 | */
22 | public boolean isConnected(double connectedPermanence) {
23 | return this.permanence >= connectedPermanence;
24 | }
25 |
26 |
27 | public double getPermanence() {
28 | return permanence;
29 | }
30 |
31 | public void setPermanence(double d) {
32 | this.permanence = Math.min(Math.max(d, 0), 1);
33 | }
34 |
35 | public static class ProximalSynapse extends Synapse {
36 | /**
37 | * WP
38 | * If the permanence value for a synapse is greater than this
39 | * value, it is said to be connected.
40 | */
41 | public static double CONNECTED_PERMANENCE = 0.2;
42 | /**
43 | * WP
44 | * Amount permanence values of synapses are incremented
45 | * during learning.
46 | */
47 | public static double PERMANENCE_INCREASE = 0.005;
48 | /**
49 | * WP
50 | * Amount permanence values of synapses are decremented
51 | * during learning.
52 | */
53 | public static double PERMANENCE_DECREASE = 0.005;
54 |
55 | public static void updateFromConfig(Config synapseCfg) {
56 | ProximalSynapse.CONNECTED_PERMANENCE = synapseCfg.getConnectedPerm();
57 | ProximalSynapse.PERMANENCE_INCREASE = synapseCfg.getPermanenceInc();
58 | ProximalSynapse.PERMANENCE_DECREASE = synapseCfg.getPermanenceDec();
59 | }
60 |
61 | private final InputSpace.Input connectedSensoryInput;
62 | private final Column belongsTo;
63 | private final double distanceToColumn;
64 |
65 | public ProximalSynapse(double initPermanence, InputSpace.Input connectedSensoryInput, Column belongsTo) {
66 | super(initPermanence);
67 | this.connectedSensoryInput = connectedSensoryInput;
68 | this.belongsTo = belongsTo;
69 | this.distanceToColumn = BaseSpace.getDistance(belongsTo.getOwner().convertInputPositionToColumnSpace(
70 | connectedSensoryInput.getPosition()),
71 | belongsTo.getPosition());
72 | }
73 |
74 |
75 | public InputSpace.Input getConnectedSensoryInput() {
76 | return connectedSensoryInput;
77 | }
78 |
79 | public double getDistanceToColumn() {
80 | return distanceToColumn;
81 | }
82 |
83 | public Column getBelongsTo() {
84 | return belongsTo;
85 | }
86 | }
87 |
88 | public static class DistalSynapse extends Synapse {
89 |
90 | public static double CONNECTED_PERMANENCE = 0.2;
91 | /**
92 | * WP
93 | * Amount permanence values of synapses are incremented
94 | * during learning.
95 | */
96 | public static double PERMANENCE_INCREASE = 0.005;
97 | /**
98 | * WP
99 | * Amount permanence values of synapses are decremented
100 | * during learning.
101 | */
102 | public static double PERMANENCE_DECREASE = 0.005;
103 |
104 | private final Cell fromCell;
105 | private DistalDendriteSegment segment;
106 |
107 |
108 | public static void updateFromConfig(Config synapseCfg) {
109 | DistalSynapse.CONNECTED_PERMANENCE = synapseCfg.getConnectedPerm();
110 | DistalSynapse.PERMANENCE_INCREASE = synapseCfg.getPermanenceInc();
111 | DistalSynapse.PERMANENCE_DECREASE = synapseCfg.getPermanenceDec();
112 | }
113 |
114 | public DistalSynapse(Cell fromCell) {
115 | //NOT sure how to deal with initial permanence, do following for now
116 | this(CONNECTED_PERMANENCE - 3 * PERMANENCE_INCREASE, fromCell);
117 | }
118 |
119 | public DistalSynapse(double initPermanence, Cell fromCell) {
120 | super(initPermanence);
121 | this.fromCell = fromCell;
122 | }
123 |
124 | public Cell getFromCell() {
125 | return fromCell;
126 | }
127 |
128 | public DistalDendriteSegment getSegment() {
129 | return segment;
130 | }
131 |
132 | public void setSegment(DistalDendriteSegment segment) {
133 | this.segment = segment;
134 | }
135 |
136 | /*Added by Kirill to track speed of permanence changes for active cells*/
137 |
138 | public static final int PERMANENCE_RANGE_BUFFER_SIZE = 20;
139 | private final PermanenceBufferedState permanenceRangeForActiveCell = new PermanenceBufferedState();
140 |
141 | public void updatePermanenceRangeForActiveCell() {
142 | permanenceRangeForActiveCell.addState(this.getPermanence());
143 | }
144 |
145 | public double getPermanenceRangeChangeForActive(){
146 | double currentPermanence = getPermanence();
147 | if(currentPermanence == 1.0 || permanenceRangeForActiveCell.size() < PERMANENCE_RANGE_BUFFER_SIZE){
148 | return 1.0;
149 | } else {
150 | return MathUtils.findMax(permanenceRangeForActiveCell) - MathUtils.findMin(permanenceRangeForActiveCell);
151 | }
152 | }
153 |
154 | private static class PermanenceBufferedState extends CircularArrayList {
155 | public PermanenceBufferedState() {
156 | super(PERMANENCE_RANGE_BUFFER_SIZE);
157 | }
158 |
159 | void addState(Double value) {
160 | this.add(0, value);
161 | }
162 |
163 | public Double getLast() {
164 | return this.get(0);
165 | }
166 | }
167 | }
168 |
169 |
170 | public static class Config {
171 | private final double connectedPerm;
172 | private final double permanenceInc;
173 | private final double permanenceDec;
174 |
175 |
176 | public Config(double connectedPerm, double permanenceInc, double permanenceDec) {
177 | this.connectedPerm = connectedPerm;
178 | this.permanenceInc = permanenceInc;
179 | this.permanenceDec = permanenceDec;
180 | }
181 |
182 | public double getConnectedPerm() {
183 | return connectedPerm;
184 | }
185 |
186 | public double getPermanenceInc() {
187 | return permanenceInc;
188 | }
189 |
190 | public double getPermanenceDec() {
191 | return permanenceDec;
192 | }
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/src/main/java/htm/visualizer/surface/LayerColumnsVerticalView.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.visualizer.surface;
10 |
11 | import htm.model.Cell;
12 | import htm.model.Column;
13 | import htm.model.Layer;
14 | import org.apache.commons.logging.Log;
15 | import org.apache.commons.logging.LogFactory;
16 |
17 | import java.awt.*;
18 | import java.awt.font.FontRenderContext;
19 | import java.awt.font.TextLayout;
20 | import java.util.List;
21 | import javax.swing.*;
22 |
23 | public class LayerColumnsVerticalView extends CellSurface implements Scrollable {
24 | private int selectedCellIndex = -1;
25 | private static final Log LOG = LogFactory.getLog(LayerColumnsVerticalView.class);
26 | protected List columns;
27 | private static final int MIN_CELL_SIZE = 28;
28 | private final int columnIndexHeight = 12;
29 |
30 | public LayerColumnsVerticalView(Layer region) {
31 | super(1, region.getCellsInColumn(), region);
32 | this.updateColumns();
33 | /* this.addElementMouseEnterListener(new ElementMouseEnterListener() {
34 | @Override
35 | public void onElementMouseEnter(ElementMouseEnterEvent e) {
36 | setSelectedCellIndex(e.getIndex());
37 | }
38 | });*/
39 | }
40 |
41 | public void updateColumns() {
42 | selectedCellIndex = -1;
43 | columns = region.getActiveColumns();
44 | this.dimension.width = columns.size();
45 | resizeAndRepaint();
46 | }
47 |
48 | @Override
49 | public Dimension getPreferredSize() {
50 | int elementSpaceAllocation = getElementSpaceAllocation(),
51 | prefHeight = super.getPreferredSize().height,
52 | prefWidth = super.getPreferredSize().width,
53 | columnWidthAllocation = elementSpaceAllocation * dimension.width,
54 | columnHeightAllocation = elementSpaceAllocation * dimension.height + columnIndexHeight;
55 | return new Dimension(columnWidthAllocation < prefWidth ? prefWidth : columnWidthAllocation,
56 | columnHeightAllocation < prefHeight ? prefHeight : columnHeightAllocation);
57 | }
58 |
59 | protected void resizeAndRepaint() {
60 | revalidate();
61 | repaint();
62 | }
63 |
64 | @Override
65 | protected int getElementSpaceAllocation() {
66 | return Math.max(MIN_CELL_SIZE, (40 - region.getCellsInColumn()* 2));
67 |
68 | }
69 |
70 | @Override protected Point getElementStartPoint(int elementSpaceAllocation) {
71 | int y = super.getElementStartPoint(elementSpaceAllocation).y + columnIndexHeight;
72 | return new Point(2, y);
73 | }
74 |
75 |
76 | @Override
77 | protected void doDrawing(Graphics2D g2d) {
78 | super.doDrawing(g2d);
79 | //Draw column index
80 | for (int i = 0; i < columns.size(); i++) {
81 | Rectangle area = getElementAreaByIndex(i);
82 | g2d.setColor(ACTIVE_COLOR);
83 | drawColumnIndex(g2d, columns.get(i).getIndex(), area);
84 | }
85 | //Draw selection
86 | Stroke originalStroke = g2d.getStroke();
87 | g2d.setStroke(new BasicStroke(2));
88 | if (selectedCellIndex != -1) {
89 | g2d.setColor(Color.RED);
90 | Rectangle aroundRec = getElementAreaWithScale(selectedCellIndex, 1 / (Math.PI / 4) * 0.9);
91 | g2d.drawOval(aroundRec.x, aroundRec.y, aroundRec.width, aroundRec.height);
92 | Column column = getCell(selectedCellIndex).getOwner();
93 | List columnCells = column.getElements();
94 | for (Cell columnCell : columnCells) {
95 | int cellInx = indexOf(columnCell);
96 | if (cellInx != selectedCellIndex) {
97 | aroundRec = getElementAreaWithScale(cellInx, 1 / (Math.PI / 4) * 0.9);
98 | g2d.setColor(Color.ORANGE);
99 | g2d.drawOval(aroundRec.x, aroundRec.y, aroundRec.width, aroundRec.height);
100 | }
101 | }
102 | }
103 | g2d.setStroke(originalStroke);
104 | }
105 |
106 | protected int getIndexCaptionYPosShift(){
107 | return SPACE_BETWEEN_ELEMENTS;
108 | }
109 |
110 | protected void drawColumnIndex(Graphics2D g2, int columnIndex, Rectangle firstCellArea) {
111 | FontRenderContext frc = g2.getFontRenderContext();
112 | Font indexFont = new Font("Helvetica", Font.BOLD, 12);
113 | TextLayout indexLayout = new TextLayout(columnIndex + "", indexFont, frc);
114 | int drawPosX = (int)(firstCellArea.getX() + (firstCellArea.getWidth() - indexLayout.getAdvance()) / 2);
115 | int drawPosY = firstCellArea.y - getIndexCaptionYPosShift();
116 | indexLayout.draw(g2, drawPosX, drawPosY);
117 | }
118 |
119 | @Override
120 | public Cell getCell(int index) {
121 | int cellIndex = index / dimension.width, columnIndex = index % dimension.width;
122 | return columns.get(columnIndex).getElementByIndex(cellIndex);
123 | }
124 |
125 | public int indexOf(Cell cell) {
126 | int index = 0;
127 | for (int y = 0; y < dimension.height; y++) {
128 | for (int x = 0; x < dimension.width; x++) {
129 | if (cell == getCell(index)) {
130 | return index;
131 | }
132 | index++;
133 | }
134 | }
135 | return -1;
136 | }
137 |
138 | public void setSelectedCellIndex(int selectedCellIndex) {
139 | this.selectedCellIndex = this.selectedCellIndex != selectedCellIndex ? selectedCellIndex : -1;
140 | repaint();
141 | }
142 |
143 | public void setSelectedCell(Cell cell) {
144 | setSelectedCellIndex(indexOf(cell));
145 | }
146 |
147 | @Override public Dimension getPreferredScrollableViewportSize() {
148 | return getParent() instanceof JViewport ? getParent().getSize() : getPreferredSize();
149 | }
150 |
151 | @Override public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
152 | return getElementSpaceAllocation();
153 | }
154 |
155 | @Override public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
156 | return getElementSpaceAllocation();
157 | }
158 |
159 | @Override public boolean getScrollableTracksViewportWidth() {
160 | return getParent() instanceof JViewport
161 | && (getParent().getWidth() > getPreferredSize().width);
162 | }
163 |
164 | @Override public boolean getScrollableTracksViewportHeight() {
165 | return getParent() instanceof JViewport
166 | && (getParent().getHeight() > getPreferredSize().height);
167 | }
168 |
169 | }
170 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/Layer.java:
--------------------------------------------------------------------------------
1 | package htm.model;
2 |
3 | import htm.model.algorithms.spatial.SpatialPooler;
4 | import htm.model.algorithms.temporal.TemporalPooler;
5 | import htm.model.space.BaseSpace;
6 | import htm.model.space.InputSpace;
7 | import htm.utils.CollectionUtils;
8 | import org.apache.commons.logging.Log;
9 | import org.apache.commons.logging.LogFactory;
10 |
11 | import java.awt.*;
12 | import java.util.List;
13 |
14 |
15 | public class Layer extends BaseSpace {
16 |
17 |
18 | private final InputSpace inputSpace;
19 | /**
20 | * inputRadius for this input Space
21 | * The concept of Input Radius is an additional parameter to control how
22 | * far away synapse connections can be made instead of allowing connections anywhere.
23 | */
24 | private final double inputRadius;
25 |
26 | /**
27 | * Furthest number of columns away (in this Region's Column grid space) to allow new distal
28 | * synapse connections. If set to 0 then there is no restriction and connections
29 | * can form between any two columns in the region.
30 | *
31 | * WP
32 | *
33 | * learningRadius The area around a temporal pooler cell from which it can get lateral connections.
34 | */
35 | private final double learningRadius;
36 | private final int cellsInColumn;
37 |
38 | private final boolean skipSpatial;
39 |
40 | private static final Log LOG = LogFactory.getLog(Layer.class);
41 |
42 | private static final CollectionUtils.Predicate BOTTOM_UP_WINNING_COLUMNS_PREDICATE = new CollectionUtils.Predicate() {
43 | @Override public boolean apply(Column column) {
44 | return column.isActive();
45 | }
46 | };
47 |
48 | //TODO not sure if Layer should directly reference algorithmic classes: Temporal/Spatial Pooler
49 | private TemporalPooler temporalPooler;
50 | private SpatialPooler spatialPooler;
51 |
52 | public TemporalPooler getTemporalPooler() {
53 | return temporalPooler;
54 | }
55 |
56 | public void setTemporalPooler(TemporalPooler temporalPooler) {
57 | this.temporalPooler = temporalPooler;
58 | }
59 |
60 | public SpatialPooler getSpatialPooler() {
61 | return spatialPooler;
62 | }
63 |
64 | public void setSpatialPooler(SpatialPooler spatialPooler) {
65 | this.spatialPooler = spatialPooler;
66 | }
67 |
68 |
69 | public Layer(Config layerCfg) {
70 | super(layerCfg.getRegionDimension().width, layerCfg.getRegionDimension().height);
71 | this.cellsInColumn = layerCfg.getCellsInColumn();
72 | this.initElementSpace();
73 | this.inputSpace = new InputSpace(layerCfg.getSensoryInputDimension().width,
74 | layerCfg.getSensoryInputDimension().height);
75 | this.inputRadius = layerCfg.getInputRadius();
76 | this.learningRadius = layerCfg.getLearningRadius();
77 | this.skipSpatial = layerCfg.isSkipSpatial();
78 | if (skipSpatial) {
79 | if (inputSpace.getDimension().height != this.getDimension().height || inputSpace.getDimension().width != this.getDimension().width) {
80 | throw new IllegalArgumentException(
81 | "With \"Skip Spatial Mode \" Sensory Input must be the same size as this Region");
82 | }
83 | } else {
84 | connectToInputSpace();
85 | }
86 | }
87 |
88 | @Override
89 | protected Column createElement(int index, Point position) {
90 | return new Column(this, index, position);
91 | }
92 |
93 | public java.util.List getColumns() {
94 | return this.getElements();
95 | }
96 |
97 | public void connectToInputSpace() {
98 | for (Column column : getColumns()) {
99 | column.createProximalSegment(inputRadius);
100 | }
101 | }
102 |
103 | public Point convertColumnPositionToInputSpace(Point columnPosition) {
104 | return convertPositionToOtherSpace(columnPosition, this.getDimension(), inputSpace.getDimension());
105 | }
106 |
107 | public Point convertInputPositionToColumnSpace(Point inputPosition) {
108 | return convertPositionToOtherSpace(inputPosition, inputSpace.getDimension(), this.getDimension());
109 | }
110 |
111 |
112 | /**
113 | * WP
114 | * activeColumns(t) t=0
115 | * List of column indices that are winners due to bottom-up input
116 | * (this is the output of the spatial pooler).
117 | *
118 | * @return
119 | */
120 |
121 | public List getActiveColumns() {
122 | return CollectionUtils.filter(this.getElements(), BOTTOM_UP_WINNING_COLUMNS_PREDICATE);
123 | }
124 |
125 | /**
126 | * WP
127 | * activeColumns(t)
128 | * List of column indices that are winners due to bottom-up input
129 | * (this is the output of the spatial pooler).
130 | *
131 | * @param time (t - 0) - current step, (t - 1) - previous step, (t- n) - n step
132 | * @return
133 | */
134 | public List getActiveColumns(final int time) {
135 | return CollectionUtils.filter(this.getElements(), new CollectionUtils.Predicate() {
136 | @Override public boolean apply(Column column) {
137 | return column.isActive(time);
138 | }
139 | });
140 | }
141 |
142 |
143 | /**
144 | * WP
145 | * averageReceptiveFieldSize()
146 | * The radius of the average connected receptive field size of all the columns.
147 | * The connected receptive field size of a column includes only the connected synapses (those with permanence values >= connectedPerm).
148 | * This is used to determine the extent of lateral inhibition between columns.
149 | */
150 |
151 | public double getAverageReceptiveFieldSize() {
152 | double sum = 0;
153 | for (Column column : getColumns()) {
154 | java.util.List connectedSynapses = column.getConnectedSynapses();
155 | double maxDistance = 0;
156 | for (Synapse.ProximalSynapse connectedSynapse : connectedSynapses) {
157 | // Determine the distance of the further proximal synapse. This will be considered the size of the receptive field.
158 | maxDistance = Math.max(maxDistance, connectedSynapse.getDistanceToColumn());
159 | }
160 | LOG.debug("maxDistance for column:#" + column.getIndex() + " - " + maxDistance);
161 | // Add the current column's receptive field size to the sum.
162 | sum += maxDistance;
163 | }
164 | return sum / getColumns().size();
165 | }
166 |
167 | public Dimension getInputSpaceDimension() {
168 | return inputSpace.getDimension();
169 | }
170 |
171 | public InputSpace getInputSpace() {
172 | return inputSpace;
173 | }
174 |
175 | public double getInputRadius() {
176 | return inputRadius;
177 | }
178 |
179 | public double getLearningRadius() {
180 | return learningRadius;
181 | }
182 |
183 | public boolean isSkipSpatial() {
184 | return skipSpatial;
185 | }
186 |
187 | public int getCellsInColumn() {
188 | return cellsInColumn;
189 | }
190 |
191 | public static class Config {
192 | private final Dimension regionDimension;
193 | private final Dimension sensoryInputDimension;
194 | private final double inputRadius;
195 | private final double learningRadius;
196 | private final boolean skipSpatial;
197 | private final int cellsInColumn;
198 |
199 |
200 | public Config(Dimension regionDimension, Dimension sensoryInputDimension,
201 | double inputRadius, double learningRadius, boolean skipSpatial, int cellsInColumn) {
202 | this.regionDimension = regionDimension;
203 | this.sensoryInputDimension = sensoryInputDimension;
204 | this.inputRadius = inputRadius;
205 | this.learningRadius = learningRadius;
206 | this.skipSpatial = skipSpatial;
207 | this.cellsInColumn = cellsInColumn;
208 | }
209 |
210 | public double getLearningRadius() {
211 | return learningRadius;
212 | }
213 |
214 | public double getInputRadius() {
215 | return inputRadius;
216 | }
217 |
218 | public Dimension getRegionDimension() {
219 | return regionDimension;
220 | }
221 |
222 | public Dimension getSensoryInputDimension() {
223 | return sensoryInputDimension;
224 | }
225 |
226 | public boolean isSkipSpatial() {
227 | return skipSpatial;
228 | }
229 |
230 |
231 | public int getCellsInColumn() {
232 | return cellsInColumn;
233 | }
234 | }
235 | }
236 |
237 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/algorithms/spatial/WhitePaperSpatialPooler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.model.algorithms.spatial;
10 |
11 | import htm.model.Column;
12 | import htm.model.Synapse;
13 | import org.apache.commons.logging.Log;
14 | import org.apache.commons.logging.LogFactory;
15 |
16 | import java.util.ArrayList;
17 | import java.util.Collections;
18 | import java.util.Comparator;
19 | import java.util.List;
20 |
21 | public class WhitePaperSpatialPooler extends SpatialPooler {
22 |
23 | private static final Log LOG = LogFactory.getLog(WhitePaperSpatialPooler.class);
24 |
25 |
26 | private static final Comparator OVERLAP_COMPARATOR = new Comparator() {
27 | @Override public int compare(Column column1, Column column2) {
28 | Double overlap1 = column1.getOverlap(), overlap2 = column2.getOverlap();
29 | return overlap2.compareTo(overlap1);
30 | }
31 | };
32 |
33 | public WhitePaperSpatialPooler(Config cfg) {
34 | super(cfg);
35 | }
36 |
37 | /**
38 | * Performs spatial pooling for the current input in this Region.
39 | * The result will be a subset of Columns being set as active as well
40 | * as (proximal) synapses in all Columns having updated permanences and boosts, and
41 | * the Region will update inhibitionRadius.
42 | *
43 | * WP
44 | * Phase 1:
45 | * Compute the overlap with the current input for each column. Given an input
46 | * vector, the first phase calculates the overlap of each column with that
47 | * vector. The overlap for each column is simply the number of connected
48 | * synapses with active inputs, multiplied by its boost. If this value is
49 | * below minOverlap, we set the overlap score to zero.
50 | *
51 | * Phase 2:
52 | * Compute the winning columns after inhibition. The second phase calculates
53 | * which columns remain as winners after the inhibition step.
54 | * desiredLocalActivity is a parameter that controls the number of columns
55 | * that end up winning. For example, if desiredLocalActivity is 10, a column
56 | * will be a winner if its overlap score is greater than the score of the
57 | * 10'th highest column within its inhibition radius.
58 | *
59 | * Phase 3:
60 | * Update synapse permanence and internal variables.The third phase performs
61 | * learning; it updates the permanence values of all synapses as necessary,
62 | * as well as the boost and inhibition radius. The main learning rule is
63 | * implemented in lines 20-26. For winning columns, if a synapse is active,
64 | * its permanence value is incremented, otherwise it is decremented. Permanence
65 | * values are constrained to be between 0 and 1.
66 | * Lines 28-36 implement boosting. There are two separate boosting mechanisms
67 | * in place to help a column learn connections. If a column does not win often
68 | * enough (as measured by activeDutyCycle), its overall boost value is
69 | * increased (line 30-32). Alternatively, if a column's connected synapses do
70 | * not overlap well with any inputs often enough (as measured by
71 | * overlapDutyCycle), its permanence values are boosted (line 34-36).
72 | */
73 |
74 | @Override
75 | public void execute() {
76 | double inhibitionRadius = layer.getAverageReceptiveFieldSize();
77 | if (layer.isSkipSpatial()) {
78 | for (Column currentColumn : layer.getElementsList()) {
79 | currentColumn.setActive(layer.getInputSpace().getInputValue(currentColumn.getIndex()));
80 | }
81 | } else {
82 | phaseOne();
83 | phaseThree(phaseTwo(inhibitionRadius), inhibitionRadius);
84 | }
85 | }
86 |
87 | public void phaseOne() {
88 | //Phase 1: Compute the overlap
89 | for (Column column : layer.getElementsList()) {
90 | computeOverlapForColumn(column);
91 | }
92 | }
93 |
94 | public List phaseTwo(double inhibitionRadius) {
95 | //Phase 2:Compute the winning columns after inhibition
96 | List activeColumns = new ArrayList();
97 | for (Column column : layer.getElementsList()) {
98 | if (computeActiveDoInhibitionForColumn(column, inhibitionRadius)) {
99 | activeColumns.add(column);
100 | }
101 | }
102 | return activeColumns;
103 | }
104 |
105 |
106 | public void phaseThree(List activeColumns, double inhibitionRadius) {
107 | // Phase 3: Update synapse permanence and internal variables
108 | if (isLearningMode()) {
109 | for (Column activeColumn : activeColumns) {
110 | learnSpatialForActiveForColumn(activeColumn);
111 | }
112 | for (Column column : layer.getElementsList()) {
113 | boostWeakForColumn(column, inhibitionRadius);
114 | }
115 | }
116 | }
117 |
118 | /**
119 | * WP
120 | * SPATIAL POOLING
121 | *
122 | * Phase 1: Overlap
123 | * Given an input vector, the first phase calculates the overlap of each column with that vector.
124 | * The overlap for each column is simply the number of connected synapses with active inputs,
125 | * multiplied by its boost. If this value is below minOverlap, we set the overlap score to zero.
126 | *
127 | * @return
128 | */
129 | public double computeOverlapForColumn(Column currentColumn) {
130 | double currentOverLap = currentColumn.getActiveConnectedSynapses().size();
131 | if (currentOverLap < this.getMinimalOverlap()) {
132 | currentOverLap = 0;
133 | } else {
134 | currentOverLap = currentOverLap * currentColumn.getBoost();
135 | }
136 | currentColumn.updateOverlap(currentOverLap);
137 | return currentOverLap;
138 | }
139 |
140 | /**
141 | * WP
142 | * SPATIAL POOLING
143 | *
144 | * Phase 2: Inhibition
145 | * The second phase calculates which columns remain as winners after the inhibition step.
146 | * desiredLocalActivity is a parameter that controls the number of columns that end up winning.
147 | * For example, if desiredLocalActivity is 10, a column will be a winner if its overlap score is
148 | * greater than the score of the 10'th highest column within its inhibition radius.
149 | *
150 | * @param inhibitionRadius
151 | * @return
152 | */
153 |
154 | public boolean computeActiveDoInhibitionForColumn(Column currentColumn, double inhibitionRadius) {
155 | double minLocalActivity = kthScore(currentColumn.getNeighbors(inhibitionRadius), this.getDesiredLocalActivity());
156 | currentColumn.setActive(currentColumn.getOverlap() > 0 && currentColumn.getOverlap() >= minLocalActivity);
157 | return currentColumn.isActive();
158 | }
159 |
160 | /**
161 | * WP
162 | * SPATIAL POOLING
163 | *
164 | * Phase 3: Learning
165 | * The third phase performs learning; it updates the permanence values of all synapses as necessary, as well as the boost and inhibition radius.
166 | *
167 | * First part
168 | * The main learning rule is implemented in lines 20-26. For winning columns, if a synapse is active, its permanence value is incremented, otherwise it is decremented. Permanence values are constrained to be between 0 and 1.
169 | */
170 |
171 | public void learnSpatialForActiveForColumn(Column currentColumn) {
172 | if (currentColumn.isActive()) {
173 | List potentialSynapses = currentColumn.getPotentialSynapses();
174 | for (Synapse.ProximalSynapse potentialSynapse : potentialSynapses) {
175 | if (potentialSynapse.getConnectedSensoryInput().getValue()) {
176 | potentialSynapse.setPermanence(
177 | potentialSynapse.getPermanence() + Synapse.ProximalSynapse.PERMANENCE_INCREASE);
178 | } else {
179 | potentialSynapse.setPermanence(
180 | potentialSynapse.getPermanence() - Synapse.ProximalSynapse.PERMANENCE_DECREASE);
181 | }
182 | }
183 | }
184 | }
185 |
186 | /**
187 | * Second part
188 | * Lines 28-36 implement boosting. There are two separate boosting mechanisms in place to help a column learn connections. If a column does not win often enough (as measured by activeDutyCycle), its overall boost value is increased (line 30-32). Alternatively, if a column's connected synapses do not overlap well with any inputs often enough (as measured by overlapDutyCycle), its permanence values are boosted (line 34-36). Note: once learning is turned off, boost(c) is frozen.
189 | * Finally, at the end of Phase 3 the inhibition radius is recomputed (line 38).
190 | *
191 | * @param inhibitionRadius
192 | */
193 | public void boostWeakForColumn(Column currentColumn, double inhibitionRadius) {
194 | double minDutyCycle = 0.01 * currentColumn.getMaxDutyCycle(inhibitionRadius);
195 | currentColumn.updateBoost(minDutyCycle, this.getBoostRate());
196 | if (currentColumn.getOverlapDutyCycle() < minDutyCycle) {
197 | currentColumn.increasePermanence(0.1 * Synapse.ProximalSynapse.CONNECTED_PERMANENCE);
198 | }
199 | }
200 |
201 |
202 | /**
203 | * WP
204 | * kthScore(cols, k)
205 | * Given the list of columns, return the k'th highest overlap value.
206 | */
207 | private double kthScore(List neighbors, int desiredLocalActivity) {
208 | Collections.sort(neighbors, OVERLAP_COMPARATOR);
209 | if (desiredLocalActivity > neighbors.size()) {
210 | desiredLocalActivity = neighbors.size();
211 | }
212 | return neighbors.get(desiredLocalActivity - 1).getOverlap();
213 |
214 | }
215 |
216 |
217 | }
218 |
--------------------------------------------------------------------------------
/src/main/java/htm/visualizer/surface/BaseSurface.java:
--------------------------------------------------------------------------------
1 | package htm.visualizer.surface;
2 |
3 | import htm.utils.MathUtils;
4 |
5 | import java.awt.*;
6 | import java.awt.event.MouseAdapter;
7 | import java.awt.event.MouseEvent;
8 | import java.awt.event.MouseMotionAdapter;
9 | import java.util.ArrayList;
10 | import java.util.Collection;
11 | import javax.swing.*;
12 |
13 | public abstract class BaseSurface extends JPanel {
14 | protected static final int SPACE_BETWEEN_ELEMENTS = 4;
15 | public static final Color BACKGROUND_COLOR = Color.WHITE;
16 | public static final Color ACTIVE_COLOR = Color.BLACK;
17 |
18 | protected final Dimension dimension;
19 | /**
20 | * need two following parameters to buffer input on mouse drag event
21 | */
22 | private int lastVisitedInputIndex = -1;
23 | private boolean mouseDragged = false;
24 |
25 | public BaseSurface(int xSize, int ySize) {
26 | this.dimension = new Dimension(xSize, ySize);
27 | setBackground(BACKGROUND_COLOR);
28 | addMouseListener(new MouseAdapter() {
29 |
30 | @Override
31 | public void mouseReleased(MouseEvent e) {
32 | lastVisitedInputIndex = -1;
33 | if (!mouseDragged) {
34 | mouseOver(e.getX(), e.getY());
35 | }
36 | mouseDragged = false;
37 | }
38 | });
39 |
40 | addMouseMotionListener(new MouseMotionAdapter() {
41 | @Override
42 | public void mouseDragged(MouseEvent e) {
43 | mouseDragged = true;
44 | mouseOver(e.getX(), e.getY());
45 | }
46 | });
47 | }
48 |
49 | protected int getElementSpaceAllocation() {
50 | Dimension size = this.getSize();
51 | double result = MathUtils.findMin((size.getHeight() - 2) / dimension.height,
52 | (size.getWidth() - 2) / dimension.width);
53 | return result < 1 ? 1 : (int)result - 1;
54 | }
55 |
56 | protected Point getElementStartPoint(int elementSpaceAllocation) {
57 | Dimension size = this.getSize();
58 | int startX = (int)(size.getWidth() - elementSpaceAllocation * this.dimension.width) / 2;
59 | int startY = (int)(size.getHeight() - elementSpaceAllocation * this.dimension.height) / 2;
60 | return new Point(startX, startY);
61 | }
62 |
63 | protected void doDrawing(Graphics2D g2d) {
64 | int elementSpaceAllocation = getElementSpaceAllocation();
65 | Point startPoint = getElementStartPoint(elementSpaceAllocation);
66 |
67 | int index = 0;
68 | for (int y = 0; y < dimension.height; y++) {
69 | for (int x = 0; x < dimension.width; x++) {
70 | drawElement(g2d, index, elementSpaceAllocation * x + startPoint.x, elementSpaceAllocation * y + startPoint.y,
71 | elementSpaceAllocation - SPACE_BETWEEN_ELEMENTS, elementSpaceAllocation - SPACE_BETWEEN_ELEMENTS);
72 | index++;
73 | }
74 | }
75 | }
76 |
77 | private void mouseOver(int mouseX, int mouseY) {
78 | int elementSpaceAllocation = getElementSpaceAllocation(), elementWidth = (elementSpaceAllocation - BaseSurface.SPACE_BETWEEN_ELEMENTS);
79 | Point startPoint = getElementStartPoint(elementSpaceAllocation);
80 | int index = 0;
81 | outer:
82 | for (int y = 0; y < dimension.height; y++) {
83 | for (int x = 0; x < dimension.width; x++) {
84 | int elementCenterX = elementSpaceAllocation * x + startPoint.x + elementWidth / 2;
85 | int elementCenterY = elementSpaceAllocation * y + startPoint.y + elementWidth / 2;
86 | if (lastVisitedInputIndex != index && isMouseOverElement(mouseX, mouseY, elementCenterX, elementCenterY,
87 | elementWidth)) {
88 | fireElementMouseEnterEvent(index);
89 | lastVisitedInputIndex = index;
90 | break outer;
91 | }
92 | index++;
93 | }
94 | }
95 | }
96 |
97 | public Point getElementPositionByIndex(int byIndex) {
98 | int index = 0;
99 | for (int y = 0; y < dimension.height; y++) {
100 | for (int x = 0; x < dimension.width; x++) {
101 | if (byIndex == index) {
102 | return new Point(x, y);
103 | }
104 | index++;
105 | }
106 | }
107 | throw new IllegalArgumentException("No Element found by Index:" + byIndex);
108 | }
109 |
110 | public Rectangle getElementAreaByIndex(int byIndex) {
111 | return getElementArea(getElementPositionByIndex(byIndex));
112 | }
113 |
114 | public Rectangle getElementArea(Point position) {
115 | int elementSpaceAllocation = getElementSpaceAllocation();
116 | Point startPoint = getElementStartPoint(elementSpaceAllocation);
117 | return new Rectangle(elementSpaceAllocation * position.x + startPoint.x,
118 | elementSpaceAllocation * position.y + startPoint.y,
119 | elementSpaceAllocation - BaseSurface.SPACE_BETWEEN_ELEMENTS + 1,
120 | elementSpaceAllocation - BaseSurface.SPACE_BETWEEN_ELEMENTS + 1);
121 |
122 |
123 | }
124 |
125 |
126 | /**
127 | * Return element area scaled by scaleFactor parameter
128 | *
129 | * @param position
130 | * @param scaleFactor
131 | * @return
132 | */
133 |
134 | public Rectangle getElementAreaWithScale(Point position, double scaleFactor) {
135 | Rectangle outsideArea = getElementArea(position);
136 | double newWidth = outsideArea.getWidth() * scaleFactor, newHeight = outsideArea.getHeight() * scaleFactor,
137 | newX = outsideArea.getX() - (newWidth - outsideArea.getWidth()) / 2, newY = outsideArea.getY() - (newHeight - outsideArea.getHeight()) / 2;
138 | return new Rectangle((int)newX, (int)newY, (int)newWidth, (int)newHeight);
139 | }
140 |
141 | public Rectangle getElementAreaWithScale(int byIndex, double scaleFactor) {
142 | return getElementAreaWithScale(getElementPositionByIndex(byIndex), scaleFactor);
143 | }
144 |
145 |
146 | protected abstract boolean isMouseOverElement(int mouseX, int mouseY, int elementCenterX, int elementCenterY,
147 | int elementWidth);
148 |
149 | protected abstract void drawElement(Graphics2D g2d, int index, int x, int y, int width, int height);
150 |
151 |
152 | @Override
153 | protected void paintComponent(Graphics g) {
154 | super.paintComponent(g);
155 | Graphics2D g2d = (Graphics2D)g;
156 | doDrawing(g2d);
157 | }
158 |
159 | /*Custom events implementation*/
160 | private final Collection _listeners = new ArrayList();
161 |
162 | public synchronized void addElementMouseEnterListener(ElementMouseEnterListener listener) {
163 | _listeners.add(listener);
164 | }
165 |
166 | public synchronized void removeElementMouseEnterListener(ElementMouseEnterListener listener) {
167 | _listeners.remove(listener);
168 | }
169 |
170 | private synchronized void fireElementMouseEnterEvent(int index) {
171 | ElementMouseEnterEvent event = new ElementMouseEnterEvent(this, index);
172 | for (ElementMouseEnterListener _listener : _listeners) {
173 | (_listener).onElementMouseEnter(event);
174 | }
175 | }
176 |
177 | /**
178 | * the amount of elements over x
179 | */
180 | public int getXSize() {
181 | return dimension.width;
182 | }
183 |
184 | /**
185 | * the amount of elements over y
186 | */
187 | public int getYSize() {
188 | return dimension.height;
189 | }
190 |
191 | public static class ElementMouseEnterEvent extends java.util.EventObject {
192 | private final int index;
193 |
194 | public ElementMouseEnterEvent(Object source, int index) {
195 | super(source);
196 | this.index = index;
197 | }
198 |
199 | public int getIndex() {
200 | return index;
201 | }
202 |
203 | }
204 |
205 | public interface ElementMouseEnterListener {
206 | public void onElementMouseEnter(ElementMouseEnterEvent e);
207 | }
208 |
209 | public static class CircleElementsSurface extends BaseSurface {
210 | protected CircleElementsSurface(int xSize, int ySize) {
211 | super(xSize, ySize);
212 | }
213 |
214 | /*
215 | Just draw empty circle.
216 | */
217 | @Override protected void drawElement(Graphics2D g2d, int index, int x, int y, int width, int height) {
218 | g2d.setColor(ACTIVE_COLOR);
219 | g2d.drawOval(x, y, width, height);
220 | }
221 |
222 | @Override
223 | protected boolean isMouseOverElement(int mouseX, int mouseY, int elementCenterX, int elementCenterY,
224 | int elementWidth) {
225 | /*circle eq in coordinates*/
226 | return Math.pow(mouseX - elementCenterX, 2) + Math.pow(mouseY - elementCenterY, 2) - Math.pow(elementWidth / 2,
227 | 2) <= 0;
228 | }
229 | }
230 |
231 | public static class SquareElementsSurface extends BaseSurface {
232 | protected SquareElementsSurface(int xSize, int ySize) {
233 | super(xSize, ySize);
234 | }
235 |
236 | /*Just draw empty square*/
237 | @Override protected void drawElement(Graphics2D g2d, int index, int x, int y, int width, int height) {
238 | g2d.setColor(ACTIVE_COLOR);
239 | g2d.drawRect(x, y, width, height);
240 | }
241 |
242 | @Override
243 | protected boolean isMouseOverElement(int mouseX, int mouseY, int elementCenterX, int elementCenterY,
244 | int elementWidth) {
245 | return MathUtils.inRange(mouseX, elementCenterX - elementWidth / 2, elementCenterX + elementWidth / 2) &&
246 | MathUtils.inRange(mouseY, elementCenterY - elementWidth / 2, elementCenterY + elementWidth / 2);
247 | }
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/Cell.java:
--------------------------------------------------------------------------------
1 | package htm.model;
2 |
3 | import htm.model.fractal.Composite;
4 | import htm.utils.CircularArrayList;
5 | import org.apache.commons.logging.Log;
6 | import org.apache.commons.logging.LogFactory;
7 |
8 | import java.util.*;
9 |
10 | public class Cell extends Composite{
11 | private static final Log LOG = LogFactory.getLog(Cell.class);
12 |
13 | /**
14 | * WP
15 | *
16 | * newSynapseCount
17 | * The maximum number of synapses added to a segment during learning.
18 | */
19 |
20 | public static int AMOUNT_OF_SYNAPSES = 30;
21 | /**
22 | * cell will keep a buffer of its last TIME_STEPS states
23 | */
24 | public static int TIME_STEPS = 6;
25 |
26 | public int getCellIndex() {
27 | return cellIndex;
28 | }
29 |
30 | public List getSegmentUpdates() {
31 | return segmentUpdates;
32 | }
33 |
34 | public enum State {
35 | ACTIVE,
36 | LEARN
37 | }
38 |
39 |
40 | //current and step before
41 | public static final int BEFORE = 1;
42 | public static final int NOW = 0;
43 |
44 | //no prediction in up coming steps
45 | public static final int NOT_IN_STEP_PREDICTION = -1;
46 |
47 |
48 | private final int cellIndex;
49 | /**
50 | * Boolean vector of Cell's active state in time t-n, ..., t-1, t
51 | */
52 | private final CellStateBuffer activeState = new CellStateBuffer();
53 | /**
54 | * learnState(c, i, t) A boolean indicating whether cell i in column c is
55 | * chosen as the cell to learn on.
56 | */
57 | private final CellStateBuffer learnState = new CellStateBuffer();
58 |
59 | /**
60 | * Boolean vector of Cell's predictive state in time t-n, ..., t-1, t
61 | */
62 | //private CellStateBuffer predictiveState = new CellStateBuffer();
63 |
64 | private final PredictInStepBuffer predictedInStepState = new PredictInStepBuffer();
65 |
66 |
67 | private final List segmentUpdates = new ArrayList();
68 |
69 | public static void updateFromConfig(Config cellCfg) {
70 | AMOUNT_OF_SYNAPSES = cellCfg.getAmountOfSynapses();
71 | TIME_STEPS = cellCfg.getTimeSteps();
72 | }
73 |
74 | public Cell(Column belongsToColumn, int cellIndex) {
75 | this.owner = belongsToColumn;
76 | this.cellIndex = cellIndex;
77 | }
78 |
79 | public List getSegments(){
80 | return getElements();
81 | }
82 |
83 | /*
84 | *Set Learn State in current time Cell.NOW
85 | */
86 | public void setLearnState() {
87 | if(!this.getActiveState(Cell.NOW)){
88 | LOG.warn("Setting non active cell as learning:" + this);
89 | }
90 | this.learnState.setState();
91 | }
92 |
93 | /**
94 | * Get Learn state in Time
95 | *
96 | * @param time
97 | */
98 | public boolean getLearnState(int time) {
99 | return this.learnState.get(time);
100 | }
101 |
102 | /**
103 | * Set active state
104 | */
105 | public void setActiveState() {
106 | this.activeState.setState();
107 | /*Added by Kirill to track speed of permanence changes for active cells*/
108 | for (DistalDendriteSegment segment : this.elementList) {
109 | for (Synapse.DistalSynapse distalSynapse : segment.getElementsList()) {
110 | distalSynapse.updatePermanenceRangeForActiveCell();
111 | }
112 | }
113 | }
114 |
115 |
116 |
117 | /**
118 | * Get Active state in Time
119 | *
120 | * WP
121 | *
122 | * activeState(c, i, t)
123 | *
124 | * A boolean vector with one number per cell.
125 | * It represents the active state of the column c cell i
126 | * at time t given the current feed-forward input and the
127 | * past temporal context.
128 | * activeState(c, i, t) is the contribution from column c cell i at time t.
129 | * If true, the cell has current feed-forward input as well as an appropriate temporal context.
130 | *
131 | * @param time
132 | */
133 | public boolean getActiveState(int time) {
134 | return this.activeState.get(time);
135 | }
136 |
137 | /**
138 | * Set Predictive state
139 | */
140 | /*public void setPredictiveState(boolean predictiveState) {
141 | this.predictiveState.setState(predictiveState);
142 | }*/
143 |
144 | /**
145 | * Get Predictive state in Time
146 | *
147 | * WP
148 | *
149 | * predictiveState(c, i, t)
150 | * A boolean vector with one number per cell.
151 | * It represents the prediction of the column c cell i at time t,
152 | * given the bottom-up activity of other columns and the past temporal context.
153 | * predictiveState(c, i, t) is the contribution of column c cell i at time t.
154 | * If 1, the cell is predicting feed-forward input in the current temporal context.
155 | *
156 | * @param time
157 | */
158 | public boolean getPredictiveState(int time) {
159 | //return this.predictiveState.get(time);
160 | return getPredictInStepState(time) != NOT_IN_STEP_PREDICTION;
161 | }
162 |
163 | public void setPredictInStepState(int step) {
164 | predictedInStepState.setPredictInStep(step);
165 | }
166 |
167 | public int getPredictInStepState(int time) {
168 | return predictedInStepState.get(time);
169 | }
170 |
171 |
172 |
173 | public boolean deleteSegment(DistalDendriteSegment toDelete) {
174 | return elementList.remove(toDelete);
175 | }
176 |
177 | public void deleteAllSegment() {
178 | elementList.clear();
179 | }
180 |
181 |
182 | @Override public String toString() {
183 | StringBuilder result = new StringBuilder().append("Column Inx:").append(this.getOwner().getIndex());
184 | result = result.append("; Cell Inx:").append(this.getCellIndex());
185 | result = result.append("; Position:").append(this.getOwner().getPosition());
186 | result = result.append("; Active:").append(this.getActiveState(Cell.NOW));
187 | result = result.append("; Learn:").append(this.getLearnState(Cell.NOW));
188 | result = result.append("; Predicted:").append(this.getPredictiveState(Cell.NOW));
189 | return result.toString();
190 | }
191 |
192 |
193 |
194 | public List getNeighborsAndMyColumn() {
195 | return this.owner.getOwner().getAllWithinRadius(this.owner.getPosition(),
196 | this.owner.getOwner().getLearningRadius());
197 |
198 | }
199 |
200 |
201 |
202 |
203 | /*Custom events implementation*/
204 | private final Collection _segmentsChangeEventListeners = new HashSet();
205 |
206 | public synchronized void addSegmentsChangeListener(SegmentsChangeEventListener listener) {
207 | _segmentsChangeEventListeners.add(listener);
208 | }
209 |
210 | public synchronized void removeSegmentsChangeListener(SegmentsChangeEventListener listener) {
211 | _segmentsChangeEventListeners.remove(listener);
212 | }
213 |
214 | public synchronized void fireUpdatesChange() {
215 | SegmentsChangeEvent event = new SegmentsChangeEvent(this);
216 | for (SegmentsChangeEventListener segmentsChangeEventListener : _segmentsChangeEventListeners) {
217 | segmentsChangeEventListener.onUpdatesChange(event);
218 | }
219 | }
220 |
221 | public synchronized void fireSegmentsChange() {
222 | SegmentsChangeEvent event = new SegmentsChangeEvent(this);
223 | for (SegmentsChangeEventListener segmentsChangeEventListener : _segmentsChangeEventListeners) {
224 | segmentsChangeEventListener.onSegmentsChange(event);
225 | }
226 | }
227 |
228 |
229 | public static class SegmentsChangeEvent extends java.util.EventObject {
230 |
231 | public SegmentsChangeEvent(Cell source) {
232 | super(source);
233 | }
234 |
235 | }
236 |
237 | public interface SegmentsChangeEventListener {
238 | public void onSegmentsChange(SegmentsChangeEvent e);
239 |
240 | public void onUpdatesChange(SegmentsChangeEvent e);
241 | }
242 |
243 |
244 | /*
245 | *Advances this cell to the next time step.
246 | *The current state of this cell (active, learning, predicting) will be set as the
247 | *previous state and the current state will be reset to no cell activity by
248 | *default until it can be determined.
249 | *Call this function before each temporal cycle
250 | */
251 | public void nextTimeStep() {
252 | this.activeState.add(Cell.NOW, false);
253 | this.predictedInStepState.add(Cell.NOW, NOT_IN_STEP_PREDICTION);
254 | this.learnState.add(Cell.NOW, false);
255 | }
256 |
257 | private static class CellStateBuffer extends CircularArrayList {
258 | public CellStateBuffer() {
259 | super(TIME_STEPS);
260 | for (int i = 0; i < TIME_STEPS; i++) {
261 | this.add(false);
262 | }
263 | }
264 |
265 | /**
266 | * Set the current state(time NOW)
267 | *
268 | */
269 | void setState() {
270 | this.set(NOW, true);
271 | }
272 | }
273 |
274 | private static class PredictInStepBuffer extends CircularArrayList {
275 | public PredictInStepBuffer() {
276 | super(TIME_STEPS);
277 | for (int i = 0; i < TIME_STEPS; i++) {
278 | this.add(NOT_IN_STEP_PREDICTION);
279 | }
280 | }
281 |
282 | void setPredictInStep(int step) {
283 | this.set(NOW, step);
284 | }
285 | }
286 |
287 | public static class Config {
288 | private final int amountOfSynapses;
289 | private final int timeSteps;
290 |
291 | public Config(int amountOfSynapses, int timeSteps) {
292 | this.amountOfSynapses = amountOfSynapses;
293 | this.timeSteps = timeSteps;
294 | }
295 |
296 |
297 | public int getAmountOfSynapses() {
298 | return amountOfSynapses;
299 | }
300 |
301 | public int getTimeSteps() {
302 | return timeSteps;
303 | }
304 | }
305 |
306 | }
--------------------------------------------------------------------------------
/src/main/java/htm/visualizer/surface/LayerSlicedHorizontalView.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.visualizer.surface;
10 |
11 | import htm.model.Cell;
12 | import htm.model.Column;
13 | import htm.model.DistalDendriteSegment;
14 | import htm.model.Layer;
15 | import htm.model.Synapse;
16 | import htm.utils.UIUtils;
17 | import org.apache.commons.logging.Log;
18 | import org.apache.commons.logging.LogFactory;
19 |
20 | import java.awt.*;
21 | import java.util.ArrayList;
22 | import java.util.Collections;
23 | import java.util.List;
24 | import javax.swing.*;
25 |
26 | public class LayerSlicedHorizontalView extends JPanel {
27 | private static final Log LOG = LogFactory.getLog(LayerSlicedHorizontalView.class);
28 | private final List layers = new ArrayList();
29 | private CellPosition clickedOnCellPosition = null;
30 | private CellPosition selectedSynapseCellPosition = null;
31 | private final List selectedSegmentSynapsesCellPositionList = new ArrayList();
32 |
33 |
34 | public List getLayers() {
35 | return Collections.unmodifiableList(layers);
36 | }
37 |
38 | public ColumnCellsByIndexSurface getLayer(int layerInx) {
39 | return layers.get(layerInx);
40 | }
41 |
42 | public void addElementMouseEnterListener(BaseSurface.ElementMouseEnterListener listener) {
43 | for (BaseSurface layer : layers) {
44 | layer.addElementMouseEnterListener(listener);
45 | }
46 | }
47 |
48 |
49 | public LayerSlicedHorizontalView(Layer region) {
50 | super(new GridLayout(0, 1));
51 | for (int i = 0; i < region.getCellsInColumn(); i++) {
52 | final ColumnCellsByIndexSurface cellLayer = new ColumnCellsByIndexSurface(this, region, i);
53 | layers.add(i, cellLayer);
54 | cellLayer.setBorder(UIUtils.LIGHT_GRAY_BORDER);
55 | this.add(new Container() {
56 | private Container init(String caption) {
57 | this.setLayout(new BorderLayout());
58 | this.add(new JLabel(caption), BorderLayout.NORTH);
59 | this.add(cellLayer, BorderLayout.CENTER);
60 | return this;
61 | }
62 | }.init("Layer #" + i));
63 | }
64 | }
65 |
66 | public CellPosition getClickedOnCellPosition() {
67 | return clickedOnCellPosition;
68 | }
69 |
70 | public void setClickedOnCell(Cell clickedOnCell) {
71 | this.setClickedOnCellPosition(new CellPosition(clickedOnCell.getOwner().getIndex(),
72 | clickedOnCell.getCellIndex()));
73 | }
74 |
75 | public void setClickedOnCellPosition(CellPosition clickedOnCellPosition) {
76 | this.clickedOnCellPosition = clickedOnCellPosition.equals(
77 | this.clickedOnCellPosition) ? null : clickedOnCellPosition;
78 | this.selectedSynapseCellPosition = null;
79 | selectedSegmentSynapsesCellPositionList.clear();
80 | repaint();
81 | }
82 |
83 |
84 | public CellPosition getSelectedSynapseCellPosition() {
85 | return selectedSynapseCellPosition;
86 | }
87 |
88 |
89 | public void resetSelectedSynapseCellPosition() {
90 | this.selectedSynapseCellPosition = null;
91 | }
92 |
93 | public void setSelectedSynapse(Synapse.DistalSynapse selectedSynapse) {
94 | CellPosition newSelectedSynapseCellPosition = new CellPosition(
95 | selectedSynapse.getFromCell().getOwner().getIndex(),
96 | selectedSynapse.getFromCell().getCellIndex());
97 | this.selectedSynapseCellPosition = this.selectedSynapseCellPosition == newSelectedSynapseCellPosition ? null : newSelectedSynapseCellPosition;
98 | }
99 |
100 | public void setSelectedSegment(DistalDendriteSegment selectedSegment) {
101 | selectedSegmentSynapsesCellPositionList.clear();
102 | if (selectedSegment != null) {
103 | for (Synapse.DistalSynapse distalSynapse : selectedSegment.getElementsList()) {
104 | selectedSegmentSynapsesCellPositionList.add(new CellPosition(
105 | distalSynapse.getFromCell().getOwner().getIndex(),
106 | distalSynapse.getFromCell().getCellIndex()));
107 | }
108 | }
109 | }
110 |
111 | public List getSelectedSegmentSynapsesCellPositionList() {
112 | return selectedSegmentSynapsesCellPositionList;
113 | }
114 |
115 |
116 | public static class CellPosition {
117 | private final int columnIndex;
118 | private final int cellIndex;
119 |
120 | private CellPosition(Integer columnIndex, Integer cellIndex) {
121 | this.columnIndex = columnIndex;
122 | this.cellIndex = cellIndex;
123 | }
124 |
125 | public Integer getColumnIndex() {
126 | return columnIndex;
127 | }
128 |
129 | public Integer getCellIndex() {
130 | return cellIndex;
131 | }
132 |
133 | public boolean equals(Object obj) {
134 | if (obj instanceof CellPosition) {
135 | CellPosition cp = (CellPosition)obj;
136 | return (columnIndex == cp.columnIndex) && (cellIndex == cp.cellIndex);
137 | }
138 | return super.equals(obj);
139 | }
140 | }
141 |
142 | public static class ColumnCellsByIndexSurface extends CellSurface {
143 |
144 |
145 | public ColumnCellsByIndexSurface(LayerSlicedHorizontalView view, Layer region, int sliceIndex) {
146 | super(region.getDimension().width, region.getDimension().height, region);
147 | this.parentView = view;
148 | this.layerIndex = sliceIndex;
149 | this.addElementMouseEnterListener(new ElementMouseEnterListener() {
150 | @Override
151 | public void onElementMouseEnter(ElementMouseEnterEvent e) {
152 | CellPosition clickedOnPosition = new CellPosition(e.getIndex(), layerIndex);
153 | parentView.setClickedOnCellPosition(clickedOnPosition);
154 | }
155 | });
156 | }
157 |
158 | @Override
159 | public Cell getCell(int columnIndex) {
160 | return region.getElementByIndex(columnIndex).getElementByIndex(layerIndex);
161 | }
162 |
163 |
164 | private final LayerSlicedHorizontalView parentView;
165 | private final int layerIndex;
166 |
167 |
168 | private CellPosition getClickedOnCellPosition() {
169 | return parentView.getClickedOnCellPosition();
170 | }
171 |
172 | private CellPosition getSelectedSynapseCellPosition() {
173 | return parentView.getSelectedSynapseCellPosition();
174 | }
175 |
176 | private List getSelectedSegmentSynapsesCellPositionList() {
177 | return parentView.getSelectedSegmentSynapsesCellPositionList();
178 | }
179 |
180 | /* private void repaintAll() {
181 | for (ColumnCellsByIndexSurface layer : parentView.getLayers()) {
182 | layer.repaint();
183 | }
184 | }
185 |
186 | public void setSelectedSynapseColumnIndex(int selectedSynapseInx) {
187 | parentView.setSelectedSynapseCellPosition(selectedSynapseInx == -1 ? null : new CellPosition(selectedSynapseInx,
188 | this.layerIndex));
189 | repaintAll();
190 | } */
191 |
192 |
193 | public void drawNeighbors(int columnIndex, Graphics2D g2d) {
194 | Cell clickedOnCell = this.getCell(columnIndex);
195 | List neighborColumns = getRegion().getAllWithinRadius(clickedOnCell.getOwner().getPosition(),
196 | getRegion().getLearningRadius());
197 | neighborColumns.remove(clickedOnCell.getOwner());
198 | g2d.setColor(Color.LIGHT_GRAY);
199 | Composite original = g2d.getComposite();
200 | g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
201 | 0.4f));
202 | for (Column column : neighborColumns) {
203 | Rectangle columnRec = this.getElementArea(column.getPosition());
204 | g2d.fillOval(columnRec.x, columnRec.y, columnRec.width, columnRec.height);
205 | }
206 | g2d.setComposite(original);
207 |
208 | }
209 |
210 | @Override
211 | protected void doDrawing(Graphics2D g2d) {
212 | super.doDrawing(g2d);
213 | //LOG.debug("Draw Sliced Region");
214 | CellPosition clickedOn = getClickedOnCellPosition(), selectedSynapse = getSelectedSynapseCellPosition();
215 | List selectedSegmentSynapsesCellPositionListCol = getSelectedSegmentSynapsesCellPositionList();
216 | if (clickedOn != null) {
217 | Stroke originalStroke = g2d.getStroke();
218 | g2d.setStroke(new BasicStroke(1.5f));
219 | if (clickedOn.getCellIndex() == layerIndex) {
220 | g2d.setColor(Color.RED);
221 | Rectangle aroundRec = getElementAreaWithScale(clickedOn.getColumnIndex(), 1 / (Math.PI / 4) * 1.05);
222 | //Rectangle aroundRec = getElementAreaByIndex(clickedOn.getColumnIndex());
223 | //g2d.drawLine(aroundRec.x + aroundRec.width/2, aroundRec.y, aroundRec.x + aroundRec.width/2, aroundRec.y + aroundRec.height);
224 | //g2d.drawLine(aroundRec.x, aroundRec.y + aroundRec.height/2, aroundRec.x + aroundRec.width, aroundRec.y + aroundRec.height/2);
225 | g2d.drawOval(aroundRec.x, aroundRec.y, aroundRec.width, aroundRec.height);
226 | } else {
227 | Rectangle aroundRec = getElementAreaWithScale(clickedOn.getColumnIndex(), 1 / (Math.PI / 4) * 1.05);
228 | g2d.setColor(Color.ORANGE);
229 | g2d.drawOval(aroundRec.x, aroundRec.y, aroundRec.width, aroundRec.height);
230 | }
231 | g2d.setStroke(originalStroke);
232 | }
233 | if (clickedOn != null) {
234 | drawNeighbors(clickedOn.getColumnIndex(), g2d);
235 | }
236 | if (selectedSynapse != null && selectedSynapse.getCellIndex() == this.layerIndex) {
237 | Composite original = g2d.getComposite();
238 | Rectangle aroundRec = getElementAreaWithScale(selectedSynapse.getColumnIndex(), 1 / (Math.PI / 4) * 1.5);
239 | g2d.setColor(UIUtils.LIGHT_BLUE);
240 | g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
241 | 0.5f));
242 | g2d.fillOval(aroundRec.x, aroundRec.y, aroundRec.width, aroundRec.height);
243 | g2d.setComposite(original);
244 | }
245 | for (CellPosition cellPosition : selectedSegmentSynapsesCellPositionListCol) {
246 | if (cellPosition.getCellIndex() == this.layerIndex) {
247 | Color originalColor = g2d.getColor();
248 | g2d.setColor(Color.DARK_GRAY);
249 | Rectangle aroundRec = getElementAreaByIndex(cellPosition.getColumnIndex());
250 | g2d.drawRect(aroundRec.x, aroundRec.y, aroundRec.width, aroundRec.height);
251 | g2d.setColor(originalColor);
252 | }
253 | }
254 | }
255 |
256 | }
257 | }
258 |
--------------------------------------------------------------------------------
/src/main/java/htm/visualizer/SpatialInfo.java:
--------------------------------------------------------------------------------
1 | package htm.visualizer;
2 |
3 | import htm.model.Column;
4 | import htm.model.Synapse;
5 | import htm.model.space.BaseSpace;
6 | import htm.utils.UIUtils;
7 |
8 | import java.awt.*;
9 | import java.util.LinkedHashMap;
10 | import java.util.Map;
11 | import javax.swing.*;
12 | import javax.swing.border.TitledBorder;
13 | import javax.swing.table.AbstractTableModel;
14 |
15 |
16 | public class SpatialInfo extends JPanel {
17 | private Column currentColumn;
18 | private final JTable proximalSynapsesTable;
19 | private final JTable neighborColumnsTable;
20 |
21 |
22 | public SpatialInfo() {
23 | this.setLayout(new GridBagLayout());
24 | GridBagConstraints c = new GridBagConstraints();
25 | c.fill = GridBagConstraints.BOTH;
26 | c.anchor = GridBagConstraints.NORTH;
27 | c.weighty = 1.0;
28 | c.weightx = 1.4;
29 | ColumnAttributesInfo left = new ColumnAttributesInfo();
30 | left.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
31 | "Column Properties",
32 | TitledBorder.CENTER,
33 | TitledBorder.TOP));
34 | this.add(left, c);
35 | c.gridx = 1;
36 | c.weightx = 1.8;
37 | //Create the scroll pane and add the table to it.
38 | proximalSynapsesTable = initSynapsesTable();
39 | JComponent center = (new JPanel() {
40 | private JPanel init() {
41 | this.setBackground(Color.WHITE);
42 | this.setLayout(new BorderLayout());
43 | add(new JScrollPane(proximalSynapsesTable), BorderLayout.CENTER);
44 | proximalSynapsesTable.setFillsViewportHeight(true);
45 | return this;
46 | }
47 | }.init());
48 | add(center);
49 | center.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
50 | "Proximal Synapses",
51 | TitledBorder.CENTER,
52 | TitledBorder.TOP));
53 |
54 |
55 | this.add(center, c);
56 | c.gridx = 2;
57 | c.weightx = 2.2;
58 | neighborColumnsTable = initNeighborColumnsTable();
59 | JComponent right = (new JPanel() {
60 | private JPanel init() {
61 | this.setBackground(Color.WHITE);
62 | this.setLayout(new BorderLayout());
63 | add(new JScrollPane(neighborColumnsTable), BorderLayout.CENTER);
64 | neighborColumnsTable.setFillsViewportHeight(true);
65 | return this;
66 | }
67 | }.init());
68 | add(right);
69 | right.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
70 | "Neighbor Columns",
71 | TitledBorder.CENTER,
72 | TitledBorder.TOP));
73 | this.add(right, c);
74 |
75 |
76 | }
77 |
78 | private JTable initSynapsesTable() {
79 | JTable table = new JTable(new ProximalSynapsesModel());
80 | table.setAutoCreateRowSorter(true);
81 | table.getColumnModel().getColumn(0).setCellRenderer(new UIUtils.PermanenceRenderer());
82 | table.getColumnModel().getColumn(1).setCellRenderer(new UIUtils.SmallDoubleRenderer());
83 | table.getColumnModel().getColumn(2).setPreferredWidth(50);
84 | table.getColumnModel().getColumn(3).setPreferredWidth(50);
85 | table.getColumnModel().getColumn(4).setCellRenderer(new UIUtils.PositionRenderer());
86 | return table;
87 | }
88 |
89 | public JTable getSynapsesTable() {
90 | return proximalSynapsesTable;
91 | }
92 |
93 | public JTable getNeighborColumnsTable() {
94 | return neighborColumnsTable;
95 | }
96 |
97 |
98 | private JTable initNeighborColumnsTable() {
99 | JTable table = new JTable(new NeighborColumnsModel());
100 | table.setAutoCreateRowSorter(true);
101 | table.getColumnModel().getColumn(0).setCellRenderer(new UIUtils.SmallDoubleRenderer());
102 | table.getColumnModel().getColumn(1).setCellRenderer(new UIUtils.SmallDoubleRenderer());
103 | table.getColumnModel().getColumn(1).setPreferredWidth(50);
104 | table.getColumnModel().getColumn(2).setCellRenderer(new UIUtils.SmallDoubleRenderer());
105 | table.getColumnModel().getColumn(3).setCellRenderer(new UIUtils.SmallDoubleRenderer());
106 | table.getColumnModel().getColumn(4).setCellRenderer(new UIUtils.SmallDoubleRenderer());
107 | table.getColumnModel().getColumn(4).setPreferredWidth(50);
108 | table.getColumnModel().getColumn(5).setPreferredWidth(40);
109 | table.getColumnModel().getColumn(6).setPreferredWidth(40);
110 | table.getColumnModel().getColumn(7).setCellRenderer(new UIUtils.PositionRenderer());
111 | return table;
112 | }
113 |
114 |
115 | public void setCurrentColumn(Column currentColumn) {
116 | this.currentColumn = this.currentColumn != currentColumn ? currentColumn : null;
117 | ((ProximalSynapsesModel)proximalSynapsesTable.getModel()).setColumn(this.currentColumn);
118 | ((NeighborColumnsModel)neighborColumnsTable.getModel()).setColumn(this.currentColumn);
119 | this.repaint();
120 | }
121 |
122 |
123 | private class ColumnAttributesInfo extends UIUtils.TextColumnInfo {
124 |
125 | @Override
126 | protected Map getAttributeMap() {
127 | Column column = currentColumn;
128 | Map result = new LinkedHashMap();
129 | if (column != null) {
130 | double inhibitionRadius = column.getOwner().getAverageReceptiveFieldSize();
131 | result.put("Index", column.getIndex() + "");
132 | result.put("Position", "X:" + (column.getPosition().x) + ", Y:" + column.getPosition().y);
133 | result.put("Active", column.isActive() ? "Yes" : "No");
134 | result.put("Active Duty Cycle", UIUtils.DF_4.format(column.getActiveDutyCycle()));
135 | result.put("Max Duty Cycle", UIUtils.DF_4.format(column.getMaxDutyCycle(inhibitionRadius)));
136 | result.put("Boost", UIUtils.DF_2.format(column.getBoost()));
137 | result.put("Overlap", UIUtils.DF_2.format(column.getOverlap()));
138 | result.put("Over. Duty Cycle", UIUtils.DF_4.format(column.getOverlapDutyCycle()));
139 | result.put("Neighbors Count", column.getNeighbors(inhibitionRadius).size() + "");
140 | result.put("Connected Syn.", column.getConnectedSynapses().size() + "");
141 | result.put("Active Syn.", column.getActiveConnectedSynapses().size() + "");
142 | result.put("Avg. Rec. Field", UIUtils.DF_2.format(inhibitionRadius) + "");
143 | }
144 | return result;
145 | }
146 |
147 | }
148 |
149 | class NeighborColumnsModel extends AbstractTableModel {
150 | private Column column = null;
151 | private java.util.List neighbors = null;
152 | private final String[] columnNames = {
153 | "Overlap",
154 | "Dist",
155 | "ADC",
156 | "ODC",
157 | "Boost",
158 | "Act",
159 | "Inx",
160 | "Position"};
161 |
162 | public void setColumn(Column column) {
163 | this.column = column != null ? column : null;
164 | neighbors = column != null ? column.getNeighbors(column.getOwner().getAverageReceptiveFieldSize()) : null;
165 | this.fireTableDataChanged();
166 | }
167 |
168 | @Override public int getRowCount() {
169 | return neighbors == null ? 0 : neighbors.size();
170 | }
171 |
172 | @Override public int getColumnCount() {
173 | return columnNames.length;
174 | }
175 |
176 | @Override
177 | public String getColumnName(int col) {
178 | return columnNames[col];
179 | }
180 |
181 | @Override public Object getValueAt(int rowIndex, int columnIndex) {
182 | Object value = null;
183 | if (neighbors != null && column != null) {
184 | Column row = neighbors.get(rowIndex);
185 | switch (columnIndex) {
186 | case 0:
187 | value = row.getOverlap();
188 | break;
189 | case 1:
190 | value = BaseSpace.getDistance(column.getPosition(), row.getPosition());
191 | break;
192 | case 2:
193 | value = row.getActiveDutyCycle();
194 | break;
195 | case 3:
196 | value = row.getOverlapDutyCycle();
197 | break;
198 | case 4:
199 | value = row.getBoost();
200 | break;
201 | case 5:
202 | value = row.isActive();
203 | break;
204 | case 6:
205 | value = row.getIndex();
206 | break;
207 | case 7:
208 | value = new UIUtils.SortablePoint(row.getPosition());
209 | break;
210 | default:
211 | value = null;
212 | }
213 | }
214 | return value;
215 | }
216 |
217 | @Override public Class> getColumnClass(int columnIndex) {
218 | Class> result;
219 | switch (columnIndex) {
220 | case 0:
221 | result = Double.class;
222 | break;
223 | case 1:
224 | result = Double.class;
225 | break;
226 | case 2:
227 | result = Double.class;
228 | break;
229 | case 3:
230 | result = Double.class;
231 | break;
232 | case 4:
233 | result = Double.class;
234 | break;
235 | case 5:
236 | result = Boolean.class;
237 | break;
238 | case 6:
239 | result = Integer.class;
240 | break;
241 | case 7:
242 | result = UIUtils.SortablePoint.class;
243 | break;
244 | default:
245 | result = super.getColumnClass(
246 | columnIndex);
247 | }
248 | return result;
249 | }
250 |
251 | }
252 |
253 | class ProximalSynapsesModel extends AbstractTableModel {
254 | private java.util.List synapses = null;
255 | private final String[] columnNames = {
256 | "Perm",
257 | "Dist",
258 | "I-Act",
259 | "I-Inx",
260 | "I-Position"};
261 |
262 | public void setColumn(Column column) {
263 | synapses = column != null ? column.getPotentialSynapses() : null;
264 | this.fireTableDataChanged();
265 | }
266 |
267 | @Override public int getRowCount() {
268 | return synapses == null ? 0 : synapses.size();
269 | }
270 |
271 | @Override public int getColumnCount() {
272 | return columnNames.length;
273 | }
274 |
275 | @Override
276 | public String getColumnName(int col) {
277 | return columnNames[col];
278 | }
279 |
280 | @Override public Object getValueAt(int rowIndex, int columnIndex) {
281 | Object value = null;
282 | if (synapses != null) {
283 | Synapse.ProximalSynapse row = synapses.get(rowIndex);
284 | switch (columnIndex) {
285 | case 0:
286 | value = row.getPermanence();
287 | break;
288 | case 1:
289 | value = row.getDistanceToColumn();
290 | break;
291 | case 2:
292 | value = row.getConnectedSensoryInput().getValue();
293 | break;
294 | case 3:
295 | value = row.getConnectedSensoryInput().getIndex();
296 | break;
297 | case 4:
298 | value = new UIUtils.SortablePoint(row.getConnectedSensoryInput().getPosition());
299 | break;
300 | default:
301 | value = null;
302 | }
303 | }
304 | return value;
305 | }
306 |
307 | @Override public Class> getColumnClass(int columnIndex) {
308 | Class> result;
309 | switch (columnIndex) {
310 | case 0:
311 | result = Double.class;
312 | break;
313 | case 1:
314 | result = Double.class;
315 | break;
316 | case 2:
317 | result = Boolean.class;
318 | break;
319 | case 3:
320 | result = Integer.class;
321 | break;
322 | case 4:
323 | result = UIUtils.SortablePoint.class;
324 | break;
325 | default:
326 | result = super.getColumnClass(
327 | columnIndex);
328 | }
329 | return result;
330 | }
331 | }
332 |
333 |
334 | }
335 |
336 |
--------------------------------------------------------------------------------
/src/main/java/htm/visualizer/ParametersEditor.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.visualizer;
10 |
11 | import java.awt.*;
12 | import java.awt.event.ActionEvent;
13 | import java.awt.event.ActionListener;
14 | import java.awt.event.ComponentAdapter;
15 | import java.awt.event.ComponentEvent;
16 | import java.awt.event.KeyEvent;
17 | import java.awt.event.WindowAdapter;
18 | import java.awt.event.WindowEvent;
19 | import java.io.Serializable;
20 | import javax.swing.*;
21 | import javax.swing.border.Border;
22 | import javax.swing.border.TitledBorder;
23 |
24 | public class ParametersEditor extends JComponent {
25 | private final static Color LIGHT_BLUE = new Color(150, 150, 255);
26 | private static final Border DEFAULT_BORDER = BorderFactory.createEmptyBorder(4, 4, 4, 4);
27 | private static final Font LABEL_FONT = UIManager.getFont("JLabel.font");
28 | private static final Color TITLE_COLOR = UIManager.getColor("Slider.foreground");
29 |
30 |
31 | public static HTMGraphicInterface.Config showDialog(Component component,
32 | String title,
33 | HTMGraphicInterface.Config initialParams) throws HeadlessException {
34 |
35 | final ParametersEditor pane = new ParametersEditor(initialParams);
36 |
37 | ParametersTracker ok = new ParametersTracker(pane);
38 | JDialog dialog = createDialog(component, title, true, pane, ok, null);
39 |
40 | dialog.setVisible(true); // blocks until user brings dialog down...
41 |
42 | return ok.getParameters();
43 | }
44 |
45 | public static JDialog createDialog(Component c, String title, boolean modal,
46 | ParametersEditor chooserPane, ActionListener okListener,
47 | ActionListener cancelListener) throws HeadlessException {
48 |
49 | Window window = getWindowForComponent(c);
50 | ParametersEditorDialog dialog;
51 | if (window instanceof Frame) {
52 | dialog = new ParametersEditorDialog((Frame)window, title, modal, c, chooserPane,
53 | okListener, cancelListener);
54 | } else {
55 | dialog = new ParametersEditorDialog((Dialog)window, title, modal, c, chooserPane,
56 | okListener, cancelListener);
57 | }
58 | return dialog;
59 | }
60 |
61 | static Window getWindowForComponent(Component parentComponent)
62 | throws HeadlessException {
63 | if (parentComponent == null) {
64 | return JOptionPane.getRootFrame();
65 | }
66 | if (parentComponent instanceof Frame || parentComponent instanceof Dialog) {
67 | return (Window)parentComponent;
68 | }
69 | return getWindowForComponent(parentComponent.getParent());
70 | }
71 |
72 | private final Parameters.TemporalPoolerParameters temporalPoolerParameters;
73 | private final Parameters.SpatialPoolerParameters spatialPoolerParameters;
74 | private final Parameters.RegionParameters regionParameters;
75 | private final Parameters.ColumnParameters columnParameters;
76 | private final Parameters.CellParameters cellParameters;
77 | private final Parameters.SynapseParameters proximalSynapsesParameters;
78 | private final Parameters.SynapseParameters distalSynapsesParameters;
79 |
80 | public void setParameters(HTMGraphicInterface.Config params) {
81 | temporalPoolerParameters.setParameters(params.getTemporalPoolerConfig());
82 | spatialPoolerParameters.setParameters(params.getSpatialPoolerConfig());
83 | regionParameters.setParameters(params.getRegionConfig());
84 | columnParameters.setParameters(params.getColumnConfig());
85 | proximalSynapsesParameters.setParameters(params.getProximalSynapseConfig());
86 | distalSynapsesParameters.setParameters(params.getDistalSynapseConfig());
87 | cellParameters.setParameters(params.getCellConfig());
88 | }
89 |
90 | public HTMGraphicInterface.Config getParameters() {
91 | return new HTMGraphicInterface.Config(null,
92 | temporalPoolerParameters.getParameters(),
93 | spatialPoolerParameters.getParameters(),
94 | regionParameters.getParameters(),
95 | columnParameters.getParameters(),
96 | cellParameters.getParameters(),
97 | proximalSynapsesParameters.getParameters(),
98 | distalSynapsesParameters.getParameters());
99 | }
100 |
101 | public ParametersEditor(HTMGraphicInterface.Config params) {
102 | regionParameters = new Parameters.RegionParameters(params.getRegionConfig());
103 | columnParameters = new Parameters.ColumnParameters(params.getColumnConfig());
104 | cellParameters = new Parameters.CellParameters(params.getCellConfig());
105 | spatialPoolerParameters = new Parameters.SpatialPoolerParameters(params.getSpatialPoolerConfig());
106 | temporalPoolerParameters = new Parameters.TemporalPoolerParameters(params.getTemporalPoolerConfig());
107 | proximalSynapsesParameters = new Parameters.SynapseParameters(params.getProximalSynapseConfig());
108 | distalSynapsesParameters = new Parameters.SynapseParameters(params.getDistalSynapseConfig());
109 |
110 | this.setLayout(new BorderLayout());
111 | JTabbedPane tabs = new JTabbedPane();
112 | tabs.addTab("General", new JComponent() {
113 | private Container init() {
114 | this.setLayout(new BorderLayout());
115 | this.add(decorateWithBorder(regionParameters, "Region Properties"));
116 | return this;
117 | }
118 | }.init());
119 | tabs.addTab("Spatial", new JComponent() {
120 | private Container init() {
121 | this.setLayout(new GridBagLayout());
122 | GridBagConstraints c = new GridBagConstraints();
123 | c.fill = GridBagConstraints.BOTH;
124 | c.gridx = 0;
125 | c.gridy = 0;
126 | c.weighty = 3.0;
127 | this.add(decorateWithBorder(spatialPoolerParameters, "Spatial Pooler"), c);
128 | c.gridy = 1;
129 | c.weighty = 1.0;
130 | this.add(decorateWithBorder(columnParameters, "Column Parameters"), c);
131 | c.gridy = 2;
132 | c.weighty = 3.0;
133 | this.add(decorateWithBorder(proximalSynapsesParameters, "Proximal Synapses"), c);
134 | return this;
135 | }
136 | }.init());
137 | tabs.addTab("Temporal", new JComponent() {
138 | private Container init() {
139 | this.setLayout(new GridBagLayout());
140 | GridBagConstraints c = new GridBagConstraints();
141 | c.fill = GridBagConstraints.BOTH;
142 | c.gridx = 0;
143 | c.gridy = 0;
144 | c.weighty = 3.0;
145 | this.add(decorateWithBorder(temporalPoolerParameters, "Temporal Pooler"), c);
146 | c.gridy = 1;
147 | c.weighty = 2.0;
148 | this.add(decorateWithBorder(cellParameters, "Cell Parameters"), c);
149 | c.gridy = 2;
150 | c.weighty = 3.0;
151 | this.add(decorateWithBorder(distalSynapsesParameters, "Distal Synapses"), c);
152 | return this;
153 | }
154 | }.init());
155 | this.add(tabs);
156 | }
157 |
158 | private JComponent decorateWithBorder(JComponent component, String title) {
159 | component.setBorder(BorderFactory.createCompoundBorder(
160 | BorderFactory.createTitledBorder(null, title, TitledBorder.CENTER, TitledBorder.TOP, LABEL_FONT,
161 | TITLE_COLOR),
162 | DEFAULT_BORDER));
163 | return component;
164 | }
165 |
166 | }
167 |
168 | class ParametersEditorDialog extends JDialog {
169 | private HTMGraphicInterface.Config initialCfg;
170 | private ParametersEditor chooserPane;
171 | private JButton cancelButton;
172 |
173 | public ParametersEditorDialog(Dialog owner, String title, boolean modal,
174 | Component c, ParametersEditor chooserPane,
175 | ActionListener okListener, ActionListener cancelListener)
176 | throws HeadlessException {
177 | super(owner, title, modal);
178 | initParametersChooserDialog(c, chooserPane, okListener, cancelListener);
179 | }
180 |
181 | public ParametersEditorDialog(Frame owner, String title, boolean modal,
182 | Component c, ParametersEditor chooserPane,
183 | ActionListener okListener, ActionListener cancelListener)
184 | throws HeadlessException {
185 | super(owner, title, modal);
186 | initParametersChooserDialog(c, chooserPane, okListener, cancelListener);
187 | }
188 |
189 | protected void initParametersChooserDialog(Component c, ParametersEditor chooserPane,
190 | ActionListener okListener, ActionListener cancelListener) {
191 | //setResizable(false);
192 |
193 | this.chooserPane = chooserPane;
194 |
195 | String okString = "Ok";
196 | String cancelString = "Cancel";
197 | String resetString = "Reset";
198 |
199 | Container contentPane = getContentPane();
200 | contentPane.setLayout(new BorderLayout());
201 | contentPane.add(chooserPane, BorderLayout.CENTER);
202 |
203 | /*
204 | * Create Lower button panel
205 | */
206 | JPanel buttonPane = new JPanel();
207 | buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER));
208 | JButton okButton = new JButton(okString);
209 | getRootPane().setDefaultButton(okButton);
210 | okButton.setActionCommand("OK");
211 | okButton.addActionListener(new ActionListener() {
212 | @Override
213 | public void actionPerformed(ActionEvent e) {
214 | setVisible(false);
215 | }
216 | });
217 | if (okListener != null) {
218 | okButton.addActionListener(okListener);
219 | }
220 | buttonPane.add(okButton);
221 |
222 | cancelButton = new JButton(cancelString);
223 |
224 | // The following few lines are used to register esc to close the dialog
225 | Action cancelKeyAction = new AbstractAction() {
226 | @Override
227 | public void actionPerformed(ActionEvent e) {
228 | for (ActionListener a : ((AbstractButton)e.getSource()).getActionListeners()) {
229 | a.actionPerformed(e);
230 | }
231 | }
232 | };
233 | KeyStroke cancelKeyStroke = KeyStroke.getKeyStroke((char)KeyEvent.VK_ESCAPE);
234 | InputMap inputMap = cancelButton.getInputMap(JComponent.
235 | WHEN_IN_FOCUSED_WINDOW);
236 | ActionMap actionMap = cancelButton.getActionMap();
237 | if (inputMap != null && actionMap != null) {
238 | inputMap.put(cancelKeyStroke, "cancel");
239 | actionMap.put("cancel", cancelKeyAction);
240 | }
241 | // end esc handling
242 |
243 | cancelButton.setActionCommand("cancel");
244 | cancelButton.addActionListener(new ActionListener() {
245 | @Override
246 | public void actionPerformed(ActionEvent e) {
247 | setVisible(false);
248 | }
249 | });
250 | if (cancelListener != null) {
251 | cancelButton.addActionListener(cancelListener);
252 | }
253 | buttonPane.add(cancelButton);
254 |
255 | JButton resetButton = new JButton(resetString);
256 | resetButton.addActionListener(new ActionListener() {
257 | @Override
258 | public void actionPerformed(ActionEvent e) {
259 | reset();
260 | }
261 | });
262 | buttonPane.add(resetButton);
263 | contentPane.add(buttonPane, BorderLayout.SOUTH);
264 |
265 | if (JDialog.isDefaultLookAndFeelDecorated()) {
266 | boolean supportsWindowDecorations =
267 | UIManager.getLookAndFeel().getSupportsWindowDecorations();
268 | if (supportsWindowDecorations) {
269 | getRootPane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG);
270 | }
271 | }
272 | applyComponentOrientation(((c == null) ? getRootPane() : c).getComponentOrientation());
273 | pack();
274 | setLocationRelativeTo(c);
275 |
276 | this.addWindowListener(new Closer());
277 | this.addComponentListener(new DisposeOnClose());
278 | }
279 |
280 | @Override public void setVisible(boolean b) {
281 | initialCfg = chooserPane.getParameters();
282 | super.setVisible(b);
283 | }
284 |
285 | public void reset() {
286 | chooserPane.setParameters(initialCfg);
287 | }
288 |
289 | class Closer extends WindowAdapter implements Serializable {
290 | @Override
291 | public void windowClosing(WindowEvent e) {
292 | cancelButton.doClick(0);
293 | Window w = e.getWindow();
294 | w.setVisible(false);
295 | }
296 | }
297 |
298 | static class DisposeOnClose extends ComponentAdapter implements Serializable {
299 | @Override
300 | public void componentHidden(ComponentEvent e) {
301 | Window w = (Window)e.getComponent();
302 | w.dispose();
303 | }
304 | }
305 | }
306 |
307 | class ParametersTracker implements ActionListener, Serializable {
308 | final ParametersEditor chooser;
309 | HTMGraphicInterface.Config cfg;
310 |
311 | public ParametersTracker(ParametersEditor c) {
312 | chooser = c;
313 | }
314 |
315 | @Override
316 | public void actionPerformed(ActionEvent e) {
317 | cfg = chooser.getParameters();
318 | }
319 |
320 | public HTMGraphicInterface.Config getParameters() {
321 | return cfg;
322 | }
323 | }
324 |
325 |
--------------------------------------------------------------------------------
/examples/pong.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 | 5.0
6 | 50.0
7 | 3
8 | 12
9 | 24
10 |
11 |
12 | 12
13 | 24
14 |
15 |
16 | 20
17 | 3
18 | 3
19 | 0.01
20 |
21 | |
22 | 5
23 | 2
24 | 0
25 | 30
26 | 6
27 | |
28 |
29 | 0.2
30 | 0.0050
31 | 0.0050
32 |
33 |
34 | 0.2
35 | 0.0050
36 | 0.0050
37 |
38 |
39 | 110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
40 | 000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
41 | 000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
42 | 000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
43 | 000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
44 | 000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
45 | 000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
46 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
47 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
48 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
49 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
50 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
51 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
52 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
53 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
54 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000
55 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000
56 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000
57 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000
58 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000
59 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000
60 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000
61 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000
62 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000
63 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000
64 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000
65 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000
66 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000
67 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000
68 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
69 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
70 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
71 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
72 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
73 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
74 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
75 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
76 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
77 | 000000000000000000000000000000000000000000000000000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
78 | 000000000000000000000000000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
79 | 000000000000000000000000000000000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
80 | 000000000000000000000000000000000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
81 | 000000000000000000000000000011000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
82 | 000000000000000000110000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
83 | 000000001100000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
84 |
85 |
86 |
--------------------------------------------------------------------------------
/src/main/java/htm/model/Column.java:
--------------------------------------------------------------------------------
1 | package htm.model;
2 |
3 | import htm.model.space.BaseSpace;
4 | import htm.model.space.Element;
5 | import htm.model.space.InputSpace;
6 | import htm.utils.CircularArrayList;
7 | import htm.utils.CollectionUtils;
8 | import htm.utils.MathUtils;
9 | import org.apache.commons.logging.Log;
10 | import org.apache.commons.logging.LogFactory;
11 |
12 | import java.awt.*;
13 | import java.util.*;
14 | import java.util.List;
15 |
16 | public class Column extends Element {
17 | private static final Log LOG = LogFactory.getLog(Column.class);
18 | public static int AMOUNT_OF_PROXIMAL_SYNAPSES = 30;
19 |
20 | private static final CollectionUtils.Predicate ACTIVE_CONNECTED_PROXIMAL_SYNAPSES_PREDICATE = new CollectionUtils.Predicate() {
21 | @Override
22 | public boolean apply(Synapse.ProximalSynapse synapse) {
23 | return synapse.isConnected(
24 | Synapse.ProximalSynapse.CONNECTED_PERMANENCE) && synapse.getConnectedSensoryInput().getValue();
25 | }
26 | };
27 |
28 | private static final CollectionUtils.Predicate CONNECTED_PROXIMAL_SYNAPSES_PREDICATE = new CollectionUtils.Predicate() {
29 | @Override
30 | public boolean apply(Synapse.ProximalSynapse synapse) {
31 | return synapse.isConnected(Synapse.ProximalSynapse.CONNECTED_PERMANENCE);
32 | }
33 | };
34 |
35 | private static final Comparator ACTIVE_DUTY_CYCLE_COMPARATOR = new Comparator() {
36 | @Override public int compare(Column column1, Column column2) {
37 | Double activeDutyCycle1 = column1.getActiveDutyCycle(), activeDutyCycle2 = column2.getActiveDutyCycle();
38 | return activeDutyCycle2.compareTo(activeDutyCycle1);
39 | }
40 | };
41 |
42 |
43 | @Override
44 | public boolean addAll(List all) {
45 | throw new NoSuchElementException("Not supported for Column, fixed number of cells");
46 | }
47 |
48 | @Override
49 | public boolean addElement(Cell element) {
50 | throw new NoSuchElementException("Not supported for Column, fixed number of cells");
51 | }
52 |
53 | @Override
54 | public void removeElement(Cell element) {
55 | throw new NoSuchElementException("Not supported for Column, fixed number of cells");
56 | }
57 |
58 |
59 | private static final int COLUMN_CYCLE_BUFFER_SIZE = 1000;
60 |
61 |
62 | public static void updateFromConfig(Config columnCfg) {
63 | Column.AMOUNT_OF_PROXIMAL_SYNAPSES = columnCfg.getAmountOfProximalSynapses();
64 | }
65 |
66 |
67 | private final List proximalSynapses = new ArrayList();
68 | private double boost = 1.0;
69 |
70 | /**
71 | * WP
72 | * overlap(c) The spatial pooler overlap of column c with a particular
73 | * input pattern.
74 | */
75 | private final ColumnBufferedState overlap; //Need to create it later in constructor to access Column instance
76 |
77 | private final ColumnBufferedState active = new ColumnBufferedState(false) {
78 | @Override protected boolean positiveCondition(Boolean active) {
79 | return active;
80 | }
81 | };
82 |
83 | private final Map> neighbors_cache = new HashMap>();
84 |
85 | public Column(final Layer layer, int columnIndex, Point columnGridPosition) {
86 | super(layer, columnGridPosition, columnIndex);
87 | for (int i = 0; i < layer.getCellsInColumn(); i++) {
88 | this.elementList.add(new Cell(this, i));
89 | }
90 |
91 |
92 | overlap = new ColumnBufferedState(0.0) {
93 |
94 | @Override protected boolean positiveCondition(Double overlap) {
95 | //TODO not sure if Column should directly reference algorithmic classes: Temporal/Spatial Pooler,
96 | //TODO but having TP properties in column as static prop even worse
97 | if(layer.getSpatialPooler() == null){
98 | throw new RuntimeException("Spatial Pooler should be defined");
99 | }
100 | return overlap >= layer.getSpatialPooler().getMinimalOverlap();
101 | }
102 | };
103 | }
104 |
105 | public void updateOverlap(double currentOverLap) {
106 | overlap.addState(currentOverLap);
107 | }
108 |
109 |
110 | /*
111 | *A Point (srcX,srcY) of this Column's 'center' position in
112 | * terms of the proximal-synapse input space.
113 | **/
114 |
115 | public Point getInputSpacePosition() {
116 | return this.getOwner().convertColumnPositionToInputSpace(this.getPosition());
117 | }
118 |
119 | /**
120 | * WP
121 | * Prior to receiving any inputs, the region is initialized by computing a list of initial
122 | * potential synapses for each column. This consists of a random set of inputs selected
123 | * from the input space. Each input is represented by a synapse and assigned a
124 | * random permanence value. The random permanence values are chosen with two
125 | * criteria. First, the values are chosen to be in a small range around connectedPerm
126 | * (the minimum permanence value at which a synapse is considered "connected").
127 | * This enables potential synapses to become connected (or disconnected) after a
128 | * small number of training iterations. Second, each column has a natural center over
129 | * the input region, and the permanence values have a bias towards this center (they
130 | * have higher values near the center).
131 | *
132 | * @param inputRadius
133 | */
134 |
135 | public void createProximalSegment(double inputRadius) {
136 | InputSpace sensoryInput = this.getOwner().getInputSpace();
137 | Point inputSpacePosition = this.getInputSpacePosition();
138 | List potentialProximalInputs = sensoryInput.getAllWithinRadius(inputSpacePosition, inputRadius);
139 | if (potentialProximalInputs.size() < AMOUNT_OF_PROXIMAL_SYNAPSES) {
140 | throw new IllegalArgumentException("Amount of potential synapses:" + AMOUNT_OF_PROXIMAL_SYNAPSES
141 | + " is bigger than number of inputs:" + potentialProximalInputs.size() + ", increase input radius");
142 | }
143 | Collections.shuffle(potentialProximalInputs);
144 | // Tie the random seed to this Column's position for reproducibility
145 | inputRadius = inputRadius < 1 ? Math.sqrt(Math.pow(sensoryInput.getDimension().height, 2) + Math.pow(
146 | sensoryInput.getDimension().width, 2)) : inputRadius;
147 | Random randomGenerator = new Random(this.getLocationSeed());
148 | for (int j = 0; j < AMOUNT_OF_PROXIMAL_SYNAPSES; j++) {
149 | InputSpace.Input input = potentialProximalInputs.get(j);
150 | //Permanence value is based on Gaussian distribution around the ConnectedPerm value, biased by distance from this Column.
151 | double distanceToInputSrc = BaseSpace.getDistance(inputSpacePosition, input.getPosition()),
152 | distanceToInputColumn = BaseSpace.getDistance(this.getOwner().convertInputPositionToColumnSpace(
153 | input.getPosition()), position),
154 | initPermanence = Synapse.ProximalSynapse.PERMANENCE_INCREASE * randomGenerator.nextGaussian() + Synapse.ProximalSynapse.CONNECTED_PERMANENCE,
155 | radiusBiasDeviation = 0.1f, //1.1 to 0.9 -> Y = 1.1 - radiusBiasDeviation / 2inputRadius * X
156 | radiusBiasScale = 1 + radiusBiasDeviation - radiusBiasDeviation / inputRadius * 2 * distanceToInputSrc,
157 | radiusBiasPermanence = initPermanence * radiusBiasScale;
158 | LOG.debug("PERMANENCE INITIALIZATION: init permanence" + initPermanence
159 | + " ,distanceToInputSrc:" + distanceToInputSrc + ", distanceToInputColumn:" + distanceToInputColumn + ", radiusBiasScale:" + radiusBiasScale + " , radiusBiasPermanence:" + radiusBiasPermanence);
160 | proximalSynapses.add(new Synapse.ProximalSynapse(radiusBiasPermanence, input, this));
161 | }
162 | }
163 |
164 | /**
165 | * WP
166 | * increasePermanence(c, s)
167 | * Increase the permanence value of every synapse in column c by a scale factor s.
168 | *
169 | * @param increaseBy
170 | */
171 | public void increasePermanence(double increaseBy) {
172 | //List proximalSynapses = this.getPotentialSynapses();
173 | for (Synapse.ProximalSynapse proximalSynapse : proximalSynapses) {
174 | proximalSynapse.setPermanence(proximalSynapse.getPermanence() + increaseBy);
175 | }
176 |
177 | }
178 |
179 |
180 | /**
181 | * overlap(c) The spatial pooler overlap of column c with a particular
182 | * input pattern.
183 | *
184 | * @return
185 | */
186 |
187 | public double getOverlap() {
188 | return overlap.getLast();
189 | }
190 |
191 | /**
192 | * WP
193 | * overlapDutyCycle(c) A sliding average representing how often column c has had
194 | * significant overlap (i.e. greater than minOverlap) with its
195 | * inputs (e.g. over the last 1000 iterations).
196 | *
197 | * @return
198 | */
199 |
200 | public double getOverlapDutyCycle() {
201 | return overlap.getSlidingAverage();
202 | }
203 |
204 | public boolean isActive() {
205 | return active.getLast();
206 | }
207 |
208 |
209 | /**
210 | * Get column active state at time
211 | *
212 | * @param time (t - 0) - current step, (t - 1) - previous step, (t- n) - n step
213 | * @return
214 | */
215 | public boolean isActive(int time) {
216 | if (time > active.size()) {
217 | throw new IllegalArgumentException("time: " + time + " can't exceed history buffer limit: " + active.size());
218 | }
219 | return active.get(time);
220 | }
221 |
222 |
223 | public void setActive(boolean active) {
224 | this.active.addState(active);
225 | }
226 |
227 | /**
228 | * WP
229 | * activeDutyCycle(c) A sliding average representing how often column c has
230 | * been active after inhibition (e.g. over the last 1000 iterations).
231 | */
232 | public double getActiveDutyCycle() {
233 | return active.getSlidingAverage();
234 | }
235 |
236 | /**
237 | * maxDutyCycle(cols)
238 | * Returns the maximum active duty cycle of the columns in the given list of columns.
239 | *
240 | * @param inhibitionRadius
241 | * @return
242 | */
243 | public double getMaxDutyCycle(double inhibitionRadius) {
244 | List neighbors = this.getNeighbors(inhibitionRadius);
245 | Collections.sort(neighbors, ACTIVE_DUTY_CYCLE_COMPARATOR);
246 | return neighbors.get(0).getActiveDutyCycle();
247 | }
248 |
249 | /*
250 | * WP
251 | * The boost value for column c as computed during learning -
252 | * used to increase the overlap value for inactive columns.
253 | */
254 | public double getBoost() {
255 | return boost;
256 | }
257 |
258 |
259 | /**
260 | * WP
261 | * boostFunction(c)
262 | * Returns the boost value of a column. The boost value is a scalar >= 1.
263 | * If activeDutyCycle(c) is above minDutyCycle(c), the boost value is 1.
264 | * The boost increases linearly once the column's activeDutyCycle starts falling below its minDutyCycle.
265 | *
266 | * @param minDutyCycle
267 | * @return
268 | */
269 | public void updateBoost(double minDutyCycle, double boostRate) {
270 | if (this.getActiveDutyCycle() > minDutyCycle) {
271 | this.boost = 1.0;
272 | } else {
273 | this.boost += boostRate;
274 | }
275 | }
276 |
277 | /*
278 | * WP
279 | * neighbors(c) A list of all the columns that are within inhibitionRadius of
280 | * column c.
281 | */
282 | public List getNeighbors(Double inhibitionRadius) {
283 | //to limit cache to 0.1 fraction
284 | Double roundedInhibitionRadius = MathUtils.round(inhibitionRadius, 1);
285 | List result;
286 | result = neighbors_cache.get(roundedInhibitionRadius);
287 | if (result == null) {
288 | result = this.getOwner().getAllWithinRadius(this.getPosition(), roundedInhibitionRadius);
289 | //remove itself
290 | result.remove(result.indexOf(this));
291 | if (result.size() == 0) {
292 | throw new IllegalArgumentException(
293 | "No neighbors found within inhibitionRadius of: " + inhibitionRadius + ". Please increase receptiveFieldSize by increasing inputRadius for input Space.");
294 | }
295 | neighbors_cache.put(roundedInhibitionRadius, result);
296 | }
297 | return result;
298 | }
299 |
300 | public List getActiveConnectedSynapses() {
301 | return CollectionUtils.filter(proximalSynapses, ACTIVE_CONNECTED_PROXIMAL_SYNAPSES_PREDICATE);
302 | }
303 |
304 | /**
305 | * WP
306 | * connectedSynapses(c)
307 | * A subset of potentialSynapses(c) where the permanence value is greater than connectedPerm.
308 | * These are the bottom-up inputs that are currently connected to column c.
309 | *
310 | * @return
311 | */
312 | public List getConnectedSynapses() {
313 | return CollectionUtils.filter(proximalSynapses, CONNECTED_PROXIMAL_SYNAPSES_PREDICATE);
314 | }
315 |
316 | /**
317 | * WP
318 | * potentialSynapses(c)
319 | * The list of potential synapses and their permanence values.
320 | *
321 | * @return
322 | */
323 | public List getPotentialSynapses() {
324 | return Collections.unmodifiableList(proximalSynapses);
325 | }
326 |
327 |
328 | public void nextTimeStep() {
329 | for (Cell cell : this.getElementsList()) {
330 | cell.nextTimeStep();
331 | }
332 | }
333 |
334 |
335 | private static abstract class ColumnBufferedState extends CircularArrayList {
336 | public ColumnBufferedState(E defValue) {
337 | super(COLUMN_CYCLE_BUFFER_SIZE);
338 | addState(defValue);
339 | }
340 |
341 | /**
342 | * Set the column state
343 | *
344 | * @param value
345 | */
346 | void addState(E value) {
347 | this.add(0, value);
348 | }
349 |
350 | public E getLast() {
351 | return this.get(0);
352 | }
353 |
354 | public double getSlidingAverage() {
355 | double result;
356 | int length = this.size(), activeCount = 0;
357 | for (int i = 0; i < length; i++) {
358 | if (positiveCondition(get(i))) {
359 | activeCount++;
360 | }
361 | }
362 | result = 1.0 * activeCount / length;
363 | return result;
364 | }
365 |
366 | protected abstract boolean positiveCondition(E state);
367 | }
368 |
369 | public static class Config {
370 | private final int amountOfProximalSynapses;
371 | public Config(int amountOfProximalSynapses) {
372 | this.amountOfProximalSynapses = amountOfProximalSynapses;
373 | }
374 |
375 | public int getAmountOfProximalSynapses() {
376 | return amountOfProximalSynapses;
377 | }
378 | }
379 | }
380 |
--------------------------------------------------------------------------------
/src/main/java/htm/utils/UIUtils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.utils;
10 |
11 | import htm.visualizer.surface.SensoryInputSurface;
12 | import org.apache.commons.logging.Log;
13 | import org.apache.commons.logging.LogFactory;
14 |
15 | import java.awt.*;
16 | import java.awt.font.FontRenderContext;
17 | import java.awt.font.TextLayout;
18 | import java.text.DecimalFormat;
19 | import java.util.Map;
20 | import java.util.Set;
21 | import javax.swing.*;
22 | import javax.swing.border.Border;
23 | import javax.swing.table.DefaultTableCellRenderer;
24 |
25 | public enum UIUtils {
26 | INSTANCE;
27 | public static final DecimalFormat DF_4 = new DecimalFormat("##0.0000");
28 | public static final DecimalFormat DF_3 = new DecimalFormat("##0.000");
29 | public static final DecimalFormat DF_2 = new DecimalFormat("##0.00");
30 |
31 |
32 | private static final Log LOG = LogFactory.getLog(UIUtils.class);
33 | public final static Color LIGHT_BLUE = new Color(153, 204, 255);
34 |
35 | public static final Border DEFAULT_BORDER = BorderFactory.createEmptyBorder(0, 4, 0, 4);
36 | public static final Border LIGHT_GRAY_BORDER = BorderFactory.createLineBorder(Color.lightGray);
37 | private static final Font sanSerifFont = new Font("SanSerif", Font.BOLD, 11);
38 |
39 | private UIUtils() {
40 | }
41 |
42 | public static void drawStatesInCircle(Graphics2D g2d, int x, int y, int width, int height, Color... stateColors) {
43 | int states = stateColors.length;
44 | if (states > 0) {
45 | int startAngle = 0, arcAngle = 360 / states;
46 | for (Color stateColor : stateColors) {
47 | g2d.setColor(stateColor);
48 | g2d.fillArc(x, y, width, height, startAngle, arcAngle);
49 | startAngle = startAngle + arcAngle;
50 | }
51 | }
52 | g2d.setColor(Color.BLACK);
53 | g2d.drawOval(x, y, width, height);
54 | }
55 |
56 | public static void drawTextInCenter(Graphics2D g2d, int x, int y, int width, int height, String predictInStepStr) {
57 | g2d.setFont(sanSerifFont);
58 | g2d.setColor(Color.WHITE);
59 | FontMetrics fm = g2d.getFontMetrics();
60 | int w = fm.stringWidth(predictInStepStr);
61 | int h = fm.getAscent();
62 | g2d.drawString(predictInStepStr, x + width/2 - (w / 2) + 2, y + height/2+ (h / 4) + 2);
63 | }
64 |
65 | public ImageIcon createImageIcon(String path) {
66 | java.net.URL imgURL = getClass().getResource(path);
67 | if (imgURL != null) {
68 | return new ImageIcon(imgURL);
69 | } else {
70 | LOG.error("Couldn't find file: " + path);
71 | throw new IllegalArgumentException("Couldn't find file: " + path);
72 | }
73 | }
74 |
75 | /*
76 | * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
77 | *
78 | * Redistribution and use in source and binary forms, with or without
79 | * modification, are permitted provided that the following conditions
80 | * are met:
81 | *
82 | * - Redistributions of source code must retain the above copyright
83 | * notice, this list of conditions and the following disclaimer.
84 | *
85 | * - Redistributions in binary form must reproduce the above copyright
86 | * notice, this list of conditions and the following disclaimer in the
87 | * documentation and/or other materials provided with the distribution.
88 | *
89 | * - Neither the name of Oracle or the names of its
90 | * contributors may be used to endorse or promote products derived
91 | * from this software without specific prior written permission.
92 | *
93 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
94 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
95 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
96 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
97 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
98 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
99 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
100 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
101 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
102 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
103 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
104 | */
105 |
106 | /**
107 | * A 1.4 file that provides utility methods for
108 | * creating form- or grid-style layouts with SpringLayout.
109 | * These utilities are used by several programs, such as
110 | * SpringBox and SpringCompactGrid.
111 | */
112 |
113 | /**
114 | * Aligns the first rows * cols
115 | * components of parent in
116 | * a grid. Each component in a column is as wide as the maximum
117 | * preferred width of the components in that column;
118 | * height is similarly determined for each row.
119 | * The parent is made just big enough to fit them all.
120 | *
121 | * @param rows number of rows
122 | * @param cols number of columns
123 | * @param initialX x location to start the grid at
124 | * @param initialY y location to start the grid at
125 | * @param xPad x padding between cells
126 | * @param yPad y padding between cells
127 | */
128 | public static void makeSpringCompactGrid(Container parent,
129 | int rows, int cols,
130 | int initialX, int initialY,
131 | int xPad, int yPad) {
132 | SpringLayout layout;
133 | try {
134 | layout = (SpringLayout)parent.getLayout();
135 | } catch (ClassCastException exc) {
136 | System.err.println("The first argument to makeCompactGrid must use SpringLayout.");
137 | return;
138 | }
139 |
140 | //Align all cells in each column and make them the same width.
141 | Spring x = Spring.constant(initialX);
142 | for (int c = 0; c < cols; c++) {
143 | Spring width = Spring.constant(0);
144 | for (int r = 0; r < rows; r++) {
145 | width = Spring.max(width,
146 | getConstraintsForCell(r, c, parent, cols).
147 | getWidth());
148 | }
149 | for (int r = 0; r < rows; r++) {
150 | SpringLayout.Constraints constraints =
151 | getConstraintsForCell(r, c, parent, cols);
152 | constraints.setX(x);
153 | constraints.setWidth(width);
154 | }
155 | x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad)));
156 | }
157 |
158 | //Align all cells in each row and make them the same height.
159 | Spring y = Spring.constant(initialY);
160 | for (int r = 0; r < rows; r++) {
161 | Spring height = Spring.constant(0);
162 | for (int c = 0; c < cols; c++) {
163 | height = Spring.max(height,
164 | getConstraintsForCell(r, c, parent, cols).
165 | getHeight());
166 | }
167 | for (int c = 0; c < cols; c++) {
168 | SpringLayout.Constraints constraints =
169 | getConstraintsForCell(r, c, parent, cols);
170 | constraints.setY(y);
171 | constraints.setHeight(height);
172 | }
173 | y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad)));
174 | }
175 |
176 | //Set the parent's size.
177 | SpringLayout.Constraints pCons = layout.getConstraints(parent);
178 | pCons.setConstraint(SpringLayout.SOUTH, y);
179 | pCons.setConstraint(SpringLayout.EAST, x);
180 | }
181 |
182 | /**
183 | * Aligns the first rows * cols
184 | * components of parent in
185 | * a grid. Each component is as big as the maximum
186 | * preferred width and height of the components.
187 | * The parent is made just big enough to fit them all.
188 | *
189 | * @param rows number of rows
190 | * @param cols number of columns
191 | * @param initialX x location to start the grid at
192 | * @param initialY y location to start the grid at
193 | * @param xPad x padding between cells
194 | * @param yPad y padding between cells
195 | */
196 | public static void makeSpringGrid(Container parent,
197 | int rows, int cols,
198 | int initialX, int initialY,
199 | int xPad, int yPad) {
200 | SpringLayout layout;
201 | try {
202 | layout = (SpringLayout)parent.getLayout();
203 | } catch (ClassCastException exc) {
204 | System.err.println("The first argument to makeGrid must use SpringLayout.");
205 | return;
206 | }
207 |
208 | Spring xPadSpring = Spring.constant(xPad);
209 | Spring yPadSpring = Spring.constant(yPad);
210 | Spring initialXSpring = Spring.constant(initialX);
211 | Spring initialYSpring = Spring.constant(initialY);
212 | int max = rows * cols;
213 |
214 | //Calculate Springs that are the max of the width/height so that all
215 | //cells have the same size.
216 | Spring maxWidthSpring = layout.getConstraints(parent.getComponent(0)).
217 | getWidth();
218 | Spring maxHeightSpring = layout.getConstraints(parent.getComponent(0)).
219 | getHeight();
220 | for (int i = 1; i < max; i++) {
221 | SpringLayout.Constraints cons = layout.getConstraints(
222 | parent.getComponent(i));
223 |
224 | maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth());
225 | maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight());
226 | }
227 |
228 | //Apply the new width/height Spring. This forces all the
229 | //components to have the same size.
230 | for (int i = 0; i < max; i++) {
231 | SpringLayout.Constraints cons = layout.getConstraints(
232 | parent.getComponent(i));
233 |
234 | cons.setWidth(maxWidthSpring);
235 | cons.setHeight(maxHeightSpring);
236 | }
237 |
238 | //Then adjust the x/y constraints of all the cells so that they
239 | //are aligned in a grid.
240 | SpringLayout.Constraints lastCons = null;
241 | SpringLayout.Constraints lastRowCons = null;
242 | for (int i = 0; i < max; i++) {
243 | SpringLayout.Constraints cons = layout.getConstraints(
244 | parent.getComponent(i));
245 | if (i % cols == 0) { //start of new row
246 | lastRowCons = lastCons;
247 | cons.setX(initialXSpring);
248 | } else { //x position depends on previous component
249 | cons.setX(Spring.sum(lastCons != null ? lastCons.getConstraint(SpringLayout.EAST) : null,
250 | xPadSpring));
251 | }
252 |
253 | if (i / cols == 0) { //first row
254 | cons.setY(initialYSpring);
255 | } else { //y position depends on previous row
256 | assert lastRowCons != null;
257 | cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH),
258 | yPadSpring));
259 | }
260 | lastCons = cons;
261 | }
262 |
263 | //Set the parent's size.
264 | SpringLayout.Constraints pCons = layout.getConstraints(parent);
265 | assert lastCons != null;
266 | pCons.setConstraint(SpringLayout.SOUTH,
267 | Spring.sum(
268 | Spring.constant(yPad),
269 | lastCons.getConstraint(SpringLayout.SOUTH)));
270 | pCons.setConstraint(SpringLayout.EAST,
271 | Spring.sum(
272 | Spring.constant(xPad),
273 | lastCons.getConstraint(SpringLayout.EAST)));
274 | }
275 |
276 | /* Used by makeCompactGrid. */
277 | private static SpringLayout.Constraints getConstraintsForCell(
278 | int row, int col,
279 | Container parent,
280 | int cols) {
281 | SpringLayout layout = (SpringLayout)parent.getLayout();
282 | Component c = parent.getComponent(row * cols + col);
283 | return layout.getConstraints(c);
284 | }
285 |
286 | public static abstract class TextColumnInfo extends JPanel {
287 | protected float finishParagraphY;
288 | protected int startX = 100;
289 |
290 | public TextColumnInfo() {
291 | setBackground(Color.WHITE);
292 | }
293 |
294 | @Override
295 | public void paint(Graphics g) {
296 | super.paint(g);
297 | Graphics2D graphics2D = (Graphics2D)g;
298 | Map cellAttributes = getAttributeMap();
299 | finishParagraphY = drawPropertyParagraph(graphics2D, cellAttributes, startX , 5, 20);
300 | }
301 |
302 |
303 | abstract protected Map getAttributeMap();
304 |
305 | protected float drawPropertyParagraph(Graphics2D g2, Map properties, float width, float x,
306 | float y) {
307 | FontRenderContext frc = g2.getFontRenderContext();
308 | float drawPosY = y;
309 | Font nameFont = new Font("Helvetica", Font.BOLD, 12);
310 | Font valueFont = new Font("Helvetica", Font.PLAIN, 12);
311 | Set names = properties.keySet();
312 | for (String name : names) {
313 | String value = properties.get(name);
314 | TextLayout nameLayout = new TextLayout(name + ":", nameFont, frc);
315 | TextLayout valueLayout = new TextLayout(value, valueFont, frc);
316 | // Set position to the index of the first character in the paragraph.
317 | float drawPosX;
318 | drawPosX = x + width - nameLayout.getAdvance();
319 | // Move y-coordinate by the ascent of the layout.
320 | drawPosY += nameLayout.getAscent();
321 | // Draw the TextLayout at (drawPosX, drawPosY).
322 | nameLayout.draw(g2, drawPosX, drawPosY);
323 | double newX = x + width + 4;
324 | valueLayout.draw(g2, (float)newX, drawPosY);
325 | // Move y-coordinate in preparation for next layout.
326 | drawPosY += nameLayout.getDescent() + nameLayout.getLeading();
327 | }
328 | return drawPosY;
329 | }
330 |
331 | }
332 |
333 | public static class SortablePoint extends Point implements Comparable {
334 | public SortablePoint(Point p) {
335 | super(p);
336 | }
337 |
338 | @Override
339 | public int compareTo(SortablePoint point) {
340 | return this.getSquare() - point.getSquare();
341 | }
342 |
343 | int getSquare() {
344 | return (int)(Math.pow(x, 2) + Math.pow(y, 2));
345 | }
346 | }
347 |
348 | public static class SmallDoubleRenderer extends DefaultTableCellRenderer {
349 | {
350 | this.setHorizontalAlignment(SwingConstants.RIGHT);
351 | }
352 |
353 | @Override protected void setValue(Object value) {
354 | super.setValue(DF_2.format(value));
355 | }
356 | }
357 |
358 | public static class PositionRenderer extends DefaultTableCellRenderer {
359 | {
360 | this.setHorizontalAlignment(SwingConstants.CENTER);
361 | }
362 |
363 | @Override protected void setValue(Object value) {
364 | Point point = (Point)value;
365 | super.setValue("X:" + (point.x) + ", Y:" + point.y);
366 | }
367 | }
368 |
369 |
370 |
371 | public static class PermanenceRenderer extends DefaultTableCellRenderer {
372 | private double permanence = 0;
373 |
374 | { // initializer block
375 | this.setHorizontalAlignment(SwingConstants.RIGHT);
376 | }
377 | /* public PermanenceRenderer() {
378 | this.setHorizontalAlignment(SwingConstants.CENTER);
379 | }*/
380 |
381 | @Override public void paint(Graphics g) {
382 | super.paint(g);
383 | Dimension size = this.getSize();
384 | Rectangle insideRec = new Rectangle(2, 2, size.height - 4, size.height - 4);
385 | Graphics2D g2d = (Graphics2D)g;
386 | SensoryInputSurface.renderSynapse(g2d, permanence, insideRec);
387 | g2d.setColor(Color.BLACK);
388 | //g2d.drawString(DF_4.format(permanence) + "", size.height + 4, 12);
389 | }
390 |
391 | @Override
392 | public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
393 | int row, int column) {
394 | this.permanence = (Double)value;
395 | return super.getTableCellRendererComponent(table, DF_3.format(value), isSelected, hasFocus, row,
396 | column);
397 | }
398 | }
399 | }
400 |
--------------------------------------------------------------------------------
/src/main/java/htm/visualizer/Parameters.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2011, Peace Technology, Inc.
3 | * $Author:$
4 | * $Revision:$
5 | * $Date:$
6 | * $NoKeywords$
7 | */
8 |
9 | package htm.visualizer;
10 |
11 | import htm.model.Cell;
12 | import htm.model.Column;
13 | import htm.model.Layer;
14 | import htm.model.Synapse;
15 | import htm.model.algorithms.spatial.SpatialPooler;
16 | import htm.model.algorithms.temporal.TemporalPooler;
17 | import htm.utils.MathUtils;
18 | import htm.utils.UIUtils;
19 |
20 | import java.awt.*;
21 | import java.util.Hashtable;
22 | import javax.swing.*;
23 | import javax.swing.event.ChangeEvent;
24 | import javax.swing.event.ChangeListener;
25 |
26 | public class Parameters {
27 |
28 | static class FixedWidthLabel extends JLabel {
29 | @Override public Dimension getPreferredSize() {
30 | return new Dimension(135, super.getPreferredSize().height);
31 | }
32 |
33 | FixedWidthLabel(String text) {
34 | super(text);
35 | }
36 | }
37 |
38 | static abstract class NumberParameter extends Container implements ChangeListener {
39 | protected static final int SLIDER_SCALE = 100;
40 | protected final int sliderScale;
41 |
42 | protected JSpinner spinnerField;
43 | protected JSlider sliderField;
44 |
45 | NumberParameter(E minValue, E maxValue, E value) {
46 | this(minValue, maxValue, value, SLIDER_SCALE);
47 | }
48 |
49 | NumberParameter(E minValue, E maxValue, E value, int sliderScale) {
50 | this.sliderScale = sliderScale;
51 | setLayout(new GridBagLayout());
52 | initFields(minValue, maxValue, value);
53 | spinnerField.setPreferredSize(new Dimension(60, 30));
54 | GridBagConstraints c = new GridBagConstraints();
55 | c.fill = GridBagConstraints.HORIZONTAL;
56 | c.weighty = 1.0;
57 | c.weightx = 3;
58 | this.add(sliderField, c);
59 | c.weightx = 1;
60 | this.add(spinnerField, c);
61 | spinnerField.addChangeListener(this);
62 | sliderField.addChangeListener(this);
63 | }
64 |
65 | public void setValue(E value) {
66 | if (sliderField.getValue() != value.intValue()) {
67 | setSliderValue(value);
68 | }
69 | if (spinnerField.getValue() != value) {
70 | spinnerField.setValue(value);
71 | }
72 | }
73 |
74 |
75 | @SuppressWarnings("unchecked") public E getValue() {
76 | return (E)spinnerField.getValue();
77 | }
78 |
79 | @SuppressWarnings("unchecked") @Override public void stateChanged(ChangeEvent e) {
80 | if (e.getSource() instanceof JSlider) {
81 | setValue(getSliderValue());
82 | } else if (e.getSource() instanceof JSpinner) {
83 | setValue((E)spinnerField.getValue());
84 | }
85 | }
86 |
87 | abstract protected void initFields(E minValue, E maxValue, E value);
88 |
89 | abstract protected E getSliderValue();
90 |
91 | abstract protected void setSliderValue(E value);
92 | }
93 |
94 | static class IntegerParameter extends NumberParameter {
95 |
96 | IntegerParameter(Integer minValue, Integer maxValue, Integer value) {
97 | super(minValue, maxValue, value);
98 | }
99 |
100 | @Override protected void initFields(Integer minValue, Integer maxValue, Integer value) {
101 | spinnerField = new JSpinner(
102 | new SpinnerNumberModel(value.intValue(), minValue.intValue(), maxValue.intValue(), 1));
103 | sliderField = new JSlider(JSlider.HORIZONTAL, minValue, maxValue, value);
104 | sliderField.setPaintLabels(true);
105 | Hashtable labelTable = new Hashtable();
106 | labelTable.put(minValue, new JLabel(minValue + ""));
107 | labelTable.put((maxValue - Math.abs(minValue)) / 2, new JLabel((maxValue - Math.abs(minValue)) / 2 + ""));
108 | labelTable.put(maxValue, new JLabel(maxValue + ""));
109 | sliderField.setLabelTable(labelTable);
110 | }
111 |
112 | @Override protected Integer getSliderValue() {
113 | return sliderField.getValue();
114 | }
115 |
116 | @Override protected void setSliderValue(Integer value) {
117 | sliderField.setValue(value);
118 | }
119 | }
120 |
121 | static class DoubleParameter extends NumberParameter {
122 |
123 | DoubleParameter(Double minValue, Double maxValue, Double value, int sliderScale) {
124 | super(minValue, maxValue, value, sliderScale);
125 | }
126 |
127 | DoubleParameter(Double minValue, Double maxValue, Double value) {
128 | super(minValue, maxValue, value);
129 | }
130 |
131 | @Override public void setValue(Double value) {
132 | Double valueConverted = MathUtils.round(value, 3);
133 | Double sliderValueConverted = MathUtils.round(1.0 * sliderField.getValue() / sliderScale, 3);
134 | Double spinnerValueConverted = MathUtils.round((Double)spinnerField.getValue(), 3);
135 | if (sliderValueConverted.doubleValue() != value) {
136 | setSliderValue(valueConverted);
137 | }
138 | if (spinnerValueConverted.doubleValue() != value) {
139 | spinnerField.setValue(valueConverted);
140 | }
141 | }
142 |
143 | @Override protected void initFields(Double minValue, Double maxValue, Double value) {
144 | int sliderMin = (int)(minValue * sliderScale),
145 | sliderMax = (int)(maxValue * sliderScale),
146 | sliderValue = (int)(value * sliderScale);
147 | spinnerField = new JSpinner(
148 | new SpinnerNumberModel(value, minValue, maxValue, new Double((maxValue - minValue) / sliderScale)));
149 | sliderField = new JSlider(JSlider.HORIZONTAL, sliderMin, sliderMax,
150 | sliderValue);
151 | sliderField.setPaintLabels(true);
152 | Hashtable labelTable = new Hashtable();
153 | labelTable.put(sliderMin, new JLabel(minValue + ""));
154 | labelTable.put((sliderMax - Math.abs(sliderMin)) / 2, new JLabel((maxValue - Math.abs(minValue)) / 2 + ""));
155 | labelTable.put(sliderMax, new JLabel(maxValue + ""));
156 | sliderField.setLabelTable(labelTable);
157 | }
158 |
159 | @Override protected Double getSliderValue() {
160 | return 1.0 * sliderField.getValue() / sliderScale;
161 | }
162 |
163 | @Override protected void setSliderValue(Double value) {
164 | sliderField.setValue((int)(value * sliderScale));
165 | }
166 |
167 | }
168 |
169 | static class RegionParameters extends JPanel {
170 | private final Parameters.IntegerParameter regionWidthParam;
171 | private final Parameters.IntegerParameter regionHeightParam;
172 | private final Parameters.IntegerParameter inputSpaceWidthParam;
173 | private final Parameters.IntegerParameter inputSpaceHeightParam;
174 | private final DoubleParameter learningRadiusParam;
175 | private final DoubleParameter inputRadiusParam;
176 | private final Parameters.IntegerParameter cellsInColumnParam;
177 | private final JCheckBox skipSpatialCb;
178 |
179 | RegionParameters(Layer.Config cfg) {
180 | setLayout(new SpringLayout());
181 | regionWidthParam = new IntegerParameter(1, 50, cfg.getRegionDimension().width);
182 | regionHeightParam = new IntegerParameter(1, 50, cfg.getRegionDimension().height);
183 | inputSpaceWidthParam = new IntegerParameter(1, 50, cfg.getSensoryInputDimension().width);
184 | inputSpaceHeightParam = new IntegerParameter(1, 50, cfg.getSensoryInputDimension().height);
185 | learningRadiusParam = new DoubleParameter(1.0, 50.0, cfg.getLearningRadius(), 200);
186 | inputRadiusParam = new DoubleParameter(1.0, 25.0, cfg.getInputRadius(), 200);
187 | cellsInColumnParam = new IntegerParameter(1, 20, cfg.getCellsInColumn());
188 | skipSpatialCb = new JCheckBox(null, null, cfg.isSkipSpatial());
189 | JLabel l = new FixedWidthLabel("Region Width");
190 | this.add(l);
191 | this.add(regionWidthParam);
192 | l = new FixedWidthLabel("Region Height");
193 | this.add(l);
194 | this.add(regionHeightParam);
195 | l = new FixedWidthLabel("Input Space Width");
196 | this.add(l);
197 | this.add(inputSpaceWidthParam);
198 | l = new FixedWidthLabel("Input Space Height");
199 | this.add(l);
200 | this.add(inputSpaceHeightParam);
201 | l = new FixedWidthLabel("Input Radius");
202 | this.add(l);
203 | this.add(inputRadiusParam);
204 | l = new FixedWidthLabel("Learning Radius");
205 | this.add(l);
206 | this.add(learningRadiusParam);
207 | l = new FixedWidthLabel("Cells per Column");
208 | this.add(l);
209 | this.add(cellsInColumnParam);
210 | l = new FixedWidthLabel("Skip Spatial");
211 | this.add(l);
212 | this.add(skipSpatialCb);
213 | UIUtils.makeSpringCompactGrid(this,
214 | 8, 2, //rows, cols
215 | 6, 6, //initX, initY
216 | 6, 6); //xPad, yPad
217 | }
218 |
219 | Layer.Config getParameters() {
220 | return new Layer.Config(new Dimension(regionWidthParam.getValue(),
221 | regionHeightParam.getValue()),
222 | new Dimension(inputSpaceWidthParam.getValue(),
223 | inputSpaceHeightParam.getValue()),
224 | inputRadiusParam.getValue(),
225 | learningRadiusParam.getValue(),
226 | skipSpatialCb.isSelected(),
227 | cellsInColumnParam.getValue());
228 | }
229 |
230 | void setParameters(Layer.Config cfg) {
231 | regionWidthParam.setValue(cfg.getRegionDimension().width);
232 | regionHeightParam.setValue(cfg.getRegionDimension().height);
233 | inputSpaceWidthParam.setValue(cfg.getSensoryInputDimension().width);
234 | inputSpaceHeightParam.setValue(cfg.getSensoryInputDimension().height);
235 | inputRadiusParam.setValue(cfg.getInputRadius());
236 | learningRadiusParam.setValue(cfg.getLearningRadius());
237 | skipSpatialCb.setSelected(cfg.isSkipSpatial());
238 | }
239 | }
240 |
241 | static class SpatialPoolerParameters extends JPanel {
242 | private final Parameters.IntegerParameter minOverlapParam;
243 | private final Parameters.IntegerParameter desiredLocalActivityParam;
244 | private final Parameters.DoubleParameter boostRateParam;
245 |
246 | SpatialPoolerParameters(SpatialPooler.Config cfg) {
247 | minOverlapParam = new IntegerParameter(1, 10, cfg.getMinOverlap());
248 | desiredLocalActivityParam = new IntegerParameter(1, 10, cfg.getDesiredLocalActivity());
249 | boostRateParam = new Parameters.DoubleParameter(0.005, 0.2, cfg.getBoostRate(), 200);
250 | setLayout(new SpringLayout());
251 | JLabel l = new FixedWidthLabel("Min Overlap");
252 | this.add(l);
253 | this.add(minOverlapParam);
254 | l = new FixedWidthLabel("Desired Local Activity");
255 | this.add(l);
256 | this.add(desiredLocalActivityParam);
257 | l = new FixedWidthLabel("Boost Rate");
258 | this.add(l);
259 | this.add(boostRateParam);
260 | UIUtils.makeSpringCompactGrid(this,
261 | 3, 2, //rows, cols
262 | 6, 6, //initX, initY
263 | 6, 6); //xPad, yPad
264 | }
265 |
266 | SpatialPooler.Config getParameters() {
267 | return new SpatialPooler.Config(minOverlapParam.getValue(),
268 | desiredLocalActivityParam.getValue(),
269 | boostRateParam.getValue());
270 | }
271 |
272 | void setParameters(SpatialPooler.Config cfg) {
273 | minOverlapParam.setValue(cfg.getMinOverlap());
274 | desiredLocalActivityParam.setValue(cfg.getDesiredLocalActivity());
275 | boostRateParam.setValue(cfg.getBoostRate());
276 | }
277 | }
278 |
279 | static class ColumnParameters extends JPanel {
280 | private final Parameters.IntegerParameter amountOfProximalSynapsesParam;
281 |
282 |
283 | ColumnParameters(Column.Config cfg) {
284 | setLayout(new SpringLayout());
285 | amountOfProximalSynapsesParam = new IntegerParameter(2, 60, cfg.getAmountOfProximalSynapses());
286 | JLabel l = new FixedWidthLabel("N of Proximal Synapses");
287 | this.add(l);
288 | this.add(amountOfProximalSynapsesParam);
289 | UIUtils.makeSpringCompactGrid(this,
290 | 1, 2, //rows, cols
291 | 6, 6, //initX, initY
292 | 6, 6); //xPad, yPad
293 | }
294 |
295 | Column.Config getParameters() {
296 | return new Column.Config(amountOfProximalSynapsesParam.getValue());
297 | }
298 |
299 | void setParameters(Column.Config cfg) {
300 | amountOfProximalSynapsesParam.setValue(cfg.getAmountOfProximalSynapses());
301 | }
302 | }
303 |
304 | static class TemporalPoolerParameters extends JPanel {
305 | private final Parameters.IntegerParameter newSynapseCountParam;
306 | private final Parameters.IntegerParameter activationThresholdParam;
307 | private final Parameters.IntegerParameter minThresholdParam;
308 |
309 | TemporalPoolerParameters(TemporalPooler.Config temporalPoolerCfg) {
310 | setLayout(new SpringLayout());
311 | newSynapseCountParam = new IntegerParameter(1, 10, temporalPoolerCfg.getNewSynapseCount());
312 | activationThresholdParam = new IntegerParameter(0, 15, temporalPoolerCfg.getActivationThreshold());
313 | minThresholdParam = new IntegerParameter(0, 5, temporalPoolerCfg.getMinThreshold());
314 | JLabel l = new FixedWidthLabel("N of New Synapses");
315 | this.add(l);
316 | this.add(newSynapseCountParam);
317 | l = new FixedWidthLabel("Activation Threshold");
318 | this.add(l);
319 | this.add(activationThresholdParam);
320 | l = new FixedWidthLabel("Minimum Threshold");
321 | this.add(l);
322 | this.add(minThresholdParam);
323 | UIUtils.makeSpringCompactGrid(this,
324 | 3, 2, //rows, cols
325 | 6, 6, //initX, initY
326 | 6, 6); //xPad, yPad
327 | }
328 |
329 |
330 | TemporalPooler.Config getParameters() {
331 | return new TemporalPooler.Config(newSynapseCountParam.getValue(),
332 | activationThresholdParam.getValue(),
333 | minThresholdParam.getValue());
334 | }
335 |
336 | void setParameters(TemporalPooler.Config temporalPoolerCfg) {
337 | newSynapseCountParam.setValue(temporalPoolerCfg.getNewSynapseCount());
338 | activationThresholdParam.setValue(temporalPoolerCfg.getActivationThreshold());
339 | minThresholdParam.setValue(temporalPoolerCfg.getMinThreshold());
340 | }
341 | }
342 |
343 | static class CellParameters extends JPanel {
344 |
345 | private final Parameters.IntegerParameter amountOfSynapsesParam;
346 | private final Parameters.IntegerParameter timeStepsParam;
347 |
348 | CellParameters(Cell.Config cellCfg) {
349 | setLayout(new SpringLayout());
350 | amountOfSynapsesParam = new IntegerParameter(5, 60, cellCfg.getAmountOfSynapses());
351 | timeStepsParam = new IntegerParameter(2, 30, cellCfg.getTimeSteps());
352 | JLabel l = new FixedWidthLabel("Amount of Synapses");
353 | this.add(l);
354 | this.add(amountOfSynapsesParam);
355 | l = new FixedWidthLabel("Time Buffer");
356 | this.add(l);
357 | this.add(timeStepsParam);
358 | UIUtils.makeSpringCompactGrid(this,
359 | 2, 2, //rows, cols
360 | 6, 6, //initX, initY
361 | 6, 6); //xPad, yPad
362 | }
363 |
364 | Cell.Config getParameters() {
365 | return new Cell.Config(amountOfSynapsesParam.getValue(),
366 | timeStepsParam.getValue());
367 | }
368 |
369 |
370 | void setParameters(Cell.Config cfg) {
371 | amountOfSynapsesParam.setValue(cfg.getAmountOfSynapses());
372 | timeStepsParam.setValue(cfg.getTimeSteps());
373 | }
374 | }
375 |
376 |
377 | static class SynapseParameters extends JPanel {
378 | private final Parameters.DoubleParameter connectedPermanenceParam;
379 | private final Parameters.DoubleParameter incPermanenceParam;
380 | private final Parameters.DoubleParameter decPermanenceParam;
381 |
382 | SynapseParameters(Synapse.Config cfg) {
383 | setLayout(new SpringLayout());
384 | connectedPermanenceParam = new Parameters.DoubleParameter(0.0, 1.0, cfg.getConnectedPerm());
385 | incPermanenceParam = new Parameters.DoubleParameter(0.005, 0.2, cfg.getPermanenceInc(), 200);
386 | decPermanenceParam = new Parameters.DoubleParameter(0.005, 0.2, cfg.getPermanenceDec(), 200);
387 | JLabel l = new FixedWidthLabel("Conn.Permanence");
388 | this.add(l);
389 | this.add(connectedPermanenceParam);
390 | l = new FixedWidthLabel("Increase By");
391 | this.add(l);
392 | this.add(incPermanenceParam);
393 | l = new FixedWidthLabel("Decrease By");
394 | this.add(l);
395 | this.add(decPermanenceParam);
396 | UIUtils.makeSpringCompactGrid(this,
397 | 3, 2, //rows, cols
398 | 6, 6, //initX, initY
399 | 6, 6); //xPad, yPad
400 | }
401 |
402 | Synapse.Config getParameters() {
403 | return new Synapse.Config(connectedPermanenceParam.getValue(), incPermanenceParam.getValue(),
404 | decPermanenceParam.getValue());
405 | }
406 |
407 | void setParameters(Synapse.Config cfg) {
408 | connectedPermanenceParam.setValue(cfg.getConnectedPerm());
409 | incPermanenceParam.setValue(cfg.getPermanenceInc());
410 | decPermanenceParam.setValue(cfg.getPermanenceDec());
411 | }
412 |
413 |
414 | }
415 |
416 |
417 | }
418 |
--------------------------------------------------------------------------------
| | |